Inno Setup 总是安装到管理员的 AppData 目录中
Inno Setup always installs into admin's AppData directory
我想将我的应用程序存储在当前用户的 AppData
目录中,以避免在自动更新我们的应用程序时(当它存储在 Program Files 中时)出现权限问题。我们不会让用户选择安装应用程序的位置。我们收到了非管理员用户的投诉,安装程序将应用程序存储在管理员的 AppData
目录中(当然是在 UAC 之后),而不是当前用户的 AppData
目录中,这会阻止应用程序从运行 将来。
首先,我有DefaultDirName={userappdata}\{#MyAppName}
。然后我尝试了DefaultDirName={commonappdata}\{#MyAppName}
。然后我尝试将其与 PrivilegesRequired=lowest
一起尝试,甚至像 Make InnoSetup installer request privileges elevation only when needed 问题所建议的那样 PrivilegesRequired=none
。
这是我目前的脚本,以防我遗漏一些明显的东西:
; 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
编辑
我已经更改了两个选项,但仍然没有成功;
PrivilegesRequired=lowest
...
[Icons]
...
Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
编辑 2:
我已经添加了 runasoriginaluser
标志并生成了一个新的 AppId
(GUID),但仍然没有成功;
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent runasoriginaluser
编辑 3:
我用源文件和 Inno 脚本创建了一个简单的 GitHub repository。
编辑 4:
我一直在测试 Windows 8.1。它似乎在 Windows 7 和 运行 在 Windows 8 上编译时有效,但在 8 和 运行 在 8 上编译时无效。
编辑 5:
现在已经解决了,但是为了解决 Edit 4 的问题,它不仅仅在我的机器上工作。它适用于其他 Windows 8 台机器。一定是一些奇怪的缓存或其他东西(即使我更改了 AppId
)。
从你问题的措辞来看,如果我理解正确的话,这听起来像是因为你是 "validating with an admin account for the install to run." 如果是这种情况,并且你正在输入一个不同的帐户(与你logged in with) 在 UAC 提示符下,当前用户实际上成为您刚刚在 UAC 提示符下输入的管理员帐户,而不是您登录时使用的帐户。因此,只要您被要求使用 UAC 提升安装,它就不会最终出现在登录用户的 AppData 目录中。
您可能需要做的是使用 runasoriginaluser
函数,它将使用登录的用户凭据而不是您在 UAC 提示符下输入的帐户,或者查找导致 UAC 提升提示符的原因。
另见 Inno Setup Creating registry key for logged in user (not admin user)。
有关 Installation Context 的 MSDN 文档也可能有用。
它应该适用于 PrivilegesRequired=lowest
。这是正确的方法。如果没有,我们希望查看日志文件。
lowest
将使安装程序在当前非特权用户的上下文中 运行。因此,所有 constants,如 {userappdata}
、{userdesktop}
等,都将引用当前用户。
无论如何,要回答您的问题,您可以使用下面的代码。
但这只是针对特殊情况,当安装程序确实需要管理员权限时(例如注册一些系统 DLL),但仍需要为原始用户部署文件。喜欢这里:Inno Setup - Register components as an administrator.
[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;
更多类似问题:
- Inno Setup - puts user files in admin documents
我想将我的应用程序存储在当前用户的 AppData
目录中,以避免在自动更新我们的应用程序时(当它存储在 Program Files 中时)出现权限问题。我们不会让用户选择安装应用程序的位置。我们收到了非管理员用户的投诉,安装程序将应用程序存储在管理员的 AppData
目录中(当然是在 UAC 之后),而不是当前用户的 AppData
目录中,这会阻止应用程序从运行 将来。
首先,我有DefaultDirName={userappdata}\{#MyAppName}
。然后我尝试了DefaultDirName={commonappdata}\{#MyAppName}
。然后我尝试将其与 PrivilegesRequired=lowest
一起尝试,甚至像 Make InnoSetup installer request privileges elevation only when needed 问题所建议的那样 PrivilegesRequired=none
。
这是我目前的脚本,以防我遗漏一些明显的东西:
; 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
编辑
我已经更改了两个选项,但仍然没有成功;
PrivilegesRequired=lowest
...
[Icons]
...
Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
编辑 2:
我已经添加了 runasoriginaluser
标志并生成了一个新的 AppId
(GUID),但仍然没有成功;
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent runasoriginaluser
编辑 3:
我用源文件和 Inno 脚本创建了一个简单的 GitHub repository。
编辑 4:
我一直在测试 Windows 8.1。它似乎在 Windows 7 和 运行 在 Windows 8 上编译时有效,但在 8 和 运行 在 8 上编译时无效。
编辑 5:
现在已经解决了,但是为了解决 Edit 4 的问题,它不仅仅在我的机器上工作。它适用于其他 Windows 8 台机器。一定是一些奇怪的缓存或其他东西(即使我更改了 AppId
)。
从你问题的措辞来看,如果我理解正确的话,这听起来像是因为你是 "validating with an admin account for the install to run." 如果是这种情况,并且你正在输入一个不同的帐户(与你logged in with) 在 UAC 提示符下,当前用户实际上成为您刚刚在 UAC 提示符下输入的管理员帐户,而不是您登录时使用的帐户。因此,只要您被要求使用 UAC 提升安装,它就不会最终出现在登录用户的 AppData 目录中。
您可能需要做的是使用 runasoriginaluser
函数,它将使用登录的用户凭据而不是您在 UAC 提示符下输入的帐户,或者查找导致 UAC 提升提示符的原因。
另见 Inno Setup Creating registry key for logged in user (not admin user)。
有关 Installation Context 的 MSDN 文档也可能有用。
它应该适用于 PrivilegesRequired=lowest
。这是正确的方法。如果没有,我们希望查看日志文件。
lowest
将使安装程序在当前非特权用户的上下文中 运行。因此,所有 constants,如 {userappdata}
、{userdesktop}
等,都将引用当前用户。
无论如何,要回答您的问题,您可以使用下面的代码。
但这只是针对特殊情况,当安装程序确实需要管理员权限时(例如注册一些系统 DLL),但仍需要为原始用户部署文件。喜欢这里:Inno Setup - Register components as an administrator.
[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;
更多类似问题:
- Inno Setup - puts user files in admin documents