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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With