在生产Windows Server上安装哪个.NET版本的简单方法是什么?

What's the foolproof way to tell which version(s) of .NET are installed on a production Windows Server?

这个问题与其说是与编程有关,不如说是与部署有关。

我发现自己经常和公司里的团队交谈,他们的工作是维护我们的生产Windows服务器并在上面部署我们的代码。出于法律和合规的原因,我对服务器没有直接的可视性或任何控制权,因此,我唯一能分辨在任何服务器上安装的.NET版本的方法是通过我向该组提供的指示。

到目前为止,我能想到的所有方法(检查与1.1或2.0匹配的管理工具,检查"添加/删除程序"列表中的条目,检查C:windowsmicrosoft.net下目录的存在性)都有缺陷(我见过至少一台计算机在admini下有2.0项,但没有2.0项)。strative tools——这个方法对3.0+没有任何影响,"添加/删除程序"列表可能与实际情况不同步,目录的存在并不一定意味着任何事情)。

考虑到我通常需要提前知道这些事情(发现"哎呀,这个没有你需要的所有版本和服务包"在短维护窗口下工作不太好),而且我必须"通过代理"进行检查,因为我不能直接进入服务器,什么是最简单的方法来判断哪些版本.NET的离子是否安装在生产Windows服务器上?最好使用一些固有的方法来实现这一点,使用框架安装的内容,因为它将更快,不需要加载某种实用程序,而且如果框架安装不正确,但仍有文件在适当位置(即,有一个目录,其中包含gacutil.exe,但该版本的fr),这种方法肯定会失败。Amework不是真正的"安装")。

编辑:如果没有一个很好的、简单的内在方法来实现这个内置在框架中,有人知道一个好的、轻量级的、不需要安装的程序可以发现这个问题吗?我可以想象有人可以很容易地写一封信,但如果已经有了,那就更好了。


您应该在要查找此信息的服务器上打开IE,然后转到以下站点:http://www.hanselman.com/smallestdotnet/

就这些。

该网站有一个脚本,可以查看浏览器的"useragent",并找出已安装(或未安装)的.NET框架的版本(如果有),然后自动显示该脚本(如果选择下载.NET框架,则计算总大小)。


您可以根据这个博客条目以编程方式检查注册表和其他一些东西。

要查看的注册表项是

1
2
3
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft
ET Framework Setup
DP\...]


从这里找到答案:

Check which .NET Framework version is installed

打开命令提示并复制粘贴以下命令行之一

1
dir %WINDIR%\Microsoft.Net\Framework\v*

1
dir %WINDIR%\Microsoft.Net\Framework\v* /O:-N /B


根据codetrawler的回答,解决方案是在资源管理器窗口中输入以下内容:

%systemroot%\Microsoft.NET\Framework

然后搜索:

Mscorlib.dll

…然后右键单击/转到每个结果的版本选项卡。


微软的方法是:

msdn:如何确定安装了哪些.NET框架版本(这将指导您访问以下注册表项:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft
ET Framework Setup
DP\...
)

如果你想要万无一失,那就另当别论了。我不会担心框架文件夹的xcopy。如果有人这样做,我会认为电脑坏了。

最简单的方法是编写一个小程序,使用每个版本的.NET和您关心的库,并运行它们。

对于不安装方法,PowerBasic是一个很好的工具。它创建小型的不需要运行时的exe。它可以自动执行上面的MS知识库文章中描述的检查。


网址:http://www.asoft.be/prod_netver.html

使用这个"好,轻,无需安装程序"


微软在知识库文章318785中给出了关于如何做到这一点的官方答案。


如果要检查的计算机安装了.NET SDK,则可以使用sdk命令提示符并运行程序CLRVer.exe


