我正在寻找一种方法来检测我的C#应用程序是否在Windows 10上运行.
我曾希望Environment.OSVersion会做的伎俩,但这似乎返回Version的6.3.9600.0在Windows 8.1和Windows 10.
如其他解决方案,这似乎并没有的Windows 8和Windows 10之间进行区分两种.
有什么建议?
为什么我需要这样做?
因为我使用WinForms WebBrowser控件来托管OAuth页面,该页面在旧的IE版本中崩溃并烧毁(我的应用程序连接到用户的Nest帐户 ......).
默认情况下,WebBrowser控件模拟IE7.使用注册表项,您可以告诉它模拟主机PC上安装的最新版本的IE.然而,该工作值高达8.1的Windows(和Windows 10的预发行版)无法在Windows 10的最终版本.
Dav*_*ams 36
回答
使用Environment.OSVersion并添加具有未supportedOS注释相关元素的应用程序清单文件.
例如,在<asmv1:assembly>下添加它
<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>
Run Code Online (Sandbox Code Playgroud)
原因
我不喜欢@Mitat Koyuncu的答案,因为它不必要地使用注册表,并且在评论中提到使用不可靠的字符串解析.
我也不喜欢@sstan的答案,因为它使用第三方代码,无论如何它都需要应用程序清单.
来自MSDN:
Windows 10:如果设置了lpVersionInfo参数以便指定Windows 8.1或Windows 10,即使当前操作系统版本为Windows 8.1或者Windows 10时,由没有Windows 8.1或Windows 10兼容性清单的应用程序调用VerifyVersionInfo也会返回false Windows 10.具体来说, VerifyVersionInfo具有以下行为:
•如果应用程序没有清单,则VerifyVersionInfo的行为就像操作系统版本是Windows 8(6.2)一样.
•如果应用程序的清单包含与Windows 8.1对应的GUID,则VerifyVersionInfo的行为就像操作系统版本是Windows 8.1(6.3)一样.
•如果应用程序的清单包含与Windows 10对应的GUID,则VerifyVersionInfo的行为就像操作系统版本是Windows 10(10.0)一样.
原因是因为Windows 10中不推荐使用VerifyVersionInfo.
我在Windows 10上测试过,Environment.OSVersion当app.Manifest包含上面的相关GUID时,确实可以正常工作.这很可能是因为他们没有从.Net Framework更改或弃用它.
Mit*_*ncu 28
如果你看一下注册表,你会发现环境名称:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName
Run Code Online (Sandbox Code Playgroud)
例如,我的产品名称是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");
}
Run Code Online (Sandbox Code Playgroud)
注意:添加using Microsoft.Win32;到您的使用中.
sst*_*tan 15
在引擎盖下,Environment.OSVersion使用GetVersionEx函数,该函数已被弃用.文档警告您观察到的行为:
未在Windows 8.1或Windows 10中显示的应用程序将返回Windows 8 OS版本值(6.2).
文档接着建议:
识别当前操作系统通常不是确定特定操作系统功能是否存在的最佳方法.这是因为操作系统可能在可再发行的DLL中添加了新功能.而不是使用GetVersionEx来确定操作系统平台或版本号,而是测试功能本身的存在.
如果上述建议不适合您的情况,并且您确实想要检查实际运行的操作系统版本,那么文档还提供了有关此内容的提示:
要将当前系统版本与所需版本进行比较,请使用VerifyVersionInfo函数,而不是使用GetVersionEx 自行执行比较.
以下文章使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
免责声明:我还没有Windows 10,所以我没有在Windows 10上测试过代码.
我建议使用注册表来查找所需的值.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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)