2

このコードを使用して、レジストリから文字列にバイナリデータを読み取ります

function ReadBinary (RootKey: HKEY; SubKey,ValueName: WideString; var Data : String): Bool;
var
  Key     : HKey;
  Buffer  : array of char;
  Size    : Cardinal;
  RegType : DWORD;
begin
  result  := FALSE;
  RegType := REG_BINARY;
  if RegOpenKeyExW(RootKey, pwidechar(SubKey), 0, KEY_READ, Key) = ERROR_SUCCESS then begin
    if RegQueryValueExW(Key,pwidechar(ValueName),NIL,@RegType, NIL,@Size) = ERROR_SUCCESS then begin
      SetLength (Buffer, Size + 1);
      FillChar(Buffer, SizeOf (Buffer), #0);
      if RegQueryValueExW(Key,pwidechar(ValueName),NIL,@RegType, @Buffer[0],@Size) = ERROR_SUCCESS then begin
        result := TRUE;
        Data := String (Buffer); // Shows empty or sometimes 1 random char.
      end;
    end;        
  end;
  RegCloseKey (Key);
end;

EDIT2:

バイト/文字の固定宣言配列で正常に動作します

function ReadBinary (RootKey: HKEY; SubKey,ValueName: WideString; var Data : String): Bool;
var
  Key     : HKey;
  Buffer  : array [0..200] of char;
  Size    : Cardinal;
  RegType : DWORD;
begin
  result  := FALSE;
  RegType := REG_BINARY;
  if RegOpenKeyExW(RootKey, pwidechar(SubKey), 0, KEY_READ, Key) = ERROR_SUCCESS then begin
    if RegQueryValueExW(Key,pwidechar(ValueName),NIL,@RegType, NIL,@Size) = ERROR_SUCCESS then begin
      FillChar(Buffer, SizeOf (Buffer), #0);
      if RegQueryValueExW(Key,pwidechar(ValueName),NIL,@RegType, @Buffer,@Size) = ERROR_SUCCESS then begin
        result := TRUE;
        Data   := String (Buffer);
      end;
    end;        
  end;
  RegCloseKey (Key);
end;

私は立ち往生しています。私は何を間違え、解決策は何ですか?

ご協力ありがとうございました。

編集:

レジストリからバイナリデータを読み取っていることを認識しています。したがって、すでに0で終了している可能性があり、誤った結果を返す可能性があります。以前に値に長いテキスト(CR / LFを含む文字列)を書き込んだため、バイナリデータに#0文字がないことを保証できます。

4

2 に答える 2

6
Buffer: array of char;

文字の動的配列、つまり、実際にはポインタ変数です。そして、この文字列はポインタをNilにリセットします。

   FillChar(Buffer, SizeOf (Buffer), #0);

したがって、動的配列は現在有効ではありません

動的配列の内容をゼロで埋めるには、次を使用する必要があります

    FillChar(Buffer[0], SizeOf(Buffer[0]) * Length(Buffer), #0)

ただし、SetLengthが機能するため、これは必要ありません。

于 2012-08-13T11:31:35.077 に答える
0
  1. 動的配列はポインタのようなものです。C / C ++では、まったく同じです。Delphiではそうではありませんが、セマンティクスについてはこのように考えることができます。@Bufferは1台目の車のアドレスではなく、ポインター自体のアドレスです。FillCharRegQueryValueExWの両方の呼び出しをIbし、代わりにBuffer[0]@Buffer[0 ]を渡す必要があります
  2. 標準のTRegistryの代わりにWindowsAPIを使用するのはなぜですか?あるいは、TNT Unicodeコントロールまたはそれに類似したものが、既製のユニコード対応のレジストリアクセスを持っているかもしれません。
  3. WinAPIxxxxxxxW関数はUnicodeに対応しています取得したデータを確認しましたか?それは8ビットですか、それとも16ビットですか?受信したデータをHEXのバイト配列として表示します-それらには$00バイトが含まれていますか?彼らがそうしているように見え、あなたはユニコードデータをバッファに入れました。次に、1文字(IntelまたはMotorolaのバイト順序によっては0)のみを受け入れることが期待され、文字列の動作が正しくなります。バッファにあるバイナリデータを確認してください。
  4. 個人的には、Bufferをバイトの配列として作成しました。次に、レジストリにアクセスした後、D7に値がある場合は、SetStringプロシージャを使用して値を取得しました。そうでない場合は、SetLength(Data、Size);のようにコピーします。Move(Buffer [0]、Data [1]、Size); そして、FillCharを完全に削除します。このようにすると、コピーはわずかに高速になり、最初の漂遊#0バイトで中断することはありません。
  5. 低レベルのバイナリデータ型キャストを行うときは、あいまいなchar型と文字列型を使用せず、具体的なAnsiString型とAnsiChar型を使用します。コードが新しいUnicode対応のDelphiまたはFreePascalでコンパイルされる場合、それは機能し続けます。ショートカット「char」および「string」は、コンパイラのバージョンによっては意味が変わる場合があります。そして、それが壊れた理由と場所、そして何をすべきかを判断するのに苦労するでしょう。
于 2012-08-13T11:50:30.403 に答える