简体   繁体   English

如何检测正在运行的 Windows 版本?

[英]How can I detect which version of Windows is running?

I have an application which runs as a Word add-in.我有一个作为 Word 插件运行的应用程序。 (VSTO). (VSTO)。

It runs on many PCs all over the world.它在世界各地的许多 PC 上运行。 In certain cases I need to trouble shoot problems (obviously remotely) and have a reporting mechanism which tells me which Windows OS is running - I use Environment.OSVersion in .NET.在某些情况下,我需要解决问题(显然是远程)并有一个报告机制来告诉我正在运行哪个 Windows 操作系统 - 我在 .NET 中使用Environment.OSVersion At least it did until Windows 10.至少在 Windows 10 之前是这样。

There is an article on MSDN ( Targeting your application for Windows ) about creating an application manifest which will enable the correct version to be returned.在 MSDN( 针对 Windows的应用程序)上有一篇关于创建应用程序清单的文章,该清单将允许返回正确的版本。

But my application is a DLL, not an EXE and so won't really accommodate the XML code referred to in that article.但是我的应用程序是一个 DLL,而不是一个 EXE,因此不会真正容纳该文章中提到的 XML 代码。

Is there no way to just ask Windows, "What version are you? Really, I won't cry if you admit to the real version".有没有办法只问Windows,“你是什么版本?真的,你承认真实版本我不会哭”。

Or an entry in the registry or something?或注册表中的条目或其他内容?

If WMI is not an option for you, You could use the SDK counterparts of the GetVersionEx functions, RtlGetVersion .如果 WMI 不适合您,您可以使用GetVersionEx函数RtlGetVersion的 SDK 对应 They don't lie.他们不说谎。

If you use .NET 5.0 or Core, Environment.OSVersion reports the actual version of Windows.如果您使用 .NET 5.0 或 Core,Environment.OSVersion 会报告 Windows 的实际版本。

I posted more detail about this as addition to the answers on this other thread: https://stackoverflow.com/a/64804643/2240196我发布了关于此的更多详细信息,作为对另一个线程的答案的补充: https : //stackoverflow.com/a/64804643/2240196