要获取已安装的dotnet版本,创建一个控制台应用程序。添加这个类运行那个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    public class GetDotNetVersion
    {
        public static void Get45PlusFromRegistry()
        {
            const string subkey = @"SOFTWARE\Microsoft
ET Framework Setup
DP\v4\Full";
            using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
            {
                if (ndpKey != null && ndpKey.GetValue("Release") != null)
                {
                    Console.WriteLine(".NET Framework Version:" + CheckFor45PlusVersion((int)ndpKey.GetValue("Release")));
                }
                else
                {
                    Console.WriteLine(".NET Framework Version 4.5 or later is not detected.");
                }
            }
        }

        // Checking the version using >= will enable forward compatibility.
        private static string CheckFor45PlusVersion(int releaseKey)
        {
            if (releaseKey >= 394802)
                return"4.6.2 or later";
            if (releaseKey >= 394254)
            {
                return"4.6.1";
            }
            if (releaseKey >= 393295)
            {
                return"4.6";
            }
            if ((releaseKey >= 379893))
            {
                return"4.5.2";
            }
            if ((releaseKey >= 378675))
            {
                return"4.5.1";
            }
            if ((releaseKey >= 378389))
            {
                return"4.5";
            }
            // This code should never execute. A non-null release key shoul
            // that 4.5 or later is installed.
            return"No 4.5 or later version detected";
        }
    }
    // Calling the GetDotNetVersion.Get45PlusFromRegistry method produces
    // output like the following:
    //       .NET Framework Version: 4.6.1
}


要确定服务器对.NET Framework 4.5和更高版本的支持(通过4.5.2测试):如果服务器上没有注册表访问权限,但对该服务器具有应用程序发布权限,请使用普通控制器创建MVC 5应用程序,如下所示:

4

然后在web.config中,在下面的部分中浏览所需的.NET框架版本,根据需要更改targetFramework值:

1
2
3
4
5
<system.web>
    <customErrors mode="Off"/>
    <compilation debug="true" targetFramework="4.5.2"/>
    <httpRuntime targetFramework="4.5.2"/>
</system.web>

将每个目标发布到服务器,然后浏览到/Default。如果您的服务器支持目标框架,那么简单的字符串将从普通控制器中显示。否则,您将收到如下错误:

Example of unsupported .NET 4.5.2 on server

因此,在本例中,我的目标服务器还不支持.NET Framework 4.5.2。


另外,请参见堆栈溢出问题如何检测安装了哪些.NET框架版本和服务包?其中还提到:

There is an official Microsoft answer to this question at the knowledge base article [How to determine which versions and service pack levels of the Microsoft .NET Framework are installed][2]

文章ID:318785-上次审阅时间:2008年11月7日-版本:20.1如何确定安装了.NET Framework的哪些版本以及是否应用了Service Pack。

不幸的是,它似乎不起作用,因为2.0目录中的mscorlib.dll版本有2.0版本,而3.0或3.5目录中没有mscorlib.dll版本,即使安装了3.5 sp1…为什么微软官方的回答会如此错误?


OneTouch部署将执行所有先决条件的检测和安装。最好是采用预先制定的解决方案,而不是自己动手。尝试自己滚动可能会导致问题,因为您输入的任何内容都可能随修补程序或服务包而改变。很可能微软对确定运行的版本有一些启发。


这里描述了检测.NET 3.0的官方方法

http://msdn.microsoft.com/en-us/library/aa480198.aspx

有缺陷,因为它要求调用者具有注册表访问权限。

msdn还提到了一种通过检查用户代理字符串来检测.NET 3.5的技术:

http://msdn.microsoft.com/en-us/library/bb909885.aspx

我认为微软应该做得比这更好。


这可能是一个很难找到版本的方法,但我总是觉得所有版本都安装到了:\WINDOWS\Microsoft.NET\Framework上。

这为文件夹提供了名称,如v2.0.50727,我认为这些名称提供了详细的版本信息。


奇怪的是,当1.1出现时,我写了一些代码来做这个(那是什么,七年前?)当2.0出来的时候稍微调整了一下。由于我们不再管理我们的服务器,我已经很多年没有看过它了。

