Answered by:
PowerShell - How to return a number of characters from the right side of a string

-
Hi,
I need to extract the right 38 characters of a string and assign the result to a variable. I'm attempting to extract the GUID out of the example string below. I have done some searching but haven't found a clear example so far.
MsiExec.exe /X{CC41B2F4-7448-4908-9836-6550EA3A2452}
and
MsiExec.exe /I{09672816-7915-EE76-B099-988C6364B44D}
Thanks for your help!
Rob
- Edited by robwm1 Thursday, March 16, 2017 11:49 PM
Question
Answers
All replies
-
One of the more simpler ways could be a regex like this:
'MsiExec.exe /X{CC41B2F4-7448-4908-9836-6550EA3A2452}' -match '({(.+)})' $matches[1] $matches[2]
... but what for do you need this? There might be a better way to achieve what you want
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join'' -
I am trying to obtain the GUID for software installed on a client computer and then build out my own command line to remove the software. Using the UninstallString value itself is not always reliable because some of them have msiexec.exe /I which is install, not uninstall.
My idea is to get just the GUID and then build the following command line:
msiexec.exe /x {CC41B2F4-7448-4908-9836-6550EA3A2452} /qn
If there is a better way where you can get the GUID for a software title, it could simplify the whole approach. I am trying to get the value from these registry paths:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
After doing some research, I found that it is highly recommended to avoid using Win32_Product.
-
-
-
-
-
P.S. - This is the uninstall command it does not need to be changed. Just run ti.
MsiExec.exe /I{09672816-7915-EE76-B099-988C6364B44D}
Some uninstallers automatically uninstall with /U and other will use /X. The "UninstallString" key is correct as is.
\_(ツ)_/
- Edited by jrv Friday, March 17, 2017 1:05 AM
-
P.S. - This is the uninstall command it does not need to be changed. Just run ti.
MsiExec.exe /I{09672816-7915-EE76-B099-988C6364B44D}
... hmmm ... if I'm not wrong that's actually the install string. The uninstall parameter for msi should be the "/X". If you wnat to make it completely silent you can add "/qn". If you want to show at least a progress bar but without a cancel button you can add "qb-!"
But what I meant before: When I create a SCCM package with install and uninstall option I usualy know before what product I want to uninstall and so I don't need to determine the product ID with a script. I place the ready to use command line to the script including the right product ID / GUID.
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join'' -
Depends on the installer. Some MSIs will uninstall with that if the product is already installed. What is missing is the need to specify quiet mode which can be added.
If I scan on W10 about 1/3 of the uninstaller use /I and when run try to un9nstall the product. If there is an uninstall key it is correct or Windows could not use it.
\_(ツ)_/
-
In my experiences the uninstall string from the registry often just starts a setup interface where you can chose to install, repair, change or uninstall. All the silent or automatic uninstalls I did until now worked quite well with the parameter "/x".
Windows Installer Command-Line Options
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join'' -
-
-
jrv,
Using this command:
$software = "CustomInvite"
$uninstallPath = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"Get-ItemProperty $uninstallPath\* | where {$_.DisplayName -eq $software} | Select-Object UninstallString
The output looks like this:
@{UninstallString=MsiExec.exe /X{CC41B2F4-7448-4908-9836-6550EA3A2452}}
I also recall seeing output like this:
UninstallString
--------------------
MsiExec.exe /X{CC41B2F4-7448-4908-9836-6550EA3A2452}(I can't remember what I used for this output)
I must be using the wrong command here. This why I initially asked to extract the GUID so I could drop the rest. I'll try some other things to get a better result.
Rob
-
-
So if I do this:
$software = "CustomInvite"
$uninstallPath = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"$result = Get-ItemProperty $uninstallPath\* | where {$_.DisplayName -eq $software} | Select-Object -Expand UninstallString
$cmdLine = "$result /qb"
cmd /c $cmdLine
The program uninstalls but I would like PowerShell to wait for this command to complete before it continues. What is the best way to do that? I have tried Invoke-Command and Invoke-Expression but haven't found the right recipe yet.
-
-
That doesn't work:
. : The term 'MsiExec.exe /X{CC41B2F4-7448-4908-9836-6550EA3A2452} /qb' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At G:\Software\_Snippets\Get-SoftwareGUID.ps1:49 char:3
+ . $cmdLine
+ ~~~~~~~~
+ CategoryInfo : ObjectNotFound: (MsiExec.exe /X{...50EA3A2452} /qb:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException.\$cmdLine doesn't work either
- Edited by robwm1 Friday, March 17, 2017 6:12 PM
-
-
-
-
jrv,
Here is the solution that I will go with pasted below. I found that running msiexec.exe /I did not uninstall anything that I tried it on so I added the -replace switch as you suggested to make it a /X before running. This may seem like a waste to be a function but I will be adding custom logging output to it and include this in my snippet library.
Function Get-SoftwareUninstallPath ($softwareTitle,$uninstallPath) { <# .SYNOPSIS Given the registry uninstall path and software title, the function returns the UninstallString for the software title passed in. .DESCRIPTION This function receives the name of a software title and registry uninstall path and returns the UninstallString from the registry location specified: HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall or HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall .EXAMPLE $result = Get-SoftwareUninstallPath $software $path .PARAMETER $softwareTitle This value is used to filter the search for a specific software title. .PARAMETER $uninstallPath Set value to the registry path where the software will be found. HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall or HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall #> #Declare variables $result = "" #Get the software's uninstall string $result = Get-ItemProperty $uninstallPath\* | where {$_.DisplayName -eq $softwareTitle} | Select-Object -expand UninstallString #Return the uninstall string return $result } #Declare variables $software = "CustomInvite" $path = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" #Get the software uninstall path from the registry $returnedValue = Get-SoftwareUninstallPath $software $path #Change msiexec.exe /I to msiexec.exe /X $returnedValue = $returnedValue -replace '/I', '/X' #Remove software & cmd /c $returnedValue /qb
Thanks for all of your help! (You really should write a book)
Rob
-
-
-
robwm1,
so you obviously know already what software product you like to uninstall. If this software does not exist in different versions in your environment you don't have to determine the uninstall string or the Product-ID / GUID with the script. You already know it before. So you just have to run the uninstall command and the issue is over. ;-)
Really simple like this:
Start-Process -FilePath 'msiexec.exe' -ArgumentList '/x{CC41B2F4-7448-4908-9836-6550EA3A2452} /qn'
Or - if you want to have it a little more sofisticated like this:
$ProductID = '{CC41B2F4-7448-4908-9836-6550EA3A2452}' $Result = (Start-Process -FilePath 'msiexec.exe' -ArgumentList "/x$ProductID /qn" -Wait -Passthru).ExitCode
Now you even have the exit code of the msi process and can check if it's been ok.
Or - if you're really curious you could tell the msi to write an advanced logfile like this:
$ProductID = '{CC41B2F4-7448-4908-9836-6550EA3A2452}' $MSILogFile = 'C:\logfile.log' $Result = (Start-Process -FilePath 'msiexec.exe' -ArgumentList "/x$ProductID /l*v '$MSILogFile' /qn" -Wait -Passthru).ExitCode
Sometimes it happens that even msi installers include custom actions who trigger an unwanted reboot. Then you can try something like this:
$ProductID = '{CC41B2F4-7448-4908-9836-6550EA3A2452}' $MSILogFile = 'C:\logfile.log' $Result = (Start-Process -FilePath 'msiexec.exe' -ArgumentList "/x$ProductID REBOOT=ReallySuppress /l*v '$MSILogFile' /qn" -Wait -Passthru).ExitCode
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join''- Edited by BOfH_666 Saturday, March 18, 2017 1:32 PM
-
Here is an Uninstall string:
"C:\ProgramData\Caphyon\Advanced Installer\{5E951FA8-E127-4C74-AB27-BBD3698E013E}\PHW17Setup_2.1.34.0_XXXXXX_x64.exe /x {5E951FA8-E127-4C74-AB27-BBD3698E013E} AI_UNINSTALLER_CTP=1"
It is composed of two parts:
$installer ="C:\ProgramData\Caphyon\Advanced Installer\{2CDC80D4-C319-40EC-8641-88A72E28548D}\SPS17Setup_5.4.136.0_XXXXXX_x64.exe"
And:
$parameters = "/x {2CDC80D4-C319-40EC-8641-88A72E28548D} AI_UNINSTALLER_CTP=1"
Note that many, if not most, installer on Windows Vista and later are custom packages. They cannot use MsiExec correctly in many cases.
Most third party software and much of Microsoft Software uses these custom installer packages. Each installer vendor may take a different approach to an uninstall. Using MsiExec against many of these packages will not work which is why there is an UnInstallString entry.
MsiExec is still being used but, as you can see above, other options are needed by the bootstrapper.
If MsiExec is used against the correct GUID then it will try to call the UnInstallString value but the product GYUD found without an uninstall string may only do a partial removal of a product.
Here is one of many installer vendors that provide MSI based installers: Caphylon Ltd. Advanced Installer
Here is an InstallShield registry setting:
InstallShield_{E1646825-D391-42A0-93AA-27FA810DA093}
There is no UninstallString.
Here is an Uninstall string witj no GUID in sight:
rundll32.exe "C:\Program Files\Synaptics\SynTP\SynISDLL.dll",standAloneUninstall
So be careful how you manage uninstall strings.
\_(ツ)_/
- Edited by jrv Saturday, March 18, 2017 5:31 PM
-
PowerShell to find keys in both registries and match all or part of string.
$keys = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' Get-ItemProperty $keys| Select-Object WindowsInstaller, DisplayName, UninstallString # OR get only MSIExec packages Get-ItemProperty $keys | Where{$_.WindowsInstaller } | Select-Object WindowsInstaller, DisplayName, UninstallString | Format-Table @{ label = 'Win'; expression = { $_.WindowsInstaller };w=3}, @{ label = 'x'; expression = { $_.DisplayName } }, @{ label = 'Uninstall'; expression={ $_.UninstallString } } # OR Get a package by name $DisplayName = 'SQL Server 2016 Batch Parser' Get-ItemProperty $keys | Where-Object{ $_.WindowsInstaller -and $_.DisplayName -match $DisplayName} | Select-Object WindowsInstaller, DisplayName, UninstallString
\_(ツ)_/
- Edited by jrv Saturday, March 18, 2017 6:19 PM