learnAndImprove
learnAndImprove

Reputation: 1359

How to set 'Run as administrator' on a file using Inno Setup

I'm creating an installer using Inno Setup. As part of the install process I'm installing Tomcat. On Windows 7 I suffer from the problem described here:

http://blog.paulbouwer.com/2010/10/23/the-case-of-the-annoying-tomcat-6-monitor/

I can fix it by manually setting the 'Run as administrator' on tomcat7w.exe (the issue and the root cause is the same for tomcat7 as well), but I don't know how to do it through Inno Setup.

I'm finding threads that explain running some_program.exe as administrator, but here the program is started when the Tomcat service starts (e.g. on machine start-up), so I need a way to flag it using Inno Setup to 'Run as administrator' rather than actually run it.

Upvotes: 15

Views: 39225

Answers (6)

Martin Prikryl
Martin Prikryl

Reputation: 202088

If you really want to set the "Run as administrator" flag of the shortcut (as opposite to forcing the target application run with administrator privileges), you can use this code:

[Icons]
Name: "{userdesktop}\My Program"; Filename: "{app}\MyProg.exe"; \
  AfterInstall: SetElevationBit('{userdesktop}\My Program.lnk')
[Code]

procedure SetElevationBit(Filename: string);
var
  Buffer: string;
  Stream: TStream;
begin
  Filename := ExpandConstant(Filename);
  Log('Setting elevation bit for ' + Filename);

  Stream := TFileStream.Create(FileName, fmOpenReadWrite);
  try
    Stream.Seek(21, soFromBeginning);
    SetLength(Buffer, 1);
    Stream.ReadBuffer(Buffer, 1);
    Buffer[1] := Chr(Ord(Buffer[1]) or $20);
    Stream.Seek(-1, soFromCurrent);
    Stream.WriteBuffer(Buffer, 1);
  finally
    Stream.Free;
  end;
end;

This is based on:


Tested on Unicode version of Inno Setup. But it should, even more naturally, work on Ansi version too, though you should use Unicode version anyway.

The TStream.Seek was broken in Inno Setup 6.3. The bug was fixed in 6.3.2.


If you want to allow user to execute the program at the end of the installation using a postinstall entry in [Run] section, you will of course need to explicitly request the elevation.

If the installer runs with Administrator privileges, you can simply add runascurrentuser flag:

[Run]
Filename: "{app}\MyProg.exe"; Description: "Launch application"; \
    Flags: postinstall nowait skipifsilent runascurrentuser 

If the installer runs without Administrator privileges, set Verb parameter to runas (for that you also need shellexec flag):

[Run]
Filename: "{app}\MyProg.exe"; Verb: runas; Description: "Launch application"; \
    Flags: postinstall nowait skipifsilent shellexec

Though, make sure you have a very good reason to run your application with Administrator privileges. User applications should not need Administrator privileges. If they need it, it's usually a sign of a bad design. One common (bad) reason to want an application to run with Administrator privileges, is that the application needs to write to its installation folder.

See Application does not work when installed with Inno Setup

Upvotes: 16

Miral
Miral

Reputation: 13020

If you need Tomcat to be run on startup as an administrator, it should be run as a Windows Service.

You will need to look through the Tomcat docs to determine if it supports this directly or if you will need to write a small wrapper service that takes care of launching Tomcat. (Or you can use an existing service wrapper, such as winsw. This is not an endorsement; I haven't used that myself.)

It is never the correct choice for a software installer to set the admin shortcut flag. That setting exists for users, not for developers; if you think you need to set it, what that actually means is that you have a bug to fix.

Upvotes: -1

Bill_Stewart
Bill_Stewart

Reputation: 24515

Please read Raymond Chen's blog posting: How do I mark a shortcut file as requiring elevation?

Excerpt:

Specifying whether elevation is required is typically something that is the responsibility of the program. This is done by adding a requestedExecutionLevel element to your manifest. ... But if the program you're running doesn't have such a manifest--maybe it's an old program that you don't have any control over--you can create a shortcut to the program and mark the shortcut as requiring elevation.

He provides code for a quick-and-dirty little program that does the work, but then notes at the bottom of the post:

(I fear that most people will read this article and say, "Awesome! My program requires elevation, and this is how I can mark my Start menu shortcut to prompt for elevation. Thanks, Raymond!" These people will have completely ignored the opening paragraph, which explains that that is the wrong thing to do.)

In other words: The recommended practice is to add a manifest to the executable so you don't have to create a shortcut requesting elevation in the first place.

With that said, however, there are cases (such as an old program, as Raymond noted up front) where this is needed. I think the appropriate approach is to use the correct binary interface to update the shortcut's flags rather than directly modifying bits in the file. To meet this need, I wrote an open-source command line tool that does it:

https://github.com/Bill-Stewart/scrunas

I make this tool available for those cases where you can't add a manifest for whatever reason and really do need to mark a shortcut as requesting elevation.

But: If you are able to add a manifest to your program, you should do that instead.

Upvotes: 3

Jaroslav Cap
Jaroslav Cap

Reputation: 1

Unfortunately, approach mentioned by @Martin Prikryl does not work in Inno Setup 6.3, as the procedure SetElevationBit encounters an AccessViolation error. The issue is that there is a bug in the TStream.Seek method in this version of Inno Setup.

Fortunately, the call to the Seek method can be replaced by using the Position property, which allows us to work around the issue until it is fixed in Inno Setup (the issue was reported here https://groups.google.com/u/1/g/innosetup/c/F0Umj7hKO_U).

The working version of the SetElevationBit method looks like this:

procedure SetElevationBit(AFilename: String);
var
  LBuffer: AnsiString;
  LStream: TStream;
begin
  AFilename := ExpandConstant(AFilename);
  Log('Setting elevation bit for ' + AFilename);

  LStream := TFileStream.Create(AFileName, fmOpenReadWrite);
  try
    LStream.Position:= 21;
    SetLength(LBuffer, 1);
    LStream.ReadBuffer(LBuffer, 1);
    LBuffer[1]:= Chr(Ord(LBuffer[1]) or $20);
    LStream.Position:= LStream.Position -1;     
    LStream.WriteBuffer(LBuffer, 1);
  finally
    LStream.Free;
  end;
end;

Upvotes: 0

Mehdi Benkirane
Mehdi Benkirane

Reputation: 445

Add the runascurrentuser flag attribute to the [Run] section

Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: runascurrentuser nowait postinstall skipifsilent; 

Upvotes: 5

RobeN
RobeN

Reputation: 5456

You can add a Registry entry in [Registry] Section that will set run as Administrator as a default action for running this app.

Example:

Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"; \
    ValueType: String; ValueName: "{app}\tomcat7w.exe"; ValueData: "RUNASADMIN"; \
    Flags: uninsdeletekeyifempty uninsdeletevalue; MinVersion: 0,6.1

Upvotes: 20

Related Questions