طريقة Registry ReadString لا تعمل في Windows 7 في Delphi 7
-
28-09-2019 - |
سؤال
عينة الكود التالية المستخدمة لإرجاع معرف Windows Me قبل ، ولكن الآن لا تعمل ، وإرجاع سلسلة فارغة ، Dunno لماذا.
function GetWindowsID: string;
var
Registry: TRegistry;
str:string;
begin
Registry := TRegistry.Create(KEY_WRITE);
try
Registry.Lazywrite := false;
Registry.RootKey := HKEY_LOCAL_MACHINE;
// Registry.RootKey := HKEY_CURRENT_USER;
if CheckForWinNT = true then
Begin
if not Registry.OpenKeyReadOnly('\Software\Microsoft\Windows NT\CurrentVersion') then showmessagE('cant open');
end
else
Registry.OpenKeyReadOnly('\Software\Microsoft\Windows\CurrentVersion');
str := Registry.ReadString('ProductId');
result:=str;
Registry.CloseKey;
finally
Registry.Free;
end; // try..finally
end;
أي شخص يمكن أن يساعد؟
المحلول
ذلك لأن المفتاح الافتراضي ' software wow6432node microsoft windows nt currentversion ' لا يحتوي على عنصر "منتج".
قم بتعديل الكود الخاص بك لإنشاء مثيل Tregistry مع
Registry := TRegistry.Create(KEY_WRITE OR KEY_WOW64_64KEY);
حيث key_wow64_64key = $ 0100. هذا سوف يمنحك النتيجة المتوقعة.
بدلا من ذلك ، الاستخدام DSIWIN32 و اتصل
DSiReadRegistry('\Software\Microsoft\Windows NT\CurrentVersion',
'ProductID', '', HKEY_LOCAL_MACHINE, KEY_QUERY_VALUE OR KEY_WOW64_64KEY);
نصائح أخرى
هناك إجراء مفيد لقراءة السجل الرئيسي في 32 بت و 64 بت enviroment.first انظر إلى النظام الذي لديك
Type TTypWin32Or64 = (Bit32,Bit64);
var TypWin32Or64 :TTypWin32Or64;
Procedure TypeOS(var TypWin32Or64:TTypWin32Or64 ) ;
if DirectoryExists('c:\Windows\SysWOW64')
then TypWin32Or64:=Bit64
else TypWin32Or64:=Bit32;
Procedure for looking Key or Create it in a Registry
procedure TForm1.ReadKeyFromRegister(TypWin32Or64:TTypWin32Or64;
TypeKey:Longword; {at once symbol HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER}
PathToKey:string;
TypeValueRead :Integer; //at once symbols as REG_SZ -- string key ,
//REG_DWORD A DWORD value, a 32-bit unsigned integer
NameValueToRead:string;
var ValueStrReaded:Ansistring; //is used if it is key string
var ValueByteReaded:Pchar; //is used if it is key Byte
ReadOnly:boolean);
var
Reg : TRegistry;
S_TStr : TStrings;
VersBios : string;
Pos0 : integer;
Key : HKEY;
Value : Array of Byte;
nValueLen : Integer;
const KEY_WOW64_64KEY = $0100 ;
begin
case TypWin32Or64 of
Bit32: Reg := TRegistry.Create;
Bit64:Reg := TRegistry.Create(KEY_WRITE OR KEY_WOW64_64KEY);
//use if if 64 bit enviroment Windows
end;
try
{ open key }
Reg.RootKey := TypeKey;
if ReadOnly
then Reg.OpenKeyReadOnly(PathToKey)
//not all key can be created or writed ie. ProductId(Serial Key)
// name Windows - especially in a 64 bit Windows XP , Win 7
else Reg.OpenKey(PathToKey, false);
//CreateKey=True--> if this key is not present will be created
case TypeValueRead of
REG_SZ: ValueStrReaded:=Reg.ReadString(NameValueToRead);
REG_BINARY : begin
nValueLen := Reg.GetDataSize(NameValueToRead);
ValueByteReaded:=Pchar(Reg.ReadBinaryData(NameValueToRead, PByte(Value), nValueLen));
end;
REG_DWORD : begin
end;
REG_MULTI_SZ: begin
S_TStr := ReadMultirowKey(Reg,NameValueToRead);
/in a enviroment 64 bit not good work - better use
//procedure ReadREG_MULTI_SZ
VersBios:=S_TStr.Text;
Pos0:=Pos(#0,VersBios);
if Pos0 > 0 then
begin
delete(VersBios,Pos0,1);
insert(' ', VersBios,Pos0);
end;
VersBios := StringReplace(VersBios,#$D#$A, ' ' , [rfReplaceAll, rfIgnoreCase]);
ValueStrReaded:=VersBios;
end;
end; //case
Reg.CloseKey;
finally
Reg.Free;
end;
end;
{------------}
Sample for reading system Key from Registry
Reading UsedWindowsVersion_Full
ReadKeyFromRegister(TypWin32Or64, {TypWin32Or64}
HKEY_LOCAL_MACHINE, {TypeKey:Longword;}
'SOFTWARE\Microsoft\Windows NT\CurrentVersion', {PathToKey:string;}
REG_SZ, {TypeValueRead :Integer; }
'BuildLabEx', {NameValueToRead:string;}
UsedWindowsVersion_Full, {ValueStrReaded:Ansistring;}
sPchar ,{ValueByteReaded:Pchar}
True {ReadOnly});
{-----------------------}
For read ProductId(also called Product Key Windows)
ReadKeyFromRegister( TypWin32Or64,
HKEY_LOCAL_MACHINE, {TypeKey:Longword;}
'SOFTWARE\Microsoft\Windows NT\CurrentVersion', {PathToKey:string;}
REG_SZ, {TypeValueRead :Integer; }
'ProductId', {NameValueToRead:string;}
SerialKey, {ValueStrReaded:Ansistring;}
sPchar, {ValueByteReaded:Pchar}
True {ReadOnly});
{------------------------}
For reading Product Name
ReadKeyFromRegister(TypWin32Or64,
HKEY_LOCAL_MACHINE, {TypeKey:Longword;}
'SOFTWARE\Microsoft\Windows NT\CurrentVersion', {PathToKey:string;}
REG_SZ, {TypeValueRead :Integer; }
'ProductName', {NameValueToRead:string;}
UsedWindowsName, {ValueStrReaded:Ansistring;}
sPchar ,{ValueByteReaded:Pchar}
True {ReadOnly});
{-----------------------}
Procedure for look miltiline key as i.e Version Bios - also 64 envir.
procedure TForm1.ReadREG_MULTI_SZ(const CurrentKey: HKey; const
Subkey, ValueName: string;
Strings: TStrings; var ValueStrRead: String);
var
valueType: DWORD;
valueLen: DWORD;
p, buffer: PChar;
key: HKEY;
begin
Strings.Clear;
// open the specified key
if RegOpenKeyEx(CurrentKey,
PChar(Subkey),
0, KEY_READ, key) = ERROR_SUCCESS then
begin
// retrieve the type and data for a specified value name
SetLastError(RegQueryValueEx(key,
PChar(ValueName),
nil,
@valueType,
nil,
@valueLen));
if GetLastError = ERROR_SUCCESS then
if valueType = REG_MULTI_SZ then
begin
GetMem(buffer, valueLen);
try
// receive the value's data (in an array).
RegQueryValueEx(key,
PChar(ValueName),
nil,
nil,
PBYTE(buffer),
@valueLen);
// Add values to stringlist
p := buffer;
while p^ <> #0 do
begin
Strings.Add(p);
Inc(p, lstrlen(p) + 1)
end
finally
ValueStrRead:=Strings.Text;
ValueStrRead:=StringReplace(ValueStrRead,#$D#$A, ' ' , [rfReplaceAll, rfIgnoreCase]);
FreeMem(buffer);
end
end
else
raise ERegistryException.Create('Stringlist expected')
else
raise ERegistryException.Create('Cannot Read MULTI_SZ Value/');
end;
end;
{-----------}
أود أن أقول أن هذا ناتج عن UAC - حاول البدء كمسؤول!
إذا كان يعمل عند بدء تشغيله كمسؤول ، فأنت بحاجة إلى تغيير طلب القراءة الخاص بك لاستخدام وضع القراءة فقط (وليس في مكتب MO ، لذا لا يمكنك تذكر كيفية القيام بذلك بالضبط)
تعديل:
function GetWindowsID: string;
var
Registry: TRegistry;
str:string;
begin
Registry := TRegistry.Create(KEY_READ);
try
Registry.RootKey := HKEY_LOCAL_MACHINE;
// Registry.RootKey := HKEY_CURRENT_USER;
if CheckForWinNT = true then
Begin
if not Registry.OpenKeyReadOnly('\Software\Microsoft\Windows NT\CurrentVersion') then showmessage('cant open');
end else
Registry.OpenKeyReadOnly('\Software\Microsoft\Windows\CurrentVersion');
str := Registry.ReadString('ProductId');
result:=str;
Registry.CloseKey;
finally
Registry.Free;
end; // try..finally
end;
يجب عليك استخدام هذا:TRegistry.Create(KEY_ENUMERATE_SUB_KEYS);
لن يمنع Windows Seven UAC تنفيذ هذا
حاول قراءتها يدويًا باستخدام Regedit. قد تحصل على "Access Enving" بسبب مشكلة الإذن ، وفي هذه الحالة ، انظر إلى مستواك وكيفية الوصول إليه.
أعتقد أن ذلك بسبب
str := Registry.ReadString('ProductId');
لا يثير استثناء عندما لا يكون هناك ProductId
. في رأيي الصادق ، هذا خطأ في دلفي.