I'm dealing with a product (I-Quest International Codes 2009) that uses a different uninstall GUID every time it's installed. That obviously makes it a little more difficult to script an uninstall. Anyone know of a way to get around that?

Push comes to shove, I may need to look at adding some code to the install that looks in C:\Program Files\Installshield Installation\ for a directory that's less than 5 minutes old, let's say, and renames it to something predictable. If this were Linux/UNIX, that would be a piece of cake. But under Windows... if there's no better solution, can anyone point me in the right direction there?
0 Comments   [ + ] Show Comments

## Comments

Please log in to comment

Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.

### Answers

0
Depending on what the actual contents is of the installer, it might be a good idea to use a snapshot tool and create your own MSI installer for this application (from what you mentioned it sounds like and old Installshield installer)

That way you'll get a consistent installer and uninstaller.

PJ
Answered 01/10/2011 by: pjgeutjens

Please log in to comment
0
i had to deal with this once;

i see 2 ways to get around this: you could add some code at the installation that will put the GUID in a text file which could be read at uninstall. or you could run a script that will check in the reg uninstall key for the GUID. either way is pretty easy to do.
Answered 01/10/2011 by: kardock

Please log in to comment
0
i see 2 ways to get around this: you could add some code at the installation that will put the GUID in a text file which could be read at uninstall. or you could run a script that will check in the reg uninstall key for the GUID. either way is pretty easy to do.

Well, I am just running the install, not packaging it. If there's a way to capture the GUID during install, I'd love to hear it.

As for the other way... the registry GUID changes, too. So I found a piece of VBScript that's supposed to hunt through all of the Uninstall keys for a specific text string and return the name of the key it's in, but I couldn't make that go, as I'm just not familiar with VBScript. If this was Linux, no sweat, I'd be done. But then, if this was Linux, I wouldn't have to deal with registries and changing GUIDs ;)
Answered 01/11/2011 by: jnojr

Please log in to comment
0

Hello,

I had a very similar problem today, and it took me a while to find an elegant solution. My application had the following UninstallString, with 'SOME GUID' being a different guid every time:

"C:\Program Files (x86)\InstallShield Installation Information\{SOME-GUID}\setup.exe" -runfromtemp -l0x0009 -removeonly

I managed to uninstall the whole thing in 3 CMD lines

FOR /F "tokens=*" %%A IN ('reg query HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /f "UNIQUE_DISPLAY_NAME" /s ^| FindStr /R "[{].*[}]"') DO SET GUID=%%Aset GUID=%GUID:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\=%"%ProgramFiles(x86)%\InstallShield Installation Information\%GUID%\setup.exe" -runfromtemp -l0x0009 -removeonly -s -f1"c:\complete\path\to\uninstall.iss"

So what this does, is search the part of the registry where the uninstallstrings are for the 'Display Name' (This name needs to be modified). The line that contains the GUID is then filtered out by searching for a regular expression with FindStr /R "[{].*[}]". The result is stored in variable GUID.

After the first line, the variable GUID should contain:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{AND-THE-ENTIRE-GUID}

The whole path is then deleted by a search and replace, with a syntax I only discoverd today, for example, to replace 'teh' with 'the': VARIALBE = %VARIALBE:teh=the%. What remains is the GUID.

