Exécuter les commandes d'invite de commandes

605

Existe-t-il un moyen d'exécuter des commandes d'invite de commandes à partir d'une application C #? Si oui, comment pourrais-je procéder comme suit:

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

Cela incorpore essentiellement un fichier RAR dans l'image JPG. Je me demandais simplement s'il y avait un moyen de le faire automatiquement en C #.

utilisateur
la source
6
Duplicate de stackoverflow.com/questions/181719/… (il y a une réponse qui fait ce que vous voulez).
Matt Hamilton
stackoverflow.com/a/5367686/492 a une meilleure réponse
CAD bloke

Réponses:

918

c'est tout ce que vous avez à faire exécuter des commandes shell à partir de C #

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

ÉDITER:

C'est pour cacher la fenêtre 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

Il est important que l'argument commence par /Csinon il ne fonctionnera pas. Comment Scott Ferguson a dit: il "Exécute la commande spécifiée par la chaîne puis se termine."

RameshVel
la source
166
/ C Exécute la commande spécifiée par chaîne, puis se termine
Scott Ferguson
16
c'est juste pour dire au cmd de s'exécuter et de se terminer (n'attendez pas qu'une entrée utilisateur ferme la fenêtre)
RameshVel
3
Merci, encore une question. Existe-t-il un moyen de masquer l'invite de commande pendant cette opération?
utilisateur
9
Je ne vois pas comment je suis le seul à penser que c'est une horrible idée. Oui, cela fonctionnera, mais c'est complètement et totalement faux. La création de processus CMD pour effectuer des opérations d'E / S simples est incorrecte, même si cela fonctionne. Lisez la documentation sur l'espace de noms System.IO. Il y a plus qu'assez de fonctionnalités pour faire ce que vous devez faire sans générer de processus inutiles.
Instance Hunter
56
Pour info: utilisez process.WaitForExit () pour attendre la fin du processus avant de continuer et process.ExitCode pour obtenir le code de sortie du processus.
shindigo
122

J'ai essayé la solution @RameshVel mais je n'ai pas pu passer d'arguments dans mon application console. Si quelqu'un rencontre le même problème, voici une solution:

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
la source
2
eh bien je ne lui ai donné aucune chance en pensant que sur ma machine il y a des restrictions admin ou anti virus mais .. le code ci-dessus fonctionne! merci Ogglas
Pete Kozak
6
cette ligne: cmd.StartInfo.CreateNoWindow = true; sauvé ma journée.
Ganesh Kamath - 'Code Frenzy'
Existe-t-il un moyen d'exécuter plusieurs commandes en une seulecmd.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
la source
2
Quel est le @signe en C #?
Pacerier du
6
@Pacerier Il indique au compilateur d'échapper tous les caractères qui devraient normalement être échappés dans la chaîne, dans ce cas \. Donc, sans le \, votre code ressemblerait àproc1.FileName = "C:\\Windows\\System32\\cmd.exe";
James Ko
1
Il convient de noter que proc1.Verb = "runas";ce processus s'exécute avec des privilèges élevés ... Ce n'est pas toujours prévu.
Dinei
1
Comment puis-je faire en sorte que cette fenêtre cmd ne se ferme pas une fois terminée?
Hrvoje T
1
J'ai trouvé que l'appel de 'cd path' rejoint par '&&' avec d'autres commandes de la ligne s'exécute toujours en dernier, même s'il est parti en premier. votre: 'proc1.WorkingDirectory = @ "C: \ Windows \ System32";' était très utile! Merci!
Nozim Turakulov
11

