Uruchom polecenia wiersza polecenia


605

Czy istnieje sposób uruchamiania poleceń wiersza polecenia z aplikacji C #? Jeśli tak, to jak powinienem wykonać następujące czynności:

copy /b Image1.jpg + Archive.rar Image2.jpg

Zasadniczo osadza plik RAR w obrazie JPG. Zastanawiałem się tylko, czy istnieje sposób, aby to zrobić automatycznie w języku C #.


6
Duplikat stackoverflow.com/questions/181719/… (tam jest odpowiedź, która robi, co chcesz).
— Matt Hamilton

Odpowiedzi:


917

to wszystko, co musisz zrobić, aby uruchomić polecenia powłoki z C #

string strCmdText;
strCmdText= "/C copy /b Image1.jpg + Archive.rar Image2.jpg";
System.Diagnostics.Process.Start("CMD.exe",strCmdText);

EDYTOWAĆ:

Ma to na celu ukrycie okna cmd.

System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C copy /b Image1.jpg + Archive.rar Image2.jpg";
process.StartInfo = startInfo;
process.Start();

EDYCJA: 2

Ważne jest to, że argument zaczyna się od, w /Cprzeciwnym razie nie zadziała. Jak powiedział Scott Ferguson : „Wykonuje polecenie określone przez ciąg, a następnie kończy działanie”.


166
/ C Wykonuje polecenie określone przez ciąg znaków, a następnie kończy działanie
— Scott Ferguson

16
po prostu informuje cmd, aby uruchomił się i zakończył (nie czekaj, aż dane wejściowe użytkownika zamkną okno)
— RameshVel 24.09.09

3
Dziękuję jeszcze jedno pytanie. Czy można w ten sposób ukryć wiersz polecenia?
— użytkownik

9
Nie rozumiem, jak jestem jedynym, który uważa, że ​​to okropny pomysł. Tak, to zadziała, ale jest całkowicie błędne. Spawnowanie procesów CMD do wykonywania prostych operacji IO jest złe, nawet jeśli działa. Przeczytaj dokumentację w przestrzeni nazw System.IO. Jest tam więcej niż wystarczająca funkcjonalność, aby zrobić to, co musisz zrobić bez odradzania niepotrzebnych procesów.
— Instance Hunter,

56
FYI: Użyj process.WaitForExit (), aby poczekać na zakończenie procesu przed kontynuowaniem i przetworzyć.ExitCode, aby uzyskać kod zakończenia procesu.
— shindigo,

122

Próbowałem rozwiązania @RameshVel, ale nie mogłem przekazać argumentów w mojej aplikacji konsoli. Jeśli ktoś napotka ten sam problem, oto rozwiązanie:

using System.Diagnostics;

Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();

cmd.StandardInput.WriteLine("echo Oscar");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());

2
cóż, nie dałem mu szansy, myśląc, że na moim komputerze są pewne ograniczenia administratora lub antywirusowe, ale ... powyższy kod działa! dzięki Ogglas
— Pete Kozak,

6
ta linia: cmd.StartInfo.CreateNoWindow = true; uratował mi dzień.
— Ganesh Kamath - „Code Frenzy”

Czy istnieje sposób wykonywania wielu poleceń w jednymcmd.StandardInput.WriteLine(@"cd C:\Test; pwd")
— Zach Smith

36
var proc1 = new ProcessStartInfo();
string anyCommand; 
proc1.UseShellExecute = true;

proc1.WorkingDirectory = @"C:\Windows\System32";

proc1.FileName = @"C:\Windows\System32\cmd.exe";
proc1.Verb = "runas";
proc1.Arguments = "/c "+anyCommand;
proc1.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(proc1);

2
Jaki jest @znak w C #?
— Pacerier

6
@Pacerier Mówi kompilatorowi, aby uszedł ze wszystkich znaków, które normalnie musiałyby być poprzedzone ciągiem znaków, w tym przypadku \. Więc bez \ twój kod wyglądałby takproc1.FileName = "C:\\Windows\\System32\\cmd.exe";
— James Ko

1
Należy zauważyć, proc1.Verb = "runas";że ten proces działa z podwyższonymi uprawnieniami ... Nie zawsze jest to zamierzone.
— Dinei

1
Jak mogę sprawić, aby to okno cmd nie zamykało się po zakończeniu?
— Hrvoje T

