31290 Posted August 11, 2016 Share Posted August 11, 2016 Hi guys One of my project is to create an uninstaller GUI that list all app on a computer so my techs can choose to remove apps without having to connect to his admin session (and loose time, especially while remotely controlling a domain machine). I did succeeded by creating a version one but it's very slow so I decided to create a version 2 of it, speeding things up and bring improvements. Here's my code so far: Spoiler expandcollapse popup#include <String.au3> #include <Array.au3> #include <Date.au3> #include <InetConstants.au3> #include <MsgBoxConstants.au3> #include <WinAPIFiles.au3> #include <WinAPISys.au3> #include <TrayConstants.au3> #include <ProgressConstants.au3> #include <ScreenCapture.au3> #include <StaticConstants.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <Date.au3> #include <File.au3> #Include <FontConstants.au3> #include <GUIConstantsEx.au3> #include <GuiEdit.au3> #include <GuiListView.au3> #include <GuiMenu.au3> #include <Array.au3> #include <ButtonConstants.au3> #include <ColorConstants.au3> #include <ComboConstants.au3> #include <ListBoxConstants.au3> #Include <EditConstants.au3> #include <WinAPISys.au3> #include <IE.au3> #include <WinAPI.au3> #include <Misc.au3> #include <GuiListView.au3> #include <MsgBoxConstants.au3> #NoTrayIcon Opt("TrayAutoPause", 0) Opt('GUIOnEventMode', 1) Opt('GUICloseOnEsc' , 1) FileDelete ("Uninstall.txt") Global $i Global $sSft Global $sGui = GUICreate('Select Programs You want to Uninstall:', 471, 650, -1, -1) Global $sLvw = GUICtrlCreateListView('Program Name', 2, 2, 467, 580, -1, $LVS_EX_CHECKBOXES) _ComputerGetSoftware($sSft) For $i = 1 To ubound($sSft) - 1 GUICtrlCreateListViewItem($sSft[$i], $sLvw) Next GUICtrlSendMsg($sLvw, 0x101E, 0, 450) Local $exp = GUICtrlCreateButton(' Uninstall ', 195, 590, 100, 55) Local $clear_sel = GUICtrlCreateButton(' Clear Selection ', 0, 600) Local $g_exit = GUICtrlCreateButton(' Exit ', 430, 600) GUICtrlSetOnEvent($exp, '_Uninstall') GUICtrlSetOnEvent($g_exit, '_AllExit') GUISetOnEvent(-3, '_AllExit') GUISetState(@SW_SHOW, $sGui) While 1 Sleep(1000) WEnd Func _ComputerGetSoftware(ByRef $aSoftwareInfo) Local Const $UnInstKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" Local $i = 1 Dim $aSoftwareInfo[1] For $j = 1 To 500 $AppKey = RegEnumKey($UnInstKey, $j) If @error <> 0 Then Exitloop If RegRead($UnInstKey & "\" & $AppKey, "DisplayName") = '' Then ContinueLoop ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1] $aSoftwareInfo[$i] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "DisplayName"), 1) $i = $i + 1 Next $aSoftwareInfo[0] = UBound($aSoftwareInfo, 1) - 1 Return _ArraySort($aSoftwareInfo) EndFunc Func _ClearSel() EndFunc Func _AllExit() GUIDelete($sGui) FileDelete ("Uninstall.txt") Exit EndFunc Func _Uninstall() Local Const $iCount = _GUICtrlListView_GetItemCount($sLvw) For $i = 1 To $iCount If _GUICtrlListView_GetItemChecked($sLvw, $i - 1) Then $sAppToUninstall = _GUICtrlListView_GetItemText($sLvw, $i - 1) Endif Next Global $g_Confirm = Msgbox (52, "WARNING", "Your're about to uninstall " & $sAppToUninstall & @CRLF & @CRLF & "Continue?") ; If $g_Confirm = $IDYES Then ; GuiSetState (@SW_DISABLE, $g_UninstallGUI) ;--------- ; Local Const $iCount = _GUICtrlListView_GetItemCount($sLvw) ; FileOpen("Uninstall.txt", 2) ; For $i = 1 To $iCount ; If _GUICtrlListView_GetItemChecked($sLvw, $i - 1) Then ; FileWrite("Uninstall.txt", _GUICtrlListView_GetItemText($sLvw, $i - 1) & @CRLF) ; EndIf ; Next ; FileClose ("Uninstall.txt") ; ShellExecute("Uninstall.bat") ; Exit EndFunc Problems are: 1/ If I click 2 items, only the last one is taken into account when I click the "uninstall" button (the msgbox is for testing outputs ATM) 2/ I can't figure out how to make the "Clear Selection" button to work (this may be a dumb question) 3/ I'd like to queue un-installations according to what the tech checked, in your opinion, what is best? (Make the script generating and executing a sort of .bat file for each selection? / Make the script running "RunAsWait($sT0_AdminUserName, "DOMAIN" ,$sT0_AdminUserPassword, 2, "WMIC.exe product where ""name like '" & $sAppToUninstall& "'"" call uninstall /nointeractive","",@SW_HIDE) for each selection? / write the selection in a .txt file and make the script read it line after line?, Other ideas? ^^) 4/ How can I exclude some programs in the soft list? I mean, I don't want the tech to see all Security Update blablabla crap and other things in the list (as the Anti Virus..) Thanks a lot for those who can help, Cheers, 31290 ~~~ Doom Shall Never Die, Only The Players ~~~ Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted August 11, 2016 Moderators Share Posted August 11, 2016 @31290 a couple of suggestions. I recently did something similar for a customer using WMI to query the machine (note, some crapware will not be seen through WMI, so I have on occasion had to do a mixture of WMI calls and searching through the registry): #include <Array.au3> Local $oWMI, $oProducts, $sApp, $aApps[1] = [""] $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") $oProducts = $oWMI.ExecQuery("Select * from Win32_Product") If IsObj($oProducts) Then If $oProducts.Count <> 0 Then For $sApp in $oProducts _ArrayAdd($aApps, $sApp.Name) Next $aApps[0] = UBound($aApps) - 1 EndIf EndIf If $aApps[0] > 0 Then _ArrayDisplay($aApps) You could then parse the array, using an if statement to weed out any programs you don't want to appear, and use this to populate your GUI. ;pseudo For $a = 1 To $aApps[0] If Not (StringInStr($aApps[$a], "<criteria>")) Then ;add to listview on GUI EndIf Next As for the uninstall, there are a couple of different options. You could again use WMI and just call the uninstall() function: ;pseudo $sAppName = ;Name returned from your GUI $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") $oProducts = $oWMI.ExecQuery("Select * from Win32_Product Where Name LIKE '%" & $sAppName & "%'") If IsObj($oProducts) Then If $oProducts.Count <> 0 Then For $sApp In $oProducts If $sApp.Name == $sAppName Then ;Match Name exactly, so as not to mistakenly uninstall any close matches $app.Uninstall() EndIf Next EndIf EndIf Or, as I am doing at a job right now, use the AppName to cycle through the registry and get the application's uninstall string: Local $sSubkey, $sAppName = "<name pulled from GUI>" Local $sKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" ;Have to account for HKLM64 if running against both 32 and 64bit machines For $a = 1 To 200 $sSubkey = RegEnumKey($sKey, $a) If @error Then ExitLoop Else If StringInStr(RegRead($sKey & "\" & $sSubkey, "DisplayName"), $sAppName) Then $sUninstall = RegRead($sKey & "\" & $sSubkey, "UninstallString") EndIf EndIf Next "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum! Link to comment Share on other sites More sharing options...
31290 Posted August 12, 2016 Author Share Posted August 12, 2016 JLogan3o13, Thanks a lot for the reply. This will help me a lot for sure. 21 hours ago, JLogan3o13 said: For $a = 1 To $aApps[0] If Not (StringInStr($aApps[$a], "<criteria>")) Then ;add to listview on GUI EndIf Next Do I have to type the entire name of the apps I don't want to be shown in the list? Because I tested with some programs and they still appears in the list. ~~~ Doom Shall Never Die, Only The Players ~~~ Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted August 12, 2016 Moderators Share Posted August 12, 2016 StringinStr is going to find any substring that you define in the criteria. So, for example, if you did this: Local $oWMI, $oProducts, $sApp $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") $oProducts = $oWMI.ExecQuery("Select * from Win32_Product") If IsObj($oProducts) Then If $oProducts.Count <> 0 Then For $sApp in $oProducts If StringInStr($sApp.Name, "Microsoft Office") Then ConsoleWrite($sApp.Name & @CRLF) Next EndIf EndIf You're going to pick up everything that matches that. On my machine it returns the following: Microsoft Office Professional Plus 2016 Microsoft Office 32-bit Components 2016 Microsoft Office Shared 32-bit MUI (English) 2016 Microsoft Office OSM MUI (English) 2016 Microsoft Office OSM UX MUI (English) 2016 Microsoft Office Shared Setup Metadata MUI (English) 2016 Microsoft Office Proofing (English) 2016 Microsoft Office Shared MUI (English) 2016 Microsoft Office Proofing Tools 2016 - English Herramientas de corrección de Microsoft Office 2016: español Outils de vérification linguistique 2016 de Microsoft Office - Français So you have to narrow the criteria down as far as you can. If I was looking for the main application, for example, I would set my criteria to something like " Office Professional Plus", so I capture only that app and none of the others. "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum! Link to comment Share on other sites More sharing options...
Carm01 Posted August 14, 2016 Share Posted August 14, 2016 I have found that WMIC command was ungodly slow, so i created a different method which is about 5x + faster than wmic. The catch is you have to know where things live in the registry and the uninstall silent switches. Its a bit more work, but in the end the time it takes to run wmic vs what I wrote below is hugely significant. I created something that will uninstall any Java runtimes, but leave anything with 'Development' or Javascript' alone as we needed something to push through Altiris and also create a set up for add java site exceptions for all users when re-installing. Below is the piece that removes Java runtimes; both 64 bit and 32 bit as an example to work off of. You will of course have to determine the reg location of the uninstall string and the silent uninstall command. This code took about 30 seconds or less to find and uninstall both 32 and 64 bit java on my machine but leave any Java development alone. Hope it will help or add to a list off suggestions for anyone else. expandcollapse popup#RequireAdmin Global $sBase_x64 = "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" Global $sBase_x32 = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" SplashTextOn("Progress", "", 220, 60, -1, -1, 16, "Tahoma", 10) ControlSetText("Progress", "", "Static1", "Uninstalling Java, please be patient could take a few minutes", 2) Call('step1') Call('u') Call('z') Exit Func U() $iEval = 1 $sSearch = "Java" While 1 $sUninst = "" $sDisplay = "" $sCurrent = RegEnumKey($sBase_x32, $iEval) If @error Then ExitLoop $sKey = $sBase_x32 & $sCurrent $sDisplay = RegRead($sKey, "DisplayName") If StringRegExp($sDisplay, "(?i).*" & $sSearch & ".*") Then If StringRegExp($sDisplay, "(?i).*" & "Development" & ".*") Then $iEval += 1 ContinueLoop ElseIf StringRegExp($sDisplay, "(?i).*" & "javascript" & ".*") Then $iEval += 1 ContinueLoop Else $sUninst1 = StringSplit(RegRead($sKey, "UninstallString"), "/X", 1) $sUninst = $sUninst1[1] & ' /QN' & ' /X' & $sUninst1[2] ControlSetText("Progress", "", "Static1", "Uninstalling " & $sDisplay, 2) RunWait($sUninst) Call('u') EndIf EndIf $iEval += 1 WEnd EndFunc ;==>U Func z() $iEval = 1 $sSearch = "Java" While 1 $sUninst = "" $sDisplay = "" $sCurrent = RegEnumKey($sBase_x64, $iEval) If @error Then ExitLoop $sKey = $sBase_x64 & $sCurrent $sDisplay = RegRead($sKey, "DisplayName") If StringRegExp($sDisplay, "(?i).*" & $sSearch & ".*") Then If StringRegExp($sDisplay, "(?i).*" & "Development" & ".*") Then $iEval += 1 ContinueLoop ElseIf StringRegExp($sDisplay, "(?i).*" & "javascript" & ".*") Then $iEval += 1 ContinueLoop Else $sUninst1 = StringSplit(RegRead($sKey, "UninstallString"), "/X", 1) $sUninst = $sUninst1[1] & ' /QN' & ' /X' & $sUninst1[2] ControlSetText("Progress", "", "Static1", "Uninstalling " & $sDisplay, 2) RunWait($sUninst) Call('z') EndIf EndIf $iEval += 1 WEnd EndFunc ;==>z Func step1() $iEval = 1 $sSearch = "Java Auto Updater" While 1 $sUninst = "" $sDisplay = "" $sCurrent = RegEnumKey($sBase_x64, $iEval) If @error Then ExitLoop $sKey = $sBase_x64 & $sCurrent $sDisplay = RegRead($sKey, "DisplayName") If StringRegExp($sDisplay, "(?i).*" & $sSearch & ".*") Then RegDelete($sKey) EndIf $iEval += 1 WEnd EndFunc ;==>step1 Link to comment Share on other sites More sharing options...
jguinch Posted August 14, 2016 Share Posted August 14, 2016 Here is my _UninstallList function, maybe it can help you... Spoiler Network configuration UDF, _DirGetSizeByExtension, _UninstallList Firefox ConfigurationArray multi-dimensions, Printer Management UDF Link to comment Share on other sites More sharing options...
31290 Posted August 19, 2016 Author Share Posted August 19, 2016 (edited) Everyone Thanks a lot for your inputs, much appreciated and really helped. But ( ) In my code, how to combine both x32 and x64 reg paths on a x64 based arch? I can only see applications located in the x32 reg path... Spoiler Func _ComputerGetSoftware(ByRef $aSoftwareInfo) If @OSArch = "x86" Then Local Const $UnInstKey = "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" Local $i = 1 Dim $aSoftwareInfo[1] For $j = 1 To 500 $AppKey = RegEnumKey($UnInstKey, $j) If @error <> 0 Then Exitloop If RegRead($UnInstKey & "\" & $AppKey, "DisplayName") = '' Then ContinueLoop ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1] $aSoftwareInfo[$i] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "DisplayName"), 1) $i = $i + 1 Next $aSoftwareInfo[0] = UBound($aSoftwareInfo, 1) - 1 Return _ArraySort($aSoftwareInfo) ElseIf @OSArch = "x64" Then Local Const $UnInstKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" Local $i = 1 Dim $aSoftwareInfo[1] For $j = 1 To 500 $AppKey = RegEnumKey($UnInstKey, $j) If @error <> 0 Then Exitloop If RegRead($UnInstKey & "\" & $AppKey, "DisplayName") = '' Then ContinueLoop ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1] $aSoftwareInfo[$i] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "DisplayName"), 1) $i = $i + 1 Next $aSoftwareInfo[0] = UBound($aSoftwareInfo, 1) - 1 Return _ArraySort($aSoftwareInfo) EndIf EndFunc I tried to play with: Spoiler If @OSArch = "X64" Then $UnInstKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\|' & _ 'HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\|' & _ 'HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' ElseIf @OSArch = "X86" Then $UnInstKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\|' & _ 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\|' & _ 'HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' EndIf But now, I have nothing in my list. Any thoughts / directions / help? Thanks EDIT: In fact, I already created an uninstaller but WMIC are too long for my techs needs. So I really need to speed it up (by reading reg paths depending on the OSArch) and add the possibility to queue uninstallations (I thought of writing their choices in a text file and then perform some RunAsWait wmic uninstall functions). I thought replacing the combobox by a listbox with check boxes but apparently this is not easy as I thought it would be... Spoiler expandcollapse popup#include <Array.au3> #include <GuiComboBox.au3> #include <ButtonConstants.au3> #include <ColorConstants.au3> #include <ComboConstants.au3> #Include <Constants.au3> #include <Date.au3> #include <File.au3> #Include <FontConstants.au3> #include <GUIConstantsEx.au3> #include <GuiEdit.au3> #include <GuiListView.au3> #include <GuiMenu.au3> #include <Misc.au3> #include <MsgBoxConstants.au3> #include <ProgressConstants.au3> #include <ScreenCapture.au3> #include <StaticConstants.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <StringConstants.au3> #include <AD.au3> Opt("GUIOnEventMode", 1) Global $Resources = "C:\SAC_IS\SEE_Uninstaller\Resources" DirCreate($Resources) FileInstall ("C:\Users\h74033\Google Drive\ZZZ_Main Resources\SAClogo.jpg", $resources & "\SAClogo.jpg", 1) f_UninstallerMainGUI() While 1 Sleep(10) Wend Func f_UninstallerMainGUI() Global $g_UninstallGUI = GuiCreate ("SEE UNINSTALLER", 400, 500) GUISetBkColor ($Color_White) GUICtrlCreatePic ($Resources & "\SAClogo.jpg", 80, 10, 240, 80) $g_DescLabel = GUICtrlCreateLabel("-- SEE UNINSTALLER --", 135, 105) GUICtrlSetFont (-1, 8.5, 700, 0) GUICtrlCreateSeparator(0, 5, 130, 2, 390) GUICtrlCreateLabel("*** Current Computer: " & @ComputerName & " ***", 100, 140, 250, 20) GUICtrlSetFont (-1, 8.5, 700, 0) GUICtrlSetColor (-1, $COLOR_PURPLE) GuiCtrlCreateLabel ("Click the above button to list Applications that can be uninstalled:", 5, 180, 370) GUICtrlSetFont (-1, 8.5, 700, 0) Global $g_AppList = GUICtrlCreateButton ("Populate list", 160, 200, 75, 50) GuiCtrlSetOnEvent (-1, "f_ListApps") GUISetOnEvent($GUI_EVENT_CLOSE, "_exit") GuiSetState() EndFunc Func f_ListApps() GuiSetState (@SW_DISABLE, $g_UninstallGUI) SplashTextOn ("", "Getting Apps, please wait...", 700, 100, -1, -1, 33, -1, -1, 700) RunWait(@ComSpec & ' /c ' & 'wmic /node:' & @Computername &' product get name > %temp%\model.txt' ,"", @SW_HIDE) Global $comboBox = GUICtrlCreateCombo(" Select App from the List", 5, 270, 395, 300, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL, $WS_VSCROLL, $CBS_SORT)) $file =(@TempDir & "/model.txt") $fileread = FileRead($file) $aFileArray = FileReadToArray($file) _ArrayDelete($aFileArray, 0) For $i = 0 To UBound($aFileArray, 1) - 1 $aFileArray[$i] = StringStripWs($aFileArray[$i], $STR_STRIPTRAILING) GUICtrlSetData($comboBox,$aFileArray[$i]) Next $sText = " Select App from the List" _GUICtrlComboBox_SelectString ($comboBox, $sText) GuiCtrlCreateButton ("Proceed to Application Uninstallation", 110, 300, -1, 50) GuiCtrlSetOnEvent (-1, "f_Uninstall") GuiCtrlCreateLabel ("TIP: You can type the first letters of the Application and press the Down arrow " & @CRLF & "to go faster.", 5, 370) SplashOff() GuiSetState (@SW_ENABLE, $g_UninstallGUI) FileDelete(@TempDir & "/model.txt") EndFunc Func f_Uninstall() ;can't be used in this example. $sAppToUninstall = GUICtrlRead ($comboBox) If $sAppToUninstall = " Select App from the List" Then MsgBox (16, "Error", "You can't do that") Else $g_Confirm = Msgbox (52, "WARNING", "Your're about to uninstall " & $sAppToUninstall & @CRLF & @CRLF & "Continue?") If $g_Confirm = $IDYES Then GuiSetState (@SW_DISABLE, $g_UninstallGUI) SplashTextOn ("", "Uninstalling " & $sAppToUninstall & ", please wait...",700, 100, -1, -1, 33, -1, -1, 700) RunAsWait($sT0_AdminUserName, "MYDOMAIN" ,$sT0_AdminUserPassword, 2, "WMIC.exe product where ""name like '" & $sAppToUninstall& "'"" call uninstall /nointeractive","",@SW_HIDE) SplashOff() GuiSetState (@SW_ENABLE, $g_UninstallGUI) $g_AnotherApp = Msgbox (36, "INFORMATION", $sAppToUninstall & " has been successfully uninstalled from the system!" & @CRLF & @CRLF & "Uninstall another Application? -- Script will be reloaded --") If $g_AnotherApp = $IDYES Then RestartScript() ElseIf $g_AnotherApp = $IDNO Then _exit() EndIf ElseIf $g_Confirm = $IDNO Then Msgbox (64, "INFORMATION", "Application won't be uninstalled!") EndIf Endif EndFunc ;Separator Creation Func GuiCtrlCreateSeparator($Direction, $Left, $Top, $Width=3, $Lenght=25) Switch $Direction Case 0 GUICtrlCreateLabel("", $Left, $Top, $Lenght, $Width, $SS_SUNKEN) Case 1 GUICtrlCreateLabel("", $Left, $Top, $Width, $Lenght, $SS_SUNKEN) EndSwitch EndFunc Func RestartScript() If @Compiled = 1 Then Run(FileGetShortName(@ScriptFullPath)) Else Run(FileGetShortName(@AutoItExe) & " " & FileGetShortName(@ScriptFullPath)) EndIf _exit() EndFunc Func f_closeGUI() GUIdelete() GuiSetState (@SW_ENABLE, $g_UninstallGUI) GuiSetState (@SW_RESTORE, $g_UninstallGUI) EndFunc Func _exit() Exit EndFunc Thanks for the help you can provide. Edited August 19, 2016 by 31290 ~~~ Doom Shall Never Die, Only The Players ~~~ Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted August 19, 2016 Moderators Share Posted August 19, 2016 @31290 from the help file: When running on 64-bit Windows if you want to read a value specific to the 64-bit environment you have to suffix the HK... with 64 i.e. HKLM64. Have you tried this? "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum! Link to comment Share on other sites More sharing options...
31290 Posted August 19, 2016 Author Share Posted August 19, 2016 8 minutes ago, JLogan3o13 said: @31290 from the help file: When running on 64-bit Windows if you want to read a value specific to the 64-bit environment you have to suffix the HK... with 64 i.e. HKLM64. Have you tried this? Yes, In my previous post I defined a variable If @OSArch = "X64" Then $UnInstKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\|' & _ 'HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\|' & _ 'HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' ElseIf @OSArch = "X86" Then $UnInstKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\|' & _ 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\|' & _ 'HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' EndIf Because on x64, I have to look mix both reg path. For example, I have an X64 version of iTunes and 7zip and they don't show in my list whereas it works with the first version of my soft (code on previous post). When looking at the regedit, many soft are installed in the x86 HKLM place and some in the x64 one (iTunes and 7Zip for example). that's why I need both of them in the same variable to populate my list... Thanks for your input btw ~~~ Doom Shall Never Die, Only The Players ~~~ Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted August 19, 2016 Moderators Share Posted August 19, 2016 I understand what you're saying, but if I do this: #include <Array.au3> Local $sSubkey, $ax86[1] = [""], $ax64[1] = [""] Local $sKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" Local $sx64Key = "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" For $a = 1 To 1000 $sSubkey = RegEnumKey($sKey, $a) If @error Then ExitLoop Else _ArrayAdd($ax86, $sSubkey) EndIf Next For $b = 1 To 1000 $sSubkey = RegEnumKey($sx64Key, $b) If @error Then ExitLoop Else _ArrayAdd($ax64, $sSubkey) EndIf Next $ax86[0] = UBound($ax86) - 1 $ax64[0] = UBound($ax64) - 1 _ArrayDisplay($ax86, "Keys Under Wow6432Node") _ArrayDisplay($ax64, "Keys Under " & $sx64Key) it enumerates the different keys just fine. If, as in your example, I am looking for 7zip, I could do something like this: #include <Array.au3> Local $sSubkey, $a7Zip[1] = [""] Local $sKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" Local $sx64Key = "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" For $a = 1 To 1000 $sSubkey = RegEnumKey($sKey, $a) If @error Then ExitLoop ElseIf StringInStr(RegRead($sKey & $sSubkey, "DisplayName"), "7-Zip") Then _ArrayAdd($a7Zip, $sKey & $sSubkey) EndIf Next If @OSArch = "X64" Then For $b = 1 To 1000 $sSubkey = RegEnumKey($sx64Key, $b) If @error Then ExitLoop ElseIf StringInStr(RegRead($sx64Key & $sSubkey, "DisplayName"), "7-Zip") Then _ArrayAdd($a7Zip, $sx64Key & $sSubkey) EndIf Next EndIf $a7Zip[0] = UBound($a7Zip) - 1 If $a7Zip[0] > 0 Then _ArrayDisplay($a7Zip, "All instances of 7-Zip") Is this not working for you? "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum! Link to comment Share on other sites More sharing options...
31290 Posted August 22, 2016 Author Share Posted August 22, 2016 Hi Sorry for the late response. Yes, this is working, but it's how to implement that to my current script to speed it up? I'm not good at all with arrays and despite reading help file, I still can't get it. Thanks ~~~ Doom Shall Never Die, Only The Players ~~~ Link to comment Share on other sites More sharing options...
youtuber Posted May 6, 2021 Share Posted May 6, 2021 I needed this code today and. I think the code given by @JLogan3o13 will scan both x86 and x64 systems, if I am wrong, please warn me or notify me. Doesn't it make more sense to look at the OSArch value first for this? #include <Array.au3> Local $a = 0, $b = 0 Local $sSubkey, $a7Zip[1] = [""] Local $sKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" Local $sx64Key = "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" If @OSArch = "X64" Then While 1 $a += 1 $sSubkey = RegEnumKey($sx64Key, $a) If @error Then ExitLoop If StringInStr(RegRead($sx64Key & $sSubkey, "DisplayName"), "7-Zip") Then _ArrayAdd($a7Zip, $sx64Key & $sSubkey) EndIf WEnd Else While 1 $b += 1 $sSubkey = RegEnumKey($sKey, $b) If @error Then ExitLoop If StringInStr(RegRead($sKey & $sSubkey, "DisplayName"), "7-Zip") Then _ArrayAdd($a7Zip, $sKey & $sSubkey) EndIf WEnd EndIf $a7Zip[0] = UBound($a7Zip) - 1 If $a7Zip[0] > 0 Then _ArrayDisplay($a7Zip, "All instances of 7-Zip") Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted May 6, 2021 Moderators Share Posted May 6, 2021 @youtuber the point of the code that I posted (5 years ago, you have been around long enough to know better) was to always search the x86 hive for software. And, if it is a 64-bit system (which 5 years later you are almost guaranteed it will be) also search the 64bit hive. The point of doing so is many applications, at that time, were still 32bit. So you could have 7zip, for example, install in either Program Files or Program Files (x86) on a 64bit system, and the OP needed a way to find the software regardless of the bitness installed. Your code will indeed search the 64bit hive for the application. However, if a 32-bit version was installed for some reason (still happens, though not as much as in 2016), you would miss it. "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum! Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now