欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET Framework CLR 版本检测

程序员文章站 2022-10-30 12:42:13
我写了一个 c# 程序来检测 .net framework clr 版本。 在 ubuntu 操作中的运行结果: ben@ben-m4000t:~/work$ ./clrinfo.exe...

我写了一个 c# 程序来检测 .net framework clr 版本。

在 ubuntu 操作中的运行结果:

ben@ben-m4000t:~/work$ ./clrinfo.exe
      os version: unix 2.6.31.16
     clr version: 2.0.50727.1433  ( mono 2.4.2.3 )
default encoding: system.text.utf8encoding

available frameworks:
  mono 1.0 profile
  mono 2.0 profile

在 windows vista 操作系统中的运行结果:

e:csclrinfo> clrinfo.exe
      os version: microsoft windows nt 6.0.6002 service pack 2
     clr version: 2.0.50727.4200  ( net 2.0.50727.4200 )
default encoding: system.text.dbcscodepageencoding

available frameworks:
  net 2.0.50727

注意,这个程序检测的是 .net framework clr 版本,而不是 .net framework 版本。实际上这个 windows vista 操作系统中安装了 .net framework 的以下版本:

  • 2.0.50727.4016
  • 3.0.30729.4037
  • 3.5.30729.01

    而三个版本的 .net framework 的 clr 版本都是 2.0.50727。

    在 windows server 2003 操作系统中的运行结果:

    e:csclrinfo> clrinfo.exe
          os version: microsoft windows nt 5.2.3790 service pack 2
         clr version: 2.0.50727.3603  ( net 2.0.50727.3603 )
    default encoding: system.text.dbcscodepageencoding
    
    available frameworks:
      net 1.1.4322
      net 2.0.50727
      net 4.0.21006
    

    另外,microsoft windows sdk 中的 clrver.exe 的运行结果:

    e:csclrinfo> clrver.exe
    versions installed on the machine:
    v1.1.4322
    v2.0.50727
    v4.0.21006
    

    我们来看看源程序吧。下面是 clrinfo.cs:

    using system;
    using system.text;
    
    namespace skyiv
    {
      public class clrinfo
      {
        static void main()
        {
          console.writeline(      os version: {0}, environment.osversion);
          console.writeline(     clr version: {0}  ( {1} ), environment.version, runtimeframework.currentframework);
          console.writeline(default encoding: {0}, encoding.default);
          console.writeline();
          console.writeline(available frameworks:);
          foreach (var frame in runtimeframework.availableframeworks) console.writeline(   + frame);
        }
      }
    }
    

    下面是 runtimeframework.cs (该程序是从 nunit 的源程序中的同名文件改写而来的):

    using system;
    using system.reflection;
    using system.collections.generic;
    using microsoft.win32;
    
    namespace skyiv
    {
      public enum runtimetype
      {
        any,   // any supported runtime framework
        net,   // microsoft .net framework
        netcf, // microsoft .net compact framework
        sscli, // microsoft shared source cli
        mono,  // mono
      }
    
      // see https://nunit.org, this class from nunit project's runtimeframework.cs
      // runtimeframework represents a particular version of a common language runtime implementation.
      [serializable]
      public sealed class runtimeframework
      {
        public runtimetype runtime { get; private set; }
        public version version { get; private set; }
        public string displayname { get; private set; }
        static runtimeframework currentframework;
    
        public static runtimeframework currentframework
        {
          get
          {
            if (currentframework == null)
            {
              var monoruntimetype = type.gettype(mono.runtime, false);
              var runtime = monoruntimetype != null ? runtimetype.mono : runtimetype.net;
              currentframework = new runtimeframework(runtime, environment.version);
              if (monoruntimetype != null)
              {
                var method = monoruntimetype.getmethod(getdisplayname, bindingflags.static |
                  bindingflags.nonpublic | bindingflags.declaredonly | bindingflags.exactbinding);
                if (method != null) currentframework.displayname = (string)method.invoke(null, new object[0]);
              }
            }
            return currentframework;
          }
        }
    
        public static runtimeframework[] availableframeworks
        {
          get
          {
            var frameworks = new list();
            foreach (var framework in getavailableframeworks(runtimetype.net)) frameworks.add(framework);
            foreach (var framework in getavailableframeworks(runtimetype.mono)) frameworks.add(framework);
            return frameworks.toarray();
          }
        }
    
        public static bool ismonoinstalled()
        {
          if (currentframework.runtime == runtimetype.mono) return true;
          // don't know how to do this on linux yet, but it's not a problem since we are only supporting mono on linux
          if (environment.osversion.platform != platformid.win32nt) return false;
          var key = registry.localmachine.opensubkey(@softwarenovellmono);
          if (key == null) return false;
          var version = key.getvalue(defaultclr) as string;
          if (string.isnullorempty(version)) return false;
          return key.opensubkey(version) != null;
        }
    
        // returns an array of all available frameworks of a given type, for example, all mono or all .net frameworks.
        public static runtimeframework[] getavailableframeworks(runtimetype rt)
        {
          var frameworks = new list();
          if (rt == runtimetype.net && environment.osversion.platform != platformid.unix)
          {
            var key = registry.localmachine.opensubkey(@softwaremicrosoft.netframeworkpolicy);
            if (key != null)
              foreach (var name in key.getsubkeynames())
                if (name.startswith(v))
                  foreach (var build in key.opensubkey(name).getvaluenames())
                    frameworks.add(new runtimeframework(rt, new version(name.substring(1) + . + build)));
          }
          else if (rt == runtimetype.mono && ismonoinstalled())
          {
            var framework = new runtimeframework(rt, new version(1, 1, 4322));
            framework.displayname = mono 1.0 profile;
            frameworks.add(framework);
            framework = new runtimeframework(rt, new version(2, 0, 50727));
            framework.displayname = mono 2.0 profile;
            frameworks.add(framework);
          }
          return frameworks.toarray();
        }
    
        public runtimeframework(runtimetype runtime, version version)
        {
          runtime = runtime;
          version = version;
          displayname = runtime.tostring() +   + version.tostring();
        }
    
        public override string tostring()
        {
          return displayname;
        }
      }
    }
    

    在 runtimeframework 类的 currentframework 属性中,如果发现当前环境是 mono 的话,就通过反射调用 mono.runtime 类的静态方法 getdisplayname 来设置 displayname 属性。

    在 runtimeframework 类的静态方法 getavailableframeworks 中,如果发现当前操作系统不是 unix 的话,就通过遍历注册表的 softwaremicrosoft.netframeworkpolicy 项来检测 .net framework clr 版本。

    下面是 makefile (关于 makefile,可以参见:gun make 中文手册):

    csc = csc
    src1 = clrinfo.cs runtimeframework.cs
    
    clrinfo.exe: $(src1)
    	$(csc) -out:$@ $(src1)
    

    在 linux 操作系统下可以用 make 命令编译。在 windows 操作系统下可以用 nmake 命令编译。

    注意,mono 的 c# 编译器是 gmcs,但是她有个别名叫 csc ,如下所示:

    ben@ben-m4000t:~$ ls -l /usr/bin/csc /usr/bin/gmcs
    lrwxrwxrwx 1 root root  4 2009-11-01 18:53 /usr/bin/csc -> gmcs
    -rwxr-xr-x 1 root root 75 2009-09-23 23:04 /usr/bin/gmcs
    ben@ben-m4000t:~$ cat /usr/bin/gmcs
    #!/bin/sh
    exec /usr/bin/mono $mono_options /usr/lib/mono/2.0/gmcs.exe $@
    ben@ben-m4000t:~$ gmcs --version
    mono c# compiler version 2.4.2.3
    ben@ben-m4000t:~$ csc --version
    mono c# compiler version 2.4.2.3