8

I have try to run "npm init" command from the c# console app, using this code:

private void Execute(string command, string arg)
    {
        Process p = new Process();
        p.StartInfo.FileName = command;
        p.StartInfo.Arguments = arg;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardInput = true;
        p.StartInfo.WorkingDirectory = @"E:\Work\";  
        p.Start();
        p.WaitForExit();
    }

    Execute(@"C:\Program Files\nodejs\npm.cmd", "init");

But nothing happening. I getting only 2 empty lines after the running my app. Please, help to resolve this problem.

Nisu
  • 185
  • 1
  • 1
  • 12

5 Answers5

9

Take a look at my example of running the npm run dist command.

var psiNpmRunDist = new ProcessStartInfo
{
    FileName = "cmd",
    RedirectStandardInput = true,
    WorkingDirectory = guiProjectDirectory
};
var pNpmRunDist = Process.Start(psiNpmRunDist);
pNpmRunDist.StandardInput.WriteLine("npm run dist & exit");
pNpmRunDist.WaitForExit();
nopara73
  • 502
  • 6
  • 24
  • I got an edit suggestion from @stefan.seeland with a comment: "An 'System.InvalidOperationException' gets thrown without setting UseShellExecute" It has been rejected by two other users. I am using .NET Core 1.1 and I don't get the exception. Anyone gets the exception without UseShellExecute in .NET Framework or other Core versions, or even (but I doubt) in this version? – nopara73 May 19 '17 at 21:25
4

The following works for me:

private static string RunCommand(string commandToRun, string workingDirectory = null)
{
    if (string.IsNullOrEmpty(workingDirectory))
    {
        workingDirectory = Directory.GetDirectoryRoot(Directory.GetCurrentDirectory());
    }

    var processStartInfo = new ProcessStartInfo()
    {
        FileName = "cmd",
        RedirectStandardOutput = true,
        RedirectStandardInput = true,
        WorkingDirectory = workingDirectory
    };

    var process = Process.Start(processStartInfo);

    if (process == null)
    {
        throw new Exception("Process should not be null.");
    }

    process.StandardInput.WriteLine($"{commandToRun} & exit");
    process.WaitForExit();

    var output = process.StandardOutput.ReadToEnd();
    return output;
}

You would use this like so:

var initResult = RunCommand("npm run init", @"E:\Work\");

This works for dotnet core as well as the standard .net framework.

JMK
  • 27,273
  • 52
  • 163
  • 280
3

I have resolved this problem like this:

foreach (string s in commands)
{
   proc = Process.Start("npm.cmd", s);
   proc.WaitForExit();
}
Nisu
  • 185
  • 1
  • 1
  • 12
1

You'll need to capture the Process.StandardOutput: ProcessStartInfo.RedirectStandardOutput

Like this:

p.Start();

// To avoid deadlocks, always read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

Although, since NPM can be a long running process, you may want to wire up an event handler like in these samples: Realtime Console Output Redirection using Process

Community
  • 1
  • 1
denvercoder9
  • 801
  • 7
  • 15
0

npm init prompts for several user inputs on a new project. For example, the project name, version, author, etc. These values are expected on StandardInput. You are correctly redirecting StandardInput, but I do not see you providing these values here. NPM will block until it receives this input, which is likely why you are seeing the application freeze. You will need to use WriteLine to provide the answers to NPM's questions in order to move forward, or at a minimum a blank WriteLine for each question will suffice. You can do this by calling p.StandardInput.WriteLine.

On my version of NPM (3.8.6), the following questions are asked:

name: (foo) 
version: (1.0.0) 
description: 
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: 
license: (ISC)

In addition to this, NPM will prompt with an "Are you sure?" at the end.

Kevin Burdett
  • 2,892
  • 1
  • 12
  • 19