Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2014年04月29日] [更新 2015年11月13日] Delphi 一般・その他
Windows のバージョンの取得
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro, 一部 Delphi XE5(UP2) Pro
[整理番号 - 0370]



  • 2015年11月09日
  • 互換モード関係の記事を追加
  • 2015年11月10日
  • Windows のバージョン取得の具体的なコードと実行結果を掲載
  • Windows のパーション取得関係のリンクも本ページを主体とした
  • 2015年11月12日
  • RtlGetVersion 関数の記事を DLL 内の関数の使用例の説明に利用できるように追加編集
  • その他、実行結果の画像追加等
  • 2015年11月13日
  • WMI による Windows のバージョン取得だけのコードと実行結果の図を掲載




Windows のバージョンの取得と Windows 8.1 以降における注意


Windows のバージョンを自アプリで取得するため参考コードです。
WMI を使用した方法以外では、アプリケーションマニフェストを使用して、そのマニフェストファイルの compatibility に該当バージョンの ID の記述がないと、正しいバージョンの値が取得できない場合があります。
何故そのような「偽造工作」がされるのかは謎です。

本ページのテストで使用している関数類が、実際にはどのように Windows のバージョンを取得しているかの内部処理については、筆者は知りません。
この他、レジストリから取得したり、システムの関係の DLL の製品バージョンから取得する方法も考えられます。必要があれば検討してみてください。



[ファイル名を指定して実行] 等で、以下のコマンドを実行するとシステム情報、あるいはバージョン情報ダイアログが表示されます。Windows のバージョンは、そのダイアログで確認できます。

control.exe /name Microsoft.System
msinfo32.exe
winver.exe

//コマンドプロンプト専用
ver
systeminfo


[備考]
Windows 10 TP(Technical Preview)のバージョンは 6.4 です。
Windows 10 では、バージョンの表記方式が変更されているようです。
2015年12月17日日現在では、Windows 10 バージョン 1511 ビルド 10586.36 ということになるようですが、筆者は、正確な表記方法を知りません。





01_Windows のバージョン取得 - CheckWin32Version 関数


CheckWin32Version 関数は、正確には、現在の Windows が、指定したバージョンより上位または下位のバージョンかをチェックする関数です。
同じような機能を持つ VerifyVersionInfo という関数があります。VerifyVersionInfo は Windows 2000 以降で使用可能です。後述の TOSVersion にも同様のメソッドが実装されています。

下図は、compatibility に Windows のバージョンの ID を記述したアプリケーションマニフェストを使用してテストした結果です。このアプリケーションマニフェストを使用しないと、Windows 8.1 以上では正しい結果が取得できません。

CheckWin32Version 関数は Delphi 6(UP2) 以降で使用可能で、Windows 95 以降の Windows のバージョンの判定に使用できます。
互換モードで実行している場合は、互換モードの Windows のバージョンで判定されます。



[備考]
Delphi 6 では、CheckWin32Version 関数の戻り値の論理値が逆になっています。以下からダウンロードしたプロジェクトを Delphi 6 の IDE でコンパイルして実行すると修正されます。



図1
Windows 7 での実行結果
図2
Windows 8.1 での実行結果
図3
Windows 10 での実行結果

リスト1
//=============================================================================
//  CheckWin32Versionを使用したWindowsのバージョンによる条件分岐
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LVersion : String;
begin
  if CheckWin32Version(10, 0) then begin
    LVersion := 'Windows 10';
  end else
  if CheckWin32Version(6, 3) then begin
    LVersion := 'Windows 8.1';
  end else
  if CheckWin32Version(6, 2) then begin
    LVersion := 'Widows 8';
  end else
  if CheckWin32Version(6, 1) then begin
    LVersion := 'Widows 7';
  end else
  if CheckWin32Version(6, 0) then begin
    LVersion := 'Widows Vista';
  end else
  if CheckWin32Version(5, 1) then begin
    LVersion := 'Widows XP';
  end else
  if CheckWin32Version(5, 0) then begin
    LVersion := 'Widows 2000';
  end else
  if CheckWin32Version(4, 90) then begin
    LVersion := 'Widows ME';
  end else
  if CheckWin32Version(4, 10) then begin
    LVersion := 'Widows 98, 98SE';
  end else
  if CheckWin32Version(4, 0) then begin
    LVersion := 'Widows 95';
  end else begin
    LVersion := 'Unknown Version';
  end;

  MessageBox(Handle, PChar(LVersion), 'Windows Version', MB_ICONINFORMATION);
