毎回新しいプロセスを作成せずに複数のコマンドを実行しようとしています。基本的に、DOSコマンドシェルを起動し、MySQLコマンドシェルに切り替えて、コマンドを実行します。プロシージャを呼び出す方法は次のとおりです(以下も参照)。また、コマンドで「\」をどのように処理しますか?
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(); }
}
標準入力をリダイレクトし、StreamWriterを使用してそれに書き込むことができます。
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);
すべてのコマンドをtempフォルダーの.cmdファイルに書き込んでから、そのファイルを実行できませんでしたか?
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);
&&
は、実行する別のコマンドがあることをコマンドシェルに伝える方法です。
Windowsの新しいバージョンでの別の答えとして、標準出力や標準エラーストリームを読み取る必要があるように思われます。そうしないと、コマンド間で停止します。遅延を使用する代わりにそれを行うより適切な方法は、非同期コールバックを使用してストリームからの出力を消費することです:
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();
}
cmd.exe
やmysql.exe
などのコマンドラインプロセスは、通常、ユーザー(ユーザー)が(キーボードで)入力したものを読み取り(および実行)します。
それを模倣するには、RedirectStandardInput
プロパティを使用したいと思います。 http://msdn.Microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardinput.aspx =
別のコマンドを送信する前に、入力からすべてのデータを読み取る必要があります!
そして、利用可能なデータがない場合、READを要求することはできません。
私の解決策...読むように頼むとき...大きなバッファを読むよう頼む... 1メガのように...
そして、あなたは最小100ミリ秒待つ必要があります...サンプルコード...
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
次のように、指定したファイルのコマンドを実行するようMySQLに指示することもできます。
mysql --user=root --password=sa casemanager < CaseManager.sql