如何检测我的应用是否在 Windows 10 上 运行
How can I detect if my app is running on Windows 10
我正在寻找一种方法来检测我的 C# 应用程序是否在 Windows 10 上 运行。
我曾希望 Environment.OSVersion
能解决问题,但这似乎 return 6.3.9600.0
的 Version
在 Windows 8.1 和 Windows10.
其他解决方案,例如this似乎也无法区分Windows 8和Windows 10。
有什么建议吗?
为什么我需要这样做?
因为我使用 WinForms WebBrowser 控件来托管 OAuth 页面,该页面在旧版 IE 中崩溃和烧毁(我的应用程序连接到 user's Nest account...)。
默认情况下,WebBrowser 控件模拟 IE7。使用注册表项,您可以告诉它模拟安装在主机 PC 上的最新版本的 IE。但是,value that worked 到 Windows 8.1(以及 Windows 10 的预发布版本)在 Windows 10 的最终版本中不起作用。
你在下面尝试过吗? [您需要添加对 Microsoft.VisulaBasic
dll 的引用]
new Microsoft.VisualBasic.Devices.ComputerInfo().OSFullName
在我的机器上,Microsoft Windows 7 Ultimate
如果您查看注册表,您会发现环境名称:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName
例如我的产品名称是Windows 10 Home
:
使用此代码,如果 Windows 10:
static bool IsWindows10()
{
var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
string productName = (string)reg.GetValue("ProductName");
return productName.StartsWith("Windows 10");
}
注意:将 using Microsoft.Win32;
添加到您的使用中。
在引擎盖下,Environment.OSVersion uses the GetVersionEx function,已被弃用。文档警告您观察到的行为:
Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2).
文档继续推荐:
Identifying the current operating system is usually not the best way to determine whether a particular operating system feature is present. This is because the operating system may have had new features added in a redistributable DLL. Rather than using GetVersionEx to determine the operating system platform or version number, test for the presence of the feature itself.
如果上述建议不适合您的情况,并且您确实想检查实际的 运行 OS 版本,那么文档也提供了有关此的提示:
To compare the current system version to a required version, use the VerifyVersionInfo function instead of using GetVersionEx to perform the comparison yourself.
以下文章发布了使用 VerifyVersionInfo 函数的有效解决方案:Version Helper API for .NET.
完全感谢那篇文章的作者,以下代码片段应该提供您正在寻找的行为:
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(IsWindowsVersionOrGreater(6, 3, 0)); // Plug in appropriate values.
}
[StructLayout(LayoutKind.Sequential)]
struct OsVersionInfoEx
{
public uint OSVersionInfoSize;
public uint MajorVersion;
public uint MinorVersion;
public uint BuildNumber;
public uint PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string CSDVersion;
public ushort ServicePackMajor;
public ushort ServicePackMinor;
public ushort SuiteMask;
public byte ProductType;
public byte Reserved;
}
[DllImport("kernel32.dll")]
static extern ulong VerSetConditionMask(ulong dwlConditionMask,
uint dwTypeBitMask, byte dwConditionMask);
[DllImport("kernel32.dll")]
static extern bool VerifyVersionInfo(
[In] ref OsVersionInfoEx lpVersionInfo,
uint dwTypeMask, ulong dwlConditionMask);
static bool IsWindowsVersionOrGreater(
uint majorVersion, uint minorVersion, ushort servicePackMajor)
{
OsVersionInfoEx osvi = new OsVersionInfoEx();
osvi.OSVersionInfoSize = (uint)Marshal.SizeOf(osvi);
osvi.MajorVersion = majorVersion;
osvi.MinorVersion = minorVersion;
osvi.ServicePackMajor = servicePackMajor;
// These constants initialized with corresponding definitions in
// winnt.h (part of Windows SDK)
const uint VER_MINORVERSION = 0x0000001;
const uint VER_MAJORVERSION = 0x0000002;
const uint VER_SERVICEPACKMAJOR = 0x0000020;
const byte VER_GREATER_EQUAL = 3;
ulong versionOrGreaterMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
uint versionOrGreaterTypeMask = VER_MAJORVERSION |
VER_MINORVERSION | VER_SERVICEPACKMAJOR;
return VerifyVersionInfo(ref osvi, versionOrGreaterTypeMask,
versionOrGreaterMask);
}
}
免责声明:我还没有 Windows 10,所以我还没有在 Windows 10 上测试代码。
回答
使用 Environment.OSVersion
并添加相关 supportedOS
元素未注释的应用程序清单文件。
例如在
下添加
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
原因
我不喜欢@Mitat Koyuncu 的回答,因为它不必要地使用了注册表,并且如评论中所述使用了不可靠的字符串解析。
我也不喜欢@sstan 的回答,因为它使用第三方代码并且无论如何都需要应用程序清单。
来自MSDN:
Windows 10: VerifyVersionInfo returns false when called by
applications that do not have a compatibility manifest for Windows 8.1
or Windows 10 if the lpVersionInfo parameter is set so that it
specifies Windows 8.1 or Windows 10, even when the current operating
system version is Windows 8.1 or Windows 10. Specifically,
VerifyVersionInfo has the following behavior:
• If the application has no manifest, VerifyVersionInfo behaves as if the operation system version is Windows 8 (6.2).
• If the application has a manifest that contains the GUID that corresponds to Windows 8.1, VerifyVersionInfo behaves as if the operation system version is Windows 8.1 (6.3).
• If the application has a manifest that contains the GUID that corresponds
to Windows 10, VerifyVersionInfo behaves as if the operation system
version is Windows 10 (10.0).
原因是因为 VerifyVersionInfo 在 Windows 10.
中被弃用了
我已经在 Windows 10 上进行了测试,当 app.Manifest 包含上述相关的 GUID 时,Environment.OSVersion
确实可以正常工作。这很可能就是他们没有更改或弃用 .Net Framework 的原因。
我建议使用注册表来查找您想要的值。 Microsoft 已更改 Windows 10 在注册表中列出的方式,因此代码需要适应该方式。
这是我使用的代码,它也正确识别了 Windows 10:
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
{
var rk = Registry.LocalMachine.OpenSubKey(path);
if (rk == null) return false;
value = rk.GetValue(key);
return value != null;
}
catch
{
return false;
}
}
}
}
您不能使用版本助手功能吗?
https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972(v=vs.85).aspx
IsWindows10OrGreater
Indicates if the current OS version matches, or is greater than, the
Windows 10 version. For Windows 10, IsWindows10OrGreater returns false
unless the application contains a manifest that includes a
compatibility section that contains the GUID that designates Windows
10.
并添加 GUID:
https://msdn.microsoft.com/en-ca/library/windows/desktop/dn481241(v=vs.85).aspx
试试这个:
string subKey = @"SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion";
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine;
Microsoft.Win32.RegistryKey skey = key.OpenSubKey(subKey);
string name = skey.GetValue("ProductName").ToString();
然后你可以只使用一个 if 子句:
if(name.Contains("Windows 10"))
{
//... procedures
}
else
{
//... procedures
}
我正在寻找一种方法来检测我的 C# 应用程序是否在 Windows 10 上 运行。
我曾希望 Environment.OSVersion
能解决问题,但这似乎 return 6.3.9600.0
的 Version
在 Windows 8.1 和 Windows10.
其他解决方案,例如this似乎也无法区分Windows 8和Windows 10。
有什么建议吗?
为什么我需要这样做?
因为我使用 WinForms WebBrowser 控件来托管 OAuth 页面,该页面在旧版 IE 中崩溃和烧毁(我的应用程序连接到 user's Nest account...)。
默认情况下,WebBrowser 控件模拟 IE7。使用注册表项,您可以告诉它模拟安装在主机 PC 上的最新版本的 IE。但是,value that worked 到 Windows 8.1(以及 Windows 10 的预发布版本)在 Windows 10 的最终版本中不起作用。
你在下面尝试过吗? [您需要添加对 Microsoft.VisulaBasic
dll 的引用]
new Microsoft.VisualBasic.Devices.ComputerInfo().OSFullName
在我的机器上,Microsoft Windows 7 Ultimate
如果您查看注册表,您会发现环境名称:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName
例如我的产品名称是Windows 10 Home
:
使用此代码,如果 Windows 10:
static bool IsWindows10()
{
var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
string productName = (string)reg.GetValue("ProductName");
return productName.StartsWith("Windows 10");
}
注意:将 using Microsoft.Win32;
添加到您的使用中。
在引擎盖下,Environment.OSVersion uses the GetVersionEx function,已被弃用。文档警告您观察到的行为:
Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2).
文档继续推荐:
Identifying the current operating system is usually not the best way to determine whether a particular operating system feature is present. This is because the operating system may have had new features added in a redistributable DLL. Rather than using GetVersionEx to determine the operating system platform or version number, test for the presence of the feature itself.
如果上述建议不适合您的情况,并且您确实想检查实际的 运行 OS 版本,那么文档也提供了有关此的提示:
To compare the current system version to a required version, use the VerifyVersionInfo function instead of using GetVersionEx to perform the comparison yourself.
以下文章发布了使用 VerifyVersionInfo 函数的有效解决方案:Version Helper API for .NET.
完全感谢那篇文章的作者,以下代码片段应该提供您正在寻找的行为:
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(IsWindowsVersionOrGreater(6, 3, 0)); // Plug in appropriate values.
}
[StructLayout(LayoutKind.Sequential)]
struct OsVersionInfoEx
{
public uint OSVersionInfoSize;
public uint MajorVersion;
public uint MinorVersion;
public uint BuildNumber;
public uint PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string CSDVersion;
public ushort ServicePackMajor;
public ushort ServicePackMinor;
public ushort SuiteMask;
public byte ProductType;
public byte Reserved;
}
[DllImport("kernel32.dll")]
static extern ulong VerSetConditionMask(ulong dwlConditionMask,
uint dwTypeBitMask, byte dwConditionMask);
[DllImport("kernel32.dll")]
static extern bool VerifyVersionInfo(
[In] ref OsVersionInfoEx lpVersionInfo,
uint dwTypeMask, ulong dwlConditionMask);
static bool IsWindowsVersionOrGreater(
uint majorVersion, uint minorVersion, ushort servicePackMajor)
{
OsVersionInfoEx osvi = new OsVersionInfoEx();
osvi.OSVersionInfoSize = (uint)Marshal.SizeOf(osvi);
osvi.MajorVersion = majorVersion;
osvi.MinorVersion = minorVersion;
osvi.ServicePackMajor = servicePackMajor;
// These constants initialized with corresponding definitions in
// winnt.h (part of Windows SDK)
const uint VER_MINORVERSION = 0x0000001;
const uint VER_MAJORVERSION = 0x0000002;
const uint VER_SERVICEPACKMAJOR = 0x0000020;
const byte VER_GREATER_EQUAL = 3;
ulong versionOrGreaterMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
uint versionOrGreaterTypeMask = VER_MAJORVERSION |
VER_MINORVERSION | VER_SERVICEPACKMAJOR;
return VerifyVersionInfo(ref osvi, versionOrGreaterTypeMask,
versionOrGreaterMask);
}
}
免责声明:我还没有 Windows 10,所以我还没有在 Windows 10 上测试代码。
回答
使用 Environment.OSVersion
并添加相关 supportedOS
元素未注释的应用程序清单文件。
例如在
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
原因
我不喜欢@Mitat Koyuncu 的回答,因为它不必要地使用了注册表,并且如评论中所述使用了不可靠的字符串解析。
我也不喜欢@sstan 的回答,因为它使用第三方代码并且无论如何都需要应用程序清单。
来自MSDN:
Windows 10: VerifyVersionInfo returns false when called by applications that do not have a compatibility manifest for Windows 8.1 or Windows 10 if the lpVersionInfo parameter is set so that it specifies Windows 8.1 or Windows 10, even when the current operating system version is Windows 8.1 or Windows 10. Specifically, VerifyVersionInfo has the following behavior:
• If the application has no manifest, VerifyVersionInfo behaves as if the operation system version is Windows 8 (6.2).
• If the application has a manifest that contains the GUID that corresponds to Windows 8.1, VerifyVersionInfo behaves as if the operation system version is Windows 8.1 (6.3).
• If the application has a manifest that contains the GUID that corresponds to Windows 10, VerifyVersionInfo behaves as if the operation system version is Windows 10 (10.0).
原因是因为 VerifyVersionInfo 在 Windows 10.
中被弃用了我已经在 Windows 10 上进行了测试,当 app.Manifest 包含上述相关的 GUID 时,Environment.OSVersion
确实可以正常工作。这很可能就是他们没有更改或弃用 .Net Framework 的原因。
我建议使用注册表来查找您想要的值。 Microsoft 已更改 Windows 10 在注册表中列出的方式,因此代码需要适应该方式。
这是我使用的代码,它也正确识别了 Windows 10:
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
{
var rk = Registry.LocalMachine.OpenSubKey(path);
if (rk == null) return false;
value = rk.GetValue(key);
return value != null;
}
catch
{
return false;
}
}
}
}
您不能使用版本助手功能吗? https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972(v=vs.85).aspx
IsWindows10OrGreater
Indicates if the current OS version matches, or is greater than, the Windows 10 version. For Windows 10, IsWindows10OrGreater returns false unless the application contains a manifest that includes a compatibility section that contains the GUID that designates Windows 10.
并添加 GUID: https://msdn.microsoft.com/en-ca/library/windows/desktop/dn481241(v=vs.85).aspx
试试这个:
string subKey = @"SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion";
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine;
Microsoft.Win32.RegistryKey skey = key.OpenSubKey(subKey);
string name = skey.GetValue("ProductName").ToString();
然后你可以只使用一个 if 子句:
if(name.Contains("Windows 10"))
{
//... procedures
}
else
{
//... procedures
}