end;




02_Windows のバージョン取得 - GetVersionEx 関数


GetVersionEx 関数を使用したテストコードです。
下図は、compatibility に Windows のバージョンの ID を記述したアプリケーションマニフェストを使用してテストした結果です。このアプリケーションマニフェストを使用しないと、Windows 8.1 以上では正しい結果が取得できません。

GetVersionEx 関数は、Windows 95 以降のバージョンを検出できます。
互換モードで実行している場合は、互換モードの Windows のバージョンの値となります。



図4
Windows 7 での実行結果
図5
Windows 8.1 での実行結果
図6
Windows 10 での実行結果

[備考]
Widows 10 は正式リリース後、ビルド番号がかなり変化しています。2015年11月05日現在のビルド番号は 10586 となっています。



リスト2
implementation

{$R *.dfm}

type
  TOSVERSIONINFOEX = packed record
    dwOSVersionInfoSize : Cardinal;
    dwMajorVersion      : Cardinal;
    dwMinorVersion      : Cardinal;
    dwBuildNumber       : Cardinal;
    dwPlatformId        : Cardinal;
    szCSDVersion        : array [0..127] of Char;
    wServicePackMajor   : WORD;
    wServicePackMinor   : WORD;
    wSuiteMask          : WORD;
    wProductType        : Byte;
    wReserved           : Byte;
  end;

//=============================================================================
//  GetVersionEx関数を使用したWindowsのバージョンの取得
//  TOSVERSIONINFOEX構造体のメンバから取得する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LGetVersionEx : function(var LPOSVERSIONINFO: TOSVERSIONINFOEX): Boolean; stdcall;
  LDLLHandle    : THandle;
  LVersion      : TOSVersionInfoEx;
  LMajor        : Cardinal;
  LMinor        : Cardinal;
  LBuild        : Cardinal;
  LCSDVersion   : String;
  LText         : String;
  LRetFlag      : Boolean;
