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
Das wird vermutlich daran liegen, dass Du proc in der Methode Ping() nochmal definierst (zusätzlich zur Klasse).
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.
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.
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?
Und was funktioniert dann nicht? -> Fehlermeldung?
Lass dir bitte nicht alle Informationen aus der Nase ziehen.
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]
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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.
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 |
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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)
{
}
}
}
}
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:
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 😉
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code