外部工具无法在我的应用程序中输出,但在 CMD 屏幕中输出很好

External tool fails to output in my app but outputs nicely in CMD screen

我正在尝试在我的 C#/WPF 应用程序中使用随 Firebird 数据库一起提供的 GFIX 工具在数据库上执行某些命令。

火鸟http://www.firebirdsql.org/en/firebird-2-5-3-upd1/

Gfix http://www.firebirdsql.org/manual/gfix.html

为此,我使用以下代码:

public string RunExternalExe(string filename, string arguments = null)
{
    var process = new Process();

    process.StartInfo.FileName = filename;
    if (!string.IsNullOrEmpty(arguments))
    {
        process.StartInfo.Arguments = arguments;
    }

    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.StartInfo.UseShellExecute = false;

    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.RedirectStandardOutput = true;
    var stdOutput = new StringBuilder();
    process.OutputDataReceived += (sender, args) => stdOutput.Append(args.Data);

    string stdError = null;
    try
    {
        process.Start();
        process.BeginOutputReadLine();
        stdError = process.StandardError.ReadToEnd();
        process.WaitForExit();
    }
    catch (Exception e)
    {
        throw new Exception("OS error while executing " + Format(filename, arguments) + ": " + e.Message, e);
    }

    if (process.ExitCode == 0)
    {
        return stdOutput.ToString();
    }
    else
    {
        var message = new StringBuilder();

        if (!string.IsNullOrEmpty(stdError))
        {
            message.AppendLine(stdError);
        }

        if (stdOutput.Length != 0)
        {
            message.AppendLine("Std output:");
            message.AppendLine(stdOutput.ToString());
        }

        throw new Exception(Format(filename, arguments) + " finished with exit code = " + process.ExitCode + ": " + message);
    }
}
private string Format(string filename, string arguments)
{
    return "'" + filename +
        ((string.IsNullOrEmpty(arguments)) ? string.Empty : " " + arguments) +
        "'";
}

在那里找到 How To: Execute command line in C#, get STD OUT results

我也尝试了在那个问题中得到解释的所有其他方法,但它仍然没有给我任何输出。

我尝试执行以下命令

gfix.exe -user foo -pa foo -shut single -force 0 app1:\bar.fdb

我在cmd中执行看到的是如下输出

"Your user name and password are not defined. Ask your database administrator to set up a Firebird login."

这是一个明显的错误,因为用户 foo 和密码 foo 不存在。

所以我的问题不是错误本身,而是 我没有在我的 C# 应用程序中得到这个输出 不管我到目前为止尝试了什么。

因为我在我的 CMD 屏幕上看到错误输出,它应该在我的 C# 应用程序中得到输出,或者是否有可能是该工具本身阻止了输出而我没有机会得到它?

到目前为止我尝试了什么:

我相信我已经尝试了调用此工具的所有可能组合,但仍然没有得到输出。

我也尝试了 RedirectStandardErrorRedirectStandardOutput,使用 async/sync 方法(开始..和 ReadToEnd), 我还尝试在 RedirectStandardInput 的帮助下输入参数,并按照我用 CMD 键入的方式准确地写下这些行,首先是 cd "C:\Test" 而不是对 gfix.exe 的调用都是徒劳的...

进一步的信息,如果我正确输入所有内容,该工具工作正常 运行s 并且完全按照它应该做的去做,但我也想在工具失败时捕捉并想要输出相应的错误.

编辑:

请注意,我现在尝试了以下操作,没有涉及我的 C# 应用程序,仅双击 bat 或在 CMD 中执行它。

我已将我的测试 bat 文件修改为:

gfix.exe -user foo -pa foo -shut single -force 0 app1:/bar.fdb > Test.txt 2> error.txt

这会创建 2 个文本文件 - 都是空的。 如果我 运行 在 CMD no 中显示此 .bat 错误,如果我删除 2> error.txt 错误消息 再次显示 在 CMD 屏幕中。所以重定向似乎 "work" 只有我的 txt 文件是空的... gfix 工具可以阻止这个吗?!?

当发生错误时,gfix 不会将其输出到标准输出,而是输出到标准错误。这是明显的标准行为。

这对我有用:

using (var process = Process.Start(
    new ProcessStartInfo
    {
        FileName = fileName,
        Arguments = args,
        WindowStyle = ProcessWindowStyle.Hidden,
        CreateNoWindow = true,
        RedirectStandardError = true,
        UseShellExecute = false,
    }))
{
    process.WaitForExit();
     if (process.ExitCode != 0)
     {
        var errorMessage = process.StandardError.ReadToEnd();
        Assert.Fail(errorMessage);
     }
}

注意 RedirectStandardError = true