I want to build my Angular 8 application programmatically for an automated process and using following C# method.
private bool RunBuildProd(string angularAppFolder)
{
try
{
ProcessStartInfo objPI = new ProcessStartInfo(@"C:\Program Files\Nodejs\npm.cmd", $"run build");
// ProcessStartInfo objPI = new ProcessStartInfo(@"cmd.exe", $"/c npm run build"); // Also tried this one
objPI.WorkingDirectory = angularAppFolder;
objPI.RedirectStandardError = true;
objPI.RedirectStandardOutput = true;
objPI.UseShellExecute = false;
objPI.CreateNoWindow = true;
objPI.WindowStyle = ProcessWindowStyle.Hidden;
Process objProcess = Process.Start(objPI);
string error = objProcess.StandardError.ReadToEnd();
string output = objProcess.StandardOutput.ReadToEnd();
objProcess.WaitForExit();
return (objProcess.ExitCode == 0);
}
catch (Exception ex)
{
return false;
}
}
When executing above method, I am facing 2 issues:
- It does not generate index.html file under dist folder when running below method. Note: if I run "npm run build" command on cmd.exe directly, it generates index.html.
- It does not exit the process for long time and I have to kill it.
What am I missing and How do I resolve it?
Note: I have already ran "npm install" prior to running above method.
UPDATE: Below is the updated code based on answer from Serg, for Avoiding deadlock on read/write of stdout & stderr...
private bool RunBuildProd(string angularAppFolder)
{
try
{
// ProcessStartInfo objPI = new ProcessStartInfo(@"cmd.exe", $"/c npm run build"); // Also tried this one
ProcessStartInfo objPI = new ProcessStartInfo(@"C:\Program Files\Nodejs\npm.cmd", $"run build");
objPI.WorkingDirectory = angularAppFolder;
objPI.RedirectStandardError = true;
objPI.RedirectStandardOutput = true;
objPI.UseShellExecute = false;
objPI.CreateNoWindow = true;
objPI.WindowStyle = ProcessWindowStyle.Hidden;
StringBuilder sbOutput = new StringBuilder();
StringBuilder sbError = new StringBuilder();
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
{
Process objProcess = Process.Start(objPI);
objProcess.OutputDataReceived += (sender, e) => {
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
sbOutput.AppendLine(e.Data);
}
};
objProcess.ErrorDataReceived += (sender, e) =>
{
if (e.Data == null)
{
errorWaitHandle.Set();
}
else
{
sbError.AppendLine(e.Data);
}
};
objProcess.BeginOutputReadLine();
objProcess.BeginErrorReadLine();
objProcess.WaitForExit();
int timeout = 42000;
if (outputWaitHandle.WaitOne(timeout) &&
errorWaitHandle.WaitOne(timeout))
{
// Process completed. Check process.ExitCode here.
return (objProcess.ExitCode == 0);
}
else
{
// Timed out.
return (objProcess.ExitCode == 0);
}
}
}
catch (Exception ex)
{
return false;
}
}