joh*_*rgo -1 windows delphi registry path
我正在开发在 64 位 Windows 11 上运行的 Delphi 12 应用程序。我的应用程序需要从注册表中读取路径(用户路径和系统路径),并且我的应用程序可以读取用户路径,但不能读取系统路径。
我使用“工具”->“选项”->“清单”要求管理员权限才能执行该程序,当我运行该应用程序时,它会提示我授权管理员模式,所以我知道它的一部分正在工作。
我已经在互联网上搜索了好几天寻找解决方案,并且尝试了我能找到的所有选项(Embarcadero 的网站本周关闭,这使得所有这一切变得更加困难,因为我在那里找到了许多文章参考文档)并且每次,代码成功打开指定的键 ( SYSTEM\CurrentControlSet\Control\Session Manager\Environment),但无法读取其中的任何属性(如path属性)。
我什至尝试TStringList使用该键下的所有属性填充 a
我创建了一个示例应用程序来演示这一点,您可以在https://github.com/johnwargo/Path-Test-2024找到它。
procedure PopulateList(pathList: TListBox; source: String; rootKey: HKEY;
regKey, regProperty: String);
var
Reg: TRegistry;
pathArray: Tarray<String>;
msg, pathStr: String;
begin
LogMessage(Format('Reading "%s" Path from "%s"', [source, regKey]));
// Reg := TRegistry.Create(KEY_ALL_ACCESS);
// Reg := TRegistry.Create(KEY_ALL_ACCESS OR KEY_WOW64_64KEY);
// Reg := TRegistry.Create(KEY_EXECUTE);
// Reg := TRegistry.Create(KEY_EXECUTE OR KEY_WOW64_64KEY);
// Reg := TRegistry.Create(KEY_READ OR KEY_WOW64_32KEY);
Reg := TRegistry.Create(KEY_READ OR KEY_WOW64_64KEY);
// Reg := TRegistry.Create(KEY_WRITE OR KEY_WOW64_32KEY);
// https://stackoverflow.com/questions/2666807/registry-readstring-method-is-not-working-in-windows-7-in-delphi-7
// Reg := TRegistry.Create(KEY_ENUMERATE_SUB_KEYS);
with Reg do begin
rootKey := rootKey;
Access := KEY_READ;
LogMessage(Format('Opening key: %s', [regKey]));
if Reg.KeyExists(regKey) then begin
if OpenKeyReadOnly(regKey) then begin
LogMessage('Key opened');
if ValueExists(regProperty) then begin
LogMessage(Format('Reading property %s', [regProperty]));
pathStr := Readstring(regProperty);
if Length(pathStr) > 0 then begin
LogMessage('Path: ' + pathStr);
pathArray := pathStr.Split([';'], TStringSplitOptions.ExcludeEmpty);
pathList.Items.AddStrings(pathArray);
end;
end else begin
msg := Format('%s Path property "%s" does not exist.',
[source, regProperty]);
LogMessage(msg);
ShowMessage(msg);
end;
CloseKey;
end else begin
msg := Format('Getting %s Path and cannot open open: %s',
[source, regKey]);
LogMessage(msg);
ShowMessage(msg);
end;
end;
end;
end;
procedure TfrmMain.FormActivate(Sender: TObject);
begin
PopulateList(UserPathList, 'User', HKEY_CURRENT_USER, 'Environment',
pathProperty);
PopulateList(SystemPathList, 'System', HKEY_LOCAL_MACHINE,
'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
pathProperty);
end;
Run Code Online (Sandbox Code Playgroud)
经过一番尝试,我添加了以下代码:
KeyInfo: TRegKeyInfo;
Reg.GetKeyInfo(KeyInfo);
LogMessage('Number of Keys: ' + IntToStr(KeyInfo.NumSubKeys));
LogMessage('Number of Subkeys: ' + IntToStr(KeyInfo.NumSubKeys));
LogMessage('Number of Values: ' + IntToStr(KeyInfo.NumValues));
Run Code Online (Sandbox Code Playgroud)
它不显示任何键、子键或值:
1/19/2024 5:25:52 PM Number of Keys: 0
1/19/2024 5:25:52 PM Number of Subkeys: 0
1/19/2024 5:25:52 PM Number of Values: 0
Run Code Online (Sandbox Code Playgroud)
我转到更高一层 ( SYSTEM\CurrentControlSet\Control\Session Manager\),得到以下结果:
1/19/2024 5:25:52 PM Number of Keys: 1
1/19/2024 5:25:52 PM Number of Subkeys: 1
1/19/2024 5:25:52 PM Number of Values: 0
Run Code Online (Sandbox Code Playgroud)
即使此时注册表有 10 个或更多键和值。
有人可以帮我理解我在这里做错了什么吗?我从 80 年代中期开始就是一名 TurboPascal 开发人员,从 1.0 版本开始我就是一名 Delphi 开发人员。我通常可以找到摆脱此类情况的出路,但此时我遇到了困难。Windows 中有些东西阻止了对这些值的访问。
问题出在这一行:
with Reg do begin
rootKey := rootKey; // <-- HER
...
end;
Run Code Online (Sandbox Code Playgroud)
您没有像您期望的那样将函数的rootkey参数分配给Reg.RootKey属性。您实际上是将Reg.rootKey属性分配回自身,完全忽略函数的rootKey参数。因此,该Reg.RootKey属性最终保持其默认值HKEY_CURRENT_USER,这就是打开Environment密钥HKEY_LOCAL_MACHINE失败的原因。
正确地将函数的rootKey参数分配给Reg.RootKey属性将解决问题(而且,您不需要管理员权限即可访问系统Environment密钥)。
这是一个典型的场景,说明了为什么使用with语句是危险的!
因此,要么将函数的rootKey参数重命名为更独特的名称,要么停止使用with.