7

我正在使用 Inno Setup 构建安装程序,并希望以管理员身份运行提取的文件。有没有办法强制提取的文件(即批处理文件)以管理员身份运行?如果是这样,我需要包含哪些代码元素来执行此操作。

安装日志显示如下内容:

2013-05-07 17:34:25.303   -- Run entry --
2013-05-07 17:34:25.303   Run as: Current user
2013-05-07 17:34:25.303   Type: Exec
2013-05-07 17:34:25.303   Filename: C:\Temp\is-U4VID.tmp\Filename.bat
2013-05-07 17:34:25.412   Process exit code: 0

我在以管理员用户身份运行时遇到问题的文件包含在该[Run]部分中。

4

2 回答 2

13

如果您正在使用[Run]部分,请确保使用runascurrentuser标志(如果指定了此标志,则生成的进程将继承安装程序/卸载的用户凭据(通常为完全管理权限))

否则,可以通过三种方式以编程方式运行应用程序(推荐方式):

function Exec(const Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ResultCode: Integer): Boolean;

function ShellExec(const Verb, Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ErrorCode: Integer): Boolean;

function ShellExecAsOriginalUser(const Verb, Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ErrorCode: Integer): Boolean;

您应该使用Exec()orShellExec()因为它们打开指定的文件或执行 Verb 指定的其他操作,使用与安装/卸载相同的凭据。

但是,如果您的安装程序未在提升模式下运行,则上述方法均无效。因此,请确保在安装程序启动之前会出现 UAC 窗口:

在部分[Setup]使用指令PrivilegesRequired

有效值:

none, poweruser, admin, 或lowest

使用管理员来确保适当的凭据。

于 2013-05-08T06:13:27.827 回答
2

但是,如果您需要在 postUninstall 时刻运行批处理文件怎么办?在这种情况下,要恢复由应用程序更改的数据库文件的备份?

花了几个小时尝试一切,直到我发现这个黑客。

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var 
  ResultCode: Integer;
  outfile: String;
  runBatHeader: String;
  runBatBody: String;

begin

  if CurUninstallStep = usPostUninstall then
  begin
    (*
        This is a messy hack, but the only way I could find to run a bat file
        during the post unistall section. In this case all files copied are 
        already removed, and it was not permitted to extract temp files in
        the uninstall phase. Code here writes 'outfile' to a system folder then runs it. 
    *)
    if DirExists('C:\ProgramData\MySQL\MySQL Server 5.7_bak') then begin
      if MsgBox('Uninstall located a possible backup of your original MySQL tables. ' +
        'Uninstall can attempt to copy it to the previous location. There is no ' +
        'guarantee that it will succeed. Do you want to try restoring this folder?', mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES then
      begin 

        outFile := 'C:\ProgramData\MySQL\restore.bat';
        runBatHeader := '@echo off' + #13#10 + #13#10;
        runBatBody := 'ECHO Attempt to stop MySQL57' + #13#10 + 
              'NET STOP MySQL57' + #13#10 + 
              'ECHO Removing application databases' + #13#10 + 
              'RMDIR /S /Q "C:\ProgramData\MySQL\MySQL Server 5.7\"' +  #13#10 + 
              'ECHO Copying backup to original location' + #13#10 + 
              'XCOPY "C:\ProgramData\MySQL\MySQL Server 5.7_bak" "C:\ProgramData\MySQL\MySQL Server 5.7\"  /C /E /H /I /K /O /Q /R /Y' +  #13#10 +   #13#10 + 
              'ECHO Try to start MySQL57' + #13#10 + 
              'NET START MySQL57';';
        SaveStringToFile(outFile, runBatHeader, False); 
        SaveStringToFile(outFile, runBatBody, True); 

        MsgBox('ShelExec : C:\ProgramData\MySQL\restore.bat', mbConfirmation, MB_OK);
        if not ShellExec('', 'C:\ProgramData\MySQL\restore.bat', '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
        begin
          // handle failure if necessary
          MsgBox('Apparently, the administrative privilege was not operational. Exiting without restoring the backup. ('+ IntToStr(ResultCode) +')', mbConfirmation, MB_OK);
        end;
        DeleteFile(outfile);

      end;
    end;
  end;
end;

但这不是我的主意。我在这里找到了一个例子

于 2015-12-15T17:06:14.290 回答