1
Odkryłem, że wywołanie „ścieżki cd” połączone przez „&&” z innymi poleceniami w linii zawsze wykonuje się na końcu, nawet jeśli było pierwsze. your: 'proc1.WorkingDirectory = @ "C: \ Windows \ System32";' był bardzo pomocny! Dzięki!
— Nozim Turakulov

11

Żadna z powyższych odpowiedzi nie pomogła z jakiegoś powodu, wydaje się, że zamiatają błędy pod dywan i utrudniają rozwiązywanie problemów z komendą. Skończyło się na tym, że może coś takiego może pomóc:

var proc = new Process
{
    StartInfo = new ProcessStartInfo
    {
        FileName = @"C:\Program Files\Microsoft Visual Studio 14.0\Common7\IDE\tf.exe",
        Arguments = "checkout AndroidManifest.xml",
        UseShellExecute = false,
        RedirectStandardOutput = true,
        CreateNoWindow = true,
        WorkingDirectory = @"C:\MyAndroidApp\"
    }
};

proc.Start();

Gdybym chciał skompilować to w samodzielnej aplikacji konsolowej, jaki inny kod musiałby zostać dodany, aby działał? (Jestem noobem do tych wszystkich rzeczy związanych z programowaniem, wykonałem tylko trochę skryptów). Używam csc.exe btw.
— script'n'code

@copyitright Przestrzeń nazw i klasa. Jeśli właśnie utworzysz nowy projekt, zostaną one dla Ciebie wygenerowane.
— coinbird

Ach nieważne. jeśli korzystasz z cmd.exeaplikacji, możesz przekazywać polecenia jako argumenty.
— Zach Smith

Dla potomnych: chciałem, aby proces się uruchomił echo Hello World!i wyświetlał dane wyjściowe polecenia w wyskakującym oknie cmd. Tak próbowałem: Filename = @"echo", Arguments = "Hello World!", UseShellExecute = false, RedirectStandardOuput = false, CreateNoWindow = false. Dzięki temu okno cmd aplikacji nadrzędnej wyświetlało „Hello World!” (co ma sens, ponieważ standardowe wyjście nie zostało przekierowane do procesu potomnego).
— Minh Tran,

10

Choć technicznie nie odpowiada to bezpośrednio na postawione pytanie, odpowiada na pytanie, jak zrobić to, co chciał oryginalny plakat: łączyć pliki. Jeśli już, to jest post, który pomoże początkującym zrozumieć, o czym rozmawiają Instance Hunter i Konstantin.

Jest to metoda, której używam do łączenia plików (w tym przypadku jpg i zip). Zauważ, że tworzę bufor, który jest wypełniany zawartością pliku zip (raczej w małych porcjach niż w jednej dużej operacji odczytu), a następnie bufor jest zapisywany z tyłu pliku jpg, aż do końca pliku zip osiągnął:

private void CombineFiles(string jpgFileName, string zipFileName)
{
    using (Stream original = new FileStream(jpgFileName, FileMode.Append))
    {
        using (Stream extra = new FileStream(zipFileName, FileMode.Open, FileAccess.Read))
        {
            var buffer = new byte[32 * 1024];

            int blockSize;
            while ((blockSize = extra.Read(buffer, 0, buffer.Length)) > 0)
            {
                original.Write(buffer, 0, blockSize);
            }
        }
    }
}

9

jeśli chcesz zachować otwarte okno cmd lub chcesz użyć go w winform / wpf, użyj go w ten sposób

    string strCmdText;
//For Testing
    strCmdText= "/K ipconfig";

 System.Diagnostics.Process.Start("CMD.exe",strCmdText);

/ K

Utrzyma otwarte okno cmd


Miły. Znalazłem to w dokumentacji dla cmdpolecenia i jego parametrów.
— pius

8

Tak, istnieje (patrz link w komentarzu Matta Hamiltona), ale łatwiej i lepiej byłoby korzystać z klas IO platformy .NET. Możesz użyć File.ReadAllBytes do odczytania plików, a następnie File.WriteAllBytes do napisania wersji „osadzonej”.


11
Ładowanie całych plików do pamięci tylko w celu ich wzajemnego połączenia nie jest bardzo wydajne, szczególnie jeśli pliki są wystarczająco duże.
— Konstantin Spirin

7
Spróbuj spojrzeć na ducha odpowiedzi. Chodzi o to, że .NET ma więcej niż wystarczająco klas IO i funkcji, aby to zrobić bez konieczności wywoływania powłoki systemu operacyjnego. Poszczególne funkcje, o których wspomniałem, mogą nie być najlepsze, ale były po prostu najprostsze. Wezwanie do powłoki w tym celu nie ma żadnego sensu.
— Instance Hunter,

