调用cmd /C时带引号路径未被正确识别的问题求助
问题:PowerShell调用cmd /C时带空格的路径未被整体识别
问题描述
尝试通过PowerShell调用cmd /C执行程序卸载时,即便给路径添加了引号,cmd仍会将带空格的路径拆分成多个部分,报错提示'C:\Program' 未被识别为内部或外部命令。相关代码及报错信息如下:
原代码
Function Remove-App-EXE-SILENT-QUOTES([String]$appName) { $appCheck = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where-Object {$_.DisplayName -eq $appName } | Select-Object -Property DisplayName,UninstallString if($appCheck -ne $null){ Write-host "Uninstalling "$appCheck.DisplayName $uninst="`"" + ($appCheck.UninstallString) + "`"" Write-Host $uninst cmd /C $uninst } else{ Write-Host "$appName is not installed on this computer" } } Remove-App-EXE-SILENT-QUOTES "DELLOSD"
报错输出
PS C:\Program Files> C:\Users\HOL-OP05\Documents\RemoveDellOSD.ps1 正在卸载 DELLOSD "C:\Program Files (x86)\InstallShield Installation Information\{50033799-D5D3-4759-9ABD-589AD04F33C1}\setup.exe -runfromtemp -l0x0009 -removeonly" cmd : 'C:\Program' 未被识别为内部或外部命令, At C:\Users\HOL-OP05\Documents\RemoveDellOSD.ps1:8 char:9 + cmd /C $uninst + ~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: ('C:\Program' is...ternal command,:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError 可运行的程序或批处理文件。
问题原因
- 函数命名违规:PowerShell函数名不能包含多个连字符(
-),否则会被解析为「动词-参数-参数」的形式,导致函数调用逻辑异常。 - 引号转义错误:构造
$uninst变量时误用了HTML转义符("),而非PowerShell原生的引号转义规则,导致最终传递给cmd的参数格式不符合要求。 - 跨进程参数解析冲突:PowerShell调用外部程序时会自动拆分带空格的参数,直接传递
$uninst给cmd /C时,cmd无法正确识别嵌套的引号结构。
解决方案
方案1:修复引号传递逻辑,正确调用cmd
修正函数名,同时调整$uninst的构造方式,使用PowerShell原生转义符,并通过嵌套引号确保cmd正确识别完整命令:
Function Remove-AppExeSilentQuotes([String]$appName) { $appCheck = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where-Object {$_.DisplayName -eq $appName } | Select-Object -Property DisplayName,UninstallString if($appCheck -ne $null){ Write-Host "正在卸载 $($appCheck.DisplayName)" # 用PowerShell转义符构造带引号的命令 $uninst = "`"$($appCheck.UninstallString)`"" Write-Host $uninst # 嵌套双引号让cmd完整解析命令 cmd /c """"$uninst"""" } else{ Write-Host "$appName 未安装在此计算机上" } } Remove-AppExeSilentQuotes "DELLOSD"
方案2:使用Invoke-Expression执行命令
通过Invoke-Expression直接解析执行命令字符串,避免参数拆分问题:
Function Remove-AppExeSilentQuotes([String]$appName) { $appCheck = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where-Object {$_.DisplayName -eq $appName } | Select-Object -Property DisplayName,UninstallString if($appCheck -ne $null){ Write-Host "正在卸载 $($appCheck.DisplayName)" $uninst = $appCheck.UninstallString Write-Host $uninst # 直接解析执行命令 Invoke-Expression "cmd /c `"$uninst`"" } else{ Write-Host "$appName 未安装在此计算机上" } } Remove-AppExeSilentQuotes "DELLOSD"
方案3:使用Start-Process(推荐)
直接用PowerShell的Start-Process执行卸载程序,无需依赖cmd,彻底避免引号嵌套和参数解析冲突:
Function Remove-AppExeSilentQuotes([String]$appName) { $appCheck = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where-Object {$_.DisplayName -eq $appName } | Select-Object -Property DisplayName,UninstallString if($appCheck -ne $null){ Write-Host "正在卸载 $($appCheck.DisplayName)" $uninstallString = $appCheck.UninstallString # 拆分卸载命令的程序路径和参数 if ($uninstallString -match '^"([^"]+)"(.*)$') { $exePath = $matches[1] $arguments = $matches[2].Trim() } else { $exePath = $uninstallString.Split(' ')[0] $arguments = $uninstallString.Substring($exePath.Length).Trim() } # 启动卸载程序并等待执行完成 Start-Process -FilePath $exePath -ArgumentList $arguments -Wait -NoNewWindow Write-Host "$($appCheck.DisplayName) 卸载完成" } else{ Write-Host "$appName 未安装在此计算机上" } } Remove-AppExeSilentQuotes "DELLOSD"
说明
方案3是最优选择,它直接操作可执行文件和参数,不受cmd与PowerShell的参数解析规则限制,同时支持静默执行(需卸载程序本身支持相关参数)。
内容的提问来源于stack exchange,提问作者Charles Staal
相关产品推荐
相关产品推荐

