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 #.

użytkownik
źródło
6
Duplikat stackoverflow.com/questions/181719/… (tam jest odpowiedź, która robi, co chcesz).
Matt Hamilton
stackoverflow.com/a/5367686/492 ma lepszą odpowiedź
facet CAD

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”.

RameshVel
źródło
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());
Ogglas
źródło
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);
HackerMan
źródło
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();
Matt Bonness
źródło
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);
            }
        }
    }
}
CarllDev
źródło
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

Unikalny design
źródło
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”.

Instance Hunter
źródło
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;
Tyrrrz
źródło
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();
kamalpreet
źródło
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
        }
    }

}
Elad
źródło
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);
Vladimir verleg
źródło
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")

XMMR12
źródło
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