Windows8.1のバージョン番号(2)

バージョンチェックが必要なのは多くは古いアプリで「未知のOSで動かすと何が起こるかわからないから起動時にバージョンチェックをしている」というパターンがほとんどだと思うので、一部とはいえプロセスの挙動が変わるCompatibility Manifestの導入には慎重にならざるをえないと思います。
かつ、Microsoftが用意しているもう一つの対応が

  • API "VersionHelpers"を使用する

というものですが、これはVisual Studio 2013かWindows 8.1 SDKが無いと使えないものなので、ますます古いアプリへの適応は悩ましいところです。
一応、Operating system version changes in Windows 8.1 - Operating system versioningには

Note that the Versionhelpers header file API is available in Visual Studio 2013 and the Windows 8.1 SDK. However, you can use the header information from the SDK’s VersionHelpers.h file in previous versions of Visual Studio.

とは書かれてますが、それって自分でバックポートしろと言ってるのに等しいので。
(さらに"IsWindows8_1OrGreater"は"IsWindows8Point1OrGreater"の間違いだし…)

これらの新APIの実体は従来からあるVerifyVersionInfo Win32APIのラッパーなので、そうであれば自分で作ってしまったほうが早いです。
具体的には

で紹介されている判定コードがそれですがVB.NET用なので、C#に書き直したものを以下に書いておきます。

判定失敗と旧バージョンだった場合を厳密に区別するか否かでRunningOnWinBlue()を2つ作成していますが、通常は引数無しのほうで問題ないでしょう。

using System;
using System.Runtime.InteropServices;

namespace Utility
{
    static class OSversion
    {
        public static bool RunningOnWinBlue()
        {
            // "Ver6.3"を設定
            OSVERSIONINFOEX osvi = new OSVERSIONINFOEX();
            osvi.dwOSVersionInfoSize = Marshal.SizeOf(osvi);
            osvi.dwMajorVersion = 6;
            osvi.dwMinorVersion = 3;

            // ConditionMaskの設定(指定バージョン以上か)
            ulong cmp = 0;
            cmp = VerSetConditionMask(cmp, (uint)typeMask.VER_MAJORVERSION, (byte)conditionMask.VER_GREATER_EQUAL);
            cmp = VerSetConditionMask(cmp, (uint)typeMask.VER_MINORVERSION, (byte)conditionMask.VER_GREATER_EQUAL);
 
            // バージョン判定
            bool result = VerifyVersionInfo(
                ref osvi, (uint)(typeMask.VER_MAJORVERSION | typeMask.VER_MINORVERSION), cmp);

            return result;
        }
        
        public static int RunningOnWinBlue(int dummy)
        {
            bool result = RunningOnWinBlue();
            if (result) {
                // Windows8.1以上
                return 1;
            }

            int errno = Marshal.GetLastWin32Error();
            if (errno == ERROR_OLD_WIN_VERSION)
            {
                // Windows8.1より古い
                return 0;
            }
            // 判定失敗
            return -1;
        }

        #region VerifyVersionInfoのための定義
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct OSVERSIONINFOEX
        {
            public int dwOSVersionInfoSize;
            public int dwMajorVersion;
            public int dwMinorVersion;
            public int dwBuildNumber;
            public int dwPlatformId;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string szCSDVersion;
            public UInt16 wServicePackMajor;
            public UInt16 wServicePackMinor;
            public UInt16 wSuiteMask;
            public byte wProductType;
            public byte wReserved;
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool VerifyVersionInfo([In] ref OSVERSIONINFOEX lpVersionInfo,
           uint dwTypeMask, ulong dwlConditionMask);

        [DllImport("kernel32.dll")]
        static extern ulong VerSetConditionMask(ulong dwlConditionMask,
           uint dwTypeBitMask, byte dwConditionMask);

        public enum typeMask : uint {
            VER_MINORVERSION  = 0x1,
            VER_MAJORVERSION = 0x2,
            VER_BUILDNUMBER = 0x4,
            VER_PLATFORMID = 0x8,
            VER_SERVICEPACKMINOR = 0x10,
            VER_SERVICEPACKMAJOR = 0x20,
            VER_SUITENAME = 0x40,
            VER_PRODUCT_TYPE = 0x80,
        }

        public enum conditionMask : byte {
            VER_EQUAL = 1,
            VER_GREATER = 2,
            VER_GREATER_EQUAL = 3,
            VER_LESS = 4,
            VER_LESS_EQUAL = 5,
            VER_AND = 6,
            VER_OR = 7,
        }

        public const int ERROR_OLD_WIN_VERSION = 1150;
        #endregion
    }
}

もう一つはDOBON.NETで以前から紹介されていた

だと、特に何もしなくてもそのまま"6.3.9600"というバージョン番号が得られます。
なので、WMIを使っていたプログラムはそのままでOKという結論です。