Deinstallation über die Registry

  • Hallo,

    ich habe da ein seltsames Problem, aber erstmal zur Verständlichkeit was das Programm überhaupt machen soll:
    Es geht darum das zwei alte Programme deinstalliert werden und zwei neue anschließend installiert werden.
    Die Installation klappt problemlos, allerdings hakt es bei der Deinstallation.
    Die realisiere ich über Hilfe der Registry, weil dort die Schlüssel für die Deinstallation angegeben sind.

    Nun zu meinem Problem. Wenn ich ein Run, RunWait, _RunDOS benutze um die Deinstallation zu starten,
    entfernt er immer nur ein Programm, halt das was zu erste aus der Registry abgefragt wird und mit der IF
    bedingung übereinstimmt.

    Habe ich die Run-Befehle entfernt, gibt er mir beide MsgBoxes aus. Somit liegt in meinem Sinne, es irgendwie an den
    Run Befehlen.


    [autoit]

    ;Programme auslesen
    $Key = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall"
    Dim $a = 0
    While 1
    $a += 1

    $var = RegEnumKey($Key, $a)

    If @error Then ExitLoop


    $regread = RegRead($Key & "\" & $var,"DisplayName")

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

    If $regread = "ScrewDrivers Client v3" Or $regread = "MetaFrame Presentation Server Client" Then
    $uninstallstring = RegRead($Key & "\" & $var,"UninstallString")

    $uninstallstring = StringReplace($uninstallstring,"/I","/uninstall ")
    ;~ _RunDOS("start " & $uninstallstring & " /passive")
    RunWait($uninstallstring & " /passive")
    MsgBox(64,"Software",$regread & " wurde deinstalliert",5)
    EndIf
    WEnd

    [/autoit]

    Kann mir da einer helfen? Weil ich glaube ich sehe langsam den Wald vor lauter Bäumen kaum :)


    Grüße
    dragst3r

  • Hi,

    hast Du denn überprüft was $uninstallstring enthält, vllt liegt da der Fehler ...

    Spoiler anzeigen
    [autoit]

    ;Programme auslesen
    $Key = "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall"
    Dim $a = 0
    While 1
    $a += 1

    $var = RegEnumKey($Key, $a)
    If @error Then ExitLoop

    $regread = RegRead($Key & "\" & $var,"DisplayName")

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

    If $regread = "ScrewDrivers Client v3" Or $regread = "MetaFrame Presentation Server Client" Then
    $uninstallstring = RegRead($Key & "\" & $var,"UninstallString")
    MsgBox(266304, Default, $uninstallstring)

    $uninstallstring = StringReplace($uninstallstring,"/I","/uninstall ")
    MsgBox(266304, Default, $uninstallstring)
    ;~ _RunDOS("start " & $uninstallstring & " /passive")
    RunWait($uninstallstring & " /passive")
    If @error Then ConsoleWrite('Errorcode: ' & @error & @CRLF)
    MsgBox(64,"Software",$regread & " wurde deinstalliert",5)
    EndIf
    WEnd

    [/autoit]

    Davon mal abgesehen, wenn Du die Schlüsselnamen und Wertnamen kennst, warum liest Du sie dann nicht direkt aus, waum der Umstand alle Subkeys in 'Uninstall' abzugrasen ... ?(


    Gruß
    Greenhorn


  • Zitat

    Versuch mal dir durch ConsoleWrites ausgeben zu lassen, was in deinen Variablen steht. evtl. hilft dir das und dann gehst du stepbystep durch.

    Habe ich schon gemacht. Jedoch ohne Erfolg.

    Zitat

    hast Du denn überprüft was $uninstallstring enthält, vllt liegt da der Fehler ...

    Ja, habe ich. Ist alles korrekt. Das lustige ist ja auch, nachdem man dann nochmal das Programm startet, macht er dann die Deinstallation.
    Was auch wiederrum komisch ist, dass wenn ich die While Schleife einfach nochmal Kopiere und einfüge, macht er es trotzdem nicht.

    Was ich eben getestet habe ist das mit _rundos("start ...) es dann funktioniert, dabei finde ich es aber doof, das durch die start option der ablauf
    parallel abgearbeitet wird und ich somit beide Deinstallation auf einmal habe. Wäre zwar die einzigste lösung zur Zeit, aber nicht gerade das was ich will.

    Zitat

    Davon mal abgesehen, wenn Du die Schlüsselnamen und Wertnamen kennst, warum liest Du sie dann nicht direkt aus, waum der Umstand alle Subkeys in 'Uninstall' abzugrasen ... ?(

    Weil in der Registry von Uninstall nur die SID der Software drinne steht, und da jede Version eine andere enthält, musste ich diesen Weg nehmen. Leider.


    dragst3r

  • Und wenn's doch mal nötig sein sollte ...
    (still in progress)

    Spoiler anzeigen
    [autoit]

    ;========================================================================================
    ; RegScanTree($szKey, $iBuffer = 100000, $iIdle = 0)
    ;
    ; Rückgabe: Erfolg - Array, enthält Namen und Werte aller Unterschlüssel des Registrierungspfades.
    ; Fehler - @error = 1, wenn HiveKey falsch oder Buffer zu hoch/niedrig.
    ;========================================================================================
    Func RegScanTree($szKey, $iBuffer = 100000, $iIdle = 0) ; OK

    $iError = CheckRegFuncParams($szKey, $iBuffer)
    If $iError Then Return SetError($iError)

    Local $arRegList, $arKeyNames, $arKeys, $arValues, $iIndex
    Dim $arRegList[$iBuffer][4]
    Dim $arSubKeys[$iBuffer]

    $arValues = RegScanVal($szKey)
    If Not IsArray($arValues) Then Return SetError(1, 5, 0)
    For $iVal = 1 To $arValues[0][0]
    $iIndex += 1
    $arRegList[$iIndex][0] = $arValues[$iVal][0]
    $arRegList[$iIndex][1] = $arValues[$iVal][1]
    $arRegList[$iIndex][2] = $arValues[$iVal][2]
    $arRegList[$iIndex][3] = $arValues[$iVal][3]
    Next

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

    $arKeyNames = RegScanKeyNames($szKey)
    If Not IsArray($arKeyNames) Then
    Return SetError(1, 3, 0)
    ElseIf Not $arKeyNames[0] Then
    $arRegList[0][0] = $iIndex
    ReDim $arRegList[$iIndex + 1][4]
    Return $arRegList
    EndIf

    For $iKey = 1 To $arKeyNames[0]
    $arValues = RegScanVal($arKeyNames[$iKey])
    If Not IsArray($arValues) Then Return SetError(1, 4, 0)
    For $iVal = 1 To $arValues[0][0]
    $iIndex += 1
    $arRegList[$iIndex][0] = $arValues[$iVal][0]
    $arRegList[$iIndex][1] = $arValues[$iVal][1]
    $arRegList[$iIndex][2] = $arValues[$iVal][2]
    $arRegList[$iIndex][3] = $arValues[$iVal][3]
    Next
    Next

    $arRegList[0][0] = $iIndex
    ReDim $arRegList[$iIndex + 1][4]
    Return $arRegList

    EndFunc
    ;========================================================================================
    ; RegScanKeyNames($szKey, $iBuffer = 100000, $iIdle = 0)
    ;
    ; Rückgabe: Erfolg - Array, enthält Namen aller Unterschlüssel des Registrierungspfades.
    ; Fehler - @error = 1, wenn HiveKey falsch oder Buffer zu hoch/niedrig.
    ;========================================================================================
    Func RegScanKeyNames($szKey, $iBuffer = 100000, $iIdle = 0) ; OK

    $iError = CheckRegFuncParams($szKey, $iBuffer)
    If $iError Then Return SetError($iError)

    Local $arKeyList, $iIndex, $iIdleHere
    Dim $arKeyList[$iBuffer]

    $arSubKeyNames = RegScanSubKeyNames($szKey)

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

    If Not $arSubKeyNames[0] Then
    ReDim $arKeyList[1]
    Return $arKeyList
    Else
    For $iSub = 1 To $arSubKeyNames[0]
    $iIndex += 1
    $arKeyList[$iSub] = $szKey & '\' & $arSubKeyNames[$iSub]
    Next
    EndIf

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

    For $iKey = 1 To $iBuffer -1
    If Not $arKeyList[$iKey] Then ExitLoop
    $arSubKeyNames = RegScanSubKeyNames($arKeyList[$iKey])
    If Not $arSubKeyNames[0] Then ContinueLoop

    For $iSub = 1 To $arSubKeyNames[0]
    If $iKey = $iIdleHere Then Sleep($iIdle)
    $iIndex += 1
    $arKeyList[$iIndex] = $arKeyList[$iKey] & '\' & $arSubKeyNames[$iSub]
    Next
    $iIdleHere += 100
    Next

    $arKeyList[0] = $iIndex
    ReDim $arKeyList[$iIndex + 1]
    Return $arKeyList

    EndFunc
    ;========================================================================================
    ; RegScanSubKeyNames($szKey, $iBuffer = 10000)
    ;
    ; Rückgabe: Erfolg - Array, enthält Namen der Unterschlüssel.
    ; Fehler - @error = 1, wenn HiveKey falsch oder Buffer zu hoch/niedrig.
    ;========================================================================================
    Func RegScanSubKeyNames($szKey, $iBuffer = 10000) ; OK

    $iError = CheckRegFuncParams($szKey, $iBuffer)
    If $iError Then Return SetError($iError)
    Local $szSubKey, $iInstance
    Dim $arSubKey[$iBuffer]

    For $iInstance = 1 To $iBuffer - 1
    $szSubKey = RegEnumKey($szKey, $iInstance)
    If @error Then ExitLoop
    $arSubKey[0] = $iInstance
    $arSubKey[$iInstance] = $szSubKey
    Next

    If Not $arSubKey[0] Then
    ReDim $arSubKey[1]
    Return $arSubKey
    Else
    ReDim $arSubKey[$arSubKey[0] + 1]
    Return $arSubKey
    EndIf

    EndFunc
    ;========================================================================================
    ; RegScanVal($szKey, $iBuffer = 1000)
    ;
    ; Rückgabe: Erfolg - Array, zweidimensional
    ; Schlüssel, Wertname, Typ und Wert des Registrierungsschlüssels.
    ; Fehler - @error = 1, wenn HiveKey falsch oder Buffer zu hoch/niedrig.
    ;========================================================================================
    Func RegScanVal($szKey, $iBuffer = 1000) ; OK !

    $iError = CheckRegFuncParams($szKey, $iBuffer)
    If $iError Then Return SetError($iError)

    Local $arRegList, $arSubKeys, $arValueNames, $vRegValue
    Dim $arRegList[$iBuffer][4]

    $arValueNames = RegScanValNames($szKey, $iBuffer - 1)
    If Not IsArray($arValueNames) Then Return SetError(1, 3, 0)
    $arRegList[0][0] = $arValueNames[0][0]
    For $iVal = 1 To $arValueNames[0][0]
    $vRegValue = RegRead($szKey, $arValueNames[$iVal][0])
    $arRegList[$iVal][0] = $szKey
    $arRegList[$iVal][1] = $arValueNames[$iVal][0]
    $arRegList[$iVal][2] = $arValueNames[$iVal][1]
    $arRegList[$iVal][3] = $vRegValue
    Next

    ReDim $arRegList[$arRegList[0][0] + 1][4]

    Return $arRegList

    EndFunc
    ;========================================================================================
    ; RegScanValNames($szKey, $iBuffer = 1000)
    ;
    ; Rückgabe: Erfolg - Array[0][1] Schlüsselname.
    ; Array[1][0] Wertname.
    ; Array[1][1] Typ.
    ; Fehler - @error = 1, wenn HiveKey falsch oder Buffer zu hoch/niedrig.
    ;========================================================================================
    Func RegScanValNames($szKey, $iBuffer = 1000) ; OK !

    $iError = CheckRegFuncParams($szKey, $iBuffer)
    If $iError Then Return SetError($iError)
    Local $arKeyVal, $szValName
    Dim $arKeyVal[$iBuffer + 1][2]

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

    For $iInstance = 1 To $iBuffer
    $szValName = RegEnumVal($szKey, $iInstance)
    If @error = -1 Then ExitLoop
    $arKeyVal[0][0] = $iInstance
    $arKeyVal[$iInstance][0] = $szValName
    $arKeyVal[$iInstance][1] = RegTypeNumToVar(@extended)
    Next
    If $arKeyVal[0][0] Then
    $arKeyVal[0][1] = $szKey
    ReDim $arKeyVal[$arKeyVal[0][0] + 1][2]
    Return $arKeyVal
    Else
    $arKeyVal[0][0] = 1
    $arKeyVal[0][1] = $szKey
    $arKeyVal[1][0] = ''
    $arKeyVal[1][1] = 'REG_SIZE'
    ReDim $arKeyVal[2][2]
    Return $arKeyVal
    EndIf

    EndFunc
    ;========================================================================================
    ; Interne Funktion.
    ;
    ; Rückgabe: Errorcode 1; Extended 1 & 2.
    ;========================================================================================
    Func CheckRegFuncParams($szKey, $iBuffer = 1) ; nicht OK !

    Local $iErrorCode
    If Not IsString($szKey) Or Not StringRegExp($szKey, '\A(HKEY_CLASSES_ROOT)|' & _
    '(HKEY_CURRENT_USER)|' & _
    '(HKEY_CURRENT_CONFIG)|' & _
    '(HKEY_LOCAL_MACHINE)|' & _
    '(HKEY_USERS)|' & _
    '(HKCR)|' & _
    '(HKCU)|' & _
    '(HKCC)|' & _
    '(HKLM)|' & _
    '(HKU)', 0) Then
    $iErrorCode = 1 ; $szKey ist kein String oder HiveKey.
    EndIf
    If Not IsInt($iBuffer) Or $iBuffer <= 0 Or $iBuffer > 16777216 Then
    If $iErrorCode Then
    $iErrorCode = 3
    Else
    $iErrorCode = 2
    EndIf
    EndIf

    Return $iErrorCode

    EndFunc
    ;========================================================================================
    ; RegTypeNumToVar($iValue)
    ;
    ; Rückgabe: Variablenstring des numerischen Wertes der Registrierungstyp-Konstanten.
    ;========================================================================================
    Func RegTypeNumToVar($iValue) ; OK

    If Not IsInt($iValue) Then Return SetError(1, 0, 0)
    Switch $iValue
    Case 0
    Return 'REG_NONE'
    Case 1
    Return 'REG_SZ'
    Case 2
    Return 'REG_EXPAND_SZ'
    Case 3
    Return 'REG_BINARY'
    Case 4
    Return 'REG_DWORD'
    Case 5
    Return 'REG_DWORD_BIG_ENDIAN'
    Case 6
    Return 'REG_LINK'
    Case 7
    Return 'REG_MULTI_SZ'
    Case 8
    Return 'REG_RESOURCE_LIST'
    Case 9
    Return 'REG_FULL_RESOURCE_DESCRIPTOR'
    Case 10
    Return 'REG_RESOURCE_REQUIREMENTS_LIST'
    Case Else
    Return SetError(1, 1, 0) ; kein Registry Wert-Typ.
    EndSwitch

    EndFunc

    [/autoit]

    Aber Vorsicht: hoher Speicherbedarf und CPU-Auslastung !!!
    Also ihr solltet nicht gerade 'HKLM' oder so eintippen, je nach System kommen da ein paar Hunderttausend Werte zusammen ...
    Wie gesagt, ich arbeite noch dran, und Vorsicht mit _ArrayDisplay, die Func frisst auch ordentlich CPU.


    Gruß


    • Offizieller Beitrag

    Hallo,

    wenn ein Schlüssel entfernt wurde (uninstall) dar $a nicht erhöht werden, weil dann der nächste Schlüssel an die Position des gelöschten Schlüssels rückt!

    So sollte es gehen:

    [autoit]

    $Key = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall"
    Dim $a = 1
    While 1

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

    $var = RegEnumKey($Key, $a)

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

    If @error Then ExitLoop

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

    $regread = RegRead($Key & "\" & $var, "DisplayName")

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

    If $regread = "ScrewDrivers Client v3" Or $regread = "MetaFrame Presentation Server Client" Then
    $uninstallstring = RegRead($Key & "\" & $var, "UninstallString")

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

    $uninstallstring = StringReplace($uninstallstring, "/I", "/uninstall ")
    ;~ _RunDOS("start " & $uninstallstring & " /passive")
    RunWait($uninstallstring & " /passive")
    MsgBox(64, "Software", $regread & " wurde deinstalliert", 5)
    Else
    $a += 1
    EndIf
    WEnd

    [/autoit]
  • Das war leider auch nicht Lösung. Es hatte ja zuvor auch schon nix gebracht, die While Schleife zu verdoppeln. So ein komisches Problem hatte ich lang nicht mehr. Naja irgendwann wird sich schon eine Lösung finden.