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



我正在尝试使用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) +
        "'";
}

在那里找到如何:在 C# 中执行命令行,获取 STD OUT 结果

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

我尝试执行以下命令

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

如果我在CMD中执行它,我看到的是以下输出

"您的用户名和密码未定义。请您的数据库管理员设置 Firebird 登录名。

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

所以我的问题不是错误本身,而只是我在我的 C# 应用程序中没有获得此输出的事实,无论我到目前为止尝试了什么。

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

到目前为止我尝试过:

  • 调用 gfix.exe 本身与参数。
  • 调用包含对 gfix 的调用的 bat .exe及其参数。
  • 使用/c 或/k 调用 cmd 来调用 gfix.exe 使用参数。
  • 使用/c 或/k 调用 CMD,调用调用 gfix.exe 的蝙蝠。

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

我也尝试了RedirectStandardError和RedirectStandardOutput,使用异步/同步方法(Begin..和ReadToEnd),我也尝试在RedirectStandardInput的帮助下输入参数,并完全按照我用CMD键入的方式编写行,首先是cd "C:Test",然后是对gfix的调用.exe所有这些都是徒劳的......

更多信息 如果我正确输入所有内容,该工具可以正常工作,它运行并完全执行它应该做的事情,但我也想捕捉工具何时失败并想要输出相应的错误。

编辑:

请注意,我现在尝试了以下内容,不涉及我的 C# 应用程序,只需双击蝙蝠或在 CMD 中执行它。

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

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

这将创建 2 个文本文件 - 都是空的。如果我在CMD中运行此.bat则不会显示任何错误,如果我删除2> error.txt则错误消息将再次显示在CMD屏幕中。所以重定向似乎"有效"只是我的 txt 文件是空的......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

当错误发生时,gfix 不会将其输出到 stdout,而是输出到 stderr。这是显而易见的性病行为。

最新更新