[英]Getting Windows OS version programmatically
我正在尝试在我的 Windows 10 机器上使用 C# 获取 Windows 版本。
我总是得到这些值(使用 C#\\C++):
专业:6
未成年人:2
根据 MSDN ,这是 Windows 8 操作系统
C#代码:
var major = OperatingSystem.Version.Major
var minor = OperatingSystem.Version.Minor
C++代码
void print_os_info()
{
//http://stackoverflow.com/questions/1963992/check-windows-version
OSVERSIONINFOW info;
ZeroMemory(&info, sizeof(OSVERSIONINFOW));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
LPOSVERSIONINFOW lp_info = &info;
GetVersionEx(lp_info);
printf("Windows version: %u.%u\n", info.dwMajorVersion, info.dwMinorVersion);
}
Windows 10 假设与那些:
专业:10
次要:0*
构建者:10.0.10586.0 (th2_release.151029-1700)
我在这里缺少什么?
在我的场景中,我需要我的应用程序来捕获计算机信息以获取可能的错误报告和统计信息。
我没有找到必须令人满意地添加应用程序清单的解决方案。 不幸的是,我在谷歌搜索时发现的大多数建议都表明了这一点。
事实是,在使用清单时,必须手动向其中添加每个操作系统版本,以便该特定操作系统版本能够在运行时报告自身。
换句话说,这变成了一种竞争条件:我的应用程序的用户很可能正在使用我的应用程序的一个版本,该版本早于正在使用的操作系统。 当 Microsoft 推出新的操作系统版本时,我必须立即升级该应用程序。 我还必须强制用户在更新操作系统的同时升级应用程序。
换句话说,不太可行。
在浏览选项后,我发现了一些建议使用注册表查找的参考(与应用程序清单相比出奇地少)。
我只有WinMajorVersion
、 WinMinorVersion
和IsServer
属性的我的(砍掉的) ComputerInfo
类如下所示:
using Microsoft.Win32;
namespace Inspection
{
/// <summary>
/// Static class that adds convenient methods for getting information on the running computers basic hardware and os setup.
/// </summary>
public static class ComputerInfo
{
/// <summary>
/// Returns the Windows major version number for this computer.
/// </summary>
public static uint WinMajorVersion
{
get
{
dynamic major;
// The 'CurrentMajorVersionNumber' string value in the CurrentVersion key is new for Windows 10,
// and will most likely (hopefully) be there for some time before MS decides to change this - again...
if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", out major))
{
return (uint) major;
}
// When the 'CurrentMajorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion'
dynamic version;
if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version))
return 0;
var versionParts = ((string) version).Split('.');
if (versionParts.Length != 2) return 0;
uint majorAsUInt;
return uint.TryParse(versionParts[0], out majorAsUInt) ? majorAsUInt : 0;
}
}
/// <summary>
/// Returns the Windows minor version number for this computer.
/// </summary>
public static uint WinMinorVersion
{
get
{
dynamic minor;
// The 'CurrentMinorVersionNumber' string value in the CurrentVersion key is new for Windows 10,
// and will most likely (hopefully) be there for some time before MS decides to change this - again...
if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMinorVersionNumber",
out minor))
{
return (uint) minor;
}
// When the 'CurrentMinorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion'
dynamic version;
if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version))
return 0;
var versionParts = ((string) version).Split('.');
if (versionParts.Length != 2) return 0;
uint minorAsUInt;
return uint.TryParse(versionParts[1], out minorAsUInt) ? minorAsUInt : 0;
}
}
/// <summary>
/// Returns whether or not the current computer is a server or not.
/// </summary>
public static uint IsServer
{
get
{
dynamic installationType;
if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "InstallationType",
out installationType))
{
return (uint) (installationType.Equals("Client") ? 0 : 1);
}
return 0;
}
}
private static bool TryGetRegistryKey(string path, string key, out dynamic value)
{
value = null;
try
{
using(var rk = Registry.LocalMachine.OpenSubKey(path))
{
if (rk == null) return false;
value = rk.GetValue(key);
return value != null;
}
}
catch
{
return false;
}
}
}
}
Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentBuildNumber", string.Empty).ToString()
从 XP 到当前 10.16299 的所有操作系统的相同代码,在 Windows 8 中无法正常工作的情况下
OSVersion 属性报告 Windows 8 和 Windows 8.1 的相同版本号 (6.2.0.0) 以及 Windows 10 的相同主要和次要版本号。
https://msdn.microsoft.com/library/system.environment.osversion.aspx
由于接受的答案仅适用于 C#,这里是 C++ 的解决方案。
它使用 ntdll.dll 中的 RtlGetVersion 使用与 GetVersionEx 相同的结构(名称不同,但元素相同)并为您提供正确的版本。 由于此函数通常用于驱动程序开发,因此该函数是在 DDK 中声明的,而不是在 SDK 中声明的。 所以我使用了动态解决方案来调用函数。 请注意,ntdll.dll 在每次调用中都会被加载和释放。 因此,如果您更频繁地需要该功能,请保持库加载。
pOSversion 指向的结构必须像 GetVersionEx 一样初始化。
BOOL GetTrueWindowsVersion(OSVERSIONINFOEX* pOSversion)
{
// Function pointer to driver function
NTSTATUS (WINAPI *pRtlGetVersion)(
PRTL_OSVERSIONINFOW lpVersionInformation) = NULL;
// load the System-DLL
HINSTANCE hNTdllDll = LoadLibrary("ntdll.dll");
// successfully loaded?
if (hNTdllDll != NULL)
{
// get the function pointer to RtlGetVersion
pRtlGetVersion = (NTSTATUS (WINAPI *)(PRTL_OSVERSIONINFOW))
GetProcAddress (hNTdllDll, "RtlGetVersion");
// if successfull then read the function
if (pRtlGetVersion != NULL)
pRtlGetVersion((PRTL_OSVERSIONINFOW)pOSversion);
// free the library
FreeLibrary(hNTdllDll);
} // if (hNTdllDll != NULL)
// if function failed, use fallback to old version
if (pRtlGetVersion == NULL)
GetVersionEx((OSVERSIONINFO*)pOSversion);
// always true ...
return (TRUE);
} // GetTrueWindowsVersion
您可以在 C# 中以与 C++ 回答相同的方式执行此操作
[SecurityCritical]
[DllImport("ntdll.dll", SetLastError = true)]
internal static extern bool RtlGetVersion(ref OSVERSIONINFOEX versionInfo);
[StructLayout(LayoutKind.Sequential)]
internal struct OSVERSIONINFOEX
{
// The OSVersionInfoSize field must be set to Marshal.SizeOf(typeof(OSVERSIONINFOEX))
internal int OSVersionInfoSize;
internal int MajorVersion;
internal int MinorVersion;
internal int BuildNumber;
internal int PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
internal string CSDVersion;
internal ushort ServicePackMajor;
internal ushort ServicePackMinor;
internal short SuiteMask;
internal byte ProductType;
internal byte Reserved;
}
...
var osVersionInfo = new OSVERSIONINFOEX { OSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX)) };
if (!RtlGetVersion(ref osVersionInfo))
{
// TODO: Error handling, call GetVersionEx, etc.
}
您可以通过代码从注册表中读取并按照您的意图执行特定操作。
比如说:
注册表项位于 HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion,然后查找“ProductName”。
您可以通过在运行中提供 regedit.exe 来打开注册表信息 (Windows+r)
var reg =Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\WindowsNT\CurrentVersion");
string productName = (string)reg.GetValue("ProductName");
if (productName.StartsWith("Windows 10"))
{
}
else
{
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.