0

I wrote a short script to uninstall a program on multiple computers (from a text doc of hostnames). The script is working as expected but is taking about 2-3 minutes per host. Is there a way to perform this on all the machines simultaneously?

Here's my script.

$computers = Get-Content C:\Computernames.txt
foreach($Computer in $computers){
    Invoke-Command -ComputerName $Computer -ScriptBlock{
    
    $application = Get-WmiObject -Class Win32_Product -Filter "Name LIKE '%Appname%'"

    #uninstall the app if it exists
    if($application){
        $application.Uninstall()
        Write-Output "Application uninstalled successfully.."
    }

    else{
        Write-Output "Application not found.."
    }
    } 
}

Can I do Invoke-Command -ComputerName $Computers and do all machines simultaneously to avoid looping through?

js2010
  • 23,033
  • 6
  • 64
  • 66
MF-
  • 185
  • 8
  • 3
    `-ComputerName` parameter supports an array of computers. So `$Computers` should work provided it contains computer names. – AdminOfThings Jan 19 '21 at 14:07
  • "Can I do ..." - have you... tried? :-) No one here is gonna stop you – Mathias R. Jessen Jan 19 '21 at 14:10
  • I tried, but I was unsure more or less how to verify that the script actually ran on each machine without manually checking. I added a ` Write-Output $env:COMPUTERNAME ` took away the loop, and used `Invoke-Command -ComputerName $Computer -ScriptBlock{ ...` and it printed every hostname as it went, so I am led to believe it worked. – MF- Jan 19 '21 at 14:15
  • FYI, you should avoid `Win32_Product` and instead [query the registry directly](https://stackoverflow.com/questions/71575378/powershell-for-software-inventory/71576041#71576041) for Windows software inventory. – codewario Mar 24 '22 at 14:27

2 Answers2

2

As suggested, using $Computers worked successfully. I was able to get rid of my loop and speed the script up tremendously.

Here's the updated script - thanks for letting me know it supports arrays.

#list of computers
$computers = Get-Content C:\Computernames.txt


Invoke-Command -ComputerName $computers -ScriptBlock{
    

$application = Get-WmiObject -Class Win32_Product -Filter "Name LIKE '%appname%'"


if($application){
    $application.Uninstall()
    Write-Output "Successful uninstall on $env:COMPUTERNAME "
    }

else{
    Write-Output "Application not found on $env:COMPUTERNAME"
    }
}
MF-
  • 185
  • 8
2

The win32_product class is notoriously slow, because it verifies every msi whenever it's used. I assume appname is replaced with a specific name. You can use the little known get-package and uninstall-package in powershell 5.1, but only with msi providers:

get-package appname | uninstall-package
js2010
  • 23,033
  • 6
  • 64
  • 66
  • Your assumption is correct. Thanks for the suggestion - I will try that next time. – MF- Jan 19 '21 at 15:59