Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute a command line utility in ASP.NET

Tags:

c#

.net

asp.net

I need some advice regarding the use of a command line utility from a C#/ASP.NET web application.

I found a 3rd party utility for converting files to CSV format. The utility works perfectly and it can be used from the command line.

I have been looking on the web for examples on how to execute the command line utility and found this example.

The problem is this is not very good. When I try to us the example code with my utility, I get a prompt asking me to install the utility on the client machine. This is not what I want. I do not want the user to see what is going on in the background.

Is it possible to execute the command server side and processing the file from there?

Any help would be greatly appreciated.

like image 827
Rup Avatar asked Dec 22 '22 11:12

Rup


2 Answers

I've done something like this several times in the past, and here's what's worked for me:

Create an IHttpHandler implementation (easiest to do as an .ashx file) to handle a convert. Within the handler, use System.Diagnostics.Process and ProcessStartInfo to run your command line utility. You should be able to redirect the standard output to the output stream of your HTTP response. Here's some code:

public class ConvertHandler : IHttpHandler
{
    #region IHttpHandler Members

    bool IHttpHandler.IsReusable
    {
        get { return false; }
    }

    void IHttpHandler.ProcessRequest(HttpContext context)
    {
        var jobID = Guid.NewGuid();

        // retrieve the posted csv file
        var csvFile = context.Request.Files["csv"]; 

        // save the file to disk so the CMD line util can access it
        var filePath = Path.Combine("csv", String.Format("{0:n}.csv", jobID));
        csvFile.SaveAs(filePath);

        var psi = new ProcessStartInfo("mycsvutil.exe", String.Format("-file {0}", filePath))
        {
            WorkingDirectory = Environment.CurrentDirectory,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true                
        };

        using (var process = new Process { StartInfo = psi })
        {
            // delegate for writing the process output to the response output
            Action<Object, DataReceivedEventArgs> dataReceived = ((sender, e) =>
            {
                if (e.Data != null) // sometimes a random event is received with null data, not sure why - I prefer to leave it out
                {
                    context.Response.Write(e.Data);
                    context.Response.Write(Environment.NewLine);
                    context.Response.Flush();
                }
            });

            process.OutputDataReceived += new DataReceivedEventHandler(dataReceived);
            process.ErrorDataReceived += new DataReceivedEventHandler(dataReceived);

            // use text/plain so line breaks and any other whitespace formatting is preserved
            context.Response.ContentType = "text/plain";

            // start the process and start reading the standard and error outputs
            process.Start();
            process.BeginErrorReadLine();
            process.BeginOutputReadLine();

            // wait for the process to exit
            process.WaitForExit();

            // an exit code other than 0 generally means an error
            if (process.ExitCode != 0)
            {
                context.Response.StatusCode = 500;
            }
        }
    }

    #endregion
}
like image 182
Daniel Schaffer Avatar answered Jan 05 '23 15:01

Daniel Schaffer


The command is running server side. Any code is running on the server. The code in the example that you give works. You just need to make sure that the utility is set up properly on the server and that you have permissions to the directory/file.

like image 42
JaCraig Avatar answered Jan 05 '23 14:01

JaCraig