0

I am looking for assistance on making a bit of code more efficient. I currently have a simple Powershell script (part of a larger script) that enumerates items from a text file (namely the string used to identify an installed program) and then tries uninstalling each of those strings using msiexec:

$javaUninstall = Get-Content .\jre-uninstall-list.txt
    foreach ($java in $javaUninstall) {
    write-host "Trying", "$java"
    $app = Get-WmiObject -Class Win32_Product | Where-Object {
        $_.IdentifyingNumber -match "$java"
    }
    &cmd /c "msiexec /uninstall $($app.IdentifyingNumber) /passive /quiet"
}

This code correctly uninstalls any version of 32-bit Java from Java 5 and on that is present on the system. However, it takes forever. Each item runs for 5-10 seconds - and then it moves on to the next. Is there any way to have it quickly skip over versions that are not found? Using a batch file this runs in under 15 seconds flat.

  • I think part of your issue is you are invoking the command shell for each uninstall. Try executing msiexec directly. – Keltari Apr 28 '14 at 13:55
  • So take the last line and change it to: msiexec /uninstall $($app.IdentifyingNumber) /passive /quiet ? – Tim P. Apr 28 '14 at 14:18
  • Gave that a whirl. It still worked correctly, but there wasn't a great improvement in the execution time compared to the standard batch file. – Tim P. Apr 28 '14 at 14:24
  • Should $_.IdentifyingNumber -match "$java" be $_.Name -match "$java"? Otherwise, if $java already contains the IdentifyingNumber, why would you query for it? – Rynant Apr 28 '14 at 14:41
  • The $_.IdentifyingNumber piece actually represents something like this: {26A24AE4-039D-4CA4-87B4-2F83217055FF} - Name would be something like "Java 7 Update 55" - what this does is looks at the Win32_Product list and finds programs that match the IdentifyingNumbers listed in the text file instead of Name, as Name might end up with false positives. – Tim P. Apr 28 '14 at 15:25
1

Since the $java variable already contains the IdentifyingNumber, just use it directly with msiexec.

$javaUninstall = Get-Content .\jre-uninstall-list.txt
foreach ($java in $javaUninstall) {
    write-host "Trying", "$java"
    msiexec /uninstall $java /passive /quiet
}
  • This is a great find. I need to call cmd /c anyway though, as the process fails if more than one Java installation exists due to the fact that it doesn't wait. So I do a cmd /c START /WAIT... and so forth. I appreciate the help, this made it much faster. – Tim P. Apr 28 '14 at 20:10
  • 1
    @Tim, can't you do Start-Process -Wait instead of calling cmd.exe? – dangph Apr 29 '14 at 7:14
0

As @dangph said, here is the PowerShell code below so you don't have to call CMD /C commands, and the user now only has to fill out the variables instead of playing with the syntax as well.

It's not much of a change I know, but the user doesn't have to worry about messing up a script that may otherwise be ok, if they need to change the script often, as I do with my scripts.

$javaUninstall = Get-Content -Path .\jre-uninstall-list.txt
$args = "/x $java /passive /quiet"
$msi = "msiexec"
foreach ($java in $javaUninstall) {
    write-host "Trying", "$java"
    Start-Process -FilePath $msi -ArgumentList $args -Wait -PassThru
}
  • Sure @DavidPostill, the user now only has to fill out the variables instead of playing with the syntax as well. It's not much of a change I know, but the user (if new to powershell, and remember that this answers not just for the person asking but anyone who also comes across this question) doesn't have to worry about messing up a script that may otherwise be ok, if they need to change the script often, as I do with my scripts. – Random206 Apr 19 '16 at 9:03
  • @DavidPostill Sure, no problems :) – Random206 Apr 19 '16 at 9:21
  • I did the edit on my iPhone via the app so not sure if it has messed up the layout and the code block sorry. – Random206 Apr 19 '16 at 9:24
-1

You could spin off each item in its own powershell instance. The solution I'm providing will likely be the most resource intensive (FYI). I don't want to take credit for another's work, so I'll link the script example provided HERE.

You'll could build the example into a function, and then iterate the function inside your foreach loop.

  • 2
    Only one MSI install/uninstall can be running at once. Spinning off separate instances would lead to collisions. – EBGreen Apr 28 '14 at 15:57
  • @ebgreen not in windows 7 – Colyn1337 Apr 28 '14 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.