InstallShield Suite中调用PowerShell替换JSON文件失败问题排查
我需要替换目标机器上已有的settings.json文件,于是在InstallShield Suite中以Event/Action方式、通过高权限执行以下PowerShell脚本:
try { $ProductName = "ravendb" $Product = Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -eq $ProductName } if ($Product) { Stop-Service RavenDB (Get-Service RavenDB).WaitForStatus('Stopped', '00:00:30') $Folder = 'C:\RavenDB-4.2.x\Server' Copy-Item -Path "settings.json" -Destination $Folder -force Start-Service RavenDB (Get-Service RavenDB).WaitForStatus('Running', '00:00:30') exit(0) } else { exit(1) } } catch { $StringValue = Resolve-SuiteString -StringId $_.Exception.Message Trace-SuiteInfo -LogMessage $StringValue exit(1) }
实际执行后,RavenDB服务能正常停止并重启,但目标目录的settings.json未被覆盖。手动绕过执行策略运行该脚本可正常完成文件替换,且InstallShield Suite的调试日志无报错信息:
2-25-2023[01:26:47 PM]: Running event 'update-ravendb-settings' 2-25-2023[01:26:47 PM]: Engine: request for proxy handler, 0, 0 2-25-2023[01:26:48 PM]: (PowerShell Action): Attempting to load through CLR 4 APIs... 2-25-2023[01:26:48 PM]: (PowerShell Action): Getting meta host... 2-25-2023[01:26:48 PM]: (PowerShell Action): Enumerating available runtimes... 2-25-2023[01:26:48 PM]: (PowerShell Action): Highest available runtime: v4.0.30319 2-25-2023[01:26:48 PM]: (PowerShell Action): Trying to use highest runtime... 2-25-2023[01:26:48 PM]: (PowerShell Action): Using highest version runtime... 2-25-2023[01:26:57 PM]: Action returned value 0x00000000 2-25-2023[01:26:57 PM]: Action 'update-ravendb-settings' returned status 0x00000000
请问为何该脚本在InstallShield Suite中作为事件/动作调用时无法正常工作?
核心原因:相对路径指向错误
脚本中Copy-Item使用了相对路径"settings.json",但InstallShield Suite执行PowerShell动作时的工作目录并非你预期的路径(比如脚本所在的安装包目录、临时解压目录),导致脚本找不到源文件。但因为你没有给Copy-Item添加错误终止参数,这个操作会静默失败,脚本继续执行后续的服务启停步骤,最终返回0(成功状态),但实际文件未被替换。
验证与修复步骤
1. 给源文件指定绝对路径
如果settings.json是打包在InstallShield Suite安装包中的文件,可以通过Suite内置变量获取其所在的临时目录,修改Copy-Item的源路径:
# 获取Suite临时目录(安装包解压后的目录) $SourceDir = Resolve-SuiteString -StringId "SUITE_TEMP_DIR" $SourceFile = Join-Path -Path $SourceDir -ChildPath "settings.json" Copy-Item -Path $SourceFile -Destination $Folder -Force -ErrorAction Stop
如果是测试阶段,也可以直接写死源文件的绝对路径(比如"C:\YourPackageFiles\settings.json"),验证是否能成功复制。
2. 添加调试日志排查
在脚本中添加日志输出,确认源文件是否存在、复制操作是否执行:
# 输出当前工作目录 Write-Host "当前工作目录: $(Get-Location)" # 检查源文件是否存在 $SourceExists = Test-Path "settings.json" Write-Host "源文件settings.json是否存在: $SourceExists" if ($SourceExists) { Write-Host "源文件路径: $(Resolve-Path "settings.json")" } # 执行复制并强制终止错误 Copy-Item -Path "settings.json" -Destination $Folder -Force -ErrorAction Stop # 检查目标文件是否更新(可对比最后修改时间) $TargetFile = Join-Path -Path $Folder -ChildPath "settings.json" Write-Host "目标文件最后修改时间: $(Get-Item $TargetFile).LastWriteTime"
之后查看InstallShield Suite的详细日志,就能明确问题出在路径还是其他环节。
3. 优化产品查询方式(可选)
原脚本中使用Get-WmiObject Win32_Product会触发MSI自动修复,可能导致不必要的系统开销,建议替换为更高效的注册表查询:
$Product = Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" | Where-Object { $_.DisplayName -eq $ProductName }
内容的提问来源于stack exchange,提问作者yBother