这不是简单的,但我还是把它贴出来了,因为我觉得它很幽默;在.NET中更容易做,在PowerShell中更容易。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
bool GetFileVersion(LPCTSTR filename,WORD *majorPart,WORD *minorPart,WORD *buildPart,WORD *privatePart)
{
    DWORD dwHandle;
    DWORD dwLen = GetFileVersionInfoSize(filename,&dwHandle);
    if (dwLen) {
        LPBYTE lpData = new BYTE[dwLen];
        if (lpData) {
            if (GetFileVersionInfo(filename,0,dwLen,lpData)) {
                UINT uLen;  
                VS_FIXEDFILEINFO *lpBuffer;  
                VerQueryValue(lpData,_T("\"),(LPVOID*)&lpBuffer,&uLen);  
                *majorPart = HIWORD(lpBuffer->dwFileVersionMS);
                *minorPart = LOWORD(lpBuffer->dwFileVersionMS);
                *buildPart = HIWORD(lpBuffer->dwFileVersionLS);
                *privatePart = LOWORD(lpBuffer->dwFileVersionLS);
                delete[] lpData;
                return true;
            }
        }
    }
    return false;
}

int _tmain(int argc,_TCHAR* argv[])
{
    _TCHAR filename[MAX_PATH];
    _TCHAR frameworkroot[MAX_PATH];
    if (!GetEnvironmentVariable(_T("systemroot"),frameworkroot,MAX_PATH))
        return 1;
    _tcscat_s(frameworkroot,_T("\\Microsoft.NET\\Framework\\*"));
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind = FindFirstFile(frameworkroot,&FindFileData);
    if (hFind == INVALID_HANDLE_VALUE)
        return 2;
    do {
        if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
            _tcslen(FindFileData.cAlternateFileName) != 0) {
            _tcsncpy_s(filename,frameworkroot,_tcslen(frameworkroot)-1);
            filename[_tcslen(frameworkroot)] = 0;
            _tcscat_s(filename,FindFileData.cFileName);
            _tcscat_s(filename,_T("\\mscorlib.dll"));
            WORD majorPart,minorPart,buildPart,privatePart;
            if (GetFileVersion(filename,&majorPart,&minorPart,&buildPart,&privatePart )) {
                _tprintf(_T("%d.%d.%d.%d

"),majorPart,minorPart,buildPart,privatePart);
            }
        }
    } while (FindNextFile(hFind,&FindFileData) != 0);
    FindClose(hFind);
    return 0;
}

我觉得这个很有用。这是来源

enter image description here


如果要查找.NET 4.5之前的版本,请对控制台应用程序使用代码。这样地:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using System.Security.Permissions;
using Microsoft.Win32;

namespace findNetVersion
{
    class Program
    {
        static void Main(string[] args)
        {
            using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
                     RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft
ET Framework Setup
DP"))
            {
                foreach (string versionKeyName in ndpKey.GetSubKeyNames())
                {
                    if (versionKeyName.StartsWith("v"))
                    {

                        RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
                        string name = (string)versionKey.GetValue("Version","");
                        string sp = versionKey.GetValue("SP","").ToString();
                        string install = versionKey.GetValue("Install","").ToString();
                        if (install =="") //no install info, must be later version
                            Console.WriteLine(versionKeyName +" " + name);
                        else
                        {
                            if (sp !="" && install =="1")
                            {
                                Console.WriteLine(versionKeyName +" " + name +"  SP" + sp);
                            }
                        }
                        if (name !="")
                        {
                            continue;
                        }
                        foreach (string subKeyName in versionKey.GetSubKeyNames())
                        {
                            RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
                            name = (string)subKey.GetValue("Version","");
                            if (name !="")
                                sp = subKey.GetValue("SP","").ToString();
                                install = subKey.GetValue("Install","").ToString();
                            if (install =="") //no install info, ust be later
                                Console.WriteLine(versionKeyName +" " + name);
                            else
                            {
                                if (sp !="" && install =="1")
                                {
                                    Console.WriteLine(" " + subKeyName +" " + name +"  SP" + sp);
                                }
                                else if (install =="1")
                                {
                                    Console.WriteLine(" " + subKeyName +" " + name);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

否则,您可以通过如下查询找到.NET 4.5或更高版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static void Get45or451FromRegistry()
{
    using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
       RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft
ET Framework Setup
DP\v4\Full"))
    {
        int releaseKey = (int)ndpKey.GetValue("Release");
        {
            if (releaseKey == 378389)

                Console.WriteLine("The .NET Framework version 4.5 is installed");

            if (releaseKey == 378758)

                Console.WriteLine("The .NET Framework version 4.5.1  is installed");

        }
    }
}

然后,控制台结果将告诉您安装了哪些版本,哪些版本可用于部署。这段代码也很有用,因为您可以随时将它们作为保存的解决方案来检查它。


我进入Windows Update查看了更新历史记录,知道服务器补丁是最新的。我向下搜索.NET更新,它精确地显示了哪些版本有更新,这让我可以断定安装了哪些版本。


嗯,就像迪恩说的,你可以看看登记处,做他做的事。要检查他是否真的安装了clr.net框架,您应该在%SystemRoot%\System32目录中查找MSCorEE.dll文件。