Inno Setup无法向LocalSystem的%LOCALAPPDATA%安装文件的问题咨询
我有一个以本地系统账户(LocalSystem)运行的Windows服务,它会将数据存储在自身的%LOCALAPPDATA%文件夹中,对应路径为:
C:\Windows\system32\config\systemprofile\AppData\Local
该服务可正常在此路径创建子文件夹并写入文件。
尝试用Inno Setup将初始文件安装到该文件夹,配置如下:
[Files] Source: "LICENSE"; DestDir: "{sys}\config\systemprofile\AppData\Local\InnoTest"; Flags: ignoreversion
安装日志显示操作成功:
[14:20:10,722] -- File entry -- [14:20:10,725] Dest filename: C:\Windows\system32\config\systemprofile\AppData\Local\InnoTest\LICENSE [14:20:10,729] Time stamp of our file: 2022-10-24 13:56:42.000 [14:20:10,731] Installing the file. [14:20:10,734] Creating directory: C:\Windows\system32\config\systemprofile\AppData\Local\InnoTest [14:20:10,738] Successfully installed the file.
但实际既看不到该文件也看不到对应的目录。
再次运行安装程序时,提示目标文件已存在:
[14:24:47,381] -- File entry -- [14:24:47,395] Dest filename: C:\Windows\system32\config\systemprofile\AppData\Local\InnoTest\LICENSE [14:24:47,398] Time stamp of our file: 2022-10-24 13:56:42.000 [14:24:47,400] Dest file exists. [14:24:47,403] Time stamp of existing file: 2022-10-24 13:56:42.000 [14:24:47,405] Installing the file. [14:24:47,410] Successfully installed the file.
即安装程序认为文件已存在,但我无法找到它。
此问题仅针对LocalSystem账户:切换到LocalService账户的%LOCALAPPDATA%路径时,安装可正常进行,配置如下:
[Files] Source: "LICENSE"; DestDir: "{win}\ServiceProfiles\LocalService\AppData\Local\InnoTest"; Flags: ignoreversion
这是Windows WOW64文件系统重定向导致的:
- Inno Setup默认编译为32位程序,在64位Windows系统上,32位程序访问
C:\Windows\system32时,会被系统自动重定向到C:\Windows\SysWOW64目录。 - 所以实际安装的文件并没有写入
C:\Windows\system32\config\systemprofile\AppData\Local\InnoTest,而是被重定向到了C:\Windows\SysWOW64\config\systemprofile\AppData\Local\InnoTest,这就是你在原路径看不到文件,但安装程序能检测到文件存在的原因。 - LocalService账户的路径
{win}\ServiceProfiles\LocalService不在重定向范围内,所以安装正常。
有三种可行的解决方法:
启用Inno Setup的64位模式
在安装脚本的[Setup]段添加以下配置,让安装程序以64位模式运行,避免重定向:[Setup] ArchitecturesInstallIn64BitMode=x64这样
{sys}会指向真实的C:\Windows\system32,文件会被安装到正确的路径。直接指定SysWOW64路径(不推荐)
如果不需要64位模式,可将目标路径中的{sys}替换为{syswow64}:[Files] Source: "LICENSE"; DestDir: "{syswow64}\config\systemprofile\AppData\Local\InnoTest"; Flags: ignoreversion但这种方法仅适用于服务也是32位的情况,若服务是64位,它会读取
system32下的路径,导致无法找到文件。动态获取LocalSystem的LocalAppData路径
通过调用Windows APISHGetFolderPath或SHGetKnownFolderPath获取LocalSystem账户的LOCALAPPDATA路径,避免硬编码。可在Inno Setup脚本中编写代码实现:[Code] function GetLocalSystemLocalAppData: string; var Path: array[0..MAX_PATH] of Char; begin if SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, Path) = S_OK then Result := Path else Result := ''; end;然后在
[Files]段中使用该动态路径:[Files] Source: "LICENSE"; DestDir: "{code:GetLocalSystemLocalAppData}\InnoTest"; Flags: ignoreversion
内容的提问来源于stack exchange,提问作者Petter Hesselberg