I then generated an uninstall.iss using the -r switch, and included it as a parameter with: -s -f1"c:\complete\path\to\uninstall.iss" (don't forget to include the full path if you do this, otherwise you may have unexpected results).

Hopefully, this will help someone, someday.

Cheers!

Answered 09/25/2012 by: cubefreak

• Some fool downvoted Cubefreak's excellent answer. Thankyou very much.
Careful with your UNIQUE_DISPLAY_NAME - I had two application names which differed by a * character and the script didn't respect batch file escaping. So I had to use another registry field to get a unique match.
But it's automated, and done. Excellent work.
Please log in to comment
0
you could modify this powershell script i use to remove java, it searches for the reg uninstall guid using the publisher and product name then uses msiexec to silently uninstall.

# Log file funtion        function time{(Get-Date -Format dd-MM-yyyy-hh:mm:ss)}    $logfile = "c:\temp\JRE-Uninstall.log" Function LogWrite {Param ([string]$logstring)Add-content $Logfile -value ($(time) + " - $logstring ")}#Product to Remove$Product = '*Java*'#Publisher$Publisher = '*Oracle*'#32bit Uninstall Strings$32bitPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'#64bit Uninstall Strings$64bitPath = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall'try{$JavaVersions = Get-ChildItem -Path $32bitPath,$64bitPath | Get-ItemProperty  -ErrorAction Stop | Where-Object { $_.DisplayName -like "$Product" -and $_.Publisher -like "$Publisher"} | Select-Object -Property DisplayName, UninstallString }catch{$_}if($JavaVersions -eq $null){exit LogWrite "Java not found"}$v = $JavaVersions.DisplayName |Out-StringLogWrite "detected$V"#Perform silent uninstall of targeted versionsforeach ($Version in$JavaVersions) {Write-Host $JavaVersions.DisplayName}do{ForEach ($Version in $JavaVersions){$v = $Version.DisplayName |Out-String$Uninstall = $Version.UninstallString.replace("MsiExec.exe /I","MsiExec.exe /X") Write-Host$Uninstall    LogWrite "Removing $v$Uninstall"		Start-Process cmd.exe -ArgumentList "/k $Uninstall /qn /norestart" logwrite "Removed$v GUID $Uninstall" Start-Sleep 60 try{$Javaremoved = Get-ChildItem -Path $32bitPath,$64bitPath | Get-ItemProperty  -ErrorAction Stop | Where-Object { $_.DisplayName -like "$Product" -and $_.Publisher -like "$Publisher"} | Select-Object -Property DisplayName, UninstallString }catch{$_}}}until($Javaremoved -eq \$null)LogWrite "Removal complete"exit
Answered 03/21/2017 by: m0del101

Please log in to comment
0
The simplest solution I use regularly is a bit of vbscript that instantiates the windows installer object and searches for a match on the product name string. Then it removes the associated MSI.  For all instances of that product name.
The actions are logged - in my case to an existing logfile set up as an environment variable by a control script, but it can of course be set to anything you choose. Return codes are yours to change according to need also.

Option Explicit
Dim WshShell, installer, appname1, appname2, comp, guid, a, fso, pname, pid, cache, exitcode, strCurrDir, strLog
exitcode=0
appname1="ALEPH"  'appnamex MUST BE UPPER CASE!
appname2=""

Set fso = CreateObject("Scripting.FileSystemObject")
Set WshShell = CreateObject("WScript.Shell")
strCurrDir = wshShell.ExpandEnvironmentStrings("%CURRDIR%")
strLog = wshShell.ExpandEnvironmentStrings("%LOG_FILE%")

' Connect to Windows Installer object
Set installer = CreateObject("WindowsInstaller.Installer")
WLog Now & " - Products Uninstalled (if any):"
on error resume next
For Each guid In installer.products
pname = installer.productinfo(guid, "InstalledProductName")
If Instr(1,UCase(pname),appname1,1)>0 Then
exitcode=1
'wscript.echo guid
cache = installer.productinfo (guid, "LocalPackage")
'wscript.echo "msiexec.exe /x " & guid & " /qn /L*v "&chr(34)&"C:\logs\"&pname&"LOG.txt"&chr(34)
WshShell.Run "msiexec.exe /x " & guid & " /qn /L*v "&chr(34)&"C:\logs\"&pname&"LOG.txt"&chr(34) ,1,true
WLog Now & " - ProductName " & pname  & "  "  & "ProductGUID " & guid & "  " & "Cached MSI filename " &  cache
End If
If appname2<>"" Then
If Instr(1,UCase(pname),appname2,1)>0 Then
exitcode=1
'wscript.echo guid
cache = installer.productinfo (guid, "LocalPackage")
'wscript.echo "msiexec.exe /x " & guid & " /qn /L*v "&chr(34)&"C:\logs\"&pname&"LOG.txt"&chr(34)
WshShell.Run "msiexec.exe /x " & guid & " /qn /L*v "&chr(34)&"C:\logs\"&pname&"LOG.txt"&chr(34) ,1,true
WLog Now & " - ProductName " & pname  & "  "  & "ProductGUID " & guid & "  " & "Cached MSI filename " &  cache
End If
End If
Next
Set installer = Nothing
a.close
wscript.quit(exitcode)

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub WLog(sTxt)  'Needs: strLog = wshShell.ExpandEnvironmentStrings("%LOG_FILE%")
Dim ts, sErrTxt
On Error Resume Next
Set ts = fso.OpenTextFile(strLog, 8, True)
ts.WriteLine sTxt
ts.Close
If Err.Number Then
If Not fso.FileExists(strLog) Then
sErrTxt = WScript.ScriptName & " - ERROR: Unable to write to log file '" & strLog & "' - Error " & Err.Number & " - " & Err.Description & vbCrlf & vbCrlf & "Log Entry: " & sTxt
wshShell.LogEvent 1, sErrTxt
WScript.Quit 114031
End If
WScript.Sleep 100
Wlog(sTxt)
End If
On Error Goto 0
Set ts = Nothing
End Sub
Answered 03/23/2017 by: EdT

Please log in to comment
or Comment on this question for clarity