Próbuję wykonać plik wsadowy w C #, ale nie mam przy tym szczęścia.
Znalazłem wiele przykładów w Internecie, ale to nie działa.
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");
}
Ciąg polecenia zawiera nazwę pliku wsadowego (przechowywanego w system32
) i niektórych plików, którymi powinien manipulować. (Przykład:) txtmanipulator file1.txt file2.txt file3.txt
. Kiedy uruchamiam plik wsadowy ręcznie, działa on poprawnie.
Podczas wykonywania kodu daje mi plik **ExitCode: 1** (Catch all for general errors)
Co ja robię źle?
c#
batch-file
process
processstartinfo
Wessel T.
źródło
źródło
command
jest. Jeśli zawiera ścieżki ze spacjami, musisz umieścić je w cudzysłowie.Odpowiedzi:
To powinno działać. Możesz spróbować zrzucić zawartość strumieni wyjściowych i strumieni błędów, aby dowiedzieć się, co się dzieje:
* EDYTOWAĆ *
Biorąc pod uwagę dodatkowe informacje zawarte w poniższym komentarzu, udało mi się odtworzyć problem. Wydaje się, że istnieje pewne ustawienie zabezpieczeń, które powoduje takie zachowanie (nie zbadano tego szczegółowo).
Działa to, jeśli plik wsadowy nie znajduje się w
C:\Windows\System32
. Spróbuj przenieść go w inne miejsce, np. Lokalizację pliku wykonywalnego. Zauważ, że przechowywanie niestandardowych plików wsadowych lub plików wykonywalnych w katalogu Windows jest i tak złą praktyką.EDIT * 2 * To Okazuje się , że jeśli strumienie są odczytywane synchronicznie, może nastąpić zakleszczenie, albo przed przeczytaniem synchronicznie
WaitForExit
lub czytając jednocześniestderr
istdout
synchronicznie jeden po drugim.Nie powinno to mieć miejsca, jeśli zamiast tego używasz asynchronicznych metod odczytu, jak w poniższym przykładzie:
źródło
ta prosta linia uruchomi plik wsadowy.
źródło
Po wielkiej pomocy steinara, oto co mi zadziałało:
źródło
~%dp0
. DodanieProcessInfo.WorkingDirectory
naprawionego.command
jeśli bezpośrednio wywołujesz plik BAT?command
parametry mogą być używane do wysyłania argumentów do pliku BAT, to nie jest to, co pokazuje tutaj kod. W rzeczywistości nie jest używany. A gdyby tak było, prawdopodobnie należałoby goarguments
zamiast tego nazwać .command
jest używany wnew ProcessStartInfo
rozmowie.To działa dobrze. Przetestowałem to tak:
Skomentowałem wyłączenie okna, żeby zobaczyć, jak działa.
źródło
Oto przykładowy kod C #, który wysyła 2 parametry do pliku bat / cmd, aby odpowiedzieć na to pytanie .
Komentarz: jak mogę podać parametry i odczytać wynik wykonania polecenia?
/ przez @Janatbek Sharsheyev
źródło
Poniższy kod działał dobrze dla mnie
źródło
źródło
Czy próbowałeś uruchomić go jako administrator? Uruchom program Visual Studio jako administrator, jeśli go używasz, ponieważ praca z
.bat
plikami wymaga tych uprawnień.źródło
Chciałem czegoś, co byłoby bardziej bezpośrednio użyteczne bez specyficznych dla organizacji wartości ciągów zakodowanych na stałe. Oferuję następujące elementy jako fragment kodu do bezpośredniego ponownego wykorzystania. Drobną wadą jest konieczność określenia i przekazania folderu roboczego podczas wykonywania połączenia.
Nazywa się tak:
W tym przykładzie z poziomu programu Visual Studio 2017 w ramach uruchomienia testowego chcę uruchomić plik wsadowy resetowania środowiska przed wykonaniem niektórych testów. (SpecFlow + xUnit). Zmęczyły mnie dodatkowe kroki do ręcznego uruchamiania pliku bat oddzielnie i chciałem po prostu uruchomić plik bat jako część kodu konfiguracji testu C #. Plik wsadowy resetowania środowiska przenosi pliki przypadków testowych z powrotem do folderu wejściowego, czyści foldery wyjściowe itp., Aby uzyskać odpowiedni stan początkowy testu do testowania. Metoda QuotesAround po prostu umieszcza cudzysłowy wokół wiersza poleceń na wypadek, gdyby w nazwach folderów były spacje („Program Files”, ktoś?). Wszystko, co w nim jest, to: prywatny ciąg QuotesAround (ciąg wejściowy) {return "\" "+ input +" \ "";}
Mam nadzieję, że niektórzy uznają to za przydatne i zaoszczędzą kilka minut, jeśli Twój scenariusz jest podobny do mojego.
źródło
W przypadku wcześniej proponowanych rozwiązań zmagałem się z wykonaniem wielu poleceń npm w pętli i wyświetleniem wszystkich wyników w oknie konsoli.
W końcu zaczęło działać po połączeniu wszystkiego z poprzednich komentarzy, ale przestawiłem przepływ wykonywania kodu.
Zauważyłem, że subskrybowanie zdarzeń zostało wykonane zbyt późno (po rozpoczęciu procesu) i dlatego niektóre dane wyjściowe nie zostały przechwycone.
Poniższy kod wykonuje teraz następujące czynności:
Kod został przetestowany pod kątem zakleszczeń, chociaż jest on synchroniczny (wykonanie jednego procesu na raz), więc nie mogę zagwarantować, co by się stało, gdyby było to uruchamiane równolegle.
źródło
Korzystanie z CliWrap :
źródło
System.Diagnostics.Process.Start(BatchFileName, Parameters);
Wiem, że to zadziała dla pliku wsadowego i parametrów, ale nie ma pomysłów, jak uzyskać wyniki w C #. Zwykle dane wyjściowe są definiowane w pliku wsadowym.
źródło