web-dev-qa-db-ja.com

アプリがWindows 10で実行されているかどうかを検出する方法

C#アプリがWindows 10で実行されているかどうかを検出する手段を探しています。

私はEnvironment.OSVersionがうまくいくことを望んでいましたが、これはWindows 8.1およびWindows 10で6.3.9600.0Versionを返すようです。

this などの他のソリューションも、Windows 8とWindows 10を区別しないようです。

助言がありますか?


なぜこれを行う必要があるのですか?

WinForms WebBrowserコントロールを使用して、OAuth古いページでクラッシュして焼き付いたページをIEバージョン(私のアプリは ユーザーのネストアカウント ...)。

既定では、WebBrowserコントロールはIE7をエミュレートします。レジストリキーを使用して、ホストPCにインストールされているIEの最新バージョンをエミュレートするように指示できます。ただし、 正常に動作した値 Windows 8.1まで(およびWindows 10のプレリリース)は、Windows 10の最終バージョンでは機能しません。

37
Richard Everett

レジストリを見ると、環境名が見つかります:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName

たとえば、私の製品名はWindows 10 Home

Registry

このコードを使用すると、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;あなたの用途に。

28
Mitat Koyuncu

回答

つかいます 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>

理由

@Mitat Koyuncuからの回答が気に入らないのは、レジストリが不必要に使用され、コメントで述べられているように、信頼できない文字列解析が使用されているためです。

また、サードパーティのコードを使用し、とにかくアプリケーションマニフェストが必要なため、@ sstanからの回答も好きではありません。

[〜#〜] msdn [〜#〜] から:

Windows 10:lpVersionInfoパラメーターが設定されている場合、Windows 8.1またはWindows 10の互換性マニフェストを持たないアプリケーションによって呼び出されると、VerifyVersionInfoはfalseを返します現在のオペレーティングシステムのバージョンがWindows 8.1またはWindows 10であっても、Windows 8.1または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)です。

その理由は、VerifyVersionInfoがWindows 10で非推奨になったためです。

私はWindows 10でテストしており、実際にEnvironment.OSVersionは、app.Manifestに上記の関連するGUID=が含まれている場合、期待どおりに動作します。これが、.Net Frameworkから変更または廃止されなかった理由です。

33
Dave Williams

内部では、 Environment.OSVersion は、廃止された GetVersionEx関数 を使用します。ドキュメンテーションは、観察した動作について警告します。

Windows 8.1またはWindows 10用に明示されていないアプリケーションは、Windows 8 OSバージョン値(6.2)を返します。

ドキュメントは推奨事項に進みます:

通常、現在のオペレーティングシステムを特定することは、特定のオペレーティングシステム機能が存在するかどうかを判断する最良の方法ではありません。これは、オペレーティングシステムの再配布可能なDLLに新しい機能が追加された可能性があるためです。 GetVersionExを使用してオペレーティングシステムプラットフォームまたはバージョン番号を決定するのではなく、機能自体の存在をテストします。

上記の推奨事項があなたのケースにふさわしくなく、実際に実行中のOSバージョンを確認したい場合は、ドキュメントでこれに関するヒントも提供されます。

現在のシステムバージョンを必要なバージョンと比較するには、GetVersionExを使用する代わりにVerifyVersionInfo関数を使用して、自分で比較を実行します。

次の記事では、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でコードをテストしていません。

15
sstan

レジストリを使用して、必要な値を見つけることをお勧めします。 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;
            }
        }
    }
}
7
Spiralis

バージョンヘルパー機能を使用できませんか? https://msdn.Microsoft.com/en-us/library/windows/desktop/dn424972(v = vs.85).aspx

IsWindows10OrGreater

現在のOSバージョンがWindows 10バージョンと一致するか、それより大きいかを示します。 Windows 10では、Windows 10を指定するGUIDを含む互換性セクションを含むマニフェストがアプリケーションに含まれていない限り、IsWindows10OrGreaterはfalseを返します。

gUIDを追加します: https://msdn.Microsoft.com/en-ca/library/windows/desktop/dn481241(v = vs.85).aspx

2
juFo

これを試してください:

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
}

以下を試しましたか? [Microsoft.VisulaBasic dllへの参照を追加する必要があります]

new Microsoft.VisualBasic.Devices.ComputerInfo().OSFullName

私のマシンではMicrosoft Windows 7 Ultimate

1
Rahul