Executar comandos do prompt de comando

605

Existe alguma maneira de executar comandos de prompt de comando de dentro de um aplicativo C #? Se sim, como eu faria o seguinte:

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

Basicamente, isso incorpora um arquivo RAR na imagem JPG. Eu só estava me perguntando se havia uma maneira de fazer isso automaticamente em c #.

do utilizador
fonte
6
Duplicar stackoverflow.com/questions/181719/… (existe uma resposta que faz o que você deseja).
Matt Hamilton
stackoverflow.com/a/5367686/492 tem uma resposta melhor
CAD bloke

Respostas:

918

isso é tudo o que você precisa fazer para executar comandos do shell em c #

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

EDITAR:

Isso é para ocultar a janela do 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();

EDIT: 2

Importante é que o argumento comece com, /Ccaso contrário, não funcionará. Como Scott Ferguson disse: "Realiza o comando especificado pela string e depois termina".

RameshVel
fonte
166
/ C Executa o comando especificado pela corda e, em seguida, termina
Scott Ferguson
16
é apenas para dizer ao cmd para executar e terminar (espera não faça para qualquer entrada do usuário para fechar a janela)
RameshVel
3
Obrigado, mais uma pergunta. Existe uma maneira de ocultar o prompt de comando durante isso?
usuário
9
Não vejo como sou o único que pensa que essa é uma ideia horrível. Sim, isso vai funcionar, mas é completamente e totalmente errado. Gerar processos CMD para executar operações simples de E / S está errado, mesmo que funcione. Leia a documentação no espaço para nome System.IO. Há funcionalidade mais do que suficiente para fazer o que você precisa fazer sem gerar processos desnecessários.
Instance Hunter
56
Para sua informação: Use process.WaitForExit () para aguardar a conclusão do processo antes de continuar e process.ExitCode para obter o código de saída do processo.
Shindigo
122

Tentei a solução @RameshVel, mas não consegui passar argumentos no meu aplicativo de console. Se alguém tiver o mesmo problema, aqui está uma solução:

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
fonte
2
bem, não tive chance de pensar que na minha máquina existem algumas restrições de administrador ou antivírus, mas .. o código acima funciona! Obrigado Ogglas
Pete Kozak
6
esta linha: cmd.StartInfo.CreateNoWindow = true; salvou o meu dia.
Ganesh Kamath - 'Code Frenzy'
Existe uma maneira de executar vários comandos em um únicocmd.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
fonte
2
Qual é o @sinal em C #?
Pacerier
6
@Pacerier Diz ao compilador para escapar de todos os caracteres que normalmente precisariam ser escapados na string, neste caso \. Portanto, sem o \, seu código seria semelhanteproc1.FileName = "C:\\Windows\\System32\\cmd.exe";
James Ko
1
É importante notar que proc1.Verb = "runas";esse processo é executado com privilégios elevados ... Isso nem sempre é intencional.
Dinei
1
Como posso fazer com que essa janela do cmd não feche após a conclusão?
Hrvoje T
1
Descobri que chamar 'cd path' junto com '&&' com outros comandos da linha sempre é executado por último, mesmo que tenha sido o primeiro. seu: 'proc1.WorkingDirectory = @ "C: \ Windows \ System32";' foi muito útil! Obrigado!
Nozim Turakulov
11

Nenhuma das respostas acima ajudou por algum motivo, parece que eles varrem os erros para debaixo do tapete e dificultam a solução de problemas do comando. Então acabei indo com algo assim, talvez isso ajude outra pessoa:

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
fonte
Se eu quiser compilar isso em um aplicativo de console autônomo, que outro código teria que ser adicionado para fazê-lo funcionar? (Eu sou um noob para todo esse material de programação, apenas fiz alguns scripts). Estou usando o csc.exe btw.
script'n'code
@copyitright Um espaço para nome e classe. Se você acabou de criar um novo projeto, eles serão gerados para você.
coinbird
Ah deixa pra lá. se você usar o cmd.exeaplicativo, poderá passar comandos como argumentos.
Zach Smith
Para a posteridade: eu queria que o processo fosse executado echo Hello World!e exibisse o comando output na janela do cmd que é exibida. Então, eu tentei: Filename = @"echo", Arguments = "Hello World!", UseShellExecute = false, RedirectStandardOuput = false, CreateNoWindow = false. Isso permitiu que a janela cmd do aplicativo pai exibisse "Hello World!" (o que faz sentido porque stdout não foi redirecionado para o processo filho).
Minh Tran
10

