How to redirect sqlpackage StdError stream through .NET Core

69 Views Asked by At

I need to call SqlPackage from a C# .NET 7 application and I'm doing so by creating a System.Diagnostics.Process. My sample code can be found below.

I can run the command, however whenever I redirect stdError if there is no error in the command I am met with

An unexpected failure occurred: The handle is invalid..

but if there is an error in the command, I will get the appropriate error message.

If I want to provide a valid command I have to remove StdError redirection in order for me the receive the contents of stdOutput.

Why am I getting an invalid handle error in the case there is no error redirected from stdError but it works fine when there is an error redirected to stdError? And if possible how can I get around this issue so that i can see both output and possible errors from the commandline.

using System.Diagnostics;

var processStartInfo = new ProcessStartInfo
{
    FileName = @"sqlpackage.exe", // Replace with your command or executable
    // Arguments = "/a:Import /tcs:\"Data Source=foo;Initial Catalog=bar;User Id=sa;Password=Passw0rd" /sf:backup.bacpac /p:DatabaseEdition=Premium /p:DatabaseServiceObjective=P4", // Invalid command to test stdError working with an invalid command
    Arguments = "/help", // Does not work if stdError is redirected
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    UseShellExecute = false,
    CreateNoWindow = true
};

// Create and start the process
using var process = new Process
{
    StartInfo = processStartInfo,
    EnableRaisingEvents = true
};

// Set up a single event handler for both output and error streams
process.OutputDataReceived += (sender, eventArgs) =>
{
    if (!string.IsNullOrEmpty(eventArgs.Data))
    {
        Console.WriteLine(eventArgs.Data);
        // You can log the output to a file or another logging mechanism here
    }
};

// Set up a single event handler for both output and error streams
process.ErrorDataReceived += (sender, eventArgs) =>
{
    if (!string.IsNullOrEmpty(eventArgs.Data))
    {
        Console.WriteLine(eventArgs.Data);
        // You can log the output to a file or another logging mechanism here
    }
};

// Start the process and begin reading the output asynchronously
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();

// Wait for the process to finish
process.WaitForExit();

Console.WriteLine("Process completed with exit code: " + process.ExitCode);
1

There are 1 best solutions below

1
AVTUNEY On

Your process is writing an empty string to the error stream and that's the issue.

Set RedirectStandardError = false and change your code like:

using System.Diagnostics;

var processStartInfo = new ProcessStartInfo
{
    FileName = @"sqlpackage.exe", 
    Arguments = "/help", 
    RedirectStandardOutput = true,
    RedirectStandardError = false,
    UseShellExecute = false,
    CreateNoWindow = true
};

using var process = new Process
{
    StartInfo = processStartInfo,
    EnableRaisingEvents = true
};

process.OutputDataReceived += (sender, eventArgs) =>
{
    if (!string.IsNullOrEmpty(eventArgs.Data))
    {
        Console.WriteLine(eventArgs.Data);
    }
};

process.Start();
process.BeginOutputReadLine();

process.WaitForExit();

Console.WriteLine("Process completed with exit code: " + process.ExitCode);