EDIT: Added example code as requested.编辑:根据要求添加了示例代码。 (You probably don't need all of it) (你可能不需要全部)

using System;
using System.Runtime.InteropServices;

namespace VersionHelper
{
    public static class VersionHelper
    {
        // The C(++) macro VER_SET_CONDITION mentioned in the documentation for RtlVerifyVersionInfo seems to be equivalent to the VerSetConditionMask function in kernel32.dll

        // https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-versetconditionmask
        [DllImport("kernel32.dll")]
        private static extern ulong VerSetConditionMask(ulong dwlConditionMask, uint dwTypeBitMask, byte dwConditionMask);

        // https://docs.microsoft.com/en-us/windows/win32/devnotes/rtlgetversion
        [DllImport("ntdll.dll")]
        private static extern int RtlGetVersion(ref OSVERSIONINFOW lpVersionInformation);

        [DllImport("ntdll.dll")]
        private static extern int RtlGetVersion(ref OSVERSIONINFOEXW lpVersionInformation);

        // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlverifyversioninfo
        [DllImport("ntdll.dll")]
        private static extern bool RtlVerifyVersionInfo([In] ref OSVERSIONINFOEXW lpVersionInformation, uint dwTypeMask, ulong dwlConditionMask);

        // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexw
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        private struct OSVERSIONINFOEXW
        {
            internal uint dwOSVersionInfoSize;
            internal uint dwMajorVersion;
            internal uint dwMinorVersion;
            internal uint dwBuildNumber;
            internal uint dwPlatformId;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            internal string szCSDVersion;
            internal ushort wServicePackMajor;
            internal ushort wServicePackMinor;
            internal ushort wSuiteMask;
            internal byte wProductType;
            internal byte wReserved;
        }
        
        // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfow
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        private struct OSVERSIONINFOW
        {
            internal uint dwOSVersionInfoSize;
            internal uint dwMajorVersion;
            internal uint dwMinorVersion;
            internal uint dwBuildNumber;
            internal uint dwPlatformId;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            internal string szCSDVersion;
        }

        /*
         * RTL_OSVERSIONINFOEX(A/W) and OSVERSIONINFOEX(A/W) are aliases for the same structures
         * RTL_OSVERSIONINFO(A/W) and OSVERSIONINFO(A/W) are aliases for the same structures
         * */

        // These constants initialized with corresponding definitions in
        // winnt.h (part of Windows SDK)
        // https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-ver_set_condition
        private const byte VER_EQUAL = 1;
        private const byte VER_GREATER = 2;
        private const byte VER_GREATER_EQUAL = 3;
        private const byte VER_LESS = 4;
        private const byte VER_LESS_EQUAL = 5;
        private const byte VER_AND = 6;
        private const byte VER_OR = 7;

        private const byte VER_CONDITION_MASK = 7;
        private const byte VER_NUM_BITS_PER_CONDITION_MASK = 3;

        private const uint STATUS_SUCCESS = 0x00000000;

        //
        // RtlVerifyVersionInfo() type mask bits
        //
        private const uint VER_MINORVERSION = 0x0000001;
        private const uint VER_MAJORVERSION = 0x0000002;
        private const uint VER_BUILDNUMBER = 0x0000004;
        private const uint VER_PLATFORMID = 0x0000008;
        private const uint VER_SERVICEPACKMINOR = 0x0000010;
        private const uint VER_SERVICEPACKMAJOR = 0x0000020;
        private const uint VER_SUITENAME = 0x0000040;
        private const uint VER_PRODUCT_TYPE = 0x0000080;

        // wProductType    
        // Any additional information about the system.This member can be one of the following values.
        private const byte VER_NT_DOMAIN_CONTROLLER = 0x0000002;
        private const byte VER_NT_SERVER = 0x0000003;
        private const byte VER_NT_WORKSTATION = 0x0000001;


        // You can customize this to check for the condition(s) you need using any field from the OSVERSIONINFOW struct with the corresponding VER_ and VER_<operator> constants
        public static bool IsWindowsVersionOrGreater(uint majorVersion, uint minorVersion, ushort servicePackMajor = 0, uint buildNumber = 0)
        {
            var osVerInfo = new OSVERSIONINFOEXW
            {
                dwOSVersionInfoSize = (uint) Marshal.SizeOf(typeof(OSVERSIONINFOEXW)),
                dwMajorVersion = majorVersion,
                dwMinorVersion = minorVersion,
                wServicePackMajor = servicePackMajor,
                dwBuildNumber = buildNumber
            };
            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;
            if (buildNumber > 0)
            {
                versionOrGreaterMask = VerSetConditionMask(versionOrGreaterMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
                versionOrGreaterTypeMask |= VER_BUILDNUMBER;
            }
            return RtlVerifyVersionInfo(ref osVerInfo, versionOrGreaterTypeMask, versionOrGreaterMask);
        }

        public static bool IsWindowsServer()
        {
            var osVerInfo = new OSVERSIONINFOEXW
            {
                dwOSVersionInfoSize = (uint) Marshal.SizeOf(typeof(OSVERSIONINFOEXW)),
                wProductType = VER_NT_WORKSTATION
            };
            ulong dwlConditionMask = VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL);
            return !RtlVerifyVersionInfo(ref osVerInfo, VER_PRODUCT_TYPE, dwlConditionMask);
        }
        
        public static int GetWindowsBuildNumber()
        {
            var osVerInfo = new OSVERSIONINFOW
            {
                dwOSVersionInfoSize = (uint) Marshal.SizeOf(typeof(OSVERSIONINFOW))
            };
            if (STATUS_SUCCESS == RtlGetVersion(ref osVerInfo)) // documented to always return STATUS_SUCCESS
                return (int)osVerInfo.dwBuildNumber;
            throw new Win32Exception("Failed to determine Windows build number.");
        }

        // Other functions replicating SDK Version Helper functions
        // https://docs.microsoft.com/en-us/windows/win32/sysinfo/version-helper-apis

        //
        // _WIN32_WINNT version constants
        //
        const ushort _WIN32_WINNT_NT4 = 0x0400;
        const ushort _WIN32_WINNT_WIN2K = 0x0500;
        const ushort _WIN32_WINNT_WINXP = 0x0501;
        const ushort _WIN32_WINNT_WS03 = 0x0502;
        const ushort _WIN32_WINNT_WIN6 = 0x0600;
        const ushort _WIN32_WINNT_VISTA = 0x0600;
        const ushort _WIN32_WINNT_WS08 = 0x0600;
        const ushort _WIN32_WINNT_LONGHORN = 0x0600;
        const ushort _WIN32_WINNT_WIN7 = 0x0601;
        const ushort _WIN32_WINNT_WIN8 = 0x0602;
        const ushort _WIN32_WINNT_WINBLUE = 0x0603;
        const ushort _WIN32_WINNT_WINTHRESHOLD = 0x0A00; 
        const ushort _WIN32_WINNT_WIN10 = 0x0A00;

        const bool FALSE = false;

        static byte LOBYTE(ushort w)
        {
            return ((byte)(w & 0xff));
        }

        static byte HIBYTE(ushort w)
        {
            return ((byte)(w >> 8 & 0xff));
        }

        public static bool
        IsWindowsXPSP1OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
        }

        public static bool
        IsWindowsXPSP2OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
        }

        public static bool
        IsWindowsXPSP3OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
        }

        public static bool
        IsWindowsVistaOrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
        }

        public static bool
        IsWindowsVistaSP1OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
        }

        public static bool
        IsWindowsVistaSP2OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
        }

        public static bool
        IsWindows7OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
        }

        public static bool
        IsWindows7SP1OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
        }

        public static bool
        IsWindows8OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
        }

        public static bool
        IsWindows8Point1OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
        }

        public static bool
        IsWindows10OrGreater()
        {
            return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0);
        }
    }
}
private String GetOSVersion()
{
    var wmiEnum = new ManagementObjectSearcher("root\\CIMV2", "SELECT Version FROM  Win32_OperatingSystem").Get().GetEnumerator();
    wmiEnum.MoveNext();
    return wmiEnum.Current.Properties["Version"].Value as String;
}

