Anfänger bittet um Optimierungsvorschläge

  • Hallo zusammen,

    ich habe ein SingleSignOn-Skript geschrieben, welches Benutzernamen und Kennwort einer Anwendung automatisch beim Start des Programmes durch den User eingibt.

    Da das Ganze auf einem Terminalserver ausgeführt wird, bin ich um jedes Quäntchen Speicher froh, welches eingespart werden kann. Daher auch mein DLL-Aufruf in der While-Schleife (Auslagerungsdatei ?!).

    Welche Tipps, gerade für die letzte While-Schleife, welche ja letztendlich bis zum Programmende durchläuft, würdet ihr mir geben? Lieber mit Switch und Case arbeiten? Den DLL-Schließen-Befehl besser außerhalb der Schleife anbringen?


    Vielen Dank !

    [autoit]

    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_Outfile=P:\PWMITDLLcloseinschleife.exe
    #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    #cs ----------------------------------------------------------------------------
    AutoIt Version: 1.0
    Author:

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

    PW-Single-Sign-On
    #ce ----------------------------------------------------------------------------
    #include <file.au3>
    #include <misc.au3>
    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <INet.au3>
    #include <ProgressConstants.au3>
    #include <StaticConstants.au3>
    Global Const $h_PsAPI = DllOpen("psapi.dll")
    $usr = @username
    ; Prüft vor dem Starten, ob es sich um den Terminalserver handelt.
    If not (@computername = "XXXX" or "XXXX" and @LogonDNSDomain = "XXXX") Then
    MsgBox(64,"XXXX - PW AutoLogin","PW kann auf diesem Endgerät nicht gestartet werden.")
    _AlarmView("Es wurde versucht, PW auf einem nicht zugelassenen Endgerät zu starten: "&@Computername&" "&@LogonDNSDomain)
    Exit
    EndIf
    ; Prüft vor dem Starten, ob bereits eine PW.exe im Taskmanager gestartet ist.
    If _Singleton("PWSSO",1) = 0 Then
    MsgBox(64,"XXXX - PW AutoLogin","PW wird bereits ausgeführt und kann nicht erneut gestartet werden.")
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " hat versucht, PW doppelt zu starten.")
    Exit
    Else
    EndIf
    ; Start von PW.exe
    $PID = run ("\\srv\PW\client\PW.exe")

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

    ; Prüft, ob die PW.Exe startet
    If not ProcessWait("PW.exe",10) = true Then
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " erhielt eine Fehlermeldung, da die PW.exe nicht gestartet werden konnte.")
    _AlarmView("PW.exe kann nicht gestartet werden")
    MsgBox(48,"XXXX - PW AutoLogin","Fehler !")
    Exit
    Else
    EndIf
    ; Prüft bis zum Erscheinen des PW-Anmeldefensters in Form einer Schleife, ob ein Fehlerdialog (Dienst nicht gestartet o.ä.) erscheint.
    While 1
    If Not WinActive("[CLASS:TFrmPopErrorDlg]", "") = 0 Then
    Send("{Enter}")
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " erhielt vor PW-Anmeldung einen Fehler (TFrmPopErrorDlg)")
    _AlarmView("TFrmPopErrorDlg vor Programmstart aufgetreten")
    MsgBox(0, "Fehler aufgetreten", "Fehler aufgetreten")
    Send("{Enter}")
    Exit
    EndIf
    If Not WinActive("[CLASS:TMessageForm]", "") = 0 Then
    Send("{ESC}")
    Send("{ESC}")
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " erhielt vor PW-Anmeldung einen Fehler (TMessageForm)")
    _AlarmView("TMessageForm vor Programmstart aufgetreten")
    MsgBox(0, "Fehler aufgetreten", "Fehler aufgetreten")
    Exit
    EndIf
    $var = WinExists("PW-Anmeldung")
    If $var = 1 then ExitLoop
    sleep(100)
    WEnd

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

    WinWait("PW-Anmeldung")

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

    ; Eingabe von Benutzernamen und Kennwort.
    BlockInput(1)
    ControlSend("PW-Anmeldung", "", "[CLASS:TEdit; INSTANCE:2]",@Username)
    ControlSend("PW-Anmeldung", "", "[CLASS:TEdit; INSTANCE:1]", "testtest")
    ControlSend("PW-Anmeldung", "", "", "{Enter}")
    BLOCKINPUT(0)
    ; Prüft, ob Benutzername oder Kennwort abgewiesen werden.
    WinWait("[CLASS:TMessageForm]", "",1)
    If WinExists("[CLASS:TMessageForm]", "") Then
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " erzeugte einen Anmeldefehler.")
    _AlarmView("Benutzername oder Kennwort abgewiesen")
    MsgBox(0, "jjjj", "PW falsch")
    ProcessClose($PID)
    Exit
    Else
    EndIf
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " angemeldet")
    ; Startet das Dispo-Auswahlfenster.
    ;WinWaitActive("[CLASS:TMainForm]", "")
    ;ControlSend("[CLASS:TMainForm]", "", "", "{F12}")
    ;sleep(100)
    ;ControlSend("[CLASS:TMainForm]", "", "", "{P}")
    ;sleep(100)
    ;ControlSend("[CLASS:TMainForm]", "", "", "{D}")
    ;sleep(100)
    ;ControlSend("[CLASS:TMainForm]", "", "", "{D}")

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

    ; Überwacht ab der erfolgreichen Anmeldung, ob die Abmeldung bzw. das Programmende eintritt oder versucht wird, das Kennwort zu ändern.
    While 1
    sleep(100)
    If Not ProcessExists($PID) Then
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " abgemeldet")
    MsgBox(0, "ende", "ende")
    Exit
    EndIf
    sleep(100)
    If WinActive("[CLASS:TFrmDBValidatePassword]", "") Then
    Send("{ESC}")
    Send("{ESC}")
    Send("{Enter}")
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " hat versucht, eine Passwortänderung durchzuführen.")
    MsgBox(0, "jjjj", "jjjj")
    EndIf
    sleep(100)
    If WinActive("[CLASS:TFrmLogin2]", "") Then
    _FileWriteLog(@ScriptDir & "\"&$usr&".log", @Username & " abgemeldet (und PW-Anmeldedialog geöffnet.")
    MsgBox(0, "F", "Fenster erkannt")
    Exit
    EndIf
    DllCall($h_PsAPI, 'int', 'EmptyWorkingSet', 'long', -1)
    DllClose($h_PsAPI)
    WEnd

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

    ; eMail-Funktion
    Func _AlarmView($text = "Kein Parameter")
    $s_SmtpServer = "192.168.9.2"
    $s_Username = ""
    $s_Password = ""
    $IPPort = 25
    $s_FromName = "PW"
    $s_FromAddress = "PW"
    $s_ToAddress = "AlarmView@192.168.9.2"
    $s_Subject = "PW-Fehlermeldung steht an"
    Dim $as_Body[2]
    $as_Body[0] = "Es wurde eine Fehlermeldung ausgegeben."
    $as_Body[1] = ""&@Username &" erzeugte den Fehler: "& $text
    $Response = _INetSmtpMail ($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject, $as_Body, @computername, -1)
    $err = @error
    If $Response = 1 Then
    Else
    EndIf
    Endfunc

    [/autoit][autoit][/autoit][autoit][/autoit]
  • Versuche doch mal eine Funktion zum Verringern der Prozessorlast einzubauen (z.B. So eine wie hier: http://www.autoitscript.com/forum/topic/13…ducememory-udf/ - funktioniert laut Beschreibung aber nur mit AutoIt EXEn).

  • Welche Tipps, gerade für die letzte While-Schleife, welche ja letztendlich bis zum Programmende durchläuft, würdet ihr mir geben?

    Sollte nicht wirklich etwas verändern aber aber du könntest z.B. die 1. If-Verzweigung aus der Schleife nehmen in dem du stattdessen die Schleife mit "While ProcessExists($PID)" einleitest und die 3 Zeilen die für den Fall gedacht waren hinter die Schleife setzt.
    Wenn du willst das die Funktion EmptyWorkingSet dauerhaft funktioniert dann darfst du die beinhaltende DLL auch nicht schließen (DllClose($h_PsAPI)).
    Die Funktion würde damit nur beim ersten Schleifendurchlauf korrekt aufgerufen - danach funktioniert sie nicht mehr da das Handle auf das $h_PsAPI zeigt ja bereits geschlossen wurde.
    Das DllClose sollte also eher hinter die Schleife.
    Ansonsten wüsste ich zu der Schleife nicht was man da noch groß Prozessor oder speichermäßig optimieren könnte.

    @CheaterDieter
    Die "ReduceMemory"-Funktion lagert lediglich Teile vom Arbeitsspeicher in die Auslagerungsdatei aus in dem es lediglich die API-Funktion EmptyWorkingSet aufruft.
    Die Prozessorlast wird dadurch also keineswegs verringert sondern durch den zusätzlichen Aufruf sogar noch leicht erhöht.
    Die Auswirkung bezieht sich lediglich auf den verwendeten Arbeitsspeicher.
    Mal davon abgesehen hat F1109 diese Funktionalität schon durch den manuellen DLL-Aufruf vollständig implementiert.

  • Hallo zusammen,

    habt vielen Dank für Eure tolle Unterstützung. Ich bin da sehr dankbar und weiß, dass es nicht selbstverständlich ist.

    Okay, ich nehme den Close-Aufruf wieder raus aus der Schleife, dadurch steigt aber die Arbeitsspeicherauslastung komischer Weise wieder.

    Ich hoffe, dass ich mir durch die Implementierung der EmptyWorkingSet-Geschichte nicht ein Eigentor schieße (Arbeitsspeicher) - die Zahlen sind aber doch phänomenal

    AspirinJunkie: Kannst Du mir das mal konkret zeigen, was Du mit der While-Schleife meinst? Denn es ist ja so, dass diese letzte Schleife darauf "warten" soll, ob a) das Programm geschlossen wird, b) das Kennwort geändert wird (bzw. der Versuch unternommen wird, dies zu tun) oder c) der Ummelden-Dialog gestartet wird.

  • ich nehme den Close-Aufruf wieder raus aus der Schleife, dadurch steigt aber die Arbeitsspeicherauslastung komischer Weise wieder.

    Das ist tatsächlich merkwürdig denn die Funktion EmptyWorkingSet wird ab dem 2. Durchlauf der Schleife nicht mehr aufgerufen (DLLCall sollte ein @error von 1 erzeugen).

    Ich hoffe, dass ich mir durch die Implementierung der EmptyWorkingSet-Geschichte nicht ein Eigentor schieße (Arbeitsspeicher) - die Zahlen sind aber doch phänomenal

    Wie gesagt - das ist ja keine Zauberei. Verringert wird daran ja auch nichts nur verschoben - vom Arbeitsspeicher in die Auslagerungsdatei.

    Kannst Du mir das mal konkret zeigen, was Du mit der While-Schleife meinst?

    Das wäre nur rein kosmetischer Natur. Auf die Prozessorlast hätte das keine Auswirkung.
    Gemeint habe ich dies ungefähr so:

    Spoiler anzeigen
    [autoit]

    While ProcessExists($PID)
    Sleep(100)
    If WinActive("[CLASS:TFrmDBValidatePassword]", "") Then
    Send("{ESC 2}{Enter}")
    _FileWriteLog(@ScriptDir & "\" & $usr & ".log", @UserName & " hat versucht, eine Passwortänderung durchzuführen.")
    MsgBox(0, "jjjj", "jjjj")
    EndIf
    Sleep(100)
    If WinActive("[CLASS:TFrmLogin2]", "") Then
    _FileWriteLog(@ScriptDir & "\" & $usr & ".log", @UserName & " abgemeldet (und PW-Anmeldedialog geöffnet.")
    MsgBox(0, "F", "Fenster erkannt")
    Exit
    EndIf
    DllCall($h_PsAPI, 'int', 'EmptyWorkingSet', 'long', -1)
    WEnd

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

    _FileWriteLog(@ScriptDir & "\" & $usr & ".log", @UserName & " abgemeldet")
    MsgBox(0, "ende", "ende")
    Exit

    [/autoit]

    Die Alternative hierzu wäre eine Event-Behandlung.
    Windows haut bei jeder Aktion eine Meldung raus was passiert ist.
    Man kann nun in AutoIt eine Funktion bestimmen welche gestartet wird wenn z.B. ein Fenster geschlossen wurde.
    Das ist zwar deutlich aufwendiger umzusetzen hätte aber den Vorteil das die Abfragen wirklich nur dann passieren wenn sie gebraucht werden.
    Desweiteren wüsste ich spontan erstmal nur wie man auf das Schließen von Fenstern reagiert.
    Ob das auch beim Schließen von Prozessen klappt weiß ich nicht.

  • Folgende includes kannst übrigens raus machen die brauchst nicht:

    ButtonConstants.au3
    GUIConstantsEx.au3
    ProgressConstants.au3
    StaticConstants.au3
    WindowsConstants.au3

    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.