Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
WinForm mit CMD Ausgabe in Textbox bei Ping lässt sich das Programm nicht beenden
Felwebel
myCSharp.de - Member



Dabei seit:
Beiträge: 7

Themenstarter:

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

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
hypersurf
myCSharp.de - Member



Dabei seit:
Beiträge: 511
Herkunft: Münster

beantworten | zitieren | melden

Das wird vermutlich daran liegen, dass Du proc in der Methode Ping() nochmal definierst (zusätzlich zur Klasse).
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von hypersurf am .
private Nachricht | Beiträge des Benutzers
Felwebel
myCSharp.de - Member



Dabei seit:
Beiträge: 7

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
p!lle
myCSharp.de - Member

Avatar #avatar-3556.jpg


Dabei seit:
Beiträge: 1053

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Felwebel
myCSharp.de - Member



Dabei seit:
Beiträge: 7

Themenstarter:

beantworten | zitieren | melden

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?
private Nachricht | Beiträge des Benutzers
p!lle
myCSharp.de - Member

Avatar #avatar-3556.jpg


Dabei seit:
Beiträge: 1053

beantworten | zitieren | melden

Was hast du versucht?
Was genau geht nicht?
private Nachricht | Beiträge des Benutzers
Felwebel
myCSharp.de - Member



Dabei seit:
Beiträge: 7

Themenstarter:

beantworten | zitieren | melden

ich hab die Variable proc in der Methode raus genommen.
private Nachricht | Beiträge des Benutzers
p!lle
myCSharp.de - Member

Avatar #avatar-3556.jpg


Dabei seit:
Beiträge: 1053

beantworten | zitieren | melden

Und was funktioniert dann nicht? -> Fehlermeldung?

Lass dir bitte nicht alle Informationen aus der Nase ziehen.
private Nachricht | Beiträge des Benutzers
Felwebel
myCSharp.de - Member



Dabei seit:
Beiträge: 7

Themenstarter:

beantworten | zitieren | melden

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]

private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Felwebel
myCSharp.de - Member



Dabei seit:
Beiträge: 7

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2341

beantworten | zitieren | melden

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 | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

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:
Zitat von https://docs.microsoft.com/de-de/dotnet/api/system.diagnostics.process.kill?view=netframework-4.8
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.
private Nachricht | Beiträge des Benutzers
Felwebel
myCSharp.de - Member



Dabei seit:
Beiträge: 7

Themenstarter:

beantworten | zitieren | melden

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)

            {
                
            }
        }
    }
}




private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers