web-dev-qa-db-ja.com

プログラムでWindowsOSバージョンを取得する

Windows 10マシンでC#を使用してWindowsバージョンを取得しようとしています。

私は常にそれらの値を取得します(C#\ C++を使用):

メジャー:6

マイナー:2

これはWindows8 OSです MSDNによると

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 *

  • (実行中のプロセスからダンプファイルを取得すると、そのファイルのOSバージョンが10.0に設定されていることがわかります)

作成者:10.0.10586.0(th2_release.151029-1700)

ここで何が欠けていますか?

11
Pavel Durov

受け入れられた答えはC#のみであるため、ここにC++のソリューションがあります。

GetVersionExと同じ構造(名前は異なりますが要素は同じです)を使用するntdll.dllのRtlGetVersionを使用し、正しいバージョンを提供します。この関数は通常、ドライバー開発に使用されるため、関数はSDKではなくDDKで宣言されます。そこで、動的ソリューションを使用して関数を呼び出しました。 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
1
Peter Thaus

私のシナリオでは、考えられるバグレポートと統計のためにコンピューター情報をキャプチャするアプリケーションが必要でした。

アプリケーションマニフェストを十分に追加する必要があるソリューションは見つかりませんでした。これをグーグルで検索しているときに見つけた提案のほとんど残念ながら、それだけを提案しました。

マニフェストを使用する場合、特定のOSバージョンが実行時にそれ自体をレポートできるようにするには、各OSバージョンを手動で追加する必要があります。

言い換えると、これは競合状態になります。私のアプリのユーザーは、以前のOSのバージョンを使用している可能性があります。使用する。新しいOSバージョンがMicrosoftによってリリースされたとき、私はアプリをアップグレードする必要がありますすぐに。また、OSの更新と同時にユーザーにアプリのアップグレードを強制する必要があります。

言い換えれば、あまり実行可能ではありません。

オプションを参照した後、代わりにレジストリルックアップの使用を提案するいくつかの参照(アプリマニフェストと比較して驚くほど少ない)を見つけました。

ComputerInfoWinMajorVersion、およびWinMinorVersionプロパティのみを持つ私の(切り詰められた)IsServerクラスは次のようになります。

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;
            }
        }
    }
}
14
Spiralis

アプリケーションにapp.manifestを追加する必要があります。

enter image description here

enter image description here

次に、次の行のコメントを解除します。

<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
5
Nasreddine
Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentBuildNumber", string.Empty).ToString()

XPから現在の10.16299までのすべてのOSで同じコード、シナリオはWindows8から正しく機能しない

OSVersionプロパティは、Windows8とWindows8.1の両方で同じバージョン番号(6.2.0.0)を報告し、Windows10では同じメジャーバージョン番号とマイナーバージョン番号を報告します。

https://msdn.Microsoft.com/library/system.environment.osversion.aspx

3
michael

あなたは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.
}
1
Richard - MSFT

Regsirtyからコードを読み取って、意図したとおりに特定のアクションを実行できます。

例を言う:

ここで見つけることができるレジストリキー:

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
        {
        }
1
Praveen M