Jump to content
Sign in to follow this  

Working with different uninstallers is getting really complicated

Recommended Posts

So is there a better solution to the problem?

Ive been throwing together some code for a multiple uninstaller, which started simply enough but is getting out of control rapidly.

The problem stems from having different types of uninstallers like this

Local $sProgramString = ""
$sProgramString = "|C:\Program Files\Program1\uninstall.exe|C:\Program Files (x86)\Program2\uninstall.exe|C:\Program Files (x86)\Program3\uninstall.exe|C:\Program Files (x86)\Program4\ExtCapUninstall\hpzscr01.exe|C:\Program Files (x86)\Program5\uninstal.exe|C:\PROGRA~1\Program6\bar\1.bin\mwsbar.dll

Which starts them fine but then i ran across MSI and other types with switches so i added this

Local $aProgramArray = StringSplit($sProgramString, "|")

For $i = 0 To UBound($aProgramArray) - 1
    If FileExists($aProgramArray[$i]) Then
        Local $UninCheck = $aProgramArray[$i]

            Case $UninCheck = "C:\Program Files (x86)\Program4\ExtCapUninstall\hpzscr01.exe" 
                ShellExecuteWait('C:\Program Files (x86)\Program4\ExtCapUninstall\hpzscr01.exe', '-datfile hpqhsc01.dat')

And these

Case $UninCheck = 'C:\Program Files (x86)\Program5\uninstal.exe'
                ShellExecuteWait('MsiExec.exe', '/X{C28D96C0-6A90-459E-A077-A6706F4EC0FC} /qb')

And these

Case $UninCheck = "C:\PROGRA~1\Program6\bar\1.bin\mwsbar.dll" 
                ShellExecuteWait('rundll32', 'C:\PROGRA~1\Program6\bar\1.bin\mwsbar.dll,O')

And to close it off

Case Else
                ShellExecuteWait($aProgramArray[$i], "")

Obviously i have to have the program in the top array as well as an individual Case just in case it has switches or msi etc

One problem i have also noticed is that sometimes it opens multiple ones at the same time which i was using the shellexecute wait to control... i guess the program opening cancels the wait?

So is there an easier way to manage this stuff than im doing it already? And i would like some way of trigger the program name in and error msg when it fails on an uninstaller

All it does is run them one after another until there is no more on that machine

Edited by Chimaera

Share this post

Link to post
Share on other sites

Have you thought about using the registry? Loop through the HKLMSOFTWAREMicrosoftWindowsCurrentVersionUninstall key, checking the DisplayName value. If it matches what you're wanting to uninstall, read the UninstallString or QuietUninstallString value in that subkey, and use that as the parameters for a RunWait line.

Share this post

Link to post
Share on other sites

Ok thanks ill have a look into that

The Quiet one seems to already have the switches set (when available)

Im sure i saw a find in registry type of code somewhere so ill have a look

Share this post

Link to post
Share on other sites

Yes, in here you have some useful keys:




Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples


Share this post

Link to post
Share on other sites

You could also skip the registry altogether and go with WMI:

#include <MsgBoxConstants.au3>

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20

$sName = InputBox("App Uninstall", "Please enter the product name")
$WMI = ObjGet("winmgmts:\\" & @ComputerName & "\root\CIMV2")
$aItems = $WMI.ExecQuery("SELECT * FROM Win32_Product", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

For $product In $aItems
    If StringInStr($product.Name, $sName) Then$
          uninst = MsgBox($MB_YESNO, $product.Name, "Would you like to uninstall?")
            If $uninst = $IDYES Then $product.Uninstall

With a slight tweak (and the proper access of course) this works for remote machines as well.

Edited by JLogan3o13

Share this post

Link to post
Share on other sites

Here is what I use

$Log ="C:\Script.log"
_FileWriteLog ($Log, "Log Started")

If @OSArch = "X86" Then
   $Keyroot = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";uninstall keyroot for X86 machines
   _FileWriteLog ($Log, "This is a 32bit machine")

If @OSArch = "X64" Then
   $Keyroot = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall";uninstall keyroot for X64 machines
    _FileWriteLog ($Log, "This is a 64bit machine")

;Uninstall Routine
_FileWriteLog ($Log, "Searching for previous installations")
SplashTextOn ("", "Searching for Software",300,50,-1,-1,1); shows text
Sleep (1500);wait, showing text

$index = 1
$subkey = "***START***"; we use this because "" will make our While loop exit
While $subkey <> ""
    $subkey = RegEnumKey($keyroot, $index)
    If StringInStr(RegRead($keyroot & "\" & $subkey, "DisplayName"), _
    "NAME HERE") Then
        $GUID = $subkey  ; Record the GUID
        $subkey = ""    ; Force the While to exit
        $GUID = ""
    $index = $index + 1
 SplashOff(); text off

If $GUID <> "" Then; if GUID is found
   _FileWriteLog ($Log, "Already Installed")
SplashTextOn ("", "Found Successfully",300,50,-1,-1,1); show text
Sleep (1500); wait with text
SplashTextOn ("", "Uninstalling",300,50,-1,-1,1); text on

_FileWriteLog ($Log, "Uninstalling....")
RunWait ("MsiExec.exe /x" & $GUID & " /quiet"); run uninstaller
_FileWriteLog ($Log, "Uninstall Finished")
SplashOff(); text off
   SplashTextOn ("", "Not Installed",300,50,-1,-1,1); show text
   _FileWriteLog ($Log, "Not Previously Installed")
   Sleep (1500); wait with text

Share this post

Link to post
Share on other sites

@JLogan3o13 i tried that but it would find somethings but not others, CCleaner was a deffo it couldnt get, strange but thanks anyway. It was good as all i needed was the name in control panel which saves work

@wisem2540 that ran but only gave 4 lines on the log with no uninstall files did i miss something?

I think im going to have to try and rethink how i started as the uninstall keys i have are valid just need a simpler way to run them

Just for info these are the main keys for all uninstallers

$path_1 = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall\"
$path_2 = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
$path_3 = "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
$path_4 = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
$path_5 = "HKCU64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"

Share this post

Link to post
Share on other sites


Did you change the display name to match the app you are trying to uninstall?  Did the log say it found the app?  If so, the uninstall string is wrong.  If not the display name is wrong..

Either way, look at the regkey....

See this line?

RunWait ("MsiExec.exe /x" & $GUID & " /quiet"); run uninstaller

 Make sure this is the uninstall string from the regkey.  You may want to do a regread and capture it once the guid is returned.  Let me know if I can help.

Share this post

Link to post
Share on other sites


try my script in the spoiler there, ive had some installers without a "quiet" option and some without an uninstallkey entry, but those were few.

Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post

Link to post
Share on other sites

Unfortunately, there are as many uninstallers as there are installers, so you will probably have to have more than one method.  WMI is the most universal method, but there are sometimes apps that don't register themselves properly to uninstall that way, and it tends to be slower in my experience.  For my uninstallers, I use the following order:

1. Scan the registry for QuietUninstallString strings, then for UninstallString.

2. Check if it can be removed using WMI

3. Use a custom uninstaller for that app (only known apps, obviously)

As far as not waiting for uninstall to complete before proceeding, some unistallers will launch other processes to do the uninstall work, then close the main process.  The only way around that, that I have found is to find some key file that the uninstaller will remove, and use While FileExists(file) to wait for it.  This works best with method #1, since there is often (though not always) an executable name somewhere in the same registry key.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Create New...