Mark Minasi's Tech Forum
Register Calendar Latest Topics Chat
 
 
 


Reply
  Author   Comment  
BtilEntrails

Avatar / Picture

New Friend (or an Old Friend who Built a New Account)
Registered:
Posts: 19
Reply with quote  #1 
Trying to create a way to do uninstalls from an array where we only have to put in the DisplayName and it searches the 2 Uninstall registry hives at once looking for the applications we want to remove. The following code works great when the registry has a value for the Uninstall registry key is the typical MSI type of value like this;
MsiExec.exe /X{9A25302D-30C0-39D9-BD6F-21E6EC160475}

The code that we have at this time that works for MSI installed apps;

$OldSoftware = @(
    'PrimeSuite Scanning Components 14.0'
    'PrimeSuite Client Components'
)
Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall -ErrorAction SilentlyContinue | Get-ItemProperty | Where-Object {$OldSoftware -contains $_.DisplayName} | % {
     Write-Host "Uninstalling $($_.DisplayName)." #Display that the above app by name is being removed
     Start-Process $UninstallString[0]  -ArgumentList ($UninstallString[1]+' /quiet /norestart') -Wait
}

So for the part that I need help with is when we have a value from the registry and that value from the Uninstall key is with double quotes in it.

Example of such a value is from the registry;
"C:\Program Files (x86)\InstallShield Installation Information\{C488B40A-4BE9-47DE-BCAC-96F525A8F659}\setup.exe" -runfromtemp -l0x0409 anything -removeonly

The code I have been trying and where the new topic is named from when I get its error. I dropped the array from this code as most as I do not want our staff to do them this way as the command line for these older Setup.exe command lines are always different.

$OldSoftware = 'PrimeSuite Scanning Components 14.0'
Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall -ErrorAction SilentlyContinue | Get-ItemProperty | Where-Object {$OldSoftware -contains $_.DisplayName} | % {
     Write-Host "Uninstalling $($_.DisplayName)." #Display that the above app by name is being removed
     $UninstallString = $_.UninstallString -replace '-runfromtemp -l0x0009anything -removeonly','-s -runfromtemp -l0x0409 anything -removeonly' -split ' ',2 # adds the -s to make the uninstall silent
     Start-Process $UninstallString[0]  -ArgumentList ($UninstallString[1]) -Wait
}

I know the error is when my formatting and the double quotes for the path of the Setup.exe is my guess on what I am doing incorrectly.

Complete text of the output error;

PS C:\> C:\temp\RemoveManual.ps1
Uninstalling PrimeSuite Scanning Components 14.0.
Start-Process : This command cannot be run due to the error: The system cannot find the file specified.
At C:\temp\RemoveManual.ps1:7 char:6
+      Start-Process $UninstallString[0]  -ArgumentList ($UninstallString[1]) -Wai ...
+      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: ([smile] [Start-Process], InvalidOperationException
    + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand












__________________
Deep Thoughts by Jack Handey - "It takes a big man to cry, but it takes a bigger man to laugh at that man."
0
cj_berlin

Avatar / Picture

Senior Member
Registered:
Posts: 226
Reply with quote  #2 
Hi,

it's not the formatting of the double quotes but the splitting by space that causes the error. $UninstallString[0] will contain the part terminating with the first space which will not be the complete path to the executable [EDIT: if there is a space in the path]. You could do one of the following:
  • Don't split and dot-source the whole string (. $string)
  • Don't split and pass the string to Invoke-Expression
  • Split intelligently, e.g. look for ".exe" and use that position for splitting

__________________
Evgenij Smirnov

My personal blog (German): http://www.it-pro-berlin.de/
My stuff on PSGallery: https://www.powershellgallery.com/profiles/it-pro-berlin.de/
0
BtilEntrails

Avatar / Picture

New Friend (or an Old Friend who Built a New Account)
Registered:
Posts: 19
Reply with quote  #3 
I am sure you answered my question, but it was over my head for a reply or I am not following.

I commented out the line with the split, which should pass the command in the Uninstall key from the registry and still getting an error.

When I use the following I am able to see the output of the current registry key and its command;

Code;
$OldSoftware = 'PrimeSuite Scanning Components 14.0'
Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall -ErrorAction SilentlyContinue | Get-ItemProperty | Where-Object {$OldSoftware -contains $_.DisplayName} | % {
     Write-Host "Uninstalling $($_.DisplayName)." #Display that the above app by name is being removed
     $UninstallString
}

Output;
PS C:\> C:\temp\RemoveManual.ps1
Uninstalling PrimeSuite Scanning Components 14.0.
"C:\Program Files (x86)\InstallShield Installation Information\{9304FBF5-4265-4B5D-8A94-15324F549A60}\setup.exe
" -runfromtemp -l0x0009anything -removeonly


So when adding back the line where I need to add the silent command line switch.

Code;
$OldSoftware = 'PrimeSuite Scanning Components 14.0'
Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall -ErrorAction SilentlyContinue | Get-ItemProperty | Where-Object {$OldSoftware -contains $_.DisplayName} | % {
     Write-Host "Uninstalling $($_.DisplayName)." #Display that the above app by name is being removed
     $UninstallString = $_.UninstallString -replace '-runfromtemp -l0x0009anything -removeonly','-s -runfromtemp -l0x0009anything -removeonly' # adds the -s to make the uninstall silent
     $UninstallString
}

Output;
PS C:\> C:\temp\RemoveManual.ps1
Uninstalling PrimeSuite Scanning Components 14.0.
"C:\Program Files (x86)\InstallShield Installation Information\{9304FBF5-4265-4B5D-8A94-15324F549A60}\setup.exe
" -s -runfromtemp -l0x0009anything -removeonly

With this being shared, I can see my code so far as it is what I need to execute where I am getting the silent switch added to the output. That is the output I need to have executed.

So what is the correct way to get this to work or execute over just dumping as an output in PShell?

__________________
Deep Thoughts by Jack Handey - "It takes a big man to cry, but it takes a bigger man to laugh at that man."
0
cj_berlin

Avatar / Picture

Senior Member
Registered:
Posts: 226
Reply with quote  #4 
dot-sourcing: just put a dot and a space in front of the variable on a new line ;-)

