Выполнить команды командной строки


606

Есть ли способ запустить команды командной строки из приложения C #? Если так, как бы я сделал следующее:

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

Это в основном встраивает файл RAR в изображение JPG. Мне просто интересно, есть ли способ сделать это автоматически в C #.


6
Дубликат stackoverflow.com/questions/181719/… (там есть ответ, который делает то, что вы хотите).
— Мэтт Гамильтон

stackoverflow.com/a/5367686/492 имеет лучший ответ
— САПР bloke

Ответы:


919

это все, что вам нужно сделать, запустить команды оболочки из C #

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

РЕДАКТИРОВАТЬ:

Это чтобы скрыть окно 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();

РЕДАКТИРОВАТЬ: 2

Важно то, что аргумент начинается с, /Cиначе он не будет работать. Как сказал Скотт Фергюсон : «Выполняет команду, указанную в строке, а затем завершается».


166
/ C Выполняет команду, указанную в строке, а затем завершается
— Скотт Фергюсон

16
просто сказать cmd запускаться и завершаться (не ждите, пока пользователь не
— введет

3
Спасибо, еще один вопрос. Есть ли способ скрыть командную строку во время этого?
— Пользователь

9
Я не понимаю, как я единственный, кто думает, что это ужасная идея. Да, это будет работать, но это совершенно неправильно. Создание процессов CMD для выполнения простых операций ввода-вывода - это неправильно, даже если это работает. Прочитайте документацию по пространству имен System.IO. Там более чем достаточно функциональности, чтобы делать то, что вам нужно, без порождения ненужных процессов.
— Охотник за экземплярами

56
К сведению: используйте process.WaitForExit (), чтобы дождаться завершения процесса, прежде чем продолжить, и process.ExitCode, чтобы получить код завершения процесса.
— Shindigo

122

Пробовал решение @RameshVel, но я не мог передать аргументы в моем консольном приложении. Если кто-то испытывает ту же проблему, вот решение:

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
ну, я не дал ему ни малейшего шанса думать, что на моей машине есть некоторые ограничения администратора или антивируса, но .. приведенный выше код работает! спасибо Огглас
— Пит Козак

6
эта строка: cmd.StartInfo.CreateNoWindow = true; спас мой день
— Ганеш Камат - «Безумный кодекс»

Есть ли способ выполнить несколько команд в однойcmd.StandardInput.WriteLine(@"cd C:\Test; pwd")
— Зак Смит

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
Что за @знак в C #?
— Pacerier

6
@Pacerier Указывает компилятору экранировать все символы, которые обычно должны быть экранированы в строке, в данном случае \. Таким образом, без \, ваш код будет выглядеть следующим образомproc1.FileName = "C:\\Windows\\System32\\cmd.exe";
— Джеймс Ко

1
Следует отметить, что proc1.Verb = "runas";этот процесс запускается с повышенными привилегиями ... Это не всегда задумано.
— Диней

1
Как сделать так, чтобы это окно cmd не закрывалось после его завершения?
— Hrvoje T

1
Я обнаружил, что вызов 'пути к компакт-диску' вместе с '&&' с другими командами в строке всегда выполняется последним, даже если он был первым. your: 'proc1.WorkingDirectory = @ "C: \ Windows \ System32";' было очень полезно! Спасибо!
— Нозим Туракулов

11

По какой-то причине ни один из приведенных выше ответов не помог, похоже, что они скрывают ошибки под ковриком и затрудняют поиск неисправностей в команде. Так что я закончил с чем-то вроде этого, может быть, это поможет кому-то еще:

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();

Если бы я хотел скомпилировать это в отдельное консольное приложение, какой другой код нужно было бы добавить, чтобы он работал? (Я новичок во всем этом программировании, только сделал несколько сценариев). Я использую csc.exe кстати.
— script'n'code

@copyitright Пространство имен и класс. Если вы просто создадите новый проект, они будут созданы для вас.
— coinbird

Ах. ничего. если вы используете cmd.exeприложение, вы можете передавать команды в качестве аргументов.
— Зак Смит

Для потомков: я хотел, чтобы процесс запустился echo Hello World!и отобразил вывод команды в появившемся окне cmd. Так что я пробовал: Filename = @"echo", Arguments = "Hello World!", UseShellExecute = false, RedirectStandardOuput = false, CreateNoWindow = false. Это позволило окну cmd родительского приложения отображать «Hello World!» (что имеет смысл, потому что stdout не был перенаправлен на дочерний процесс).
— Мин Чан

10

Хотя технически это не дает прямого ответа на поставленный вопрос, оно отвечает на вопрос о том, как сделать то, что хотел сделать первоначальный плакат: объединить файлы. Во всяком случае, этот пост поможет новичкам понять, о чем говорят Инстанс Хантер и Константин.

Этот метод я использую для объединения файлов (в данном случае это jpg и zip). Обратите внимание, что я создаю буфер, который заполняется содержимым zip-файла (небольшими порциями, а не одной большой операцией чтения), и затем буфер записывается в конец jpg-файла до тех пор, пока конец zip-файла не станет достиг:

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

если вы хотите оставить окно cmd открытым или хотите использовать его в winform / wpf, используйте его следующим образом

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

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

/ K

Будет держать окно cmd открытым


Ницца. Нашел эту документацию для cmdкоманды и ее параметров.
— Пий

8

Да, есть (см. Ссылку в комментарии Мэтта Гамильтона), но было бы проще и лучше использовать классы ввода-вывода .NET. Вы можете использовать File.ReadAllBytes для чтения файлов, а затем File.WriteAllBytes для записи «встроенной» версии.


11
Загрузка целых файлов в память просто для добавления друг к другу не очень эффективна, особенно если файлы достаточно велики.
— Константин Спирин

7
Попробуйте взглянуть на дух ответа. Дело в том, что в .NET более чем достаточно классов и функций ввода-вывода, чтобы сделать это без вызова оболочки ОС. Отдельные функции, которые я упомянул, могут быть не самыми лучшими, но они были простейшими. Нет никакого смысла вызывать оболочку, чтобы сделать это.
— Охотник за экземплярами

7

Вы можете сделать это, используя CliWrap в одну строку:

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

Я проголосовал за это ... но репо сейчас, похоже, отсутствует:Unable to find package 'CliWrap' at source
— Зак Смит

1
@ZachSmith не уверен, что вы имеете в виду, nuget.org/packages/CliWrap, кажется, работает нормально. Оригинальная ссылка тоже.
— Тырррз

Ах. Извините ... по какой-то причине, когда я не смог подключиться к своему репозиторию Nuget через vpn, я не смог установить этот пакет. nuget до сих пор остается для меня загадкой. Должно быть, это неправильно настроено
— Зак Смит


5

Вот немного простой и менее версии кода. Это также скроет окно консоли.

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

если вы хотите выполнить команду в асинхронном режиме - и распечатать результаты. Вы можете вам этот класс:

    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

Вы можете достичь этого, используя следующий метод (как упоминалось в других ответах):

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

Когда я попробовал методы, перечисленные выше, я обнаружил, что моя пользовательская команда не работает с использованием синтаксиса некоторых из ответов выше.

Я обнаружил, что более сложные команды должны быть заключены в кавычки для работы:

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

1

Вы можете просто написать код в .batрасширении формата, код пакетного файла:

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

используйте этот код C #:

Process.Start("file_name.bat")


если вы хотите скрыть cmd во время работы, вы можете использовать простой код Visual Basic в .vbsрасширении формата, код:CreateObject("Wscript.Shell").Run "filename.bat",0,True
— XMMR12
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.