Installed Software

  • Hallo liebe Community.

    Ich bin neu hier und hoffe das ich hier richtig bin :)
    Ich habe ein kniffliges Problem.
    Zuerst mal, was möchte ich eigentlich machen?
    Ich würde mir gerne die installierten Programme auf meinem Computer auslesen.
    Das ist nicht das Problem, da man dies sehr leicht über die Registry erreichen kann.
    Aber wenn es so einfach wäre, würde ich ja nicht hier posten :D
    Das Problem ist folgendes:
    Beim auslesen gibt es viele Einträge (z.B. Windows Live Messenger etc mehrfach!)
    Ich verwende aktuell dieses Skript:

    [autoit]


    #include <GUIConstants.au3>

    $gui_width = 500
    $gui_height = 600

    Global $count = 1, $all_keys = "", $main_key = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"

    GUICreate("Installed Software", $gui_width, $gui_height, @Desktopwidth/2 - $gui_width/2, @DesktopHeight/2 - $gui_height/2 - 75)
    $gui_list = GUICtrlCreateList ("", 10, 10, $gui_width - 20, $gui_height - 20)
    GUISetState ()

    While 1
    $act_key = RegEnumKey ($main_key, $count)
    If @error <> 0 then ExitLoop
    $act_name = RegRead ($main_key & "" & $act_key, "Displayname")
    $act_name = StringReplace ($act_name, " (remove only)", "")
    If $act_name <> "" Then $all_keys = $all_keys & $act_name & "|"
    $count = $count + 1
    WEnd

    GUICtrlSetData ($gui_list, $all_keys)
    While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    Wend

    [/autoit]

    Hier kann man erkennen das es mehrere Einträge vielfach gibt:

    [Blockierte Grafik: http://s7.directupload.net/images/131228/cwcwv9kq.gif]


    Ich habe vieles versucht, auch die Einträge aus der Registry auszulesen, selbes Problem.
    Allerdings, wenn man mal in die Systemsteuerung schaut, fällt auf, das dieses Problem dort nicht auftaucht:

    [Blockierte Grafik: http://s7.directupload.net/images/131228/ymvpeawy.gif]


    Kann mir jemand helfen die Installierten programme so auszulesen wie es in der Systemsteuerung auch gemacht wird?
    Normalwerweise wird ja dieser Key verwendet:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall



    Wo liegt das Problem?
    WMI mit Namespace: root/CiMv2 in Class: Win32_Product hat nichts gebracht, gleiches Problem.


    Kann mir jemand helfen?

  • Hab dein Script mal ein wenig geändert. Doubletten sollten nun nicht mehr möglich sein, außerdem liest es sowohl den 32bit, als auch den 64bit Schlüssel aus. Bei mir erscheinen manche Einträge aber trotzdem mehrfach und unterscheiden sich nur in der Sprachversion, desweiteren sollte man Windowsupdates noch ausfiltern, dazu einfach den aktuellen Namen mit stringinstr prüfen und bei Bedarf ein continueloop anstatt den key zur Liste hinzuzufügen, schon ist der ungewünschte Eintrag übersprungen...

    Spoiler anzeigen
    [autoit]


    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_UseX64=n
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    #include <GUIConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $gui_width = 500
    $gui_height = 600

    [/autoit] [autoit][/autoit] [autoit]

    Global $count = 1, $all_keys = "", $abort = 0
    Global $main_key = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    Global $main_key64 = "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    Global $key = $main_key

    [/autoit] [autoit][/autoit] [autoit]

    GUICreate("Installed Software", $gui_width, $gui_height, @Desktopwidth/2 - $gui_width/2, @DesktopHeight/2 - $gui_height/2 - 75)
    $gui_list = GUICtrlCreateList ("", 10, 10, $gui_width - 20, $gui_height - 20)
    GUISetState ()

    [/autoit] [autoit][/autoit] [autoit]

    do
    $act_key = RegEnumKey ($key, $count)
    If @error <> 0 then
    $abort += 1
    $count = 1
    $key = $main_key64
    Else
    $count = $count + 1
    $act_name = RegRead ($key & '\' & $act_key, "Displayname")
    $act_name = StringReplace ($act_name, " (remove only)", "")
    if stringinstr($act_name,"Security Update") then continueloop
    if stringinstr($act_name,"Update for Microsoft") then continueloop
    if stringinstr($act_name,"Hotfix für") then continueloop
    if stringinstr($act_name,"Hotfix for") then continueloop
    if stringinstr($act_name,"Service Pack") then continueloop
    If $act_name <> "" And Not StringInStr($all_keys,"|" & $act_name & "|") Then $all_keys = $all_keys & $act_name & "|"
    EndIf
    until $abort = 2

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlSetData ($gui_list, $all_keys)
    While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    Wend

    [/autoit]

    2 Mal editiert, zuletzt von misterspeed (28. Dezember 2013 um 21:26)

  • misterspeed
    Danke das ist auf jeden Fall schonmal ein Fortschritt.
    Bei mir werden allerdings auch noch Manche Einträge in verschiedenen Sprachen aufgelistet:

    [Blockierte Grafik: http://s7.directupload.net/images/131228/5wxp7yf3.png]


    Wie wäre das zu lösen?
    Ich wüsste nicht wie ich das realisieren kann, da hier ein simples StringInStr nicht sehr hilfreich ist.
    Und in der Systemsteuerung werden ja auch keine Einträge in unterschiedlichen Sprachen angezeigt...

  • Pobier mal das hier...

    Spoiler anzeigen
    [autoit]


    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_UseX64=n
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    #include <GUIConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $gui_width = 500
    $gui_height = 600

    [/autoit] [autoit][/autoit] [autoit]

    Global $count = 1, $all_keys = "", $abort = 0
    Global $main_key = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    Global $main_key64 = "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    Global $key = $main_key

    [/autoit] [autoit][/autoit] [autoit]

    GUICreate("Installed Software", $gui_width, $gui_height, @Desktopwidth/2 - $gui_width/2, @DesktopHeight/2 - $gui_height/2 - 75)
    $gui_list = GUICtrlCreateList ("", 10, 10, $gui_width - 20, $gui_height - 20)
    GUISetState ()

    [/autoit] [autoit][/autoit] [autoit]

    $foundItems = 0
    do
    $act_key = RegEnumKey ($key, $count)
    If @error <> 0 then
    $abort += 1
    $count = 1
    $key = $main_key64
    Else
    $count = $count + 1
    $act_name = RegRead ($key & '\' & $act_key, "Displayname")
    $act_name = StringReplace ($act_name, " (remove only)", "")
    if stringinstr($act_name,"Security Update") then continueloop
    if stringinstr($act_name,"Update for Microsoft") then continueloop
    if stringinstr($act_name,"Hotfix für") then continueloop
    if stringinstr($act_name,"Hotfix for") then continueloop
    if stringinstr($act_name,"Service Pack") then continueloop
    If $act_name <> "" And Not StringInStr($all_keys,"|" & $act_name & "|") Then
    $dontShow = RegRead($key & '\' & $act_key, "SystemComponent")
    ConsoleWrite( $dontShow & @TAB & $act_name & @CRLF)
    If $dontShow = 1 Then ContinueLoop
    $all_keys = $all_keys & $act_name & "|"
    $foundItems += 1
    EndIf
    EndIf
    until $abort = 2
    ConsoleWrite ("Einträge: " & $foundItems & @CRLF)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    GUICtrlSetData ($gui_list, $all_keys)
    While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    Wend

    [/autoit]
  • Was genau?

    Die letzte Änderung liest zusätzlich noch den Schlüssel "SystemComponent" aus, welcher sich bei manchen Einträgen befindet. Meine Vermutung war, dass in der Systemsteuerung ausgeblendete Programme genau diesen Schlüssel mit dem Wert 1 besitzen, zumindestens ist bei mir soweit ich das beim groben Überfliegen gesehen habe keines der Programme sichtbar, welches diesen Schlüssel mit dem Wert 1 besitzt. Daher habe ich alle Einträge die diese Bedingung erfüllen mit continueloop übersprungen, genau wie ich es weiter oben bereits mit den Update/Hotfix Einträgen mache. In der Scite console lasse ich zur Kontrolle alle Einträge mit dem zugehörigen Schlüsselwert ausgeben, d.h. du könntest alle Zeilen die mit 1 beginnen mit der Systemsteuerung überprüfen um sicherzustellen, dass nicht zuviel übersprungen wird. Ich denke aber mal bei dir wird sich ebenfalls herausstellen, dass alle diese Einträge normalerweise ausgeblendet werden. Somit macht mein abgewandeltes Script vermutlich das gleiche wie die Routine der Systemsteuerung.

  • Meine function sieht jetzt so aus:

    [autoit]

    ShowInstalledSoftware()

    [/autoit][autoit][/autoit][autoit]

    func ShowInstalledSoftware()
    $AppArray = ''
    Do
    $act_key = RegEnumKey ($key, $count)
    If @error <> 0 then
    $abort += 1
    $count = 1
    $key = $main_key64
    Else
    $count = $count + 1
    $act_name = RegRead($key & '\' & $act_key, "Displayname")
    $act_name = StringReplace ($act_name, " (remove only)", "")
    if stringinstr($act_name,"Security Update") then continueloop
    if stringinstr($act_name,"Update for Microsoft") then continueloop
    if stringinstr($act_name,"Hotfix for") then continueloop
    if stringinstr($act_name,"Service Pack") then continueloop
    If $act_name <> "" And Not StringInStr($all_keys,"|" & $act_name & "|") Then
    $dontShow = RegRead($key & '\' & $act_key, "SystemComponent")
    If not $dontShow then
    $Publisher = RegRead($key & '\' & $act_key, "Publisher")
    $Version = RegRead($key & '\' & $act_key, "DisplayVersion")
    $UninstallString = RegRead($key & '\' & $act_key, "UninstallString")

    [/autoit][autoit][/autoit][autoit]

    If $Publisher = '' Then
    $Publisher = 'Unknown Publisher'
    EndIf
    If $Version = '' Then
    $Version = 'Unknown Version'
    EndIf
    If $UninstallString = '' Then
    $UninstallString = 'No Uninstaller found'
    EndIf
    ConsoleWrite($act_name & ' ||| ' & $Publisher & ' ||| ' & $Version & ' ||| ' & $UninstallString & '~~~' & @CRLF)
    Endif
    If $dontShow = 1 Then ContinueLoop
    $all_keys = $all_keys & $act_name & "|"
    $foundItems += 1
    EndIf
    EndIf
    Until $abort = 2
    ConsoleWrite ("Einträge: " & $foundItems & @CRLF)
    EndFunc

    [/autoit]

    Ich versuche gerade das ganze als array zurückzugeben, kriegs aber nicht wirklich hin...

    Einmal editiert, zuletzt von Madara (29. Dezember 2013 um 22:18)

  • Ok, ich habs nochmal richtig formatiert. :)
    Ist es iwie möglich die gewünschten Einträge als Array zurückzugeben?
    Also Array[1] beeinhaltet eben NameDes1Programms|||HerstellerDes1Programms|||VersionDes1Programms|||UninstallStringDes1Programms~~~
    Und Array[2] beeinhaltet eben NameDes2Programms|||HerstellerDes2Programms|||VersionDes2Programms|||UninstallStringDes2Programms~~~


    usw, usw.
    Wie mach ich das am besten?  :huh:

  • Die Funktion gibt nun ein 2D-Array mit allen gewünschten Daten zurück. Ich war außerdem mal so frei und habe alle Variablen lokal deklariert und einige andere Kleinigkeiten was die Reihenfolge und Übersicht anbelangt geändert.

    Spoiler anzeigen
    [autoit]


    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_UseX64=n
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

    [/autoit] [autoit][/autoit] [autoit]

    #include <array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $aApp = ShowInstalledSoftware()
    _ArrayDisplay($aApp)

    [/autoit] [autoit][/autoit] [autoit]

    func ShowInstalledSoftware()
    Local $count = 1, $all_keys = "", $abort = 0
    Local $Publisher, $UninstallString, $Version, $act_name, $act_key, $dontShow

    [/autoit] [autoit][/autoit] [autoit]

    Local $main_key = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    Local $main_key64 = "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    Local $key = $main_key

    [/autoit] [autoit][/autoit] [autoit]

    Local $aReturn[1][4] = [["Programm","Hersteller","Version","Uninstall String"]]

    [/autoit] [autoit][/autoit] [autoit]

    Do
    $act_key = RegEnumKey ($key, $count)
    If @error <> 0 then
    $abort += 1
    $count = 1
    $key = $main_key64
    Else
    $count = $count + 1

    [/autoit] [autoit][/autoit] [autoit]

    $dontShow = RegRead($key & '\' & $act_key, "SystemComponent")
    If $dontShow = 1 Then ContinueLoop

    [/autoit] [autoit][/autoit] [autoit]

    $act_name = RegRead($key & '\' & $act_key, "Displayname")
    if stringinstr($act_name,"Security Update") then continueloop
    if stringinstr($act_name,"Update for Microsoft") then continueloop
    if stringinstr($act_name,"Hotfix for") then continueloop
    if stringinstr($act_name,"Service Pack") then continueloop

    [/autoit] [autoit][/autoit] [autoit]

    $act_name = StringReplace ($act_name, " (remove only)", "")

    [/autoit] [autoit][/autoit] [autoit]

    If $act_name <> "" And Not StringInStr($all_keys,"|" & $act_name & "|") Then

    [/autoit] [autoit][/autoit] [autoit]

    $all_keys = $all_keys & $act_name & "|"

    [/autoit] [autoit][/autoit] [autoit]

    $Publisher = RegRead($key & '\' & $act_key, "Publisher")
    $Version = RegRead($key & '\' & $act_key, "DisplayVersion")
    $UninstallString = RegRead($key & '\' & $act_key, "UninstallString")

    [/autoit] [autoit][/autoit] [autoit]

    If $Publisher = '' Then $Publisher = 'Unknown Publisher'
    If $Version = '' Then $Version = 'Unknown Version'
    If $UninstallString = '' Then $UninstallString = 'No Uninstaller found'

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite("DEBUG: " & $act_name & ' ||| ' & $Publisher & ' ||| ' & $Version & ' ||| ' & $UninstallString & '~~~' & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    ReDim $aReturn[UBound($aReturn)+1][4] ; Array um eine Zeile vergrößern

    [/autoit] [autoit][/autoit] [autoit]

    ; Einträge in die neue Zeile des Arrays machen
    $aReturn[UBound($aReturn)-1][0] = $act_name
    $aReturn[UBound($aReturn)-1][1] = $Publisher
    $aReturn[UBound($aReturn)-1][2] = $Version
    $aReturn[UBound($aReturn)-1][3] = $UninstallString

    [/autoit] [autoit][/autoit] [autoit]

    Endif
    EndIf
    Until $abort = 2

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite ("Einträge: " & UBound($aReturn)-1 & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    Return $aReturn
    EndFunc

    [/autoit]