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框架版本(这将指导您访问以下注册表项:
ET Framework Setup
DP\...
如果你想要万无一失,那就另当别论了。我不会担心框架文件夹的xcopy。如果有人这样做,我会认为电脑坏了。
最简单的方法是编写一个小程序,使用每个版本的.NET和您关心的库,并运行它们。
对于不安装方法,PowerBasic是一个很好的工具。它创建小型的不需要运行时的exe。它可以自动执行上面的MS知识库文章中描述的检查。
网址:http://www.asoft.be/prod_netver.html
使用这个"好,轻,无需安装程序"
微软在知识库文章318785中给出了关于如何做到这一点的官方答案。
如果要检查的计算机安装了.NET SDK,则可以使用sdk命令提示符并运行程序
要获取已安装的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框架版本,根据需要更改
1 2 3 4 5 | <system.web> <customErrors mode="Off"/> <compilation debug="true" targetFramework="4.5.2"/> <httpRuntime targetFramework="4.5.2"/> </system.web> |
将每个目标发布到服务器,然后浏览到
因此,在本例中,我的目标服务器还不支持.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目录中的
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
我认为微软应该做得比这更好。
这可能是一个很难找到版本的方法,但我总是觉得所有版本都安装到了
这为文件夹提供了名称,如
奇怪的是,当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; } |
我觉得这个很有用。这是来源
如果要查找.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框架,您应该在