运行具有管理员访问权限的程序写入注册表

时间:2014-04-02 17:50:27

标签: delphi

我尝试使用本教程来工作: https://stackoverflow.com/a/14710803/1149172

首先使用提供的内容创建名称为uac.manifest的文件 然后创建uac.rc

1 24 "uac.manifest"宽度内容

然后将文件复制到程序文件夹(在delphi程序源文件夹中)并更改项目文件,如下所示:

program Project4;

{.$R 'uac.res' 'uac.rc'} // UAC only

uses
  Vcl.Forms,
  Unit6 in 'Unit6.pas' {Form6};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm6, Form6);
  Application.Run;
end.

最后我将我的注册码放在表格

procedure AddEntryToRegistry;
var key: string;
     Reg: TRegIniFile;
begin
  key := 'Software\Microsoft\Windows\CurrentVersion\Run';
  Reg := TRegIniFile.Create;
  try
    Reg.RootKey:=HKEY_LOCAL_MACHINE;
    Reg.CreateKey(Key);
    if Reg.OpenKey(Key,False) then Reg.WriteString(key, 'MyApp', 'c:MyApp.exe');
  finally
    Reg.Free;
  end;
end;

每件事似乎都没问题,我没有任何运行时错误 但点击按钮后没有任何事情发生(不要鞋子任何错误,不要添加钥匙到注册)! 我的作品出了问题!?

我的delphi是xe5并且在win 8ul上工作

2 个答案:

答案 0 :(得分:2)

首先,我打算将其视为您的程序正在升级运行。如果没有发生,那么就不需要查看任何代码了。你没有另外说,所以让我们在你成功提升的假设下继续前进。

你正在患registry redirector。您的32位进程在64位计算机上运行。因此HKLM\Software被重定向到32位视图,存储在HKLM\Software\Wow6432Node

如果需要,您可以使用KEY_WOW64_64KEY标志访问64位视图。将其与注册表对象的Access属性中的标志相结合。

但是,在枚举启动程序时,系统会从注册表的32位和64位视图中读取密钥,因此您无需执行此操作。为了简单和可预测性,我将把32位程序写入32位视图。

您应该删除对CreateKey的来电。系统会创建该密钥,您可以放心地认为它存在。你不应该使用TRegIniFile。请改用TRegistry

您的代码应如下所示:

procedure AddEntryToRegistry;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_ALL_ACCESS);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', False) then
      Reg.WriteString('MyApp', 'C:\MyApp.exe');
  finally
    Reg.Free;
  end;
end;

如果您觉得需要写入64位视图,那么就像这样完成:

procedure AddEntryToRegistry;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    Reg.Access := KEY_ALL_ACCESS or KEY_WOW64_64KEY;
    if Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', False) then
      Reg.WriteString('MyApp', 'C:\MyApp.exe');
  finally
    Reg.Free;
  end;
end;

根据您的评论判断,看起来您可能无法提升。程序启动时缺少UAC对话框是发生这种情况的迹象。一旦你的程序在没有UAC对话框的情况下启动,那就没有意义了。如果没有提升,你不会写信给HKLM。

关于您的清单,您只能链接一个。因此,如果要指定IDE可以提供的启用运行时主题清单以外的清单,则需要自己完成所有操作。

在项目选项中指定您要使用自定义清单。那是Project | Options | Application | Runtime themes下的。将下拉列表设置为使用自定义清单。然后提供清单的文件名。您将要添加comctl32 v6部分以确保获得运行时主题。但现在不要担心。只需集中精力进行高程排序,并使注册表代码正常工作。

你也默默地忽略任何使事情变得更难调试的错误。如果碰巧你没有提升,那么运行代码是没有意义的。你知道它必须失败。但是,如果OpenKey失败,您至少可以通过抛出错误来更轻松地诊断问题。

procedure AddEntryToRegistry;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_ALL_ACCESS);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if not Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', False) then
      raise EMyExceptionClass.Create('Could not open registry key');
    Reg.WriteString('MyApp', 'C:\MyApp.exe');
  finally
    Reg.Free;
  end;
end;

最后要说的是,写入此注册表项是一项管理任务。您应该只需要提升一次,而不是每次应用程序启动时。如果您计划仅为此目的要求应用程序的高程,那么您必须重新设计。此管理任务应在主应用程序之外执行。最自然的地方是您的安装程序,用户将接受要求提升。

答案 1 :(得分:2)

您正在将应用路径保存到Run配置单元的HKEY_LOCAL_MACHINE键。您应该使用HKEY_CURRENT_USER配置单元,然后您将不再需要使用UAC提升(除非您的应用正在执行需要管理员权限的其他事项)。