Jump to content

Reading remote apps list from registry


Recommended Posts

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. TIA

#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 by powaking
Link to comment
Share on other sites

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

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. :P 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 by powaking
Link to comment
Share on other sites

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. :P

Change the following line:

Case $MSG = $but1

for this one

Case $MSG = $but1 Or $MSG = $chkbox

also 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

  • 2 weeks later...

Change the following line:

Case $MSG = $but1

for this one

Case $MSG = $but1 Or $MSG = $chkbox

also I will change the checkbox text Enable\Disable Silent Uninstall for Show Only Silent Unistall

Sorry 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

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...