问题,使用c#在cmd中执行命令

时间:2010-06-14 05:28:47

标签: c#

我需要在命令提示符下执行以下命令。

C:\MySQL\MySQL Server 5.0\bin>mysql -uroot -ppassword < d:/admindb/aar.sql

当我在cmd中手动执行此操作时,我会得到我的结果。

现在我尝试以编程方式执行此操作,以便从c#代码中执行cmd。

我使用以下代码来执行此操作。我没有收到任何错误和结果!!!

当我调试时,我得到字符串commandLine的值,如下所示,

"\"C:\\MySQL\\MySQL Server 5.0\\bin\\\" -uroot -ppassword > \"D:/admindb/AAR12.sql"

我猜问题是这个字符串,传递给cmd。怎么解决这个问题??。

public void Execute()
{
    string commandLine = "\"" + MySqlCommandPath + "\"" + " -u" + DbUid + " -p" + DbPwd + " > " + "\"" + Path.Combine(Path_Backup, FileName_Backup + ExcID + ".sql");
    System.Diagnostics.ProcessStartInfo PSI = new System.Diagnostics.ProcessStartInfo("cmd.exe");
    PSI.RedirectStandardInput = true;
    PSI.RedirectStandardOutput = true;
    PSI.RedirectStandardError = true;
    PSI.UseShellExecute = false;
    System.Diagnostics.Process p = System.Diagnostics.Process.Start(PSI);
    System.IO.StreamWriter SW = p.StandardInput;
    System.IO.StreamReader SR = p.StandardOutput;
    SW.WriteLine(commandLine);
    SW.Close();
}

2 个答案:

答案 0 :(得分:4)

我使用了更多面向对象的approch来执行相同的任务。

我使用StreamReader读取文件并使用控制台重定向将文本直接注入mysql exe文件。像魅力一样。

更新:这是代码,它是VB而不是C#,但应该很容易翻译。 我使用此代码为某些单元测试创​​建一个空数据库。与仅使用文件作为输入从命令行启动mysql的优点是

a)如果出现故障,我会创建一个例外 b)您可以轻松地使用此代码来控制mysql而无需实际文件 c)在TestProject中,如果抛出异常,则直接在TestProtocol中从mysql获取错误输出。

请注意,我的班级中的UserName,UserName,Password,Schema是共享属性,您只需用字符串替换它们或修改函数调用。

Public Shared Sub SetupDatabase()

    ' basic configuration
    Dim infile As String = "..\..\..\MyProject\initial_db.sql"
    Dim mysql_binary As String = "mysql.exe"
    Dim mysql_args As String = String.Format("-h {0} -u{1} -p{2} {3}", HostName, UserName, Password, Schema)

    ' Creates a StreamReader from infile
    Dim reader As New StreamReader(infile)

    ' Create the process
    Dim p As New Process()
    p.StartInfo.FileName = mysql_binary
    p.StartInfo.Arguments = mysql_args

    ' Redirect input/output/stderr
    p.StartInfo.RedirectStandardOutput = True
    p.StartInfo.RedirectStandardError = True
    p.StartInfo.RedirectStandardInput = True
    p.StartInfo.UseShellExecute = False
    p.StartInfo.CreateNoWindow = True
    p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden

    ' start the process
    p.Start()

    ' read from infile and pass it to mysql
    Do While reader.EndOfStream = False
        p.StandardInput.WriteLine(reader.ReadLine)
    Loop

    ' close stdin
    p.StandardInput.Close()

    ' read from stdout / stderr
    Dim stdout As String = p.StandardOutput.ReadToEnd()
    Dim stderr As String = p.StandardError.ReadToEnd()

    ' wait for mysql to stop
    p.WaitForExit()

    ' if exitcode != 0 we raise an exception and include the output from stderr
    If p.ExitCode <> 0 Then
        Throw New Exception("Initial DB Setup failed with Exitcode " & p.ExitCode & ":" & vbNewLine & stderr)
    End If

    p.Close()
    reader.Close()

End Sub

答案 1 :(得分:1)

可能是因为你想进行I / O重定向,所以你正在向cmd.exe进行外壳攻击。为什么不自己设置文件句柄,然后直接调用MySQL.exe?

public void Execute() {

  Process p = new Process();
  p.StartInfo.FileName = @"C:\MySQL\MySQL Server 5.0\bin\mysql.exe";
  p.StartInfo.Arguments = String.Format( "-u{0} -p{1}", user, password );
  p.StartInfo.UseShellExecute = false;
  p.StartInfo.RedirectStandardInput = true;
  p.StartInfo.RedirectStandardOutput = true;
  p.StartInfo.RedirectStandardError = true;

  p.Start();

  System.IO.StreamWriter SW = p.StandardInput;
  System.IO.StreamReader SR = p.StandardOutput;

  /* Send data to MySQL and capture results */

  SW.Close();
}

您可能还需要/需要设置WorkingDirectory属性...

当然,真正的问题是,为什么不使用ODBC或某些更高级别的API与MySQL交谈而不是尝试自己运行mysql.exe?我可以看到使用它运行mysqladmin.exe,但mysql.exe的所有功能都可以从ODBC获得。

如果你真的想在cmd.exe上推出那个可怕的命令行,那么你应该@try @-quoting syntax for strings - 它允许你避免转义反斜杠,并使用""来表示{{ 1}}在字符串中。你的字符串最终定义如下:

"

编写字符串连接的更好方法是使用String.Format(),如下所示:

@"""C:\MySQL\MySQL Server 5.0\bin\mysql.exe"" -uroot -password < ""D:/admindb/AAR12.SQL"""