10

I'm trying to execute a command line program with parameters from C#. I would have imagined that standing this up and making this happen would be trivial in C# but its proving challenging even with all the resources available on the this site and beyond. I'm at a loss so I will provide as much detail as possible.

My current approach and code is below and in the debugger the variable command has the following value.

command = "C:\\Folder1\\Interfaces\\Folder2\\Common\\JREbin\\keytool.exe -import -noprompt -trustcacerts -alias myserver.us.goodstuff.world -file C:\\SSL_CERT.cer -storepass changeit -keystore keystore.jks"

The problem may be how I am calling and formatting the string I use in that variable command.

Any thoughts on what might be the issue?

ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/c " + command);

    procStartInfo.RedirectStandardOutput = true;
    procStartInfo.UseShellExecute = false;
    procStartInfo.CreateNoWindow = true;
    Process process = new Process();
    process.StartInfo = procStartInfo;
    process.Start();
    string result = process.StandardOutput.ReadToEnd();
    Console.WriteLine(result);

I get back no information or error in the variable result once its completes.

2
  • 1
    did you try this command on a command line? maybe you need to wrap the command string in double quotes. What error do you actually get? Commented May 31, 2016 at 15:04
  • I can run the exact command in command line successfully. Maybe those steps differ slight because I set the directory to C:\Folder1\Interfaces\Folder2\Common\JREbin\ and then execute keytool.exe -import -noprompt -trustcacerts -alias myserver.us.goodstuff.world -file C:\SSL_CERT.cer -storepass changeit -keystore keystore.jks I get back no error when this runs, the console string is empty unfortunately. Commented May 31, 2016 at 15:15

4 Answers 4

18

Wait for the process to end (let it do its work):

ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/c " + command);

procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;

// wrap IDisposable into using (in order to release hProcess) 
using(Process process = new Process()) {
  process.StartInfo = procStartInfo;
  process.Start();

  // Add this: wait until process does its work
  process.WaitForExit();

  // and only then read the result
  string result = process.StandardOutput.ReadToEnd();
  Console.WriteLine(result);
}
Sign up to request clarification or add additional context in comments.

4 Comments

After some tinkering and finger fudging I got this to work including the console window. Thanks against for the prompt reply.
using your code I am not able to generate keystore.jks file and not getting any error.
@Hkachhia: Try using absolute path: instead of ... -keystore keystore.jks put something like ... -keystore c:\mydir\keystore.jks, and check if you have c:\mydir\keystore.jks file created
@DmitryBychenko: Using absolute path it's not working but when I directly use keytool then it's working. Means it's creating keystore file using my installed JAVA. But I want to generate keystore using other jdk version which is used by my application. I have gave absolute path of that JDK but it's not working.
2

When it comes to executing CLI processes from C#, it may seem like a simple task, but there are quite a few pitfalls that you might not even notice until much later. For example, both of the currently given answers will not work if the child process writes enough data to stdout, as explained here.

I wrote a library that simplifies working with CLIs by abstracting the Process interaction entirely, solving the whole task by executing one method - CliWrap.

Your code would then look like this:

var cmd = Cli.Wrap("cmd")
    .WithArguments(a => a.Add("/c").Add(command));

var result = await cmd.ExecuteBufferedAsync();
var stdOut = result.StandardOutput;

Comments

1

I realized I may have left out some detail that some people may need to solve this in the future.

Here are the values of the method parameters at run time. I had some confusion as to what the object ProcessStartInfo and Process needed to be stood up correctly I think others may as well.

exeDir = "C:\folder1\folder2\bin\keytool.exe"

args = "-delete -noprompt -alias server.us.goodstuff.world -storepass changeit -keystore keystore.jks"

public bool ExecuteCommand(string exeDir, string args)
{
  try
  {
    ProcessStartInfo procStartInfo = new ProcessStartInfo
    {
      FileName = exeDir,
      Arguments = args,
      RedirectStandardOutput = true,
      UseShellExecute = false,
      CreateNoWindow = true,
    };

    using (Process process = new Process())
    {
      process.StartInfo = procStartInfo;
      process.Start();

      process.WaitForExit();

      string result = process.StandardOutput.ReadToEnd();
      Console.WriteLine(result);
    }
    return true;
  }
  catch (Exception ex)
  {
    Console.WriteLine("*** Error occured executing the following commands.");
    Console.WriteLine(exeDir);
    Console.WriteLine(args);
    Console.WriteLine(ex.Message);
    return false;
  }
}

Between Dmitry's assistance and the following resource,

http://www.codeproject.com/Articles/25983/How-to-Execute-a-Command-in-C

I was able to cobble this together. Thank you!

1 Comment

For those who may have figured out that I am trying to automate installing a certificate into a JRE Keystore here is the import command I am using, "-import -noprompt -trustcacerts -alias server.us.goodstuffworld -file C:\\folder1\\mycertname.cer -storepass changeit -keystore keystore.jks"
0

Try this!

Console.WriteLine("Creating Directories...");
Directory.CreateDirectory("Old_Files");
Directory.CreateDirectory("Old_Files\\529930");
Directory.CreateDirectory("Old_Files\\530610");
Directory.CreateDirectory("Old_Files\\530611");
Directory.CreateDirectory("Old_Files\\564190");
Console.WriteLine("Working On The First File...");
File.Copy("529930\\re_dlc_000.pak", "Old_Files\\529930");
var process = new ProcessStartInfo();
process.FileName = "RE7 - Patcher.exe";
process.Arguments = "-v -d -s '529930\re_dlc_000.pak' '529930.REFA' 're_dlc_000.pak'";
File.Move("re_dlc_000.pak", "529930");
Console.WriteLine("First One Completed!");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.