Embora tecnicamente isso não responda diretamente à pergunta feita, ele responde à pergunta de como fazer o que o pôster original queria: combinar arquivos. Se alguma coisa, este é um post para ajudar os novatos a entender o que Instance Hunter e Konstantin estão falando.

Este é o método que eu uso para combinar arquivos (neste caso, um jpg e um zip). Observe que eu crio um buffer que é preenchido com o conteúdo do arquivo zip (em pequenos pedaços em vez de em uma grande operação de leitura) e, em seguida, o buffer é gravado na parte de trás do arquivo jpg até o final do arquivo zip. alcançado:

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
fonte
9

se você quiser manter a janela do cmd aberta ou quiser usá-la no winform / wpf, use-a assim:

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

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

/ K

Manterá a janela do cmd aberta

Design único
fonte
Agradável. Encontrei esta documentação para o cmdcomando e seus parâmetros.
Pius
8

Sim, existe (veja o link no comentário de Matt Hamilton), mas seria mais fácil e melhor usar as classes de E / S do .NET. Você pode usar File.ReadAllBytes para ler os arquivos e, em seguida, File.WriteAllBytes para gravar a versão "incorporada".

Caçador de Instâncias
fonte
11
Carregar arquivos inteiros na memória apenas para acrescentar um ao outro não é muito eficiente, especialmente se os arquivos forem grandes o suficiente.
Konstantin Spirin
7
Tente olhar para o espírito da resposta. O ponto é que o .NET possui classes e funções de E / S mais do que suficientes para fazer isso sem precisar chamar o shell do SO. As funções específicas que mencionei podem não ser as melhores, mas essas foram apenas as mais simples. Não faz nenhum sentido chamar o shell para fazer isso.
Instance Hunter
7

Você pode fazer isso usando o CliWrap em uma linha:

var stdout = new Cli("cmd")
         .Execute("copy /b Image1.jpg + Archive.rar Image2.jpg")
         .StandardOutput;
Tyrrrz
fonte
Votei positivamente isso ... mas o repo parece estar faltando agora:Unable to find package 'CliWrap' at source
Zach Smith
1
@ZachSmith não sabe ao certo o que você quer dizer, nuget.org/packages/CliWrap parece funcionar bem. O link original também.
Tyrrrz
Ah, desculpe .. por algum motivo, quando não consegui me conectar ao meu nuget repo pela vpn, não consegui instalar este pacote. pepita ainda é principalmente um mistério para mim. deve ter configurado errado
Zach Smith
6

com uma referência a Microsoft.VisualBasic

Interaction.Shell("copy /b Image1.jpg + Archive.rar Image2.jpg", AppWinStyle.Hide);
Slai
fonte
5

Aqui está uma versão de código pouco simples e menos. Também ocultará a janela do console.

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
fonte
5

se você deseja executar o comando no modo assíncrono - e imprima os resultados. você pode esta classe:

    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
fonte
2

Você pode conseguir isso usando o seguinte método (conforme mencionado em outras respostas):

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

Quando tentei os métodos listados acima, descobri que meu comando personalizado não funcionava usando a sintaxe de algumas das respostas acima.

Eu descobri que comandos mais complexos precisam ser encapsulados em aspas para funcionar:

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

você pode simplesmente escrever o código em uma .batextensão de formato, o código do arquivo em lote:

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

use este código c #:

Process.Start("file_name.bat")

XMMR12
fonte
se você deseja ocultar o cmd durante a execução, pode usar um código de script simples do visual basic em uma .vbsextensão de formato, o código:CreateObject("Wscript.Shell").Run "filename.bat",0,True
XMMR12