7

Możesz to zrobić za pomocą CliWrap w jednym wierszu:

var stdout = new Cli("cmd")
         .Execute("copy /b Image1.jpg + Archive.rar Image2.jpg")
         .StandardOutput;

Głosowałem za tym ... ale wydaje się, że repozytorium teraz brakuje:Unable to find package 'CliWrap' at source
— Zach Smith,

1
@ZachSmith nie jestem pewien, co masz na myśli, nuget.org/packages/CliWrap wydaje się działać dobrze. Oryginalny link też.
— Tyrrrz

Ah.sorry .. z jakiegoś powodu, gdy nie mogłem połączyć się z moim repozytorium nuget przez VPN, nie mogłem zainstalować tego pakietu. nuget nadal jest dla mnie w większości tajemnicą. musiał źle to ustawić
— Zach Smith,


5

Oto trochę prosta i mniejsza wersja kodu. Ukryje także okno konsoli-

System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/C copy /b Image1.jpg + Archive.rar Image2.jpg";
process.Start();

5

jeśli chcesz uruchomić polecenie w trybie asynchronicznym - i wydrukuj wyniki. możesz zrobić tę klasę:

    public static class ExecuteCmd
{
    /// <summary>
    /// Executes a shell command synchronously.
    /// </summary>
    /// <param name="command">string command</param>
    /// <returns>string, as output of the command.</returns>
    public static void ExecuteCommandSync(object command)
    {
        try
        {
            // create the ProcessStartInfo using "cmd" as the program to be run, and "/c " as the parameters.
            // Incidentally, /c tells cmd that we want it to execute the command that follows, and then exit.
            System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
            // The following commands are needed to redirect the standard output. 
            //This means that it will be redirected to the Process.StandardOutput StreamReader.
            procStartInfo.RedirectStandardOutput =  true;
            procStartInfo.UseShellExecute = false;
            // Do not create the black window.
            procStartInfo.CreateNoWindow = true;
            // Now we create a process, assign its ProcessStartInfo and start it
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo = procStartInfo;
            proc.Start();

            // Get the output into a string
            string result = proc.StandardOutput.ReadToEnd();

            // Display the command output.
            Console.WriteLine(result);
        }
        catch (Exception objException)
        {
            // Log the exception
            Console.WriteLine("ExecuteCommandSync failed" + objException.Message);
        }
    }

    /// <summary>
    /// Execute the command Asynchronously.
    /// </summary>
    /// <param name="command">string command.</param>
    public static void ExecuteCommandAsync(string command)
    {
        try
        {
            //Asynchronously start the Thread to process the Execute command request.
            Thread objThread = new Thread(new ParameterizedThreadStart(ExecuteCommandSync));
            //Make the thread as background thread.
            objThread.IsBackground = true;
            //Set the Priority of the thread.
            objThread.Priority = ThreadPriority.AboveNormal;
            //Start the thread.
            objThread.Start(command);
        }
        catch (ThreadStartException )
        {
            // Log the exception
        }
        catch (ThreadAbortException )
        {
            // Log the exception
        }
        catch (Exception )
        {
            // Log the exception
        }
    }

}

2

Możesz to osiągnąć za pomocą następującej metody (jak wspomniano w innych odpowiedziach):

strCmdText = "'/C some command";
Process.Start("CMD.exe", strCmdText);

Kiedy wypróbowałem metody wymienione powyżej, okazało się, że moje niestandardowe polecenie nie działa przy użyciu składni niektórych z powyższych odpowiedzi.

Odkryłem, że bardziej złożone polecenia muszą być zawarte w cudzysłowach, aby działać:

string strCmdText;
strCmdText = "'/C cd " + path + " && composer update && composer install -o'";
Process.Start("CMD.exe", strCmdText);

1

możesz po prostu napisać kod w .batrozszerzeniu formatu, kod pliku wsadowego:

c:/ copy /b Image1.jpg + Archive.rar Image2.jpg

użyj tego kodu c #:

Process.Start("file_name.bat")


jeśli chcesz ukryć cmd podczas działania, możesz użyć prostego wizualnego podstawowego kodu skryptu w .vbsrozszerzeniu formatu, kod:CreateObject("Wscript.Shell").Run "filename.bat",0,True
— XMMR12
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.