Хотелось бы универсального способа разбить разные строки на несколько частей с помощью PowerShell - PullRequest
2 голосов
/ 26 мая 2020

Я работаю над методом чтения 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) *')

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 28 мая 2020

Попробуйте следующий сценарий тестирования, в котором простое консольное приложение CliParser.exe просто повторяет аргументы командной строки (написанные в C, вдохновленные здесь ). Использована точная копия с пробелом в имени CliParser noPause.exe; он показывает, что . $Uninstaller $UninsParams должен работать, даже если путь $Uninstaller содержит пробелы.

Нет необходимости использовать Start-Process -FilePath cmd.exe …; просто примените оператор выбора точки как . $Uninstaller $UninsParams

Коллекция $lines содержит почти репрезентативные шаблоны синтаксиса строк удаления (взятых из моего Windows 10):

$lines = @'
MsiExec.exe /X{FFC6E93A-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 /X{FFC6E93A-B9AD-3F20-9B06-EE20E24AAEAF}
param 1 = /X{FFC6E93A-B9AD-3F20-9B06-EE20E24AAEAF}

. "D:\Program Files (x86)\Virtual Russian Keyboard\unins000.exe"

. C:\Windows10Upgrade\Windows10UpgraderApp.exe /Uninstall
param 1 = /Uninstall

. C:\Windows\SysWOW64\msiexec.exe /package {CFEF48A8-BFB8-3EAC-8BA5-DE4F8AA267CE} /uninstall {815F0BC1-7E54-300C-9ACA-C9460FDF6F78} /qb+ REBOOTPROMPT=""
param 1 = /package
param 2 = {CFEF48A8-BFB8-3EAC-8BA5-DE4F8AA267CE}
param 3 = /uninstall
param 4 = {815F0BC1-7E54-300C-9ACA-C9460FDF6F78}
param 5 = /qb+
param 6 = REBOOTPROMPT=""

. "C:\Program Files (x86)\InstallShield Installation Information\{8833FFB6-5B0C-4764-81AA-06DFEED9A476}\Setup.exe" -runfromtemp -removeonly
param 1 = -runfromtemp
param 2 = -removeonly

. C:\WINDOWS\SysWOW64\RunDll32.exe "C:\Program Files\NVIDIA Corporation\Installer2\InstallerCore\NVI2.DLL",UninstallPackage Display.Driver
param 1 = C:\Program Files\NVIDIA Corporation\Installer2\InstallerCore\NVI2.DLL,UninstallPackage
param 2 = Display.Driver

. C:\WINDOWS\system32\sdbinst.exe -u "C:\WINDOWS\AppPatch\CustomSDB\{9f4f4a9b-eec5-4906-92fe-d1f43ccf5c8d}.sdb"
param 1 = -u
param 2 = C:\WINDOWS\AppPatch\CustomSDB\{9f4f4a9b-eec5-4906-92fe-d1f43ccf5c8d}.sdb
0 голосов
/ 27 мая 2020

Это очень легко работает для установок msi:

get-package *whatever* | uninstall-package

Вот пример тихой деинсталляции, отличной от msi, но вам нужно добавить «/ S» или любой другой вариант тихой деинсталляции:

get-package notepad++* | 
  % { & $_.Meta.Attributes['UninstallString'] /S }
0 голосов
/ 27 мая 2020

Разобрался. Может быть, есть лучший способ сделать это, но мне кажется, что он работает.

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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...