Aucune des réponses ci-dessus n'a aidé pour une raison quelconque, il semble qu'elles balaient les erreurs sous le tapis et rendent le dépannage de sa commande difficile. J'ai donc fini par faire quelque chose comme ça, peut-être que cela aidera quelqu'un d'autre:

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
la source
Si je veux compiler cela dans une application console autonome, quel autre code faudrait-il ajouter pour le faire fonctionner? (Je suis un noob à tous ces trucs de programmation, je n'ai fait que quelques scripts). J'utilise csc.exe btw.
script'n'code
@copyitright Un espace de noms et une classe. Si vous venez de créer un nouveau projet, il sera généré pour vous.
coinbird
Ah. ça ne fait rien. si vous utilisez l' cmd.exeapplication, vous pouvez passer des commandes comme arguments.
Zach Smith
Pour la postérité: je voulais que le processus s'exécute echo Hello World!et affiche la sortie de la commande dans la fenêtre cmd qui apparaît. J'ai donc essayé: Filename = @"echo", Arguments = "Hello World!", UseShellExecute = false, RedirectStandardOuput = false, CreateNoWindow = false. Cela a permis à la fenêtre cmd de l'application parente d'afficher "Hello World!" (ce qui est logique car stdout n'a pas été redirigé vers le processus enfant).
Minh Tran
10

Bien que techniquement cela ne réponde pas directement à la question posée, cela répond à la question de savoir comment faire ce que l'affiche originale voulait faire: combiner des fichiers. Si quoi que ce soit, c'est un article pour aider les débutants à comprendre de quoi parlent Instance Hunter et Konstantin.

C'est la méthode que j'utilise pour combiner des fichiers (dans ce cas un jpg et un zip). Notez que je crée un tampon qui est rempli avec le contenu du fichier zip (en petits morceaux plutôt qu'en une grande opération de lecture), puis le tampon est écrit à l'arrière du fichier jpg jusqu'à la fin du fichier zip. atteint:

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
la source
9

si vous voulez garder la fenêtre cmd ouverte ou si vous voulez l'utiliser dans winform / wpf alors utilisez-la comme ceci

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

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

/ K

Gardera la fenêtre cmd ouverte

Modèle unique
la source
Agréable. Trouvé cette documentation pour la cmdcommande et ses paramètres.
pius
8

Oui, il y en a (voir le lien dans le commentaire de Matt Hamilton), mais il serait plus facile et mieux d'utiliser les classes IO de .NET. Vous pouvez utiliser File.ReadAllBytes pour lire les fichiers, puis File.WriteAllBytes pour écrire la version "intégrée".

Chasseur d'instances
la source
11
Charger des fichiers entiers en mémoire juste pour les ajouter les uns aux autres n'est pas très efficace, surtout si les fichiers sont assez gros.
Konstantin Spirin
7
Essayez de regarder l'esprit de la réponse. Le fait est que .NET a plus qu'assez de classes et de fonctions d'E / S pour ce faire sans avoir à appeler le shell du système d'exploitation. Les fonctions particulières que j'ai mentionnées ne sont peut-être pas les meilleures, mais elles étaient simplement les plus simples. Cela n'a aucun sens d'appeler le shell pour le faire.
Instance Hunter
7

Vous pouvez le faire en utilisant CliWrap sur une seule ligne:

var stdout = new Cli("cmd")
         .Execute("copy /b Image1.jpg + Archive.rar Image2.jpg")
         .StandardOutput;
Tyrrrz
la source
J'ai voté pour cela ... mais le dépôt semble manquer maintenant:Unable to find package 'CliWrap' at source
Zach Smith
1
@ZachSmith ne sait pas ce que vous voulez dire, nuget.org/packages/CliWrap semble bien fonctionner. Le lien d'origine aussi.
Tyrrrz
Ah. Désolé .. pour une raison quelconque, lorsque je n'ai pas pu me connecter à mon dépôt de pépites sur vpn, je n'ai pas pu installer ce package. pépite est encore un mystère pour moi. doit avoir mal réglé
Zach Smith
5

Voici une petite version de code simple et moins. Cela masquera également la fenêtre de la 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
la source
5

si vous souhaitez exécuter la commande en mode asynchrone - et imprimer les résultats. vous pouvez vous cette 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
la source
2

Vous pouvez y parvenir en utilisant la méthode suivante (comme mentionné dans d'autres réponses):

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

Lorsque j'ai essayé les méthodes répertoriées ci-dessus, j'ai constaté que ma commande personnalisée ne fonctionnait pas en utilisant la syntaxe de certaines des réponses ci-dessus.

J'ai découvert que des commandes plus complexes doivent être encapsulées entre guillemets pour fonctionner:

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

vous pouvez utiliser simplement écrire le code dans une .batextension de format, le code du fichier batch:

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

utilisez ce code c #:

Process.Start("file_name.bat")

XMMR12
la source
si vous souhaitez masquer la cmd pendant l'exécution, vous pouvez utiliser un code de script de base visuel simple dans une .vbsextension de format, le code:CreateObject("Wscript.Shell").Run "filename.bat",0,True
XMMR12