or feed the variable to Invoke-Expression

__________________
Evgenij Smirnov

My personal blog (German): http://www.it-pro-berlin.de/
My stuff on PSGallery: https://www.powershellgallery.com/profiles/it-pro-berlin.de/
0
BtilEntrails

Avatar / Picture

New Friend (or an Old Friend who Built a New Account)
Registered:
Posts: 19
Reply with quote  #5 
That still did not help, just new things to chase down that I am without the skills to resolve.

So back to my previous post, if I can get the results in output in the powershell IDE as shared in the Output details above, how would I write the execute line?

I am able to get the details out of the registry keys and then make the changes I need by way of getting the silent switch to appear in the output. But not matter how I have attempted to execute the setup.exe as listed in the output, I keep getting path errors or some other errors as shared in by first post.

How would you write the line to execute, that would be what I am asking for assistance with.

Thanks in advance..

__________________
Deep Thoughts by Jack Handey - "It takes a big man to cry, but it takes a bigger man to laugh at that man."
0
cj_berlin

Avatar / Picture

Senior Member
Registered:
Posts: 226
Reply with quote  #6 
OK, try this: Once you have got your uninstall string ready, run

Code:

Invoke-Expression "cmd /c '$UninstallString'"


(those are single quotes around the $UninstallString)

__________________
Evgenij Smirnov

My personal blog (German): http://www.it-pro-berlin.de/
My stuff on PSGallery: https://www.powershellgallery.com/profiles/it-pro-berlin.de/
0
BtilEntrails

Avatar / Picture

New Friend (or an Old Friend who Built a New Account)
Registered:
Posts: 19
Reply with quote  #7 
Thank you!!!  Spot on!

$OldSoftware = 'PrimeSuite Scanning Components 14.0'

Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall -ErrorAction SilentlyContinue | Get-ItemProperty | Where-Object {$OldSoftware -contains $_.DisplayName} | % {
     $UninstallString = $_.UninstallString -replace '-runfromtemp -l0x0009anything -removeonly','-s -runfromtemp -l0x0409 anything -removeonly' -split ' ',2 # adds the -s to make the
Invoke-Expression "cmd /c '$UninstallString'"
}

The help files are great in PS, and is how I was able to get as far as I was when I made the post.  But the Start-Process command and the Invoke-Expression left me with gaps and confusion.

My shortfall was the use of CMD where with the MSI installs we use and the PS code in my first post, Start-Process kept me stuck in trying to make that work. And I had never used Invoke for the sort of work I am doing.

Once I seen your post, an instant level of happiness with a new level of respect for all this site has done for me over the years.

Thank you cj_berlin and all others that provide your time for others here.


__________________
Deep Thoughts by Jack Handey - "It takes a big man to cry, but it takes a bigger man to laugh at that man."
0
BtilEntrails

Avatar / Picture

New Friend (or an Old Friend who Built a New Account)
Registered:
Posts: 19
Reply with quote  #8 
Thank you!!!  Spot on!

$OldSoftware = 'PrimeSuite Scanning Components 14.0'

Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall -ErrorAction SilentlyContinue | Get-ItemProperty | Where-Object {$OldSoftware -contains $_.DisplayName} | % {
     $UninstallString = $_.UninstallString -replace '-runfromtemp -l0x0009anything -removeonly','-s -runfromtemp -l0x0409 anything -removeonly' -split ' ',2 # adds the -s to make the
Invoke-Expression "cmd /c '$UninstallString'"
}

The help files are great in PS, and is how I was able to get as far as I was when I made the post.  But the Start-Process command and the Invoke-Expression left me with gaps and confusion.

My shortfall was the use of CMD where with the MSI installs we use and the PS code in my first post, Start-Process kept me stuck in trying to make that work. And I had never used Invoke for the sort of work I am doing.

Once I seen your post, an instant level of happiness with a new level of respect for all this site has done for me over the years.

Thank you cj_berlin and all others that provide your time for others here.


__________________
Deep Thoughts by Jack Handey - "It takes a big man to cry, but it takes a bigger man to laugh at that man."
0
Previous Topic | Next Topic
Print
Reply

Quick Navigation:

Easily create a Forum Website with Website Toolbox.