Programm startet zu häufig!! -- $cmdline fehler?

  • Heyho, ich reiss mir gleich alle (restlichen) Haare aus!

    Ich bau mir ein Hauptprogramm, von der aus ich ein 2. Programm (eigene Exe) starte.
    Das Hauptprogramm erstellt dynamisch Buttons in eine GUI, für jede Exe, die sich im BasisOrdner des Hauptprogramms befinden.
    Jeder erstellte Button trägt den Namen einer Exe und soll bei Klick die entsprechende Exe starten. Dies funktioniert auch über GuiGetCursorInfo() ganz gut, ABER:

    Das Programm startet in unregelmäßiger Anzahl mehrfach, OBWOHL ich das 2. Program mittels _Singleton() abgesichert habe.
    Es startet also mal 3-fach, beim nächsten Versuch wird es dann 8 mal gestartet usw, bis jetzt war 8 das meisste.

    Ich komm nicht dahinter, warum?! Aus dem Hauptprogramm heraus starte ich die 2. Anwendung so

    [autoit]

    ShellExecute($_SCRIPT_FOLDER & ControlGetText("","",$this[4]) & "_MVL.exe", " -start")

    [/autoit]


    Mittlerweile weiss ich, dass es irgendwie am 2. Programm liegen muss. Wenn ich im 2. Programm den $CmdLine Kram auskommentiere funktioniert es problemlos.
    Aber ich will Parameter übergeben. und daran scheitert es offensichtlich. Was mach ich falsch?


    MfG Lo..

    Edit:

    [autoit]

    ; hier ist das Hauptprogramm
    ; ich hoffe es läuft beu euch
    #include <Array.au3>
    #include <String.au3>
    #include <GuiConstants.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <Misc.au3>
    #include <file.au3>

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

    _Singleton("Mastergui")

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

    Global $_SCRIPTVERSION = "1.1.00"
    Global $_SCRIPT_BUTTON_FONT[5] = [4, "Gabriola", "Georgia", "Arial", "Lucida Console"]
    Global $_SCRIPT_FOLDER = @DesktopDir & "\MVL\"
    ;~ Global $_SCRIPT_FOLDER = @UserProfileDir & "\MvL__\"
    ;~ Global $_SCRIPT_INI_FILE = $_SCRIPT_FOLDER & "MultiTool_von_Lottich.ini"
    Global $_SCRIPT_GUI_HEIGHT, $_SCRIPT_GUI_BREITE, $_SCRIPT_GUI_HEIGHT_EX, $_SCRIPT_COUNT_EXEFILE, $_SCRIPT_GUI, $_SCRIPT_BTN_OPEN_INI
    Global $_BTN_CTRL_POS_LINKS, $_BTN_CTRL_POS_BREIT
    Dim $_SCRIPT_GUI_BUTTONS[1]

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

    _MainGui()

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

    Func _MainGui()
    #Region ; Variablen der _MainGUI
    $_SCRIPT_GUI_HEIGHT = 60
    $_SCRIPT_GUI_BREITE = 200
    $_BTN_CTRL_POS_LINKS = 20
    $_BTN_CTRL_POS_BREIT = 160
    $_SCRIPT_GUI_HEIGHT_EX = _Count_ExeFiles(1) ; ermittelt die Extra-Höhe, abhängig von der Anzahl existierender ExeFiles
    $_SCRIPT_COUNT_EXEFILE = _Count_ExeFiles(0) ; enthält das Array der vorhandenen ExeFiles ( Anzahl und Namen )
    If IsArray($_SCRIPT_COUNT_EXEFILE) Then ReDim $_SCRIPT_GUI_BUTTONS[$_SCRIPT_COUNT_EXEFILE[0] + 1] ; ReDim, weil ExeFiles zur Laufzeit hinzu kommen könnten
    Local $_BTN_CTRL_HEIGHT, $_BTN_CTRL_BORDER_HEIGHT, $_BTN_CTRL_TEXT
    Local $VOben = $_SCRIPT_GUI_HEIGHT - 16
    Local $vLinks = $_BTN_CTRL_POS_LINKS - 1
    Local $VRechts = $_BTN_CTRL_POS_LINKS + $_BTN_CTRL_POS_BREIT + 1
    Local $VUnten = $_SCRIPT_GUI_HEIGHT + $_SCRIPT_GUI_HEIGHT_EX - 19
    #EndRegion

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

    $_SCRIPT_GUI = GUICreate("Multitool", $_SCRIPT_GUI_BREITE, $_SCRIPT_GUI_HEIGHT + $_SCRIPT_GUI_HEIGHT_EX)
    $_SCRIPT_BTN_OPEN_INI = GUICtrlCreateButton("INI", 5, 5, 30, 25)

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

    #Region ; Dynamisch erstellte Buttons
    If IsArray($_SCRIPT_COUNT_EXEFILE) Then
    For $i = 1 To $_SCRIPT_COUNT_EXEFILE[0]
    $_BTN_CTRL_HEIGHT = ($_SCRIPT_GUI_HEIGHT - 45) + ($i * 30)
    ;~ $_BTN_CTRL_TEXT = StringTrimRight($_SCRIPT_COUNT_EXEFILE[$i], 8)
    $_BTN_CTRL_TEXT = StringTrimRight($_SCRIPT_COUNT_EXEFILE[$i], 4)
    $_SCRIPT_GUI_BUTTONS[$i] = GUICtrlCreateButton($_BTN_CTRL_TEXT, $_BTN_CTRL_POS_LINKS, $_BTN_CTRL_HEIGHT, $_BTN_CTRL_POS_BREIT, 25)
    GUICtrlSetFont(-1, 16, 600, "", $_SCRIPT_BUTTON_FONT[1])
    Next
    EndIf
    #EndRegion

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

    #Region ; Dynamisch erstellter Rahmen rings um die Buttons
    If IsArray($_SCRIPT_COUNT_EXEFILE) Then
    $_BTN_CTRL_BORDER_HEIGHT = ($_SCRIPT_COUNT_EXEFILE[0] * 30) + 20
    GUICtrlCreateLabel("", 10, ($_SCRIPT_GUI_HEIGHT - 25), 180, 2, $WS_BORDER)
    GUICtrlCreateLabel("", 10, $_SCRIPT_GUI_HEIGHT - 32 + $_BTN_CTRL_BORDER_HEIGHT, 180, 2, $WS_BORDER)
    GUICtrlCreateLabel("", 10, ($_SCRIPT_GUI_HEIGHT - 25), 2, $_BTN_CTRL_BORDER_HEIGHT - 5, $WS_BORDER)
    GUICtrlCreateLabel("", 190, ($_SCRIPT_GUI_HEIGHT - 25), 2, $_BTN_CTRL_BORDER_HEIGHT - 5, $WS_BORDER)
    EndIf
    #EndRegion

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

    GUISetState(@SW_SHOW)
    While 1
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    Exit
    ;~ Case $_SCRIPT_BTN_OPEN_INI
    ;~ ShellExecute($_SCRIPT_INI_FILE)
    EndSwitch
    If _IsPressed(01) Then
    $this = GUIGetCursorInfo()
    If IsArray($this) Then
    If $this[0] > $vLinks And $this[0] < $VRechts And $this[1] > $VOben And $this[1] < $VUnten And $this[4] <> 0 Then
    ;~ ShellExecute($_SCRIPT_FOLDER & ControlGetText("","",$this[4]) & "_MVL.exe", " -start")
    ShellExecute($_SCRIPT_FOLDER & ControlGetText("","",$this[4]) & ".exe", " -start")
    EndIf
    EndIf
    EndIf
    WEnd
    EndFunc ;==>_MainGui

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

    Func _Count_ExeFiles($var = 0);$var <> 0 gibt die GUI-Höhe an, wird $var = 0 werden die Anzahl und Namen der Exe-Files als Array zurückgegeben
    Local $aRet, $this = _FileListToArray($_SCRIPT_FOLDER, "*.exe")
    If IsArray($this) Then
    $aRet = $this[0] * 30
    If $var = 1 Then
    Return $aRet
    Else
    Return $this
    EndIf
    Else
    Return 0
    EndIf
    EndFunc ;==>_Count_ExeFiles
    ; ..:: END OF FILE ::..

    [/autoit]


    [autoit]

    ; Minimalbeispiel des 2. Programms, muss mit Parameter aufgerufen werden...
    #include <File.au3>
    #include <WindowsConstants.au3>
    #include <Misc.au3>

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

    If @Compiled Then
    _ArrayDisplay($CmdLine)
    If $CmdLine[0] = 1 Then
    If $CmdLine[1] <> "-start" Then Exit MsgBox(0,"Fehler", "Das Programm kann nicht einzeln gestartet werden!")
    Else
    Exit MsgBox(0,"Fehler", "Das Programm kann nicht einzeln gestartet werden!")
    EndIf
    EndIf
    _Singleton("bliblablub_Instanz")

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

    Global $_SCRIPTVERSION = "1.0.00"
    Global $hMainGUI = GUICreate("Multitool v ", 600, 400, -1, -1, BitOR($WS_SYSMENU, $WS_MINIMIZEBOX))

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

    GUISetState(@SW_SHOW)
    While Sleep(50)
    $_GUI_MSG = GUIGetMsg()
    Switch $_GUI_MSG
    Case -3
    Exit
    EndSwitch
    WEnd

    [/autoit]

    Edit2: Nach jedem nachträglichen editieren wird die Autoit Syntax zerschossen....

  • Bau das mal mit ein:

    [autoit]


    $Ispressed=false

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

    If _IsPressed(01) and NOT $Ispressed Then
    $Ispressed=true
    $this = GUIGetCursorInfo()
    If IsArray($this) Then
    If $this[0] > $vLinks And $this[0] < $VRechts And $this[1] > $VOben And $this[1] < $VUnten And $this[4] <> 0 Then
    ;~ ShellExecute($_SCRIPT_FOLDER & ControlGetText("","",$this[4]) & "_MVL.exe", " -start")
    ShellExecute($_SCRIPT_FOLDER & ControlGetText("","",$this[4]) & ".exe", " -start")
    EndIf
    EndIf
    ElseIf NOT _IsPressed(01) and $Ispressed then
    $Ispressed=false
    EndIf

    [/autoit]

    Meiner Meinung nach liegt das Problem da:
    Du startest dein Hauptprogramm. Dort startest du dein Script, sooft, wielange 01 gedrückt ist. Dadurch, dass du kein Sleep hast, ziemlich oft.
    In deinem 2. Programm überprüfst du zwar mit _Singleton, ob bereits ein Programm läuft, aber damit dort angeschlagen wird, muss dein Programm 2, dass bereits vorher mehrmals gestartet wurde, an der Stelle angelangt sein, wo das _singleton registriert wurde. Ich denke, dass benötigt wenige Millisekunden. In diesen Millisekunden ist das Programm allerdings schon mehrmals an der Stelle, also fast gelichzeitig, sodass es mehrmals läuft und erst bei den Programmen danach abbricht.
    Somit solltest du den klick nur einmal nehmen, so wie ich das oben gemacht habe, oder zumindest ein Sleep(10), oder so, einbauen.

  • Ich verstehe sowieso nicht warum er ispressed verwendet um einen Klick auf die Buttons zu erkennen. Ich würde den ganzen murks raushauen und im guigetmsg switch case alle Buttons mit dem Event vergleichen:

    [autoit]


    While 1
    $guimsg = GUIGetMsg()
    Switch $guimsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case else
    If IsArray($_SCRIPT_COUNT_EXEFILE) Then
    For $i = 1 To $_SCRIPT_COUNT_EXEFILE[0]
    if $_SCRIPT_GUI_BUTTONS[$i] = $guimsg then
    ShellExecute($_SCRIPT_FOLDER & guictrlread($guimsg) & ".exe", " -start")
    exitloop
    endif
    Next
    EndIf
    EndSwitch
    WEnd

    [/autoit]
    • Offizieller Beitrag

    Du fängst doch die Button-ID sowieso in einem Array auf. Nimm dafür ein 2D-Array und füge die aufzurufende Funktion mit hinzu.

    z.B. so:

    [autoit]

    While 1
    $nMsg = GUIGetMsg()
    For $i = 0 To UBound($_SCRIPT_GUI_BUTTONS) -1
    ; Ausführen - wenn man das Array als 2D erstellt kann man die ID an [$i][0] und den Programmnamen an [$i][1] führen
    If $_SCRIPT_GUI_BUTTONS[$i][0] = $nMsg Then
    ; dann wäre hier: Call($_SCRIPT_GUI_BUTTONS[$i][1])
    EndIf
    ExitLoop
    Next
    ; ...
    WEnd

    [/autoit]

    Edit: Syntaxhighlight scheint ja besser zu sein - dafür werden jetzt alle Indents gekillt, wenn man den Code einfügt - Shit. Nacheditieren nützt nichts. :thumbdown:

  • Moin!

    Da kann man misterspeed nur Recht geben, sowas mit _ispressed zu "versuchen" ist ziemlicher Murks. Ich finds sogar haarsträubend...
    Hier mal mein Vorschlag dazu, mit einem etwas anderen Ansatz und um eine "Refresh"-Funktion erweitert.
    Ob es sinnvoll ist, möglichst wenige globale Variablen zu verwenden wurde hier schon des öfteren diskutiert. Ich bin mir selber nicht sicher, finde es so aber deutlich übersichtlicher:

    [autoit]

    #include <GUIConstantsEx.au3>
    #include <File.au3>

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

    Opt("GUIOnEventMode", 1) ; OnEvent ist meiner Meinung nach besser fuer diese Art Programm geeignet

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

    ;Das Programm hat nur 3 globale Variablen
    ;Die Fileliste, die Button IDs und das Fenster Handle; alles Andere wird nur lokal benötigt
    ;Schluesselwort Global hier eigendlich ueberfluessig, da es auf der untersten Ebene NUR globale Variablen gibt
    Global $aFileList = _FileListToArray(@ScriptDir, "*.exe")
    If @error Then Exit ; Keine Exe'n, kein Programm. Allerdings wird logischerweise die Programm-Exe selbst immer gefunden, was man noch beruecksichtigen sollte
    Global $aidButtons[$aFileList[0] + 1]

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

    Global $hGui = _GuiCreateCustom() ; Vermeidung ueberfluessiger Globaler Variablen (sinnvoll???)

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

    GUISetState(@SW_SHOW, $hGUI)

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

    While Sleep(3000)
    WEnd

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

    Func _Central()
    ; @GUI_CtrlId ist abhängig vom Zeitpunkt an dem sie während der GUI-Erstellung angelegt werden
    ConsoleWrite(@GUI_CtrlId - $aidButtons[1] + 1 & @CRLF)
    ShellExecute(@ScriptDir & "\" & $aFileList[@GUI_CtrlId - $aidButtons[1] + 1], "-start") ; +1 Versatz wegen Refresh Button
    EndFunc

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

    Func _Refresh() ; keine schoene Funktion, aber sie laeuft und ist unkompliziert ;)
    Local $iXpos = Default, $iYpos = Default
    $aFileList = _FileListToArray(@ScriptDir, "*.exe")
    If @error Then Exit
    ReDim $aidButtons[$aFileList[0] + 1]
    $aWinPos = WinGetPos($hGui) ; Position des alten Fensters merken
    If IsArray($aWinPos) Then ; reiner Aberglaube um Arrayfehlern vorzubeugen ;)
    $iXpos = $aWinPos[0]
    $iYpos = $aWinPos[1]
    EndIf
    GUIDelete($hGui)
    $hGui = _GuiCreateCustom($iXpos, $iYpos)
    GUISetState(@SW_SHOW, $hGUI)
    EndFunc

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

    Func _GuiCreateCustom($iX = Default, $iY = Default)
    Local $iButtonWidth = 180, $iButtonHeight = 24
    Local $iHeight = 18 + ($iButtonHeight + 4) * ($aFileList[0] + 1) ; +1 Versatz wegen Refresh Button
    Local $hG = GUICreate("Multitool", 20 + $iButtonWidth, $iHeight, $iX, $iY)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    $aidButtons[0] = GUICtrlCreateButton("Refresh", 10, 10, $iButtonWidth, $iButtonHeight) ;Refresh Button als erstes
    GUICtrlSetOnEvent(-1, "_Refresh")
    For $i = 1 To $aFileList[0]
    $iYpos = 10 + ($iButtonHeight + 4) * ($i - 0)
    $aidButtons[$i] = GUICtrlCreateButton(StringTrimRight($aFileList[$i], 4), 10, $iYpos, $iButtonWidth, $iButtonHeight)
    GUICtrlSetOnEvent(-1, "_Central")
    Next
    Return $hG ;Fensterhandle rurueckgeben
    EndFunc

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

    Func _Exit()
    Exit
    EndFunc

    [/autoit]

    Für die Formatierng kann ich nix, das neue Forum ist Schuld ;(

  • Danke für eure Antworten.

    Ich hab mich für BugFix´s Variante entschieden. Das ist eine clevere Lösung. Wann immer ich bisher Controls in Schleifen erzeugte,
    arbeitete ich mit GuiGetCursorInfo(), weil mir nix schlaueres einfiel. und warum ändern, wenn es doch bisher prima (wenn auch umständlich) funktionierte?

    Danke BugFix für den Gedankenschupser mit dem 2D Array.

    Mfg, Lo..