begin
  LRetFlag   := False;
  LDLLHandle := LoadLibrary('kernel32.dll');

  if LDLLHandle <> 0 then begin
    try
      {$IFDEF UNICODE}
      @LGetVersionEx := GetProcAddress(LDLLHandle, 'GetVersionExW');
      {$ELSE}
      @LGetVersionEx := GetProcAddress(LDLLHandle, 'GetVersionExA');
      {$ENDIF}

      if @LGetVersionEx <> nil then begin
        LVersion.dwOSVersionInfoSize := SizeOf(LVersion);
        FillChar(LVersion.szCSDVersion, SizeOf(LVersion.szCSDVersion), #0);

        if LGetVersionEx(LVersion) then begin
          LRetFlag    := True;
          LMajor      := LVersion.dwMajorVersion;
          LMinor      := LVersion.dwMinorVersion;
          LBuild      := LVersion.dwBuildNumber;
          LCSDVersion := LVersion.szCSDVersion;

          LText := IntToStr(LMajor) + '.' + IntToStr(LMinor) + '.' + IntToStr(LBuild)
                 + sLineBreak + LCSDVersion;
        end;
      end;
    finally
      FreeLibrary(LDLLHandle);
    end;
  end;

  if not LRetFlag then begin
    MessageBox(Handle, 'Unknown Version', 'Windows Version', MB_ICONINFORMATION);
  end else begin
    MessageBox(Handle, PChar(LText), 'Windows Version', MB_ICONINFORMATION);
  end;
end;




03_RtlGetVersion 関数でバージョン取得 - DLL の静的リンク


RtlGetVersion 関数を使用するテストコードです。
この関数の機能は GetVersionEx 関数とほとんど同じですが、アプリケーションマニフェストを使用しなくても、Windows 8.1 以上で正しい Windows のバージョンの値を取得することができます。 RtlGetVersion 関数は、Windows 2000 以上で使用可能です。

実行結果は、前項の GetVersionEx 関数の場合と全く同じとなります。
互換モードで実行している場合は、互換モードの Windows のバージョンの値となります。



[備考]
RTL_OSVERSIONINFOEXW と OSVERSIONINFOEXW は同じ中身の構造体です。



リスト3
implementation

{$R *.dfm}

  function RtlGetVersion(var AVersion: TOSVersionInfoExW): Integer;
    stdcall; external 'ntdll.dll';

//=============================================================================
//  RtlGetVersion関数を使用したWindowsのバージョンの取得
//  TOSVersionInfoExW構造体のメンバから取得する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LVersion    : TOSVersionInfoExW;
  LMajor      : Cardinal;
  LMinor      : Cardinal;
  LBuild      : Cardinal;
  LCSDVersion : String;
  LText       : String;
begin
  LVersion.dwOSVersionInfoSize := SizeOf(LVersion);
  FillChar(LVersion.szCSDVersion, SizeOf(LVersion.szCSDVersion), #0);

  if RtlGetVersion(LVersion) = 0 then begin
    LMajor      := LVersion.dwMajorVersion;
    LMinor      := LVersion.dwMinorVersion;
    LBuild      := LVersion.dwBuildNumber;
    LCSDVersion := LVersion.szCSDVersion;

    LText := IntToStr(LMajor) + '.' + IntToStr(LMinor) + '.' + IntToStr(LBuild)
           + sLineBreak + LCSDVersion;
    MessageBox(Handle, PChar(LText), 'Windows Version', MB_ICONINFORMATION);
  end;
end;




04_RtlGetVersion 関数でバージョン取得 - DLL の動的リンク ( 1 )


RtlGetVersion 関数は、Windows 9X では使用できません。アプリケーションを Windows 9X で使用されてしまう可能性がある場合は、下のように DLL を実行時にロードして、その DLL がシステムに存在するのか、その DLL 内に、該当する関数が実装されているかを確認するようにします。
このような方法を「 DLL の動的リンク」言うことがあります。一方、上のコードのような方法を「DLL の静的リンク」と言っています。

アプリケーションを Windows 2000 以前で動作させるためには、Ansi 版である Delphi 2007 以前でコンパイルして EXE を作成します。
下図は、Windows 7 U64(SP1) + Delphi 2007-R2 で作成した EXE を実行した結果です。Delphi 2007 には TOSVersionInfoExW 構造体が実装されていないので、コード内で定義しています。

このコードは、Delphi 6, 7, 2007-R2 で動作確認しています。Delphi 2007 以降でも使用可能です。



図7
Windows 98 での実行結果
図8
Windows 2000(SP4) での実行結果
  • Service Pack 4 がインストールされているが表示されていない
図9
Windows XP(SP3) での実行結果

リスト4
implementation

{$R *.dfm}

type
  TOSVERSIONINFOEXW = packed record
    dwOSVersionInfoSize : Cardinal;
    dwMajorVersion      : Cardinal;
    dwMinorVersion      : Cardinal;
    dwBuildNumber       : Cardinal;
    dwPlatformId        : Cardinal;
    szCSDVersion        : array [0..127] of WideChar;
    wServicePackMajor   : WORD;
    wServicePackMinor   : WORD;
    wSuiteMask          : WORD;
    wProductType        : Byte;
    wReserved           : Byte;
  end;

//=============================================================================
//  RtlGetVersion関数を使用したWindowsのバージョンの取得
//  TOSVersionInfoExW構造体のメンバから取得する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LRtlGetVersion : function (var AVersion: TOSVersionInfoExW): Integer; stdcall;
  LDLLHandle     : THandle;
  LVersion    : TOSVersionInfoExW;
  LMajor      : Cardinal;
  LMinor      : Cardinal;
  LBuild      : Cardinal;
  LCSDVersion : String;
  LText       : String;
  LRetFlag    : Boolean;
begin
  LRetFlag   := False;
  LDLLHandle := LoadLibrary('ntdll.dll');

  if LDLLHandle <> 0 then begin
    try
      @LRtlGetVersion := GetProcAddress(LDLLHandle, 'RtlGetVersion');
      if @LRtlGetVersion <> nil then begin
        LRetFlag := True;

        LVersion.dwOSVersionInfoSize := SizeOf(LVersion);
        FillChar(LVersion.szCSDVersion, SizeOf(LVersion.szCSDVersion), #0);

        if LRtlGetVersion(LVersion) = 0 then begin
          LMajor      := LVersion.dwMajorVersion;
          LMinor      := LVersion.dwMinorVersion;
          LBuild      := LVersion.dwBuildNumber;
          LCSDVersion := LVersion.szCSDVersion;

          LText := IntToStr(LMajor) + '.' + IntToStr(LMinor) + '.' + IntToStr(LBuild)
                 + sLineBreak + LCSDVersion;
          ShowMessage(LText);
        end;
      end;
    finally
      FreeLibrary(LDLLHandle);
    end;
  end;

  if not LRetFlag then begin
    ShowMessage('このパソコンでは使用できません。');
    Close;
  end;
end;

end.




05_RtlGetVersion 関数でバージョン取得 - DLL の動的リンク ( 2 )


上のコードは、DLL 内の関数 RtlGetVersion をイベント内だけで使用する場合です。
ユニット内の別の場所でもこの関数を使用する場合は、以下のように、関数をグローバルに type 宣言して使用します。実際には、DLL のロードや関数のアドレスの取得も、OnCreate イベント内等で処理することになるでしょう。他のユニットからも利用できるようにするには、implementation 部ではなく、interface 部で宣言します。

下のコードでは、TRtlGetVersion という、関数名と同じ名前の型にしていますが、これは任意の名前にできます。
このコードも、もちろん、Delphi 2007 以降でも使用可能です。



リスト5
implementation

{$R *.dfm}

type
  TOSVERSIONINFOEXW = packed record
    dwOSVersionInfoSize : Cardinal;
    dwMajorVersion      : Cardinal;
    dwMinorVersion      : Cardinal;
    dwBuildNumber       : Cardinal;
    dwPlatformId        : Cardinal;
    szCSDVersion        : array [0..127] of WideChar;
    wServicePackMajor   : WORD;
    wServicePackMinor   : WORD;
    wSuiteMask          : WORD;
    wProductType        : Byte;
    wReserved           : Byte;
  end;

  TRtlGetVersion = function (var AVersion: TOSVersionInfoExW): Integer; stdcall;

var
  LRtlGetVersion : TRtlGetVersion;

//=============================================================================
//  RtlGetVersion関数を使用したWindowsのバージョンの取得
//  TOSVersionInfoExW構造体のメンバから取得する
//
//  グローバルでType宣言で定義した関数を使用する例
//  TRtlGetVersionとしているが,この名前は任意
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LDLLHandle     : THandle;
  LVersion       : TOSVersionInfoExW;
  LMajor         : Cardinal;
  LMinor         : Cardinal;
  LBuild         : Cardinal;
  LCSDVersion    : String;
  LText          : String;
  LRetFlag       : Boolean;
begin
  LRetFlag   := False;
  LDLLHandle := LoadLibrary('ntdll.dll');

  //以下省略(上のコードと同じ)




06_TOSVersion による Windows のバージョン取得


Delphi XE2 以降であれば、SysUtils.TOSVersion のメソッドやプロパティが利用できます。
TOSVersion.Check メソッドではサービスパックも含めたチェックができます。レコード型のクラスメソッドですから TOSVersion を Create する必要はありません。

下図は、compatibility に Windows のバージョンの ID を記述したアプリケーションマニフェストを使用してテストした結果です。このアプリケーションマニフェストを使用しないと、Windows 8.1 以上では正しい結果が取得できません。

TOSVersion を使用したプログラムは、Windows XP 以降で実行可能です。
互換モードで実行している場合は、互換モードの Windows のバージョンの値となります。



図10
Windows 7 での実行結果
図11
Windows 8.1 での実行結果
図12
Windows 10 での実行結果

リスト6
//=============================================================================
//  TOSVersionによるWindowsのバージョンの取得
//  メジャー,マイナーバージョン番号等も独立して取得可能
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LVersion : String;
  LText    : String;
begin
  LText := TOSVersion.Name + sLineBreak + TOSVersion.ToString;
  MessageBox(Handle, PChar(LText), '情報', MB_ICONINFORMATION);
end;




07_WMI を使用した Windows のバージョン取得


Windows のバージョン情報等は、WMI の Win32_OperatingSystem でも取得できます。
下図は、[900] [01_コンピュータシステムの情報を取得] のサンプルの Edit1 にクラス名を入力してクエリを実行した結果です。

WMI を使用したこの方法は、このアプリケーションマニフェストを使用しなくても正しい Windows のバージョンの値を取得することができます。また、Windows のビットバージョン、サービスパックのバージョンやエディションの種類も取得できます。
互換モードで実行している場合も、取得情報はシステムの Windows のバージョンの値です。

Windows のバージョン情報の取得としては、WMI を使用した方法が最も確実と思われますが、Windows 2000 以降に限られます。



図13
Windows 7 での実行結果
図14
Windows 8.1 での実行結果
図15
Windows 10 での実行結果

WMI は Windows 2000 以上で使用可能です。Windows 95, Windows 98, Windows NT4.0 で WMI を使用するには別途インストールが必要ですが、既にサポートが終了しているバージョンです。ダウンロードが可能であるかは確認していません。



図16
Windows 2000(SP4) での実行結果
  • EXE は Windows 7 U64(SP1) + Delphi XE(UP1) Pro で作成
図17
Windows XP(SP3) での実行結果
  • EXE は Windows 7 U64(SP1) + Delphi XE(UP1) Pro で作成




08_WMI を使用して Windows のバージョンだけを取得

以下のコードは、WMI を使用して Windows のバージョンの値だけを文字列として取得するコードと、その実行結果です。
uses に WbemScripting_TLB, ActiveX が必要です。



図18
Windows 7 での実行結果

リスト7
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, WbemScripting_TLB, ActiveX;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    function GetWMIPropSetEnum(ASQLText: WideString): IEnumVariant;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  Win32_OperatingSystemクラスからVersionプロパティの値を取得
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LIEmunVariant : IEnumVariant;
  LobjTemp      : OleVariant;
  LValue        : LongWord;
  LwmiPropSet   : ISWbemPropertySet;
  LwmiProperty  : ISWbemProperty;
  LText         : String;
begin
  //プロパティのセットのコレクションを取得
  LIEmunVariant := GetWMIPropSetEnum('Win32_OperatingSystem');

  //OSの情報はおそらく1つだけなので実際には1回しかループしない
  while LIEmunVariant.Next(1, LobjTemp, LValue) = 0 do begin
    //プロパティのセットを取得
    LwmiPropSet := (IUnknown(LobjTemp) as ISWBemObject).Properties_;
    //Versionプロパティを取得
    LwmiProperty := LwmiPropSet.Item('Version', 0);

    LText := LwmiProperty.Name + sLineBreak + LwmiProperty.Get_Value;
    MessageBox(Handle, PChar(LText), '情報', MB_ICONINFORMATION);
  end;
end;

//-----------------------------------------------------------------------------
//  WMIのクエリを実行してプロパティのセットのコレクションを取得するルーチン
//-----------------------------------------------------------------------------
function TForm1.GetWMIPropSetEnum(ASQLText: WideString): IEnumVariant;
var
  LISWbemLocator  : ISWbemLocator;
  LISWbemService  : ISWbemServices;
  LSWbemObjectSet : ISWbemObjectSet;
begin
  //WMIのオブジェクトを生成
  LISWbemLocator := CoSWbemLocator.Create;
  //WMIサービスに接続
  LISWbemService := LISWbemLocator.ConnectServer(
                     '',
                     'root\cimv2',
                     '',
                     '',
                     '',
                     '',
                     0,
                     nil);
  //クエリーを実行して、プロパティのセットのオブジェクトを取得
  LSWbemObjectSet := LISWbemService.ExecQuery(
                     'Select * From ' + ASQLText,
                     'WQL',
                     wbemFlagReturnImmediately,
                     nil);


  //プロパティのセットのコレクションを取得
  Result := LSWbemObjectSet._NewEnum as IEnumVariant;
end;

end.


プロパティの値は、次のように、直接 OleVariant 型の値として取得することもできます。



リスト8
//=============================================================================
//  Win32_OperatingSystemクラスからVersionプロパティの値を取得
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LIEmunVariant : IEnumVariant;
  LobjTemp      : OleVariant;
  LValue        : LongWord;
  LText         : String;
begin
  //プロパティのセットのコレクションを取得
  LIEmunVariant := GetWMIPropSetEnum('Win32_OperatingSystem');

  //OSの情報はおそらく1つだけなので実際には1回しかループしない
  while LIEmunVariant.Next(1, LobjTemp, LValue) = 0 do begin
    //Versionプロパティを取得
    LText := LobjTemp.Version;
    LText := 'Verstion' + sLineBreak + LText;

    MessageBox(Handle, PChar(LText), '情報', MB_ICONINFORMATION);
  end;
end;


タイプライブラリの取り込みで WbemScripting_TLB を作成するのは面倒だし、WbemScripting_TLB は使いたくないという場合は、以下のように、全て OleVariant 型で処理することになります。



リスト9
implementation

uses
  ActiveX,
  ComObj;

{$R *.dfm}

//=============================================================================
//  Win32_OperatingSystemクラスからVersionプロパティの値を取得
//
//  IEnumVariantの使用にはusesにActiveXが必要
//  CreateOleObjectの使用にはusesにComObjが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LSQLText        : WideString;
  LISWbemLocator  : OleVariant;
  LISWbemService  : OleVariant;
  LSWbemObjectSet : OleVariant;
  LIEmunVariant   : IEnumVariant;
  LobjTemp        : OleVariant;
  LValue          : LongWord;
  LText           : String;
begin
  LSQLText := 'Win32_OperatingSystem';

  //WMIのオブジェクトを生成
  LISWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  //WMIサービスに接続
  LISWbemService := LISWbemLocator.ConnectServer('', 'root\cimv2');
  //クエリーを実行して、プロパティのセットのオブジェクトを取得
  LSWbemObjectSet := LISWbemService.ExecQuery('SELECT * FROM ' + LSQLText);
  //プロパティのセットのコレクションを取得
  LIEmunVariant := IUnknown(LSWbemObjectSet._NewEnum) as IEnumVariant;


  //実際には1回しかループしない
  while LIEmunVariant.Next(1, LobjTemp, LValue) = 0 do begin
    //Versionプロパティを取得
    LText := LobjTemp.Version;
    LText := 'Verstion' + sLineBreak + LText;

    MessageBox(Handle, PChar(LText), '情報', MB_ICONINFORMATION);
  end;
end;




09_ver コマンドで Windows のバージョンを確認


コマンドプロセッサの ver コマンドを使用すると、現在の Windows のバージョンを簡単に確認することができます。リファレンスとして利用できます。



図19
コマンドプロンプトで ver コマンドを実行
  • 現在の Windows のバージョンが取得できる




10_互換モードでの Windows のバージョンと互換モードの取得


互換モードで動作させているプログラムの場合、取得する Windows のバージョンの値は、バージョンの取得に使用する方法によって異なります。下記のリンクの記事も参考にしてください。



下のコードは、自分自身が互換モードで動作するように設定してある場合に、その互換モードの値を取得するサンプルです。互換モードの値は、アプリケーションのフルパスを使用して、レジストリから読み取ります。



図20
[プロパティ] のダイアログで [互換モード] 設定
  • ここでは Windows 2000 に設定
図21
実行結果
  • Windows 2000 の場合は WIN2000 となる

互換モードの値は、レジストリの以下のキーにあります。このキー内の各項目が、互換モードを設定しているプログラムのフルバスです。この項目 (名前) のデータが互換モードの値です。
筆者の環境では、今回テスト用に設定したプログラムだけとなっています。


HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers

現在のコンピュータの全ユーザの互換モードの設定は、以下の場所に記録されます。
逆に、これらのレジストリを操作することにより、互換モードを設定することができます。


HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers


図22

リスト10
//=============================================================================
//  自分自身が互換モードで動作しているかを調査
//  互換モードで動作している場合はその種類を取得して表示
//
//   TRegistryの使用にはusesにRegistryが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LAppFullPath  : String;
  LRegistry     : TRegistry;
  LRegKeyName   : String;
  LRegItemValue : String;
begin
  LAppFullPath := Application.ExeName;

  LRegistry := TRegIniFile.Create;
  try
    LRegistry.Access  := KEY_READ;
    LRegistry.RootKey := HKEY_CURRENT_USER;
    LRegKeyName       := 'Software\Microsoft\Windows NT\CurrentVersion\'
                       + 'AppCompatFlags\Layers';

    LRegItemValue := '';
    if LRegistry.OpenKey(LRegKeyName, False) then begin
      LRegItemValue := LRegistry.ReadString(LAppFullPath);
    end;

    if LRegItemValue = '' then begin
      MessageBox(Handle, '互換モードは未設定です', '互換モード', MB_ICONINFORMATION);
    end else begin
      MessageBox(Handle, PChar(LRegItemValue), '互換モード', MB_ICONINFORMATION);
    end;
  finally
    FreeAndNil(LRegistry);
  end;
end;




11_Windows 7 以降では EXE は Vista 互換モードで実行される


Windows 7 以降では、アプリケーションマニフェストを使用して、compatibility に該当バージョンの ID の記述をしないと、Windows Vista 互換モードで動作します。
この時、この互換モードは上のコードでは検出できませんが、リソースモニタ (resmon.exe) の [オペレーティングシステムのコンテキスト] で確認することができます。

[オペレーティングシステムのコンテキスト] の列がない場合は、リソースモニタのタイトル部でマウスの右ボタンクリックのメニューから [列の選択] を選択します。現れたダイアログで [オペレーティングシステムのコンテキスト] にチェックを入れると表示できます。

互換モードを設定したプログラムは、このリソースモニタでは Windows 7 となります。



図23