Returns 6.1.7601 on my W7 system and 10.0.14393 on my Server 2016 system.在我的 W7 系统上返回 6.1.7601,在我的 Server 2016 系统上返回 10.0.14393。

No need to add a target manifest.无需添加目标清单。

WMI is the best way to do this kind of stuff You can use this to retrieve OS informations : WMI 是执行此类操作的最佳方法您可以使用它来检索操作系统信息:

ManagementObjectSearcher objMOS = 
       new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM  Win32_OperatingSystem");

OS.Name = ((string)objMOS["Caption"]).Trim();
OS.Version = (string)objMOS["Version"];
OS.MaxProcessCount = (uint)objMOS["MaxNumberOfProcesses"];
OS.MaxProcessRAM = (ulong)objMOS["MaxProcessMemorySize"];
OS.Architecture = (string)objMOS["OSArchitecture"];
OS.SerialNumber = (string)objMOS["SerialNumber"];
OS.Build = ((string)objMOS["BuildNumber"]).ToUint();

This can fetch the OS details for you.这可以为您获取操作系统详细信息。

You can try GetVersionEx Win32 API.您可以尝试GetVersionEx Win32 API。

https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx

Note that Windows 10 in fact is version 6.4.请注意,Windows 10 实际上是 6.4 版。 Ver 6.0 is Vista, 6.1 - 7, 6.2 - 8. 6.0 版是 Vista、6.1 - 7、6.2 - 8。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何检测我的应用程序是否在Windows 10上运行 - How can I detect if my app is running on Windows 10 如何检测哪个Windows帐户正在运行.net应用程序? - How to detect which Windows account is running a .net application? 如何检测用于解决“,”或“。”的Windows版本。 字符串转换为双数时出现问题? - How can I detect the Windows version for solving ',' or '.' problems when converting string to double? 如何检测应用程序在哪个 .NET 版本上运行? - How do I detect what .NET version the application is running on? 如何判断我正在运行哪个WCF版本? - How do I tell which WCF version I am running? 如何检测我们是否在.NET中的Windows 10的ARM64版本下运行? - How to detect we're running under the ARM64 version of Windows 10 in .NET? 如何检测连接到运行Windows 10 IoT核心版的Raspberry Pi的USB上的文件? (C#UWP) - How can I detect a file on a USB connected to a Raspberry Pi running Windows 10 IoT Core? (C# UWP) 如何确定Windows是哪个版本? - How to determine which version of Windows? 如何检测正在运行的ASP.NET版本 - How to detect running ASP.NET version 如何在 macOS 上使用 windows 表单应用程序在这种情况下我可以使用哪个版本的 vs 代码? - How can I use the windows form application on macOS which version o f vs code could i use in this situation?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM