使用WScript.Shell创建快捷方式时目标路径被自动添加C:\的问题求助
问题:PowerShell创建含自定义环境变量的快捷方式时自动添加C:\前缀的原因
现象
使用PowerShell的WScript.Shell ComObject创建快捷方式,代码如下:
$Shell = New-Object -ComObject WScript.Shell $ShortCut = $Shell.CreateShortcut("Path\to\Shortcut.lnk") $ShortCut.TargetPath = "%APP_HOME%\launcher.exe" $ShortCut.Save()
执行后,快捷方式的目标路径被自动修改为C:\%APP_HOME%\launcher.exe,而非预期的%APP_HOME%\launcher.exe。
实际案例中,Blender安装程序创建的快捷方式能正确保留环境变量格式(截图显示其目标路径未被添加驱动器前缀),对应的PowerShell安装脚本采用了不同的快捷方式创建逻辑。
原因
WScript.Shell的TargetPath属性对路径的解析逻辑如下:
- 若路径以驱动器盘符(如
C:\)、网络共享路径(如\\server\share)开头,或包含系统预定义的环境变量(如%windir%、%ProgramFiles%),会被识别为绝对路径,保留原始格式。 - 对于自定义环境变量(如
%APP_HOME%),WScript.Shell无法预先判断其指向的是绝对路径还是相对路径,因此会将%APP_HOME%\launcher.exe视为相对路径,自动拼接当前进程工作目录的驱动器根路径(通常为C:\)作为前缀。
Blender安装程序的快捷方式能正常保留环境变量,是因为它使用了更底层的ShellLink API直接写入路径字段,绕过了WScript.Shell的自动路径解析逻辑。
解决方法
要保留自定义环境变量的原始路径格式,可采用以下两种方案:
方案1:使用底层ShellLink API(可靠)
通过调用Windows原生的ShellLink COM接口直接设置路径,避免WScript.Shell的自动解析。示例代码:
$shellLink = New-Object -ComObject ShellLink.ShellLink $shellLink.Path = "%APP_HOME%\launcher.exe" $shellLink.Save("Path\to\Shortcut.lnk")
注:部分系统可能需要提前注册ShellLink组件。
方案2:绕过自动解析的临时方案
先创建一个带临时绝对路径的快捷方式,再手动替换路径内容:
$tempPath = "C:\TEMP\placeholder.exe" $shortcutPath = "Path\to\Shortcut.lnk" # 创建临时快捷方式 $Shell = New-Object -ComObject WScript.Shell $ShortCut = $Shell.CreateShortcut($shortcutPath) $ShortCut.TargetPath = $tempPath $ShortCut.Save() # 替换为目标环境变量路径 $lnkBytes = [System.IO.File]::ReadAllBytes($shortcutPath) $tempBytes = [System.Text.Encoding]::Unicode.GetBytes($tempPath) $targetBytes = [System.Text.Encoding]::Unicode.GetBytes("%APP_HOME%\launcher.exe") $index = [System.Array]::IndexOf($lnkBytes, $tempBytes[0]) if ($index -ge 0) { [System.Array]::Copy($targetBytes, 0, $lnkBytes, $index, $targetBytes.Length) [System.IO.File]::WriteAllBytes($shortcutPath, $lnkBytes) }
内容的提问来源于stack exchange,提问作者Andreas Gottardi
相关产品推荐
相关产品推荐

