Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

windows - Inno Setup - Access unprivileged account folders from installer that requires privileges

I'm using Inno Setup to install documents/files rather than an application, and this is primarily for Windows 7 users. As such my DestDir is based on {userdocs} so that all files will be installed in a folder below that user's Documents library.

The problem arises when I use the same installer to install a TTF font. This requires elevated privileges (admin or superuser). The problem I'm seeing is that if a non-admin user runs the install, they are correctly prompted via UAC for the admin/superuser password...but at that point the DestDir for the installation changes to the Admin documents folder rather than the user's documents folder. Is there any way to work around this or prevent this from happening?

Example, non-Admin account Fre has a documents path of:

C:UsersFredMy Documents

And if I do not include the TTF font as part of the installation, this is what the installer will use as the base path for the installation {userdocs} and it works perfectly.

If I DO include the TTF font as part of the installation with same non-Admin user Fred, by the time the install is done {userdocs} has become

C:UsersAdminUserMy Documents 

...which is not the intended result...just need Admin privileges for the font installation piece and need the files installed into the actual user's documents area.

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Create a child installer for the fonts, with the PrivilegesRequired=admin directive, that you will run from within the master non-elevated installer.

Master installer code will be like:

[Setup]
PrivilegesRequired=lowest

[Files]
Source: "ttfsetup.exe"; DestDir: {tmp}; Flags: deleteafterinstall

[Run]
Filename: "{tmp}tfsetup.exe"; Parameters: /silent; StatusMsg: "Installing TTF fonts..."

And of course, you should uninstall the child installer from the master uninstaller.

You may also want to make sure, the user did not run the master installer with administrator privileges explicitly. See my answer to How to write to the user's My Documents directory with installer when the user used 'Run As Administrator'.

Another way to implement this is to use ShellExec function with runas verb to execute an elevated external copy utility (copy, xcopy, robocopy). See Inno Setup - Register components as an administrator (it runs regsvr32, but the concept is the same).


Another option is to execute a non-elevated process, from the elevated installer, only to resolve the path to the original user documents folder.

Use the ExecAsOriginalUser function.

You have to exchange the path between the installers via some temporary file that is accessible to both accounts. E.g. a file in {commondocs}, as can be seen in the Inno Setup always installs into admin's AppData directory.

[Files]
Source: "*.txt"; DestDir: "{code:GetUserDocumentsFolder}"

[Code]

var
  UserDocumentsFolder: string;

function GetUserDocumentsFolder(Params: string): string;
begin
  Result := UserDocumentsFolder;
end;

function InitializeSetup(): Boolean;
var
  TempFile: string;
  Code: string;
  Buf: TArrayOfString;
  ResultCode: Integer;
begin
  Result := True;

  TempFile := { some path accessible by both users };
  Code :=
    '[Environment]::GetFolderPath(''MyDocuments'') | ' +
    'Out-File "' + TempFile + '" -Encoding UTF8';
  Log(Format('Executing: %s', [Code]));
  if (not ExecAsOriginalUser('powershell.exe', Code, '', SW_HIDE,
                             ewWaitUntilTerminated, ResultCode)) or
     (ResultCode <> 0) or
     (not LoadStringsFromFile(TempFile, Buf)) then
  begin
    MsgBox('Failed to resolve user MyDocuments path', mbError, MB_OK);
    Result := False;
  end
    else
  begin
    UserDocumentsFolder := Buf[0];
    Log(Format('User Documents path resolved to "%s"', [UserDocumentsFolder]));
  end;
end;

Related discussions:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...