想要一种使用 PowerShell 将不同字符串拆分为多个部分的通用方法
Posted
技术标签:
【中文标题】想要一种使用 PowerShell 将不同字符串拆分为多个部分的通用方法【英文标题】:Would like a universal way to split different strings into multiple parts using PowerShell 【发布时间】:2020-09-13 08:43:24 【问题描述】:我正在研究一种从注册表中读取软件的 UninstallStrings 的方法。然后我尝试执行这些字符串来卸载软件。
当我打印出保存字符串信息的变量时,它会正确打印整个字符串(带有参数),但我无法运行这些字符串。 这个问题有多个部分。
一些安装字符串的格式是这样的
c:\file path\blah\app.exe /uninstall
"c:\file path\blah\app.exe" /uninstall
c:\file path\blah\app.exe --uninstall
'c:\file path\blah\app.exe' /uninstall
我想做的是找出能够以“通用”方式运行卸载程序的最佳方式。 有没有办法有效地做到这一点?
我尝试了两种不同的方式来执行字符串。
& $uninstaller
和
Start-Process -FilePath cmd.exe -ArgumentList '/c', $uninstaller -Wait
它们似乎都不起作用。没有错误,但它们似乎没有运行,因为当我检查应用程序时它仍然安装。
我尝试用几种方法拆分文本。
$Uninstaller.split("/")[0]
$Uninstaller.split("/",2)[1]
$($Uninstaller) | Invoke-Expression
$Uninstaller.Substring(0,$Uninstaller.lastIndexOf('.exe '))
$Uninstaller.split('^(*?\.exe) *')
提前致谢!
【问题讨论】:
我猜您需要用双引号将app.exe
的完整路径括起来?例如。后者为'c:\file path\blah\app.exe' /uninstall
到"c:\file path\blah\app.exe" /uninstall
?
感谢您的回复,问题是,并非注册表中的所有 UninstallStrings 都采用该语法。这就是让这有点复杂的原因。一些卸载字符串是 msiexec,另一些是带有自定义参数的可执行卸载程序。并不是所有的论点都是普遍的。它们基于可执行文件。一个 exe 可能有破折号,另一个是正斜杠。
【参考方案1】:
想通了。也许有更好的方法,但这似乎对我有用。
CLS
$Software = "OneDrive"
$Filter = "*" + $Software + "*"
$Program = $ProgUninstall = $FileUninstaller = $FileArg = $NULL
try
if (Test-Path -Path "HKLM:\SOFTWARE\WOW6432Node")
$programs = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction Stop
$programs += Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction Stop
$programs += Get-ItemProperty -Path "Registry::\HKEY_USERS\*\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue
catch
Write-Error $_
break
foreach($Program in $Programs)
$ProgDisplayName = $Program.DisplayName
$ProgUninstall = $Program.UninstallString
if($ProgDisplayName -like $Filter)
if($ProgUninstall -like "msiexec*")
$FileUninstaller = $ProgUninstall.split(" ")[0]
$FileArg = ($($ProgUninstall).split(" ",2)[1])
else
if(($ProgUninstall -like '"*"*') -or ($ProgUninstall -like "'*'*"))
#String has quotes, don't need to do anything
else
if($NULL -ne $ProgUninstall)
#String doesn't have quotes so we should add them
$ProgUninstall = '"' + ($ProgUninstall.Replace('.exe','.exe"'))
#Let's grab the uninstaller and arguments
$FileUninstaller = $ProgUninstall.split('"')[1]
$FileArg = $ProgUninstall.split('"')[-1]
#Debug
#$FileUninstaller
#$FileArg
#Run the Uninstaller
Start-Process $FileUninstaller -ArgumentList $FileArg -wait -ErrorAction SilentlyContinue
【讨论】:
【参考方案2】:这对于 msi 安装非常容易:
get-package *whatever* | uninstall-package
这是一个非 msi 静默卸载示例,但您必须添加“/S”或任何静默卸载选项:
get-package notepad++* |
% & $_.Meta.Attributes['UninstallString'] /S
【讨论】:
感谢您的更新回复,但就我的情况而言,我希望它尽可能无缝。我在下面发布了一个我认为对我很有效的解决方案,但 JoesefZ 的解决方案似乎更好。它与我的输出完全相同(这是我需要的),代码更少,所以我觉得这是最好的答案。【参考方案3】:尝试以下测试脚本,其中简单的控制台应用程序CliParser.exe
仅回显命令行参数(用C 编写,灵感来自here)。使用名称中带有空格的精确副本CliParser noPause.exe
;它表明 . $Uninstaller $UninsParams
应该可以工作,即使路径 $Uninstaller
包含空格。
无需使用Start-Process -FilePath cmd.exe …
;只需将点源运算符应用为. $Uninstaller $UninsParams
...
$lines
集合包含几乎具有代表性的卸载字符串语法模式(取自我的 Windows 10):
$lines = @'
MsiExec.exe /XFFC6E93A-B9AD-3F20-9B06-EE20E24AAEAF
"D:\Program Files (x86)\Virtual Russian Keyboard\unins000.exe"
"C:\Windows10Upgrade\Windows10UpgraderApp.exe" /Uninstall
C:\Windows\SysWOW64\msiexec.exe /package CFEF48A8-BFB8-3EAC-8BA5-DE4F8AA267CE /uninstall 815F0BC1-7E54-300C-9ACA-C9460FDF6F78 /qb+ REBOOTPROMPT=""
C:\Program Files (x86)\InstallShield Installation Information\8833FFB6-5B0C-4764-81AA-06DFEED9A476\Setup.exe -runfromtemp -removeonly
"C:\WINDOWS\SysWOW64\RunDll32.EXE" "C:\Program Files\NVIDIA Corporation\Installer2\InstallerCore\NVI2.DLL",UninstallPackage Display.Driver
%windir%\system32\sdbinst.exe -u "C:\WINDOWS\AppPatch\CustomSDB\9f4f4a9b-eec5-4906-92fe-d1f43ccf5c8d.sdb"
'@ -split [System.Environment]::NewLine
$FakeUninstaller = "D:\bat\CLIParser noPause.exe"
foreach ( $line in $lines )
# $line
$aux = $line -split @('\.exe'),2,[System.StringSplitOptions]::None
$Uninstaller = (cmd /c echo $($aux[0].TrimStart('"').TrimStart("'") + '.exe')).Trim('"')
$UninsParams = $aux[1].TrimStart('"').TrimStart("'").Trim().split(' ',[System.StringSplitOptions]::RemoveEmptyEntries)
". $Uninstaller $UninsParams"
. $FakeUninstaller $UninsParams | Where-Object $_ -notlike "param 0 = *"
输出:D:\PShell\SO\62023960.ps1
. MsiExec.exe /XFFC6E93A-B9AD-3F20-9B06-EE20E24AAEAF 参数 1 = /XFFC6E93A-B9AD-3F20-9B06-EE20E24AAEAF . “D:\Program Files (x86)\Virtual Russian Keyboard\unins000.exe” . C:\Windows10Upgrade\Windows10UpgraderApp.exe /卸载 参数 1 = /卸载 . C:\Windows\SysWOW64\msiexec.exe /package CFEF48A8-BFB8-3EAC-8BA5-DE4F8AA267CE /uninstall 815F0BC1-7E54-300C-9ACA-C9460FDF6F78 /qb+ REBOOTPROMPT="" 参数 1 = /包 参数 2 = CFEF48A8-BFB8-3EAC-8BA5-DE4F8AA267CE 参数 3 = /卸载 参数 4 = 815F0BC1-7E54-300C-9ACA-C9460FDF6F78 参数 5 = /qb+ 参数 6 = REBOOTPROMPT="" . “C:\Program Files (x86)\InstallShield 安装信息\8833FFB6-5B0C-4764-81AA-06DFEED9A476\Setup.exe”-runfromtemp -removeonly 参数 1 = -runfromtemp 参数 2 = -removeonly . C:\WINDOWS\SysWOW64\RunDll32.exe "C:\Program Files\NVIDIA Corporation\Installer2\InstallerCore\NVI2.DLL",UninstallPackage Display.Driver 参数 1 = C:\Program Files\NVIDIA Corporation\Installer2\InstallerCore\NVI2.DLL,UninstallPackage 参数 2 = Display.Driver . C:\WINDOWS\system32\sdbinst.exe -u "C:\WINDOWS\AppPatch\CustomSDB\9f4f4a9b-eec5-4906-92fe-d1f43ccf5c8d.sdb" 参数 1 = -u 参数 2 = C:\WINDOWS\AppPatch\CustomSDB\9f4f4a9b-eec5-4906-92fe-d1f43ccf5c8d.sdb
【讨论】:
感谢您的分享。这实际上似乎比我在下面发布的解决方案要好。它基本上用更少的代码行做同样的事情,所以我更喜欢你的。我唯一不明白的是最后一行(卸载程序),它似乎对我不起作用。我尝试使用 & $file,但仍然没有。无论如何,我通过使用 Start-Process $Uninstaller -ArgumentList $UninsParams -wait 让它工作. $Uninstaller $UninsParams
可能会失败,因为如果echo
ed 字符串包含空格,cmd
会添加双引号。例如,$y='a b'; echo $y; cmd /c echo $y; cmd /c "echo $y"
返回字符串a b
、"a b"
和a b
。但是,正确转义 cmd /c echo $($aux[0].TrimStart('"').TrimStart("'") + '.exe')
中的所有双引号似乎是一个棘手的问题。可以简单地使用一个额外的辅助变量来完成,或者作为$Uninstaller = (cmd /c echo $($aux[0].TrimStart('"').TrimStart("'") + '.exe')).Trim('"')
,查看更新的答案。
您好,我做了调整。您拥有的最后一行,我使用以下命令进行了调整以适合我的示例: 。 $卸载程序 $UninsParams | Where-Object $_ -notlike "param 0 = *" 但是,我收到此错误:". : The term '"C:\Program Files (x86)\Microsoft OneDrive\20.064.0329.0008_7\OneDriveSetup.exe" ' 未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包含路径,请验证路径是否正确,然后重试。"
我的错误,对不起。调整后(答案)在$Uninstaller = (cmd /c echo $($aux[0].TrimStart('"').TrimStart("'") + '.exe')).Trim('"')
中缺少最左括号…以上是关于想要一种使用 PowerShell 将不同字符串拆分为多个部分的通用方法的主要内容,如果未能解决你的问题,请参考以下文章
如何解析csv文件,查找触发器并使用PowerShell拆分成新文件