Ich versuche, eine Batch-Datei in C # auszuführen, habe aber kein Glück damit.
Ich habe im Internet mehrere Beispiele dafür gefunden, aber es funktioniert bei mir nicht.
public void ExecuteCommand(string command)
{
int ExitCode;
ProcessStartInfo ProcessInfo;
Process Process;
ProcessInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = false;
Process = Process.Start(ProcessInfo);
Process.WaitForExit();
ExitCode = Process.ExitCode;
Process.Close();
MessageBox.Show("ExitCode: " + ExitCode.ToString(), "ExecuteCommand");
}
Die Befehlszeichenfolge enthält den Namen der Batchdatei (gespeichert in system32
) und einige Dateien, die bearbeitet werden sollen. (Beispiel:txtmanipulator file1.txt file2.txt file3.txt
. Wenn ich die Batchdatei manuell ausführe, funktioniert sie ordnungsgemäß.
Bei der Ausführung des Codes gibt es mir eine **ExitCode: 1** (Catch all for general errors)
Was mache ich falsch?
c#
batch-file
process
processstartinfo
Wessel T.
quelle
quelle
command
ist. Wenn es Pfade mit Leerzeichen enthält, müssen Sie sie in Anführungszeichen setzen.Antworten:
Das sollte funktionieren. Sie könnten versuchen, den Inhalt der Ausgabe- und Fehlerströme zu löschen, um herauszufinden, was passiert:
* BEARBEITEN *
Aufgrund der zusätzlichen Informationen in Ihrem Kommentar unten konnte ich das Problem neu erstellen. Es scheint eine Sicherheitseinstellung zu geben, die zu diesem Verhalten führt (habe dies nicht im Detail untersucht).
Dies funktioniert , wenn sich die Batchdatei nicht in befindet
C:\Windows\System32
. Versuchen Sie, es an einen anderen Speicherort zu verschieben, z. B. an den Speicherort Ihrer ausführbaren Datei. Beachten Sie, dass das Speichern benutzerdefinierter Batchdateien oder ausführbarer Dateien im Windows-Verzeichnis ohnehin eine schlechte Praxis ist.* EDIT 2 * Es stellt sich heraus, dass beim synchronen Lesen der Streams ein Deadlock auftreten kann, entweder durch synchrones Lesen vor
WaitForExit
oder durch Lesen von beidenstderr
undstdout
synchron nacheinander.Dies sollte nicht passieren, wenn stattdessen die asynchronen Lesemethoden verwendet werden, wie im folgenden Beispiel:
quelle
Diese einfache Zeile führt die Batchdatei aus.
quelle
Nach einiger großer Hilfe von Steinar hat dies für mich funktioniert:
quelle
~%dp0
. Hinzufügen derProcessInfo.WorkingDirectory
behoben es.command
wenn Sie die BAT-Datei direkt aufrufen?command
Parameter zum Senden von Argumenten an die BAT-Datei verwendet werden könnten, wird der Code hier nicht angezeigt. Es wird in der Tat überhaupt nicht verwendet. Und wenn ja, sollte es wahrscheinlich stattdessen benanntarguments
werden.command
imnew ProcessStartInfo
Anruf verwendet.Es funktioniert gut. Ich habe es so getestet:
Ich habe das Fenster ausgeschaltet, damit ich sehen kann, wie es läuft.
quelle
Hier ist ein Beispiel-C # -Code, der 2 Parameter an eine bat / cmd-Datei sendet, um diese Frage zu beantworten .
Kommentar: Wie kann ich Parameter übergeben und ein Ergebnis der Befehlsausführung lesen?
/ von @Janatbek Sharsheyev
quelle
Der folgende Code hat für mich gut funktioniert
quelle
quelle
Haben Sie versucht, es als Administrator zu starten? Starten Sie Visual Studio als Administrator, wenn Sie es verwenden, da für die Arbeit mit
.bat
Dateien diese Berechtigungen erforderlich sind.quelle
Ich wollte etwas, das direkter ohne organisationsspezifische fest codierte Zeichenfolgenwerte verwendet werden kann. Ich biete Folgendes als direkt wiederverwendbaren Codeabschnitt an. Der kleine Nachteil ist, dass der Arbeitsordner beim Tätigen des Anrufs ermittelt und übergeben werden muss.
So genannt:
In diesem Beispiel möchte ich in Visual Studio 2017 im Rahmen eines Testlaufs eine Batchdatei zum Zurücksetzen der Umgebung ausführen, bevor einige Tests ausgeführt werden. (SpecFlow + xUnit). Ich hatte es satt, zusätzliche Schritte zum manuellen Ausführen der Bat-Datei separat auszuführen, und wollte die Bat-Datei nur als Teil des C # -Test-Setup-Codes ausführen. Die Batchdatei zum Zurücksetzen der Umgebung verschiebt Testfalldateien zurück in den Eingabeordner, bereinigt Ausgabeordner usw., um den richtigen Teststartstatus für das Testen zu erreichen. Die QuotesAround-Methode setzt einfach Anführungszeichen um die Befehlszeile, falls Leerzeichen in Ordnernamen vorhanden sind ("Programme", jemand?). Alles, was drin ist, ist Folgendes: privater String QuotesAround (String-Eingabe) {return "\" "+ input +" \ "";}
Hoffe, einige finden dies nützlich und sparen ein paar Minuten, wenn Ihr Szenario meinem ähnlich ist.
quelle
Bei zuvor vorgeschlagenen Lösungen hatte ich Probleme, mehrere npm-Befehle in einer Schleife auszuführen und alle Ausgaben im Konsolenfenster zu erhalten.
Es fing endlich an zu funktionieren, nachdem ich alles aus den vorherigen Kommentaren kombiniert, aber den Code-Ausführungsfluss neu geordnet hatte.
Was mir aufgefallen ist, ist, dass das Abonnieren von Ereignissen zu spät erfolgte (nachdem der Prozess bereits gestartet wurde) und daher einige Ausgaben nicht erfasst wurden.
Der folgende Code bewirkt nun Folgendes:
Der Code wurde gegen die Deadlocks getestet, obwohl er synchron ist (jeweils eine Prozessausführung), sodass ich nicht garantieren kann, was passieren würde, wenn dies parallel ausgeführt würde.
quelle
Verwenden von CliWrap :
quelle
System.Diagnostics.Process.Start(BatchFileName, Parameters);
Ich weiß, dass dies für Batch-Dateien und Parameter funktioniert, aber keine Ideen, wie die Ergebnisse in C # erhalten werden können. Normalerweise werden die Ausgaben in der Batch-Datei definiert.
quelle