-1

I am trying to use the GFIX tool that gets shipped with Firebird Database inside my C#/WPF Application to execute certain commands on the database.

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

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

To do this I use the following code:

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) +
        "'";
}

Found there How To: Execute command line in C#, get STD OUT results

also I tried every other approach that gets explained in that question, but it still doesn't get me any output.

I try to execute the following command

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

What I see if I execute it in CMD is the following output

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

That's an obvious error because user foo with password foo doesn't exist.

So my problem isn't the error itself, its just the fact that I do NOT get this output inside my C# application not matter what I tried so far.

Since I am seeing the error output in my CMD screen it should get output in my C# application or is there any possibility that the tool itself is blocking the output and I don't have a chance to get it?

What I tried so far:

  • Calling the gfix.exe itself with the arguments.
  • Calling a bat that contains the call to gfix.exe with its arguments.
  • Calling CMD with /c or /k that calls the gfix.exe with arguments.
  • Calling CMD with /c or /k that calls a bat that calls the gfix.exe.

I believe I tried all possible combinations of calling this tool but still I don't get an output.

Also I have tried both RedirectStandardError and RedirectStandardOutput, with async/sync approaches (Begin.. and ReadToEnd), also I tried to input the arguments with the help of RedirectStandardInput and wrote the lines exactly as I would type it with CMD, first a cd "C:\Test" and than the call to gfix.exe all in vain...

Further info the tool works fine if I input everything correctly its runs through and does exactly what it should do, but I would also like to catch when the tool fails and want to output the corresponding error.

Edit:

Notice that I tried the following now, without my C# app involved only doubleclick the bat or executing it in CMD.

I have modified my test bat file to this:

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

Which creates 2 Text files - both empty. If I run this .bat in CMD no error is displayed, if I remove the 2> error.txt the error message again gets displayed in the CMD screen. So the redirect seems to "work" only that my txt files are empty... could the gfix tool block this?!?

Community
  • 1
  • 1
Rand Random
  • 7,300
  • 10
  • 40
  • 88
  • Have you tried reading the output after `process.WaitForExit();`? – Danny Varod Mar 16 '15 at 11:37
  • @DannyVarod Yes that's the very first thing I tried since it felt more logical that I want the output after the WaitForExit(), but in every google search hit its after. – Rand Random Mar 16 '15 at 11:45
  • If you change your code to the process have a Window and is visible (not hidden), can you see the program being executed with any output? Gfix is in our PATH env var? Or in the same folder as your executable? – Luizgrs Mar 16 '15 at 11:46
  • @Luizgrs in this case I have set the `WorkingDirectory` to the path where the file is, but I have already tried it with the fullpath aswell. Yeah I also tried to display the cmd window in my C# app but there is no output visible. – Rand Random Mar 16 '15 at 12:26

2 Answers2

0

This works for me:

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);
     }
}

Note the RedirectStandardError = true.

Danny Varod
  • 17,324
  • 5
  • 69
  • 111
  • But does it work with the gfix tool, I know it should work that way and works great with other stuff but it fails with gfix. – Rand Random Mar 16 '15 at 12:56
  • @RandRandom Your edit is unclear - what are you asking? Trying passing `"gfix.exe"` as filename and `"-user foo -pa foo -shut single -force 0 app1:/bar.fdb"` as args. – Danny Varod Mar 16 '15 at 13:52
  • Not sure how my edit is unclear, maybe you can explain in more detail where the problem is. The edit just says I created a .bat file and tried to redirect error to a file which fails as well so it has nothing to do with my C# application a simple bat file fails to redirect the output as well. Thanks for explaining how to use the code but as I mentioned if I change the username and password and database to correct info everything works fine, only the error output is the problem. Maybe you can try it yourself and verify that you don't get an output since I can guarantee you I have tried a lot. – Rand Random Mar 16 '15 at 14:06
  • @RandRandom If the problem is unrelated to your C# code, then close the question and ask a new one (e.g. why doesn't gfix.exe output to stdout or to stderr or why isn't my batch file working). The question is no longer relevant. – Danny Varod Mar 16 '15 at 20:11
-2

When error happens gfix outputs it not to stdout, but to stderr. This is obvious and std behavior.

alex
  • 1
  • As I mentioned I have tried `RedirectStandardError` and `RedirectStandardOutput`, also notice that the current code which is like the 1000th I have tried so far calls to `stdError = process.StandardError.ReadToEnd();` and no output, also I have tried instead of StandardError.ReadToEnd the BeginErrorReadLine() method and still no luck. – Rand Random Mar 16 '15 at 12:24