【问题标题】:Inno Setup - Access unprivileged account folders from installer that requires privilegesInno Setup - 从需要权限的安装程序访问非特权帐户文件夹
【发布时间】:2017-02-15 17:51:39
【问题描述】:

我使用 Inno Setup 来安装文档/文件而不是应用程序,这主要是为 Windows 7 用户准备的。因此,我的DestDir 基于{userdocs},因此所有文件都将安装在该用户的文档库下方的文件夹中。

当我使用相同的安装程序安装 TTF 字体时出现问题。这需要提升权限(adminsuperuser)。我看到的问题是,如果非管理员用户运行安装,则会通过 UAC 正确提示他们输入管理员/超级用户密码...但此时 DestDir 用于安装更改为管理员文档文件夹而不是用户的文档文件夹。有什么办法可以解决这个问题或防止这种情况发生吗?

例如,非管理员帐户 Fre 的文档路径为:

C:\Users\Fred\My Documents\

如果我不将 TTF 字体作为安装的一部分,安装程序将使用它作为安装的基本路径{userdocs},它可以完美运行。

如果我在安装过程中使用相同的非管理员用户 Fred 包含 TTF 字体,那么在安装完成时 {userdocs} 已变为

C:\Users\AdminUser\My Documents\ 

...这不是预期的结果...只需要字体安装块的管理员权限,并且需要将文件安装到实际用户的文档区域中。

谢谢。

【问题讨论】:

    标签: windows installation inno-setup elevated-privileges


    【解决方案1】:

    使用PrivilegesRequired=admin directive 为字体创建一个子安装程序,您将在主非提升安装程序中运行该安装程序。

    主安装程序代码如下:

    [Setup]
    PrivilegesRequired=lowest
    
    [Files]
    Source: "ttfsetup.exe"; DestDir: {tmp}; Flags: deleteafterinstall
    
    [Run]
    Filename: "{tmp}\ttfsetup.exe"; Parameters: /silent; StatusMsg: "Installing TTF fonts..."
    

    当然,您应该从主卸载程序中卸载子安装程序。

    您可能还想确保用户没有明确地以管理员权限运行主安装程序。请参阅我对How to write to the user's My Documents directory with installer when the user used 'Run As Administrator' 的回复。

    实现此目的的另一种方法是使用ShellExec functionrunas 动词来执行提升的外部复制实用程序(copyxcopyrobocopy)。见Inno Setup - Register components as an administrator(它运行regsvr32,但概念是一样的)。


    另一种选择是从提升的安装程序执行非提升的进程,仅解析原始用户文档文件夹的路径。

    使用ExecAsOriginalUser function

    您必须通过两个帐户都可以访问的一些临时文件来交换安装程序之间的路径。例如。 {commondocs} 中的一个文件,可以在 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;
    

    相关讨论:

    【讨论】:

    • 第一个选项非常适合我的情况。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2014-02-28
    • 1970-01-01
    • 2015-05-21
    • 2019-06-06
    • 1970-01-01
    • 2010-12-10
    • 2020-06-11
    • 1970-01-01
    相关资源
    最近更新 更多