Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2015年03月11日] [更新 2015年03月11日] Delphi 一般・その他
   
レジストリのキー名のコピー方法等
動作確認等 indows 7 U64(SP1) + Delphi XE(UP1) Pro
[整理番号 - 0980]







01_レジストリのキー名のコピー方法


レジストリのキー名は,下図のように,該当するキー名の上にマウスカーソルを移動して,右ボタンクリックで現れるメニューで,[キー名のコピー] をクリックするとコピーできます.


[備考]
Delphi でレジストリを操作するには TRegistry を使用します.



図1
キー名のコピー

下図は,コピーしたキー名を,テキストエディタに貼り付けた結果です.
テキストエディタは,メモ帳等のように,文字列だけが入力できるアプリ (プログラム) です.


図2
取得したキー名




02_64 ビット版の Windows にはレジストリエディタが 2 つある


レジストリエディタは,[ファイル名を指定して実行] のダイアログで Regedit で起動できます.
この場合,64 ビット版の Windows 7 では 64 ビット版のレジストリエディタが起動します.64 ビッ版の Windows の場合,32 版のレジストリエディタが別にあります.
以下のコマンドで起動できます.
64 ビットのレジストリにも,32 ビットのレジストリの内容が記録されています.

C:\Windows\SysWOW64\Regedit



問題となるのは 64 ビットの Windows の場合です.32 ビットの EXE から 64 ビットのレジストリにアクセスする時と,64 ビットの EXE から 32 ビットのレジストリにアクセスする時です.

64 ビットのレジストリにアクセスする時は,TRegistry.Access に KEY_WOW64_64KEY を含めます.また 32 ビットのレジストリにアクセスする時は KEY_WOW64_32KEY を含めます.
下に示すコードは 64 ビットのレジストリにアクセスする例です.



リスト1
implementation

uses
  Registry;

{$R *.dfm}

//-----------------------------------------------------------------------------
//  32ビットのWindowsか64ビットのWindowsかを調べる関数
//  64ビット版のWindowsの場合はTrueを返す
//-----------------------------------------------------------------------------
function Is64bitWindows: Boolean;
var
  Wow64Proc : function(hProcess: THandle; var Wow64: BOOL): BOOL stdcall;
  RetFlag   : LongBool;
begin
  @Wow64Proc := GetProcAddress(GetModuleHandle('Kernel32.dll'), 'IsWow64Process');
  if @Wow64Proc <> nil then begin
    Wow64Proc(GetCurrentProcess, RetFlag);

    if SizeOf(THandle) = 4 then begin
      Result := RetFlag;
    end else
    if SizeOf(THandle) = 8 then begin
      Result := True;
    end;
  end else begin
    //Windows XPの64ビット版か
    Result := CheckWin32Version(5, 2);
  end;
end;

//=============================================================================
//  32ビットのEXEから64ビットのレジストリにアクセスする方法
//  動作確認 : Windows 7 U64(SP1) + Delphi XE(UP1) Pro
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LRegistry : TRegistry;
  LRegKey   : string;
  LItemName : string;
  LText     : string;
begin
  LRegistry := TRegistry.Create;
  if Is64bitWindows then begin
    LRegistry.Access := KEY_READ or KEY_WOW64_64KEY;
  end else begin
    LRegistry.Access := KEY_READ;
  end;
  try
    LRegistry.RootKey := HKEY_LOCAL_MACHINE;
    LRegKey := 'SOFTWARE\Microsoft\Windows NT\CurrentVersion';

    LItemName := 'CurrentBuildNumber';
    if LRegistry.OpenKey(LRegKey, False) then begin
      if LRegistry.ValueExists(LItemName) then begin
        LText := LRegistry.ReadString(LItemName);
      end;
      LRegistry.CloseKey;
    end;
  finally
    FreeAndNil(LRegistry);
  end;
  ShowMessage(LText);
end;




03_レジストリのキーとハイブ ( Hives ) と項目名のコピー


レジストリのキー名は,レジストリエディタの左ペインでに表示される部分です.
例えば以下は短いですがフルキー名です.

HKEY_CLASSES_ROOT\.jpg

このキー名に右ペインの項目の項目名,レジストリエディタでは [名前の欄] の部分を含めたものをハイブと呼んでいます.
ハイブとしてのコピーはできませんが,下図のように項目を選択してポップアップメニュー表示し,[名前の変更] を選択すると項目名が編集状態となります.この状態で [Ctrl] + [C] で項目の名前をコピーすることができます.

HKEY_CLASSES_ROOT\.jpg\Content Type


図3
項目の名前のコピー




04_レジストリのデータの種類とデータのコピー


レジストリに記録されているデータには下表のような種類があります.


種類 (型) 説明
REG_BINARY バイナリ値
表示は 16 進数または 10 進数表示
REG_DWORD 4 バイトの整数値 (32 ビットの整数値)
16 進数または 10 進数表示
REG_EXPAND_SZ

