John
John

Reputation: 25333

Inno Setup Run Extracted Batch File As Administrator

I am building an installer with Inno Setup and would like for the extracted files to be run as an administrator. Is there a way to force the extracted files (i.e. batch file) to run as an administrator? If so, what code elements do I need to include to perform this.

The setup log shows something like the following:

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

The files that I am having problems with running as an admin user are included in the [Run] section.

Upvotes: 7

Views: 14205

Answers (2)

ndasusers
ndasusers

Reputation: 747

But what if you need to run a batch file in the postUninstall moment? In this case to restore a backup of database files that were altered by the application?

It tooks some hours trying everything until I found this hack.

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;

It was not my idea though. I found an example here.

Upvotes: 2

Slappy
Slappy

Reputation: 5472

If you are using [Run] section then make sure you use runascurrentuser flag (If this flag is specified, the spawned process will inherit Setup/Uninstall's user credentials (typically, full administrative privileges))

Else there are three ways how to run applications programatically (recommended way):

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;

You should use Exec() or ShellExec() because they open the specified file or performs another action specified by Verb, using the same credentials as Setup/Uninstall.

But none of mentioned ways will work if your installer is not running in elevated mode. So make sure the UAC window will appear before installer starts:

In section [Setup] use directive PrivilegesRequired

Valid values:

none, poweruser, admin, or lowest

Use admin to ensure appropriate credentials.

Upvotes: 13

Related Questions