web-dev-qa-db-fra.com

Exécutez plusieurs lignes de commande avec le même processus en utilisant .NET

J'essaie d'exécuter plusieurs commandes sans créer un nouveau processus à chaque fois. En gros, je veux démarrer la commande DOS Shell, basculer vers la commande MySQL Shell et exécuter une commande. Voici comment j'appelle la procédure (également ci-dessous). Aussi, comment gérer les "\" dans la commande?

ExecuteCommand("mysql --user=root --password=sa casemanager", 100, false);

ExecuteCommand(@"\. " + Environment.CurrentDirectory + @"\MySQL\CaseManager.sql", 100, true);

private void ExecuteCommand(string Command, int Timeout, Boolean closeProcess)
{
    ProcessStartInfo ProcessInfo;
    Process Process;

    ProcessInfo = new ProcessStartInfo("cmd.exe", "/C " + Command);
    ProcessInfo.CreateNoWindow = false;
    ProcessInfo.UseShellExecute = false;
    Process = Process.Start(ProcessInfo);
    Process.WaitForExit(Timeout);

    if (closeProcess == true) { Process.Close(); }
}
50
Clint

Vous pouvez rediriger l’entrée standard et utiliser un StreamWriter pour y écrire:

        Process p = new Process();
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = "cmd.exe";
        info.RedirectStandardInput = true;
        info.UseShellExecute = false;

        p.StartInfo = info;
        p.Start();

        using (StreamWriter sw = p.StandardInput)
        {
            if (sw.BaseStream.CanWrite)
            {
                sw.WriteLine("mysql -u root -p");
                sw.WriteLine("mypassword");
                sw.WriteLine("use mydb;");
            }
        }
71
scottm
const string strCmdText = "/C command1&command2";
Process.Start("CMD.exe", strCmdText);
40
Filip

Ne pourriez-vous pas simplement écrire toutes les commandes dans un fichier .cmd du dossier temporaire, puis exécuter ce fichier?

9
M4N
ProcessStartInfo pStartInfo = new ProcessStartInfo();
pStartInfo.FileName = "CMD";
pStartInfo.Arguments = @"/C mysql --user=root --password=sa casemanager && \. " + Environment.CurrentDirectory + @"\MySQL\CaseManager.sql"
pStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(pStartInfo);

Le && permet d’indiquer à la commande Shell qu’une autre commande doit être exécutée.

4
Jimmy

Un processus de ligne de commande tel que cmd.exe ou mysql.exe lira (et exécutera) tout ce que vous (l'utilisateur) saisirez (au clavier).

Pour imiter cela, je pense que vous souhaitez utiliser la propriété RedirectStandardInput: http://msdn.Microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardinput.aspx

2
ChrisW

Vous pouvez aussi dire à MySQL d’exécuter les commandes du fichier donné, comme ceci:

mysql --user=root --password=sa casemanager < CaseManager.sql
1
Ben Hoffstein

Comme une autre réponse fait allusion aux versions plus récentes de Windows, il semble nécessaire de lire la sortie standard et/ou les flux d’erreurs standard, faute de quoi les commandes seront bloquées. Un moyen plus pratique de faire cela au lieu d'utiliser des délais consiste à utiliser un rappel asynchrone pour utiliser la sortie du flux:

static void RunCommands(List<string> cmds, string workingDirectory = "")
{
    var process = new Process();
    var psi = new ProcessStartInfo();
    psi.FileName = "cmd.exe";
    psi.RedirectStandardInput = true;
    psi.RedirectStandardOutput = true;
    psi.RedirectStandardError = true;
    psi.UseShellExecute = false;
    psi.WorkingDirectory = workingDirectory;
    process.StartInfo = psi;
    process.Start();
    process.OutputDataReceived += (sender, e) => { Console.WriteLine(e.Data); };
    process.ErrorDataReceived += (sender, e) => { Console.WriteLine(e.Data); };
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();
    using (StreamWriter sw = process.StandardInput)
    {
        foreach (var cmd in cmds)
        {
            sw.WriteLine (cmd);
        }
    }
    process.WaitForExit();
}
1
PeterJ

Vous devez LIRE TOUTES les données de l'entrée avant d'envoyer une autre commande!

Et vous ne pouvez pas demander à LIRE si aucune donnée n’est disponible ... un peu nul n’est-ce pas?

Mes solutions ... quand demande à lire ... demande à lire un gros tampon ... comme 1 MEGA ... 

Et vous devrez attendre un minimum de 100 millisecondes ... exemple de code ...

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim oProcess As New Process()
        Dim oStartInfo As New ProcessStartInfo("cmd.exe", "")
        oStartInfo.UseShellExecute = False
        oStartInfo.RedirectStandardOutput = True
        oStartInfo.RedirectStandardInput = True
        oStartInfo.CreateNoWindow = True
        oProcess.StartInfo = oStartInfo
        oProcess.Start()


        Dim Response As String = String.Empty
        Dim BuffSize As Integer = 1024 * 1024
        Dim x As Char() = New Char(BuffSize - 1) {}
        Dim bytesRead As Integer = 0


        oProcess.StandardInput.WriteLine("dir")
        Threading.Thread.Sleep(100)
        bytesRead = oProcess.StandardOutput.Read(x, 0, BuffSize)
        Response = String.Concat(Response, String.Join("", x).Substring(0, bytesRead))




        MsgBox(Response)
        Response = String.Empty






        oProcess.StandardInput.WriteLine("dir c:\")
        Threading.Thread.Sleep(100)
        bytesRead = 0
        bytesRead = oProcess.StandardOutput.Read(x, 0, BuffSize)
        Response = String.Concat(Response, String.Join("", x).Substring(0, bytesRead))

        MsgBox(Response)


    End Sub
End Class