Prüfen, ob Anwendung gestartet wurde und danach beenden

  • VB.NET

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Prüfen, ob Anwendung gestartet wurde und danach beenden

    Moin Moin,

    ich stehe gerade voll auf dem Schlauch... vermutlich zu lange rumprobiert.

    Ich möchte aus meiner Form eine Anwendung starten, habe testweise die notepad.exe genommen. Das klappt ja auch.
    Nun möchte ich jedoch auch eine MsgBox ausgeben, wenn der Prozess beendet wurde, kann mir jemand sagen, was ich falsch mache?

    Habe das Ganze momentan im Timer.Tick-Event.

    VB.NET-Quellcode

    1. 'Prozess starten
    2. Dim p() As Process
    3. Dim prog As String = TxtProzess.Text
    4. p = Process.GetProcessesByName(prog)
    5. Dim Prozess_gestartet As Boolean
    6. Dim Starte_Notepad As Boolean
    7. If Starte_Notepad And p.Count = 0 Then
    8. Process.Start("notepad.exe")
    9. Prozess_gestartet = True
    10. Label6.Text = Prozess_gestartet
    11. End If
    12. 'Prozess wurde beendet
    13. If Label6.Text = "True" And p.Count = 0 Then
    14. Prozess_gestartet = False
    15. Label6.Text = Prozess_gestartet
    16. MsgBox("Prozess beendet")
    17. End If
    @Murdersquad So was:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private WithEvents prc As Process
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. prc = New Process
    5. prc.StartInfo.FileName = "notepad.exe"
    6. prc.EnableRaisingEvents = True
    7. prc.Start()
    8. End Sub
    9. Private Sub prc_exit(sender As Object, e As EventArgs) Handles prc.Exited
    10. MessageBox.Show("Prozess beendet")
    11. End Sub
    12. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, die Funktion ist bereits die Richtige.
    Das Ganze funktioniert bei mir jedoch nur mit notepad. Ich habe mal eine andere Anwendung, keine Windows-eigene, benutzt und dann meckert er.
    Ich vermute, dass ich bei

    prc.StartInfo.FileName nicht den kompletten Pfad zur EXE angeben darf, sondern nur den Namen der EXE selbst, oder?

    Murdersquad schrieb:

    oder?
    Geht das Ausprobieren mit und ohne Pfad schneller oder langsamer als hier einen Post zu schreiben?
    Ist das jetzt die vollständige Problembeschreibung?
    In welchem (besonderen) Verzeichnis befindet sich Notepad.exe?
    Was sagt die MSDN zu .StartInfo.FileName?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich hatte mein Problem falsch beschrieben.
    Da ich ja im Timer.Tick-Event gearbeitet habe, habe ich das p.count beibehalten, da ich den Prozess ja nur ein Mal starten möchte. Ich hatte einfach vergessen, dass ich ja dann auch den Prozessnamen in meiner prog-Variable anpassen muss. Mit notepad hat es freilich geklappt, mit anderen Prozessen wurde einfach mein Bildschirm geflutet.

    Sorry für das Missverständnis.
    Ich habe nochmal eine doofe Frage...
    Ich übergebe, wenn die Anwendung geschlossen wurde, ein True an eine externe Stelle.
    Da das Signal nicht immer richtig durch ging, habe ich eine Schleife erstellt, bis die Gegenstelle sagt, dass die Variable True ist.

    Das sieht beispielhaft so aus:

    VB.NET-Quellcode

    1. Private Sub prc_exit(sender As Object, e As EventArgs) Handles prc.Exited
    2. Dim Meine_Variable As Boolean = Meine_Variable.ExternesProgramm
    3. If Meine_Variable = False Then
    4. Do
    5. Schreiben_in_externes_Programm(Meine_Variable, True)
    6. Loop Until Meine_Variable = True
    7. End If
    8. End Sub


    Wenn ich nun in dem externen Programm die Variable wieder auf False setze, dann springt sie sofort wieder auf True.
    Wird das Sub prc_exit nach Beenden der Anwendung dauerhaft durchlaufen? Kann man es nicht einmalig ausführen?

    Ich hoffe, dass ich es halbwegs verständlich erklären konnte.

    PS: Auch ein Exit Sub in der Schleife bringt nichts...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Murdersquad“ ()

    @Murdersquad Ich denke mal, dass Du das Abholen der Information in der Schleife tun solltest, damit die Information aktuell ist. Allerdings blockiert diese Schleife die GUI.
    Wenn Du das ganze mit Events machst, sollte es flüssiger gehen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die GUI ist nicht sooo wichtig, da sie lediglich zur Anzeige dient, aber stimmt schon einfrieren soll sie natürlich trotzdem nicht.

    Ich habe jetzt folgendes angelegt:

    VB.NET-Quellcode

    1. Public Event Programm_closed()
    2. Function Prog_closing() As Object
    3. Dim Meine_Variable As Boolean = Meine_Variable.ExternesProgramm
    4. Do
    5. If Meine_Variable = False Then
    6. Schreiben_in_externes_Programm(Meine_Variable, True)
    7. End If
    8. Loop Until Meine_Variable = True
    9. RaiseEvent Programm_closed()
    10. End Function


    Nun wird doch trotz des geänderten Aufrufs weiterhin meine Variable durch die Schleife dauerhaft überschrieben?
    @Murdersquad Nicht verstanden. ;)
    Ich meinte etwa dies (nicht getestet):

    VB.NET-Quellcode

    1. Sub Prog_closing()
    2. Dim Meine_Variable As Boolean
    3. Do
    4. Meine_Variable = Meine_Variable.ExternesProgramm
    5. If Meine_Variable = False Then
    6. Schreiben_in_externes_Programm(Meine_Variable, True)
    7. End If
    8. Loop Until Meine_Variable = True
    9. RaiseEvent Programm_closed()
    10. End Sub

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, ich habe vor langer Zeit mal ein Event angelegt, weiß aber mittlerweile fast gar nichts mehr davon. Habe mich eben nochmal reingelesen, aber es klickt einfach nicht...

    Ich habe ja noch immer das Sub prc_exit von oben. Dort habe ich den Aufruf des Subs Prog_closing gemacht.
    Wie soll das RaiseEvent das nun stoppen bzw. verhindern, dass es erneut durchläuft? Das will mir nicht in den Kopf rein.
    Ist mir wahrscheinlich zu hoch...
    @Murdersquad Beschreib mal verbal, ohne Code, was da ablaufen soll.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Aus meinem Code heraus starte ich eine externe Anwendung.
    Sobald diese Anwendung beendet wird, soll eine Variable vom Typ Boolean an ein anderes System übergeben werden.
    Das Ganze läuft gerade mit deinem Codeschnipsel vom 29.12. (aus diesem Beitrag).

    An der Stelle, wo die MsgBox(„Prozess beendet“) erscheint, habe ich die Variable an das übergeordnete System auf True gesetzt. Es hat auch funktioniert, doch leider nicht immer. Die Messagebox kam übrigens immer.
    Daher dachte ich, dass in dem anderen System irgendwas läuft, wodurch meine Variable gelegentlich verschluckt wird. Also habe ich es so gemacht, dass ich in einer Schleife die Variable so lange Abfrage und setze, bis sie True ist. Das funktioniert ja auch. Gehe ich nun in das andere System und möchte die Variable auf False setzen, damit der Vorgang neu beginnen kann, dann wird sie durch das Hauptprogramm immer wieder auf True gesetzt.

    Die Schleife wird quasi erneut ausgeführt. Ich dachte das „Private Sub prc_exit„ wird nach Schließen der überwachten Anwendung nur ein einziges Mal durchlaufen, das scheint jedoch nicht der Fall zu sein.

    Im Prinzip möchte ich meine Schleife solange wiederholen, bis meine Variable auf True ist. Die Schleife soll erst wieder anlaufen, wenn das überwachte Programm erneut beendet wurde.

    Ist das halbwegs verständlich? Dachte an eine Art XOR-Schalter, bin aber aktuell in einer Sackgasse.
    Was ist

    Murdersquad schrieb:

    ein anderes System
    ?
    Laufen da 3 Programme gleichzeitig?
    Warum kann "das andere System" das Laufen der Anwendung nicht selbst abtesten?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, vom Prinzip her ist das so.

    Mein Programm bildet letztlich die Schnittstelle zwischen einer Software und einer kleinen SPS.
    Ich greife Signale aus der Software ab und gebe sie weiter an die SPS. Ich kann zwar von ihr lesen und in sie schreiben, sie kann jedoch nicht von mir lesen.
    @Murdersquad OK.
    Jetzt sag mal noch, wer was macht.
    Dein Programm belauscht ein anderes Programm bei der Kommunikation mit der SPS (TCP, RS232, ?) und beendet dieses?
    Ein Programm macht ietwas, Dein Programm belauscht dieses und beendet die SPS?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die SPS startet ein Programm X und mein Programm belauscht dieses.
    Die Kommunikation findet über TCP statt.
    Sobald das Programm X beendet wird, möchte ich ein Signal an die SPS geben.

    Ich habe schnell mal den Code von meinem Werkstatt-Rechner gezogen.

    VB.NET-Quellcode

    1. Private Sub prc_exit(sender As Object, e As EventArgs) Handles prc.Exited
    2. Dim alp() As Byte = BitConverter.GetBytes(1)
    3. Client.DBWrite(System.Convert.ToInt32(TxtDBNr.Text), 3, 1, alp)
    4. End Sub


    Nun ist es halt so, dass das Signal nicht immer durch geht...
    @Murdersquad Noch mal.
    Die SPS startet ein Programm, das auf der SPS läuft.
    Dein auf einem externen PC (nicht der SPS-Rechner) laufendes Programm stellt fest, dass auf der SPS ein Programm läuft.
    Dein PC-Programm wartet auf Beendigung des SPS-Programms und gibt der SPS ein Signal?
    Dann könnte doch auf der SPS ein Watcher-Programm laufen, alles auf der SPS und ohne PC.
    Oder hab ich da was falsch verstanden?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    wenn ich mein geschriebenes lese, dann könnte ich es auch so interpretieren, aber es ist doch etwas anders.

    Die SPS gibt ein Signal an mein Programm. Dann startet mein Programm das Programm X. Wenn Programm X geschlossen wird, dann meldet dies mein Programm zurück an die SPS.

    Mein Programm ist quasi die Schnittstelle zwischen SPS und Programm X.

    Mein Programm und Programm X laufen beide auf Windows.
    @Murdersquad Wenn Dein Programm das Programm X per Process.Start startet, bekommst Du das Beendigungs-Event, hier am Beispiel von Notapad:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private WithEvents prc As Process
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. prc = New Process
    5. prc.StartInfo.FileName = "notepad.exe"
    6. prc.EnableRaisingEvents = True
    7. prc.Start()
    8. End Sub
    9. Private Sub prc_exit(sender As Object, e As EventArgs) Handles prc.Exited
    10. MessageBox.Show("Prozess beendet")
    11. End Sub
    12. End Class
    Statt der MsgBox sendest Du das Signal an die SPS.
    Feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, genau das habe ich getan. Das Signal geht aber nicht immer durch.

    Meine Vermutung: Die SPS arbeitet ja zyklisch und liest nur zu Beginn eines neuen Zyklus die Signale. Wenn es während des Zyklus und dann auch nur ganz kurz kommt, dann merkt es die SPS nicht.

    Daher dachte ich an einen Handshake bzw. an die Schleife, die erst endet, wenn mein geschriebenes Signal als True gelesen wird. Das wiederum geht nicht, da das Sub prc_exit mit der Schleife das Bit immer wieder auf True setzt, sprich das Sub prc-Exit verhält sich bei mir wie ein Timer. Ist das normal?

    Hier mal ein Auszug aus meinem Code. Bitte nicht über die lines() schimpfen, ich arbeite manchmal mit txts, obwohl ich die ApplicationSettings kenne.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    2. Dim p() As Process
    3. Dim prog As String = lines(8)
    4. Dim argumente As String = "-open " & Chr(34) & lines(14) & Chr(34)
    5. p = Process.GetProcessesByName(prog)
    6. If DB30_DBX01 And p.Count = 0 Then
    7. prc = New Process
    8. prc.StartInfo.FileName = lines(11)
    9. If Not lines(14) = "" Then
    10. prc.StartInfo.Arguments = argumente
    11. End If
    12. prc.EnableRaisingEvents = True
    13. prc.Start()
    14. Dim wrDB30_DBB1() As Byte = BitConverter.GetBytes(1)
    15. Client.DBWrite(System.Convert.ToInt32(TxtDBNr.Text), 1, 1, wrDB30_DBB1)
    16. End If
    17. End Sub
    18. Private Sub prc_exit(sender As Object, e As EventArgs) Handles prc.Exited
    19. Dim eins() As Byte = BitConverter.GetBytes(1)
    20. Client.DBWrite(System.Convert.ToInt32(TxtDBNr.Text), 3, 1, eins)
    21. End Sub


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Murdersquad“ ()