我正在开发在 64 位 Windows 11 上运行的 Delphi 12 应用程序。我的应用程序需要从注册表中读取路径(用户路径和系统路径),并且我的应用程序可以读取用户路径,但不能读取系统路径。
我使用“工具”->“选项”->“清单”要求管理员权限才能执行该程序,当我运行该应用程序时,它会提示我授权管理员模式,所以我知道它的一部分正在工作。
我已经在互联网上搜索了好几天寻找解决方案,并且尝试了我能找到的所有选项(Embarcadero 的网站本周关闭,这使得所有这一切变得更加困难,因为我在那里找到了许多文章参考文档)并且每个此时,代码成功打开指定的键 (
SYSTEM\CurrentControlSet\Control\Session Manager\Environment
),但无法读取其中的任何属性(如 path
属性)。
我什至尝试使用该键下的所有属性填充
TStringList
我创建了一个示例应用程序来演示这一点,您可以在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;
经过一番尝试,我添加了以下代码:
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));
它不显示键、子键或值:
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
Ii 我再上一层(
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
即使此时注册表有 10 个或更多键和值。
有人可以帮我理解我在这里做错了什么吗?我从 80 年代中期开始就是一名 TurboPascal 开发人员,从 1.0 版本开始我就是一名 Delphi 开发人员。我通常可以找到摆脱此类情况的出路,但此时我遇到了困难。 Windows 中的某些内容阻止了对这些值的访问。
问题就在这里:
with Reg do begin
rootKey := rootKey; // <-- HERE
您没有更新
Reg.RootKey
属性,正如您所期望的那样。实际上,您是将 rootKey
变量 分配回自身。因此, Reg.RootKey
属性保持其默认值 HKEY_CURRENT_USER
,这就是打开 Environment
的 HKEY_LOCAL_MACHINE
键失败的原因。
这是为什么你不应该使用
with
语句的经典论点!