Laden...

WinForm mit CMD Ausgabe in Textbox bei Ping lässt sich das Programm nicht beenden

Erstellt von Felwebel vor 4 Jahren Letzter Beitrag vor 4 Jahren 11.758 Views
F
Felwebel Themenstarter:in
7 Beiträge seit 2019
vor 4 Jahren
WinForm mit CMD Ausgabe in Textbox bei Ping lässt sich das Programm nicht beenden

Hallo Forum

als Neuling meine erste Frage bitte nicht gleich Steinigen, also zu minem Problem.

Ich habe eine Windows Form mit zwei Textboxen eine für die Eingabe von cmd Befehlen und eine für die Ausgabe der Befehle, die Befehle starte ich mit einbem Button.

Dies Funktioniert soweit auch sehr gut.

Jetzt zu meinem Problem ich wollte einen zusätzlichn Button hinzufügen mit dem ich die Ausgabe unterbrechen kann z. B wenn ich den Ping befehl starte läuft diser permanent und ich kann ihn nicht mehr stoppen. ich hab hetzt kine Ahnung wie ich weiter vorgehen soll hänge hier total in der Luft.

Vorab schonmal dnake für eure Hilfe.

Hier ein Code:



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace CMDAusführen
{
    public partial class Form1 : Form
    {
        private Process proc;
    
        public Form1()
        {
            InitializeComponent();
        }

     

        private void cmbAusführen_Click(object sender, EventArgs e)
        {
            proc = new Process();
            startNewThread();

        }


        public void Log(string line)
        {
            txtAnzeigen.Text += line + System.Environment.NewLine;
        }


        private void startNewThread()
        {
            Thread x = new Thread(new ThreadStart(Ping));
            x.IsBackground = true;
            x.Start();
        }


        private void Ping()
        {

            string command = txtStart.Text;

            ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd.exe","/c " + command);


            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.UseShellExecute = false;
            procStartInfo.CreateNoWindow = true;

            Process proc = new Process();
            proc.StartInfo = procStartInfo;
            proc.Start();



            while (proc.StandardOutput.Peek() > -1)
            {
                Invoke((MethodInvoker)delegate () { Log(proc.StandardOutput.ReadLine()); });
                proc.StandardOutput.DiscardBufferedData();
            }


        }

        private void cmbBeenden_Click(object sender, EventArgs e)
        {
          proc.Kill();
        }
    }
}




Wenn ich mit proc.Kill(); die Ausführung beenden möchte bekomme ich den Fehler System.InvalidOperationException (Diesem Objekt ist kein Prozess zugeordnet).

Ich habe absolut keine Ahnung wie ich hier weiter vorgehen soll hoffe auf eure Hilfe

H
523 Beiträge seit 2008
vor 4 Jahren

Das wird vermutlich daran liegen, dass Du proc in der Methode Ping() nochmal definierst (zusätzlich zur Klasse).

F
Felwebel Themenstarter:in
7 Beiträge seit 2019
vor 4 Jahren

Guten Morgen
und schonmal danke, schön für den tip.
Hast du für mich vielleicht nen Tip wie ich das am besten umschreiben könnte.
Das wäre klasse vorab schonmal danke für die Unterstützung.

1.040 Beiträge seit 2007
vor 4 Jahren

Vorab ein Stichwort zum Googlen: Scope

Du hast das Feld proc in deiner Klasse definiert.
Zusätzlich hast du in der Methode Ping() die Variable proc definiert. Mit dieser arbeitest du in der Methode. Du musst aber mit dem Feld der Klasse arbeiten, damit du eben in anderen Methoden die gleiche Instanz nutzt.

Bitte ebenfalls beachten: [Artikel] C#: Richtlinien für die Namensvergabe.
Dadurch wird klarer, ob es ein Feld, eine Variable oder irgendwas anderes ist.

F
Felwebel Themenstarter:in
7 Beiträge seit 2019
vor 4 Jahren

Ok danke, ich hab versucht das jetzt um zu schreiben aber dann geht irgendwie garnichts mehr.

Ich komm einfach nicht drauf wie ich die Ping Methode bei schreiben soll.
Hättest du vielleicht Zeit mir die Ping Methode umzuschreiben.
Das ich meine Schlussfolgerungen daraus ziehen kann?

1.040 Beiträge seit 2007
vor 4 Jahren

Was hast du versucht?
Was genau geht nicht?

F
Felwebel Themenstarter:in
7 Beiträge seit 2019
vor 4 Jahren

ich hab die Variable proc in der Methode raus genommen.

1.040 Beiträge seit 2007
vor 4 Jahren

Und was funktioniert dann nicht? -> Fehlermeldung?

Lass dir bitte nicht alle Informationen aus der Nase ziehen.

F
Felwebel Themenstarter:in
7 Beiträge seit 2019
vor 4 Jahren

Soory hier die Fehlermeldung wen ich auf den Button Beenden klicke :


System.InvalidOperationException: "Die Anforderung kann nicht verarbeitet werden, da der Prozess (36500) beendet wurde."

Diese Ausnahme wurde ursprünglich bei dieser Aufrufliste ausgelöst:
	System.Diagnostics.Process.GetProcessHandle(int, bool)
	System.Diagnostics.Process.Kill()
    CMDAusführen.Form1.cmbBeenden_Click(object, System.EventArgs) in Form1.cs
	System.Windows.Forms.Control.OnClick(System.EventArgs)
	System.Windows.Forms.Button.OnClick(System.EventArgs)
	System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs)
	System.Windows.Forms.Control.WmMouseUp(ref System.Windows.Forms.Message, System.Windows.Forms.MouseButtons, int)
	System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message)
	System.Windows.Forms.ButtonBase.WndProc(ref System.Windows.Forms.Message)
	System.Windows.Forms.Button.WndProc(ref System.Windows.Forms.Message)
    ...
    [Aufrufliste abgeschnitten]


