powaking Posted August 30, 2006 Share Posted August 30, 2006 (edited) I extracted this from Firestorms compinfo tool. Wanted to make a stand alone add/remove programs for both local and remote machines. For some reason when reading remote machines it is not populating the entire list. Getting maybe 1/3 of the programs from the registry.You can view my reply to Firestorms app here Edit: If you run the tool and put your own machine name in the field it will give different results even though its supposidly reading the same keys on the same machine. TIAexpandcollapse popup#include <CompInfo.au3> #include <Inet.au3> #include <File.au3> #include <Constants.au3> #include <GuiStatusBar.au3> #include <GUIConstants.au3> #include <GuiListView.au3> #include <process.au3> #NoTrayIcon GUISetIcon("install.ico") Dim $Software Dim $Key = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall" Dim $Title = "Display Uninstall" Dim $EnableList = 1 Dim $RemoteComputer Local $a_PartsRightEdge[2] = [344,-1] Local $a_PartsText[2] = ["","v .1 2006"] $SelectedCount = 0 Global $wait $mainWindows = GUICreate("Software Uninstaller", 490, 391, -1, -1) GUICtrlCreateIcon("shell32.dll", 162, 23, 17, 32, 32) $Progress1 = GUICtrlCreateProgress(16, 340, 457, 20,$PBS_SMOOTH) GUICtrlSetState($Progress1, $GUI_HIDE) $ulist = GUICtrlCreateListView(" |Display Name|Key Item", 16, 64, 457, 269, BitOR($LVS_NOSORTHEADER, $LVS_REPORT, $LVS_SHOWSELALWAYS), BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $LVS_EX_SUBITEMIMAGES)) GUICtrlSetResizing($ulist, $GUI_DOCKBORDERS) _GUICtrlListViewSetColumnWidth($ulist, 0, $LVSCW_AUTOSIZE_USEHEADER) _GUICtrlListViewSetColumnWidth($ulist, 1, 310) _GUICtrlListViewSetColumnWidth($ulist, 2, 310) $but1 = GUICtrlCreateButton("Refresh List", 74, 32, 100, 25, $BS_DEFPUSHBUTTON) GUICtrlSetResizing($but1, $GUI_DOCKALL) $but2 = GUICtrlCreateButton("Uninstall Program", 175, 32, 100, 25) GUICtrlSetResizing($but2, $GUI_DOCKALL) GUICtrlSetState($but2, $GUI_DISABLE) $chkbox = GUICtrlCreateCheckbox("Enable\Disable Silent Uninstall", 300, 34) GUICtrlSetResizing($chkbox, $GUI_DOCKALL) $Label1 = GUICtrlCreateLabel("Remote Computer (Leave blank for local list): ", 70, 10, 230, 20) GUICtrlSetResizing($Label1, $GUI_DOCKALL) $Input1 = GUICtrlCreateInput("", 290, 8, 180, 20, BitOR($ES_LEFT, $ES_AUTOHSCROLL, $ES_UPPERCASE)) GUICtrlSetResizing($Input1, $GUI_DOCKALL) $StatusBar1 = _GuiCtrlStatusBarCreate($mainWindows, $a_PartsRightEdge, $a_PartsText, $SBT_TOOLTIPS) _GuiCtrlStatusBarSetMinHeight($StatusBar1, 15) GUICtrlSetResizing($Progress1, $GUI_DOCKSTATEBAR) GUISetState() While 1 $msg = GUIGetMsg() Select Case $msg = $GUI_EVENT_CLOSE _Selfdelete() Exit Case $MSG = $but1 _GUICtrlStatusBarSetIcon($StatusBar1, 0,"shell32.dll", 171) GUICtrlSetState($Progress1, $GUI_SHOW) _GUICtrlListViewDeleteAllItems ($ulist) $RemoteComputer = StringReplace(GUICtrlRead($Input1), '\', '') $List = ReadKeys($RemoteComputer) GUICtrlSetData($Input1, '') GUICtrlSetData($progress1,0) GUICtrlSetState($Progress1, $GUI_HIDE) Case $MSG = $but2 _GUICtrlStatusBarSetIcon($StatusBar1, 0, "shell32.dll", 162) $ListIndices = _GUICtrlListViewGetSelectedIndices ($ulist, 1) If $ListIndices == $LV_ERR Then ContinueLoop If $ListIndices[0] > 1 Then GUICtrlSetState($Progress1, $GUI_SHOW) Opt('RunErrorsFatal', 0) $Count = 0 ControlListView('', '', $ulist, "SelectClear") For $x = $ListIndices[0] To 1 Step - 1 $Count += 1 $SelectKey = '' GUICtrlSetData($Progress1, Int(($Count / $ListIndices[0]) * 100)) $ListInfo = StringSplit($List[$ListIndices[$x]], '|');ListInfo[0] = 5, ListInfo[1] = Display Name, ListInfo[2] = Regkey Name, ListInfo[3] = Icon, ListInfo[4] = QuietUninstallString, ListInfo[5] = UnistallString If GUICtrlRead($chkbox) == $GUI_CHECKED Or $RemoteComputer <> '' Then $SelectKey = $ListInfo[4] If $SelectKey == '' Then $SelectKey = StringReplace($ListInfo[5], '/i', '/X', 1) & ' /qn /norestart' _GuiCtrlStatusBarSetText ($StatusBar1, ' Uninstalling Program ' & $Count & ' Of ' & $ListIndices[0] & ' ' & $ListInfo[1]) EndIf If GUICtrlRead($chkbox) == $GUI_UNCHECKED And $SelectKey == '' Then $SelectKey = $ListInfo[5] _GuiCtrlStatusBarSetText ($StatusBar1, ' Uninstalling Program ' & $Count & ' Of ' & $ListIndices[0] & ' ' & $ListInfo[1]) EndIf If $RemoteComputer == '' Then $Pid = Run($SelectKey, @WorkingDir, @SW_SHOW) Else $Pid = Run('BeyondExecv2.exe ' & StringMid($RemoteComputer, 1, StringInStr($RemoteComputer, '\', 0, -1) - 1) & ' -s -n -r ' & $SelectKey, @WorkingDir, @SW_HIDE) EndIf If @error Then _FileWriteLog(@ScriptDir & '\UninstallFail.Log', $ListInfo[1] & ' | ' & $SelectKey) EndIf If Not @error And $RemoteComputer <> "" Then GUISetCursor(15, 1);set cursor to wait While ProcessExists($Pid) Sleep(50) WEnd GUISetCursor(2, 1);set cursor to arrow ;ProcessWaitClose($Pid) SetError(0) RegRead($RemoteComputer & $Key & "\" & $ListInfo[2], 'UninstallString') If @error == 1 Then _GUICtrlListViewDeleteItem ($ulist, $ListIndices[$x]) _ArrayDelete($List, $ListIndices[$x]) EndIf Next Opt('RunErrorsFatal', 1) If $ListIndices[0] > 1 Then GUICtrlSetState($Progress1, $GUI_HIDE) _GUICtrlStatusBarSetIcon($StatusBar1, 0,"shell32.dll", 171) If $RemoteComputer == '' Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Local Computer: ' & _GUICtrlListViewGetItemCount ($ulist) & ' Objects, ' & _GUICtrlListViewGetSelectedCount ($ulist) & ' Objects Selected') Else _GuiCtrlStatusBarSetText ($StatusBar1, ' Remote Computer: ' & '"' & StringReplace($RemoteComputer, '\', '') & '"' & ', ' & _GUICtrlListViewGetItemCount ($ulist) & ' Objects, ' _ & _GUICtrlListViewGetSelectedCount ($ulist) & ' Objects Selected') EndIf GUICtrlSetState($but2, $GUI_DISABLE) Case $MSG = $GUI_EVENT_CLOSE Exit ; resize columns based on window size Case $MSG = $GUI_EVENT_MINIMIZE $width = ControlGetPos($mainWindows, "", $ulist) $Resize = $width[2] - _GUICtrlListViewGetColumnWidth ($ulist, 0) _GUICtrlListViewSetColumnWidth ($ulist, 1, $Resize / 2.1) _GUICtrlListViewSetColumnWidth ($ulist, 2, $Resize / 2.1) _GuiCtrlStatusBarResize ($StatusBar1) Case $MSG = $GUI_EVENT_MAXIMIZE $width = ControlGetPos($mainWindows, "", $ulist) $Resize = $width[2] - _GUICtrlListViewGetColumnWidth ($ulist, 0) _GUICtrlListViewSetColumnWidth ($ulist, 1, $Resize / 2.1) _GUICtrlListViewSetColumnWidth ($ulist, 2, $Resize / 2.1) _GuiCtrlStatusBarResize ($StatusBar1) Case $MSG = $GUI_EVENT_RESIZED $width = ControlGetPos($mainWindows, "", $ulist) $Resize = $width[2] - _GUICtrlListViewGetColumnWidth ($ulist, 0) _GUICtrlListViewSetColumnWidth ($ulist, 1, $Resize / 2.1) _GUICtrlListViewSetColumnWidth ($ulist, 2, $Resize / 2.1) _GuiCtrlStatusBarResize ($StatusBar1) Case $MSG = $GUI_EVENT_RESTORE $width = ControlGetPos($mainWindows, "", $ulist) $Resize = $width[2] - _GUICtrlListViewGetColumnWidth ($ulist, 0) _GUICtrlListViewSetColumnWidth ($ulist, 1, $Resize / 2.1) _GUICtrlListViewSetColumnWidth ($ulist, 2, $Resize / 2.1) _GuiCtrlStatusBarResize ($StatusBar1) Case Else If $EnableList And $SelectedCount == 1 Then $EnableList = 0 GUICtrlSetState($but2, $GUI_ENABLE);enable uninstall button EndIf If Not $EnableList And $SelectedCount == 0 Then $EnableList = 1 GUICtrlSetState($but2, $GUI_DISABLE);disable uninstall button EndIf If $SelectedCount <> _GUICtrlListViewGetSelectedCount ($ulist) Then $SelectedCount = _GUICtrlListViewGetSelectedCount ($ulist) If $RemoteComputer == '' Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Local Computer: ' & _GUICtrlListViewGetItemCount ($ulist) & ' Objects, ' & _GUICtrlListViewGetSelectedCount ($ulist) & ' Objects Selected') Else _GuiCtrlStatusBarSetText ($StatusBar1, ' Remote Computer: ' & '"' & StringReplace($RemoteComputer, '\', '') & '"' & ', ' & _GUICtrlListViewGetItemCount ($ulist) & ' Objects, ' _ & _GUICtrlListViewGetSelectedCount ($ulist) & ' Objects Selected') EndIf EndIf EndSelect WEnd Func ReadKeys($s_RemoteComputer = '') GUISetCursor(15, 1);set cursor to wait Local $even = 1 Local $Count = 1 Dim $avArray[1] If $s_RemoteComputer <> '' Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Reading Remote Registry Keys... Please Wait....') If StringMid($s_RemoteComputer, 1, 1) <> '\' Or StringMid($s_RemoteComputer, 2, 1) <> '\' Or StringRight($s_RemoteComputer, 1) <> '\' Then $s_RemoteComputer = '\\' & StringReplace($s_RemoteComputer, '\', '') & '\' EndIf Else _GuiCtrlStatusBarSetText ($StatusBar1, ' Reading Registry Keys, Please Wait....') EndIf Local Const $regkey = $s_RemoteComputer & 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall' While 1 $skey = RegEnumKey($regkey, $Count) If @error <> 0 Then ExitLoop $line = RegRead($regkey & '\' & $skey, 'Displayname') $line = StringReplace($line, ' (remove only)', '') If $line == '' Then $line = "No Display Name" $SilentUnistall = RegRead($regkey & '\' & $skey, 'QuietUninstallString') $Unistall = RegRead($regkey & '\' & $skey, 'UninstallString') $Icon = RegRead($regkey & '\' & $skey, 'DisplayIcon') $Icon = StringReplace(StringMid($Icon, 1, StringInStr($Icon, ',') - 1), '"', '') If $Icon = "" Then $Icon = "SHELL32.DLL" If $SilentUnistall <> '' Or $Unistall <> '' Then If (GUICtrlRead($chkbox) == $GUI_CHECKED And $SilentUnistall <> '') Or ($s_RemoteComputer <> '' And $SilentUnistall <> '') Then $avArray[UBound($avArray) - 1] = $line & '|' & $skey & '|' & $Icon & '|' & $SilentUnistall & '|' ReDim $avArray[UBound($avArray) + 1] ElseIf ($s_RemoteComputer == '' And GUICtrlRead($chkbox) == $GUI_UNCHECKED) Or (GUICtrlRead($chkbox) == $GUI_CHECKED And StringInStr($Unistall, 'msiexec.exe')) Or ($s_RemoteComputer <> '' And StringInStr($Unistall, 'msiexec.exe')) Then $avArray[UBound($avArray) - 1] = $line & '|' & $skey & '|' & $Icon & '|' & $SilentUnistall & '|' & $Unistall ReDim $avArray[UBound($avArray) + 1] EndIf EndIf $Count += 1 WEnd If (UBound($avArray) - 1) == 0 Then If $RemoteComputer == '' Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Local Computer: ' & _GUICtrlListViewGetItemCount ($ulist) & ' Objects, ' & _GUICtrlListViewGetSelectedCount ($ulist) & ' Objects Selected') If $RemoteComputer <> '' And _GUICtrlListViewGetItemCount ($ulist) Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Remote Computer: ' & '"' & StringReplace($RemoteComputer, '\', '') & '"' & ', ' & _GUICtrlListViewGetItemCount ($ulist) & ' Objects, ' _ & _GUICtrlListViewGetSelectedCount ($ulist) & ' Objects Selected') $RemoteComputer = '\\' & $RemoteComputer & '\' ElseIf $RemoteComputer <> '' And _GUICtrlListViewGetItemCount ($ulist) == 0 Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Could Not Connect To Remote Computer ' & '"' & StringReplace($RemoteComputer, '\', '') & '"') $RemoteComputer = '' EndIf Else ReDim $avArray[UBound($avArray) - 1] _ArraySort($avArray) For $i = 0 To UBound($avArray) - 1 GUICtrlSetData($Progress1, Int(($i / (UBound($avArray) - 1)) * 100)) $Item = StringSplit($avArray[$i], '|') Local $lv_item = GUICtrlCreateListViewItem("" & "|" & $Item[1] & "|" & $Item[2], $ulist) GUICtrlSetImage(-1, $Item[3]) If $even Then $even = 0 GUICtrlSetBkColor($lv_item, 0x5CACEE) Else GUICtrlSetBkColor($lv_item, 0x9FB6CD) $even = 1 EndIf Sleep(15) Next Sleep(1000) If $RemoteComputer == '' Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Local Computer: ' & _GUICtrlListViewGetItemCount ($ulist) & ' Objects, ' & _GUICtrlListViewGetSelectedCount ($ulist) & ' Objects Selected') If $RemoteComputer <> '' And _GUICtrlListViewGetItemCount ($ulist) Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Remote Computer: ' & '"' & StringReplace($RemoteComputer, '\', '') & '"' & ', ' & _GUICtrlListViewGetItemCount ($ulist) & ' Objects, ' _ & _GUICtrlListViewGetSelectedCount ($ulist) & ' Objects Selected') $RemoteComputer = '\\' & $RemoteComputer & '\' ElseIf $RemoteComputer <> '' And _GUICtrlListViewGetItemCount ($ulist) == 0 Then _GuiCtrlStatusBarSetText ($StatusBar1, ' Could Not Connect To Remote Computer ' & '"' & StringReplace($RemoteComputer, '\', '') & '"') $RemoteComputer = '' EndIf EndIf GUISetCursor(2, 1);set cursor to arrow Return ($avArray) EndFunc;==>ReadKeys Edited August 31, 2006 by powaking Link to comment Share on other sites More sharing options...
Danny35d Posted August 31, 2006 Share Posted August 31, 2006 For some reason when reading remote machines it is not populating the entire list. Getting maybe 1/3 of the programs from the registry.This is basically the same script as this other post by big_daddy. Any way the answer to you question, for the remote machines the script will only show you all the applications that can be silently uninstall. Otherwise you will have to physically walk to the remote computer to answer the unistall windows messages. AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line Link to comment Share on other sites More sharing options...
powaking Posted August 31, 2006 Author Share Posted August 31, 2006 (edited) This is basically the same script as this other post by big_daddy. Any way the answer to you question, for the remote machines the script will only show you all the applications that can be silently uninstall. Otherwise you will have to physically walk to the remote computer to answer the unistall windows messages. Ok that answers that question but is there anyway to have it list all keys depending on if the checkbox is checked? If the checkbox is not checked it would list all keys. Should you click on the checkbox then the list would modify to only show ones that can be silently uninstalled. I seem to get the same results regardless if the checkbox is checked when checking my own machine. Edit: Ok I think I have it. It seems to display the list correctly now on remote machines when reading the checkbox. I haven't tested uninstalling anything just yet though. Added this. ElseIf ($s_RemoteComputer <> '' And GUICtrlRead($chkbox) == $GUI_CHECKED) Then $avArray[UBound($avArray) - 1] = $line & '|' & $skey & '|' & $Icon & '|' & $SilentUnistall & '|' & $Unistall ReDim $avArray[UBound($avArray) + 1] oÝ÷ Ù:-+ºÚ"µÍY ÌÍÔÚ[[[Ý[ ÉÝÈ ÌÎNÉÌÎNÈÜ ÌÍÕ[Ý[ ÉÝÈ ÌÎNÉÌÎNÈ[Y ÕRPÝXY ÌÍØÚØÞ HOH ÌÍÑÕRWÐÒPÒÑQ[ ÌÍÔÚ[[[Ý[ ÉÝÈ ÌÎNÉÌÎNÊHÜ ÌÍÜ×Ô[[ÝPÛÛ] ÉÝÈ ÌÎNÉÌÎNÈ[ ÌÍÔÚ[[[Ý[ ÉÝÈ ÌÎNÉÌÎNÊH[ ÌÍØ]^VÕPÝ[ ÌÍØ]^JHHWHH ÌÍÛ[H [È ÌÎNß ÌÎNÈ [È ÌÍÜÚÙ^H [È ÌÎNß ÌÎNÈ [È ÌÍÒXÛÛ [È ÌÎNß ÌÎNÈ [È ÌÍÔÚ[[[Ý[ [È ÌÎNß ÌÎNÂQ[H ÌÍØ]^VÕPÝ[ ÌÍØ]^JH ÈWB[ÙRY ÌÍÜ×Ô[[ÝPÛÛ]OH ÌÎNÉÌÎNÈ[ÕRPÝXY ÌÍØÚØÞ HOH ÌÍÑÕRWÕSÒPÒÑQ HÜ ÕRPÝXY ÌÍØÚØÞ HOH ÌÍÑÕRWÐÒPÒÑQ[Ý[Ò[Ý ÌÍÕ[Ý[ ÌÎNÛÚY^XË^IÌÎNÊJHÜ ÌÍÜ×Ô[[ÝPÛÛ] ÉÝÈ ÌÎNÉÌÎNÈ[Ý[Ò[Ý ÌÍÕ[Ý[ ÌÎNÛÚY^XË^IÌÎNÊJH[ ÌÍØ]^VÕPÝ[ ÌÍØ]^JHHWHH ÌÍÛ[H [È ÌÎNß ÌÎNÈ [È ÌÍÜÚÙ^H [È ÌÎNß ÌÎNÈ [È ÌÍÒXÛÛ [È ÌÎNß ÌÎNÈ [È ÌÍÔÚ[[[Ý[ [È ÌÎNß ÌÎNÈ [È ÌÍÕ[Ý[Q[H ÌÍØ]^VÕPÝ[ ÌÍØ]^JH ÈWBBBQ[ÙRY ÌÍÜ×Ô[[ÝPÛÛ] ÉÝÈ ÌÎNÉÌÎNÈ[ÕRPÝXY ÌÍØÚØÞ HOH ÌÍÑÕRWÐÒPÒÑQ H[BBBIÌÍØ]^VÕPÝ[ ÌÍØ]^JHHWHH ÌÍÛ[H [È ÌÎNß ÌÎNÈ [È ÌÍÜÚÙ^H [È ÌÎNß ÌÎNÈ [È ÌÍÒXÛÛ [È ÌÎNß ÌÎNÈ [È ÌÍÔÚ[[[Ý[ [È ÌÎNß ÌÎNÈ [È ÌÍÕ[Ý[Q[H ÌÍØ]^VÕPÝ[ ÌÍØ]^JH ÈWB[Y[Y Now if I could only make it change the list when the button is clicked so as not to have to do a Refresh on the list all over again. Unless make it list all apps but only make the ones that can be silently uninstallable enabled. The others would be disabled but still listable. Need to have it list all installed apps on remote machines not just ones that be silently uninstalled. Edited August 31, 2006 by powaking Link to comment Share on other sites More sharing options...
Danny35d Posted August 31, 2006 Share Posted August 31, 2006 Now if I could only make it change the list when the button is clicked so as not to have to do a Refresh on the list all over again. Change the following line:Case $MSG = $but1for this oneCase $MSG = $but1 Or $MSG = $chkboxalso I will change the checkbox text Enable\Disable Silent Uninstall for Show Only Silent Unistall AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line Link to comment Share on other sites More sharing options...
powaking Posted September 15, 2006 Author Share Posted September 15, 2006 Change the following line:Case $MSG = $but1for this oneCase $MSG = $but1 Or $MSG = $chkboxalso I will change the checkbox text Enable\Disable Silent Uninstall for Show Only Silent UnistallSorry replying so late but yes this does seem to work well. The only down side I see in this app now (and I know its the way its written) is how long it takes to read the keys from a remote machine. The only other way I can think of expediting this process is to use TCP calls where you would shoot over a small tcp app that would read the keys locally and shoot them over instead of re-regreading the keys over and over until it finishes. What are your thoughts on this? 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