展開可能な文字列
環境変数 (%PATH% 等) 等,展開前の nill 終端文字列

REG_MULTI_SZ

複数行の文字列
nill 終端文字列で構成される配列型の文字列.null 終端文字が最後にもう 1 つ追加されている.null 終端文字のかわりにスペース,コンマ,または他の文字が使われる場合もある

REG_SZ

null 終端文字列

REG_RESOURCE_LIST バイナリ値で 16 進数表示
デバイスドライバ等のリソースの格納に使用され,配列形式
REG_RESOURCE_REQUIREMENTS_LIST バイナリ値で 16 進数表示
ハードウェア等のリソース情報等で,ネストされた一連の配列
REG_FULL_RESOURCE_DESCRIPTOR バイナリ値で 16 進数表示
リソース一覧の格納用
REG_NONE 特定の型を持たないデータ
バイナリ値として 16 進数形式で表示
REG_LINK シンボリックリンクの名前
REG_QWORD 8 バイトの整数値 (64 ビットの整数値)
16 進数または 10 進数表示


データは下図のような操作でコピーできます.
まず項目を選択します.ポップアップメニューから [修正] を選択するとダイアログが現れます.このダイアログのデータを選択して [Ctrl] + [C] でコピーてきます.


図4
項目を選択して [修正]
図5
表示値を選択して [Ctrl} +[C] でコピーできる




05_レジストリの日付の文字列を TDateTime 型の値に変換


レジストリの,年月日の区切り文字がない日付の文字列を TDateTime 型の値に変換する例です.
このコードでは,まず文字列を浮動小数点の値に変換して,その数値を FormatFloat で年,月,日の間に / を挿入した文字列に変換します.その文字列を TDateTime 型の値にしています.


リスト2
//=============================================================================
//  レジストリの日付の文字列をTDateTime型の値に変換する例
//  動作確認 : Windows 7 U64(SP1) + Delphi XE(UP1) Pro
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LText : string;
  LDate : TDateTime;
begin
  LText := '20150202';
  LDate := StrToDate(FormatFloat('0000/00/00', StrToFloat(LText)));

  ShowMessage(FormatDateTime('yyyy年mm月dd日', LDate));
end;


図6
日付のデータは文字列
図7
上のコードの実行結果




06_レジストリの整数型の日付時刻の値を TDateTime 型の値に変換


日付時刻の値は,UTC の UNIX 形式の整数値で記録されていることがあります.
このような値は,UnixToDateTime で TDateTime 型の値に変換し,TTimeZone.Local.ToLocalTime でローカルな日付時刻に変換することができます.

下のコードは,その例です.Windows をシステムにインストールした日時を取得して表示します.このコードは 32 ビットの Windows 専用となっています>



図8
レジストリの UNIX 形式の日付時刻の値を,ローカルな日付時刻の TDateTime 型の値に変換

リスト3
implementation

uses
  Registry,
  DateUtils;

{$R *.dfm}

//=============================================================================
//  レジストリのUTCの日付の整数値をローカルなTDateTime型の値に変換する例

//  usesにRegistry, DateUtilsが必要
//  開発環境 : Windows 7 U64(SP1) + Delphi XE(UP1) Pro
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LRegistry      : TRegistry;
  LRegKey        : string;
  LItemName      : string;
  LItemInt       : UInt64;
  LUtcDateTime   : TDateTime;
  LLocalDateTime : TDateTime;
  LText          : string;
begin
//  LUtcDateTime   := Now;
//  LLocalDateTime := Now;

  LRegistry := TRegistry.Create;
  LRegistry.Access  := KEY_READ;
  try
    LRegistry.RootKey := HKEY_LOCAL_MACHINE;
    LRegKey := 'SOFTWARE\Microsoft\Windows NT\CurrentVersion';

    LItemName := 'InstallDate';
    if LRegistry.OpenKey(LRegKey, False) then begin
      if LRegistry.ValueExists(LItemName) then begin
        LItemInt := LRegistry.ReadInteger(LItemName);
        if LItemInt > 0 then begin
          LUtcDateTime   := DateUtils.UnixToDateTime(LItemInt);
          LLocalDateTime := DateUtils.TTimeZone.Local.ToLocalTime(LUtcDateTime);

          LText := IntToStr(LItemInt) + sLineBreak
                 + FormatDateTime('yyyy年mm月dd日 hh時mm分ss秒', LUtcDateTime) + sLineBreak
                 + FormatDateTime('yyyy年mm月dd日 hh時mm分ss秒', LLocalDateTime);
          MessageBox(Handle, PChar(LText), '結果', MB_ICONINFORMATION);
        end;
      end;
      LRegistry.CloseKey;
    end;
  finally
    FreeAndNil(LRegistry);
  end;
end;