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(); }
}
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;");
}
}
const string strCmdText = "/C command1&command2";
Process.Start("CMD.exe", strCmdText);
Ne pourriez-vous pas simplement écrire toutes les commandes dans un fichier .cmd du dossier temporaire, puis exécuter ce fichier?
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.
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
Vous pouvez aussi dire à MySQL d’exécuter les commandes du fichier donné, comme ceci:
mysql --user=root --password=sa casemanager < CaseManager.sql
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();
}
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