简体   繁体   English

Inno Setup 始终安装到管理员的 AppData 目录中

[英]Inno Setup always installs into admin's AppData directory

I want to store my app in the current user's AppData directory to avoid problems with permissions we had when auto-updating our app (when it's stored in Program Files).我想将我的应用程序存储在当前用户的AppData目录中,以避免在自动更新我们的应用程序时(当它存储在程序文件中时)出现权限问题。 We don't give the user the option of where to install the app.我们不会让用户选择安装应用程序的位置。 We've had complaints from non-admin users that the installer stores the app in the admin's AppData directory (after UAC of course), instead of the current user's AppData directory, which then prevents the app from running in the future.我们收到来自非管理员用户的投诉,称安装程序将应用程序存储在管理员的AppData目录中(当然在 UAC 之后),而不是当前用户的AppData目录,这会阻止应用程序在未来运行。

Firstly, I had DefaultDirName={userappdata}\\{#MyAppName} .首先,我有DefaultDirName={userappdata}\\{#MyAppName} Then I tried DefaultDirName={commonappdata}\\{#MyAppName} .然后我尝试了DefaultDirName={commonappdata}\\{#MyAppName} Then I tried that along with PrivilegesRequired=lowest and even as PrivilegesRequired=none as the Make InnoSetup installer request privileges elevation only when needed question suggested.然后,我尝试将其与PrivilegesRequired=lowest一起尝试,甚至将PrivilegesRequired=none作为Make InnoSetup 安装程序请求权限提升,仅在需要的问题建议时使用。

This is my script as of right now in case I'm missing something obvious:这是我现在的脚本,以防我遗漏了一些明显的东西:

; Script generated by the Inno Setup Script Wizard.
;SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Teamwork Chat"
#define MyAppVersion "0.10.0"
#define MyAppPublisher "Digital Crew, Ltd."
#define MyAppURL "http://www.teamwork.com/"
#define MyAppExeName "TeamworkChat.exe"

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{0F063485-F5AF-4ADE-A9F9-661AB3BAA661}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={userappdata}\{#MyAppName}
DisableDirPage=yes
DefaultGroupName={#MyAppName}
OutputDir=E:\chat-client\dist
OutputBaseFilename={#MyAppName}_for_Windows32_Installer-{#MyAppVersion}
SetupIconFile=E:\chat-client\icons\teamwork_chat.ico
WizardImageFile=E:\chat-client\icons\chatWizardImageFile.bmp
Compression=lzma
SolidCompression=yes
PrivilegesRequired=none

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "E:\chat-client\dist\TeamworkChat\win32\TeamworkChat.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "E:\chat-client\dist\TeamworkChat\win32\ffmpegsumo.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "E:\chat-client\dist\TeamworkChat\win32\icudtl.dat"; DestDir: "{app}"; Flags: ignoreversion
Source: "E:\chat-client\dist\TeamworkChat\win32\libEGL.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "E:\chat-client\dist\TeamworkChat\win32\libGLESv2.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "E:\chat-client\dist\TeamworkChat\win32\nw.pak"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

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

Edit编辑

I've changed two options but still no luck;我改变了两个选项,但仍然没有运气;

PrivilegesRequired=lowest
...
[Icons]
...
Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

Edit 2:编辑2:

I've added the runasoriginaluser flag and generated a new AppId (GUID) but still no luck;我添加了runasoriginaluser标志并生成了一个新的AppId (GUID),但仍然没有运气;

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

Edit 3:编辑3:

I've created a simple GitHub repository with the source files and Inno script.我用源文件和 Inno 脚本创建了一个简单的GitHub 存储库

Edit 4:编辑4:

I had been testing on Windows 8.1.我一直在 Windows 8.1 上进行测试。 It seems to work when compiled on Windows 7, and ran on Windows 8, but not when compiled on 8 and ran on 8.它似乎在 Windows 7 上编译并在 Windows 8 上运行时有效,但在 8 上编译并在 8 上运行时不起作用。

Edit 5:编辑5:

It's solved now but to clear things up regarding Edit 4 , it wasn't working only on my machine.现在已经解决了,但为了解决Edit 4 问题,它不仅在我的机器上工作。 It worked on other Windows 8 machines.它适用于其他 Windows 8 机器。 Must've been some weird caching or something (even though I changed the AppId ).一定是一些奇怪的缓存或其他东西(即使我更改了AppId )。

From the wording of your question and if I am understanding you correctly, it sounds like this is because you are "validating with an admin account for the install to run."从您的问题的措辞来看,如果我对您的理解正确的话,这听起来像是因为您“正在使用管理员帐户进行验证以运行安装”。 If this is the case and you are entering a different account (from that which you are logged in with) at the UAC prompt, the current user then actually becomes the Administrator account you just entered at the UAC prompt and not the account you are logged in with.如果是这种情况,并且您在 UAC 提示符下输入不同的帐户(与您登录时使用的帐户不同),则当前用户实际上将成为您在 UAC 提示符下输入的管理员帐户,而不是您登录的帐户在与。 Therefore, as long as you are being asked to elevate the installation using UAC, it will not end up in the logged in user's AppData directory.因此,只要您被要求使用 UAC 提升安装,它就不会最终出现在登录用户的 AppData 目录中。

What you may need to do is use the runasoriginaluser function, which will use the logged in user credentials instead of the account you entered at the UAC prompt, or find what is causing the UAC elevation prompt.您可能需要做的是使用runasoriginaluser函数,它将使用登录的用户凭据而不是您在 UAC 提示符下输入的帐户,或者查找导致 UAC 提升提示的原因。

See also Inno Setup Creating registry key for logged in user (not admin user) .另请参阅Inno Setup 为登录用户(非管理员用户)创建注册表项

The MSDN documentation on Installation Context may also be useful.有关安装上下文的 MSDN 文档也可能有用。

It should work with PrivilegesRequired=lowest .它应该与PrivilegesRequired=lowest And it's the correct approach.这是正确的方法。 If it does not, we want to see a log file.如果没有,我们希望查看日志文件。

The lowest will make the installer run within context of the current unprivileged user. lowest将使安装程序在当前非特权用户的上下文中运行。 Hence all constants , like {userappdata} , {userdesktop} , etc, will refer to the current user.因此,所有常量,如{userappdata}{userdesktop}等,都将引用当前用户。


Anyway, to answer your question, you can use the code below.无论如何,要回答您的问题,您可以使用下面的代码。

But that's just for special situations, when the installer really needs administrator privileges (eg to register some system DLL), but still needs to deploy files for the original user.但这只是针对特殊情况,当安装程序确实需要管理员权限(例如注册某些系统 DLL),但仍需要为原始用户部署文件时。 Like here: Inno Setup - Register components as an administrator .像这里: Inno Setup - 以管理员身份注册组件

[Files]
Source: "MyProg.exe"; DestDir: "{code:GetAppData}"

[Code]

var
  AppDataPath: string;

function GetAppData(Param: string): string;
begin
  Result := AppDataPath;
end;  

function InitializeSetup(): Boolean;
var
  Uniq: string;
  TempFileName: string;
  Cmd: string;
  Params: string;
  ResultCode: Integer;
  Buf: AnsiString;
begin
  AppDataPath := ExpandConstant('{userappdata}');
  Log(Format('Default/Fallback application data path is %s', [AppDataPath]));
  Uniq := ExtractFileName(ExpandConstant('{tmp}'));
  TempFileName :=
    ExpandConstant(Format('{commondocs}\appdata-%s.txt', [Uniq]));
  Params := Format('/C echo %%APPDATA%% > %s', [TempFileName]);
  Log(Format('Resolving APPDATA using %s', [Params]));
  Cmd := ExpandConstant('{cmd}');
  if ExecAsOriginalUser(Cmd, Params, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and
     (ResultCode = 0) then
  begin
    if LoadStringFromFile(TempFileName, Buf) then
    begin
      AppDataPath := Trim(Buf);
      Log(Format('APPDATA resolved to %s', [AppDataPath]));
    end
      else
    begin
      Log(Format('Error reading %s', [TempFileName]));
    end;
    DeleteFile(TempFileName);
  end
    else
  begin
    Log(Format('Error %d resolving APPDATA', [ResultCode]));
  end;

  Result := True;
end;

More similar questions:更多类似问题:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM