Offene Prozesse abfragen, MSGBox zum schliessen einblenden OK /Cancel - Errorlevel übergeben

  • Hallo zusammen

    Ich will ein Programm via Softwareverteilung auf mehreren Client-PCs installieren, welches erfordert das gewisse Programme geschlossen werden.

    Der User muss aber die Möglichkeit haben, auf die Messagebox mit Ok oder Cancel zu reagieren. Bei Ok muss geprüft werden, ob die Prozesse zu sind, falls ja, darf es im Script weiter gehen, falls nicht, die Messagebox erneut eingeblendet werden.

    Falls Cancel gedrückt wird, müsste die exe mit einem Errorlevel enden.

    Für einen einzelnen Prozess sähe das ca. so aus:


    [autoit]

    While ProcessExists($ProcessToCheck)
    $Msgbox = MsgBox(8192+65,$Titel,"Please close " & $ProcessToCheck & " to install an update or new version of " & $AppToInstall )
    If $Msgbox = 2 Then
    Exit(1)
    Endif
    WEnd

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

    oder mit mehreren könnte es vielleicht so aussehen:

    [autoit]


    $AppToInstall="Office"
    Global $abfrage = 0
    While 1
    $list = ProcessList()
    For $i = 1 To $list[0][0]
    Switch $list[$i][0]
    Case "Winword.exe", "Outlook.exe", "Excel.exe", "Powerpnt.exe", "MSACCESS.EXE", "acrobat.exe", "AcroRd32.exe", "iexplore.exe"
    Sleep(1000)
    $Msgbox = MsgBox(8192+65,"Installer","Please close " & $list[$i][0] & " to install an update or new version of " & $AppToInstall )
    If $Msgbox = 2 Then
    Exit(1)
    Endif
    $abfrage = $abfrage + 1
    EndSwitch
    Next
    Sleep(1000)
    WEnd

    [/autoit]

    Nun zu meinen Problemen / Fragen:

    z.B. der Prozess AcroRd32.exe ist nicht selbsterklärend für den User - wie könnte man erreichen, dass der User aufgefordert wird, Acrobat Reader zu schliessen, und nicht den Namen des laufenden Prozesses?

    Ich hoffe ihr schubst mich von der Leitung, auf der ich stehe ;(

    Einmal editiert, zuletzt von Surfy (10. August 2011 um 15:55)

    • Offizieller Beitrag

    z.B. der Prozess AcroRd32.exe ist nicht selbsterklärend für den User - wie könnte man erreichen, dass der User aufgefordert wird, Acrobat Reader zu schliessen, und nicht den Namen des laufenden Prozesses?


    Lies den Titel des aktiven Fensters für diesen Prozeß aus und verwende diesen. Wie das geht findest du hier im Forum, wurde mehrfach gepostet.

  • Das wäre irreführend, weil gerade beim PDF - der Fenstertitel der Name des PDF`s wäre.

    Nein, das geht auch nicht ;)

    Ich suche eine Lösung wo ich angeben kann:

    $Query1= AcroRd32.exe

    $Titel1= Acrobat Reader

    Und das für alle Prozesse.

  • Naja arbeite halt mit einem 2d Array (machst du ja bereits...) oder ggf mit einer ini Datei in der es Zuordnungen zwischen Prozessname und verständlichem Klartextnamen gibt.


    Bsp:

    ini:

    Code
    [names]
    acroRD32.exe=Acrobat Reader
    MSACCESS.exe=Microsoft Office Access
    [autoit]


    $PnameToGoodName=iniread($ini, "names",$list[$i][0],$list[$i][0]) ; wenn in der ini nichts gefunden wird wird der Prozessname benutzt...

    [/autoit]

    Die ganzen ini Teile könntest du natürlich auch schon vorab in einer weiteren Arrayspalte speichern, dann kannst du die Klarnamen direkt per Arrayindex ansprechen.
    Als Alternative zu einer Art Übersetzungsdatenbank kannst du auch mal das hier anschauen:

    [autoit]

    FileGetVersion()

    [/autoit]

    Damit kann man nicht nur die Version auslesen wie der Name vermuten lässt sondern auch weitere Metadaten der exe, wie z.B den Produktnamen.

  • @ Misterspeed: Danke, genau in die Richtung wollte ich gehen, inifile hatte ich auch eingeplant - nur war das halt sehr nooblike:

    [autoit]

    $config = (@ScriptDir & "\config.ini")
    $ProcessToCheck = IniRead($config, "Configuration", "ProcessToCheck", "NichtGefunden")
    $AppToInstall = IniRead($config, "Configuration", "AppToInstall", "NichtGefunden")

    [/autoit]

    Wie müsste jetzt die Case Schleife aussehen, damit auch da schon auf

    [autoit]

    $list[$i][0],$list[$i][0]

    [/autoit]

    basis abgefragt wird?

    [autoit]

    Global $abfrage = 0
    While 1
    $list = ProcessList()
    For $i = 1 To $list[0][0]
    Switch $list[$i][0]
    Case $list[$i][0]
    Sleep(1000)
    $Msgbox = MsgBox(8192+65,"Installer","Please close " & $list[$i][0] & " to install an update or new version of " & $AppToInstall )
    If $Msgbox = 2 Then
    Exit(1)
    Endif
    $abfrage = $abfrage + 1
    EndSwitch
    Next
    Sleep(1000)
    WEnd

    [/autoit]


    Ist es wirklich soooo einfach? ?(

  • Was hat ini mit n00b zu tuen? Richtig nichts.

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Hier mal 2 Varianten, die letzte ist vorzuziehen...

    Spoiler anzeigen
    [autoit]


    #cs
    Test.ini:

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

    [prozesse]
    notepad.exe="Microsoft Notepad undso"
    mspaint.exe="Microsoft N00b Grafikprogramm"
    #ce

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

    #include <array.au3> ; kann entfernt werden wird nur für debug zwecke benötigt
    Global $abfrage = 0 ; ????????
    Global $ini = @ScriptDir & "\test.ini"
    Global $aToCheck = IniReadSection($ini,"prozesse")
    _ArrayDisplay($aToCheck) ; debug
    Global $found = True ; Abbruchbedingung für while Schleife

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

    While $found = True
    $found = False ; wird zu Beginn auf false gesetzt, also wenn er keine laufenden problematischen Prozesse findet verlässt er die Schleife nach einem Durchlauf
    $list = ProcessList()
    For $i = 1 To $list[0][0] ; geht liste aller Prozesse durch
    For $j = 1 to $aToCheck[0][0] ; gleicht den aktuellen Prozess mit allen Prozessen die in der ini vermerkt sind ab
    if $list[$i][0] = $aToCheck[$j][0] Then ; der Prozess ist in der ini vorhanden und läuft noch
    $found = True ; sorgt dafür, dass die while Schleife mindestens noch einmal durchläuft um sicherzustellen, dass keine prozesse mehr laufen
    $Msgbox = MsgBox(8192+65,"Installer","Please close " & $aToCheck[$j][0] & " to install an update or new version of " & $aToCheck[$j][1])
    If $Msgbox = 2 Then
    Exit(1)
    Endif
    $abfrage = $abfrage + 1 ; wozu brauchst du diesen Zähler ?
    EndIf
    Next
    Next
    Sleep(1000)
    WEnd

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

    MsgBox(0,"Fertig","Es laufen keine Prozesse mehr, die Installation kann nun starten...")
    ; installmytools()

    [/autoit]

    Oder du machs das so, ist deutlich kürzer und schneller:

    Spoiler anzeigen
    [autoit]


    #cs
    Test.ini:

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

    [prozesse]
    notepad.exe="Microsoft Notepad undso"
    mspaint.exe="Microsoft N00b Grafikprogramm"
    #ce

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

    #include <array.au3> ; kann entfernt werden wird nur für debug zwecke benötigt
    Global $ini = @ScriptDir & "\test.ini"
    Global $aToCheck = IniReadSection($ini,"prozesse")
    _ArrayDisplay($aToCheck) ; debug
    Global $found = True ; Abbruchbedingung für while Schleife

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

    While $found = True
    $found = False ; wird zu Beginn auf false gesetzt, also wenn er keine laufenden problematischen Prozesse findet verlässt er die Schleife nach einem Durchlauf
    For $i = 1 to $aToCheck[0][0]
    if ProcessExists($aToCheck[$i][0]) Then
    $found = True ; sorgt dafür, dass die while Schleife mindestens noch einmal durchläuft um sicherzustellen, dass keine prozesse mehr laufen
    $Msgbox = MsgBox(8192+65,"Installer","Please close " & $aToCheck[$i][0] & " to install an update or new version of " & $aToCheck[$i][1])
    If $Msgbox = 2 Then Exit(1)
    EndIf
    Next
    WEnd
    MsgBox(0,"Fertig","Es laufen keine Prozesse mehr, die Installation kann nun starten...")
    ; installmytools()

    [/autoit]
  • Herzlichen dank! Das funktioniert 1a - und ist genial!

    Gibt es noch irgend einen Weg, um das X (Fenster schliessen) zu disablen? Oder reagiert das gleich wie "Cancel"?

    Surfy

  • Noch eine letzte knacknuss:

    Unsere Softwareverteilung installiert immer in einen Maschinenteil, und einem Userteil.

    - Der Maschinenteil läuft unter einem speziellen User, welcher lokale Adminrechte besitzt.

    - Der Userteil läuft unter dem jeweils eingeloggten User ab, mit den rechten des Users

    ZB eine Setup.exe oder ein MSI wird unter den Maschinenteil abgearbeitet, der Userteil wird nur manchmal benötigt, um zB Files im Userprofile zu kopieren etc.

    Unser Programm funktiniert nun 1a - im Usercontext. Das bekomme ich die Messagebox angezeigt, und den Errorlevel zurück.

    Dh wenn ich jetzt nur noch Userbasiert, und mit Runas Scripten installieren würde, wäre die Lösung bereits fertig..

    Jetzt kommt aber die Herausfoderung, dies auch im context des "Maschinenteil Users" dh aus einem anderen Usercontext heraus, mit dem User zu interagieren.

    Das MesageBox Progamm als Service einrichten geht ja schnell - und das läuft auch mit srvany. Aber wie kann ich an den Errorlevel kommen?

    Im Maschinenteil kann ich den Service starten, der unter Systemrechten mit "Interact with logged on User" auch die Messagebox bringt..

    Nur - wie komme ich nun im Installtionscript des Maschinenteils an die notwendige info?

    Ich könnte eine zweite Exe starten, im Maschinencontext, die den Service startet, und mit Processwaitclose wartet, bis meine MsGbox weg ist, und dann einen (vom MessageBox Programm) in die Registry geschriebenen Wert abfragt. Oder?

    Ich hoffe ihr habt noch ein paar bessere Ideen :S