16.807 Beiträge seit 2008
vor 4 Jahren

Naja, da steht der Fehler ja recht deutlich: Prozess beendet.
Dann kannst halt auch nicht mehr drauf zugreifen.

Einen Ping kannst Du auch einfach mit dem System.Net.NetworkInformation Namespace ohne extra Prozess ausführen.

F
Felwebel Themenstarter:in
7 Beiträge seit 2019
vor 4 Jahren

Hallo
es geht mir nicht nur um den Ping sonder um das CMD ausführen.
also CMD Befehle wie herunter fahren usw kann ich ohne Probleme ausführen das geht alles.
Nur ich Ping ausführe kann ich es nicht mehr beenden, das ist mein Problem.

2.298 Beiträge seit 2010
vor 4 Jahren

Die Antwort hat dir doch Abt geliefert?

Dein Programm führt das Kommando aus. Wenn das Kommando abgeschlossen ist wird die "Konsole" beendet. Du versuchst nun einen nicht (mehr) laufenden Prozess zu beenden.

Man kann z.B. auch Prozessstatus abfragen. Vielleicht hilft dir das ja?

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

16.807 Beiträge seit 2008
vor 4 Jahren

Felwebel, Du wirst hier ohne ein Basic Try-Catch nicht drum herum kommen.

Selbst wenn Du den Process-Status abfragst, kann Kill weiterhin eine InvalidOperationException werfen, weil zwischen Status-Abfrage und Kill der Prozess beendet wurde.

Und wenn Du versuchst einen Prozess zu beenden oder darauf zuzugreifen, wenn er schon beendet wurde, dann kommt eben eine InvalidOperationException raus.
Siehe auch ein kurzer Sekunden-Blick in die Doku:

InvalidOperationException
Der Prozess wurde bereits beendet.

  • oder - Diesem Process-Objekt ist kein Prozess zugeordnet.

Daher bleibt Dir NICHTS anderes übrig als:

try
{
  process.Kill();
catch (InvalidOperationException ex)
{
   // already exited
}

Nen bisschen musst halt auch selbst lesen, verstehen, umsetzen.
Das ist die Aufgabe als Programmierer / Entwickler.

F
Felwebel Themenstarter:in
7 Beiträge seit 2019
vor 4 Jahren

Hi
erstmal danke für eure Unterstüzung.

ich hab das Try-Catch jetzt eingebaut also fehler hab ich jetzt keinen mehr jedoch wird der Ping Befehl
immer nach wie vor ausgeführt wenn ich auf den Button Beenden klicke.
Habt ihr vielleit noch ne Idee?

Mein Code sieht jetzt so aus:



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace CMDAusführen
{
    public partial class Form1 : Form
    {
        private Process proc;
    
        public Form1()
        {
            InitializeComponent();
        }

     

        private void cmbAusführen_Click(object sender, EventArgs e)
        {
            proc = new Process();
            startNewThread();

          

   


        }


        public void Log(string line)
        {
            txtAnzeigen.Text += line + System.Environment.NewLine;
        }


        private void startNewThread()
        {
            Thread x = new Thread(new ThreadStart(Ping));
            x.IsBackground = true;
            x.Start();
        }


        private void Ping()
        {



            
            string command = txtStart.Text;

         

            ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd.exe","/c " + command);


            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.UseShellExecute = false;
            procStartInfo.CreateNoWindow = true;
            proc.StartInfo = procStartInfo;
            proc.Start();



            while (proc.StandardOutput.Peek() > -1)
            {
                Invoke((MethodInvoker)delegate () { Log(proc.StandardOutput.ReadLine()); });
                proc.StandardOutput.DiscardBufferedData();
            }


        }

        private void cmbBeenden_Click(object sender, EventArgs e)
        {
            try
            {
                proc.Kill();
               
             
            }
            catch (InvalidOperationException)

            {
                
            }
        }
    }
}





16.807 Beiträge seit 2008
vor 4 Jahren

Nimm Dir einfach mal ein paar Minuten Zeit und schau Dir an, was Du da überhaupt machst.
Damit würdest Du selbst auch schneller voran kommen - und verstehen, wieso das nicht funktioniert und auch nicht funktionieren kann. 👍

Im Prinzip machst Du:

  • Deine Anwendung startet den Kommandozeilen-Prozess
  • Die Kommandozeile startet den Ping-Prozess

Der Kill killt natürlich nur die Kommandozeile - nicht den Ping. ⚠
Der Ping ist ein eigener Prozess, den nicht Du startest - sondern eben die Kommandozeile.
Damit hast Du auch keine direkte Managementmöglichkeit für den Ping-Prozess.

Du müsstest, wenn Du den Ping selbst killen willst, alle laufende Prozesse suchen und dann den Ping-Prozess finden und diesen stoppen.
Mit Hilfe von WMI kannst Du aber auch alle Child Prozesse eines Prozesses herausfinden; und diese dann alle stoppen.
Sprich die Kommandozeile und eben alle von der Kommandozeile gestarteten Prozesse.

Daher hab ich bereits auch in meinem anderen Beitrag gesagt:
Verwende den .NET Namespace, wenn Du einen Ping durchführen willst, und nicht diesen Kommandozeilen-Käse.
Das ist totaler Bastelmurks 😉