Inno Setup安装时全局部署NuGet与PowerShell模块问题求助
问题场景
在Windows 10/11环境下用Inno Setup制作安装程序,以管理员权限运行时,NuGet包提供器和AudioDeviceCmdlets模块安装本身无问题,但被安装的应用myApp(支持管理员/非管理员权限运行)无法调用该模块。手动在管理员PowerShell/CMD窗口执行安装命令后,myApp无论权限均可正常调用模块,用IExpress自动化虽可行但并非理想方案,需实现模块安装完成后全局可用。
核心原因
- 位数不匹配:Inno Setup默认是32位程序,调用PowerShell时会默认启动32位版本,安装的模块会被放到32位的全局模块路径(
C:\Program Files (x86)\WindowsPowerShell\Modules),而如果myApp是64位程序,会优先去64位路径(C:\Program Files\WindowsPowerShell\Modules)查找模块,导致找不到。 - 模块缓存未刷新:PowerShell会缓存已发现的模块列表,安装完成后未触发缓存更新,导致后续会话无法识别新安装的模块。
- 安装范围不明确:未明确指定
-Scope AllUsers,可能导致模块仅安装到当前管理员用户的路径,而非全局路径。
具体解决方案
1. 强制调用64位PowerShell执行安装命令
在Inno Setup中,通过SysNative路径绕过32位程序的文件系统重定向,直接调用64位PowerShell执行安装命令,同时明确指定全局安装范围:
[Code] procedure CurStepChanged(CurStep: TSetupStep); var ResultCode: Integer; begin if CurStep = ssPostInstall then begin // 调用64位PowerShell执行全局安装 Exec( 'C:\Windows\SysNative\WindowsPowerShell\v1.0\powershell.exe', '-ExecutionPolicy Bypass -Command "Install-PackageProvider -Name NuGet -Force -Scope AllUsers; Install-Module -Name AudioDeviceCmdlets -Force -Scope AllUsers"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode ); end; end;
如果需要同时支持32位环境,可以再额外调用32位PowerShell(路径为C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe,32位程序下会自动重定向到SysWOW64)执行相同命令,确保两个位数环境下都有模块。
2. 安装后刷新模块缓存与环境变量
安装完成后,执行命令刷新PowerShell的模块缓存,并更新PSModulePath环境变量,确保后续会话能识别新模块:
在上述CurStepChanged过程中,追加执行以下命令:
Exec( 'C:\Windows\SysNative\WindowsPowerShell\v1.0\powershell.exe', '-ExecutionPolicy Bypass -Command "$env:PSModulePath = [Environment]::GetEnvironmentVariable(''PSModulePath'', ''Machine'') + '';'' + [Environment]::GetEnvironmentVariable(''PSModulePath'', ''User''); Import-Module -Name AudioDeviceCmdlets -Force"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode );
3. 手动复制模块到全局路径(备用方案)
如果上述方法无效,可以手动将模块复制到64位和32位的全局模块路径:
首先获取模块安装后的路径,然后在Inno Setup中添加CopyFiles命令:
[Files] Source: "{tmp}\AudioDeviceCmdlets\*"; DestDir: "{commonpf}\WindowsPowerShell\Modules\AudioDeviceCmdlets"; Flags: recursesubdirs createallsubdirs Source: "{tmp}\AudioDeviceCmdlets\*"; DestDir: "{commonpf32}\WindowsPowerShell\Modules\AudioDeviceCmdlets"; Flags: recursesubdirs createallsubdirs
注:需要先将模块下载到临时目录,再执行复制操作,可通过PowerShell的Save-Module命令提前下载到{tmp}目录。
验证步骤
- 安装完成后,分别以管理员和非管理员权限打开PowerShell,执行
Get-Module -ListAvailable AudioDeviceCmdlets,确认模块已列出。 - 运行
myApp,测试模块调用功能是否正常。
内容的提问来源于stack exchange,提问作者gbernardi

