2012-08-13 51 views
2

我使用此代碼從註冊表中讀取二進制數據爲字符串讀REG_BINARY爲String

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字符,因爲我在Value之前寫了一個長文本(帶有CR/LF的字符串)。

+2

如果你在'Data:= String(Buffer)'賦值處設置了一個調試斷點,並看看'Buffer',那麼它究竟是什麼? – 2012-08-13 11:00:55

+0

看起來像我甚至無法訪問它。但我認爲它的#0。如果我嘗試這樣的事情,我會得到很多訪問衝突:if buffer [0] =''then messagebox(0,'ERROR','',0); – 2012-08-13 11:09:20

+0

編輯:我得到000000 messagebox(0,pchar(格式('%8p',[@buffer [0]])),'',0); – 2012-08-13 11:24:57

回答

6
Buffer: array of char; 

是動態字符數組,也就是實際上是指針變量。而這個字符串指針復位至零:

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

所以動態數組現在是無效

要由零填充動態數組的內容,你必須使用

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

但是這是沒有必要的,因爲SetLength使工作。

+0

真棒。就是這樣!非常感謝。當然,我並不是指從數組中刪除地址。 – 2012-08-13 11:44:15

0
  1. 動態數組有點像指針一樣。在C/C++中,它將完全相同。在Delphi中它不是,但是你可以這樣思考語義。 @Buffer不是第一輛車的地址,而是指針本身的地址。盈透FillChar兩個呼叫函數RegQueryValueExW你應該通過緩衝區[0]@Buffer [0]代替
  2. 爲什麼ü使用Windows API而不是標準TRegistry?或者,也許TNT的Unicode控制或somethign類似有現成的unicode感知的註冊表訪問。
  3. Win API xxxxxxxW功能是unicode意識。你檢查了你得到的數據嗎?它是8位還是16位?以十六進制字節數組的形式查看收到的數據 - 它們是否包含$ 00字節?它看起來像他們一樣,你有unicode數據進入緩衝區。然後它會預期和正確的行爲只接受1個字母(或0,取決於英特爾或摩托羅拉字節順序)。檢查你在Buffer中獲得的二進制數據。
  4. 就我個人而言,我把緩衝區作爲字節數組。然後,在註冊表訪問後,我會使用SetString過程來獲取值,如果D7有它。如果沒有,那麼我會複製它像SetLength(Data,Size);移動(緩衝區[0],數據[1],大小);我會完全刪除FillChar。這種方式複製將會稍微快一點,並且不會在第一個流浪號碼0字節中斷。
  5. 在做低級二進制數據類型轉換時,我不會使用含糊的char和string類型,而是使用具體的AnsiString和AnsiChar類型。如果你的代碼會被新的支持Unicode的Delphi或FreePascal編譯,那麼它會保持它的工作。根據編譯器版本,快捷鍵「char」和「string」可能會改變它們的含義。然後,你將很難確定爲什麼,在哪裏打破以及該做什麼。
+0

-1。雖然這其中大部分都是很好的信息,但它並不回答這裏提出的問題。 – 2012-08-13 18:47:51

+1

@KenWhite:他在這裏有一些有效的分數(他仍然服用過多的藥物恕我直言)... – whosrdaddy 2012-08-14 07:37:32

+1

@whosrdaddy,我這樣說。但是,問題仍然存在,那就是解決這個問題的唯一方法就是提供解決方案。 (不使用'FillChar'使'buffer'nil不被使用) – 2012-08-14 10:53:19