在C#中使用参数执行命令行.exe

10

我试图在C#中使用参数来执行命令行程序。我本以为在C#中实现这个目标会很简单,但是即使在这个网站和其他资源的帮助下,它也变得具有挑战性。我感到很困惑,因此我将提供尽可能多的细节。

我目前的方法和代码如下,在调试器中,变量command具有以下值:

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"

问题可能在于我调用并格式化变量命令中使用的字符串方式。

对此有何想法?

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);
我完成后,在变量 result 中没有返回任何信息或错误。

1
你尝试在命令行上执行过这个命令吗?也许你需要用双引号将“command”字符串包裹起来。你实际得到了什么错误? - René Vogt
我可以在命令行中成功运行准确的命令。 可能这些步骤略有不同,因为我将目录设置为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 运行时没有错误返回,但遗憾的是控制台字符串为空。 - Bryan Harrington
4个回答

17

等待过程结束 (让其完成):

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);
}

经过一些调试和手指搞弄,我成功让它工作,并包括了控制台窗口。再次感谢您的快速回复。 - Bryan Harrington
使用您的代码,我无法生成keystore.jks文件,并且没有收到任何错误提示。 - Hkachhia
@Hkachhia:尝试使用绝对路径:而不是... -keystore keystore.jks,请将其更改为类似于... -keystore c:\mydir\keystore.jks的内容,并检查您是否已创建了c:\mydir\keystore.jks文件。 - Dmitry Bychenko
@DmitryBychenko:使用绝对路径无法工作,但是直接使用keytool时可以工作。这意味着它正在使用我安装的JAVA创建密钥库文件。但我想使用应用程序使用的其他jdk版本生成密钥库。我已经给出了那个JDK的绝对路径,但它无法工作。 - Hkachhia

2
当涉及从C#执行CLI进程时,这似乎是一个简单的任务,但有很多陷阱,你可能甚至直到更晚才注意到。例如,如此处所述,如果子进程向stdout写入足够的数据,则两个当前给定的答案都不起作用。
我编写了一个库,通过完全抽象化Process交互来简化与CLIs一起工作的过程,通过执行一个方法 - CliWrap来解决整个任务。
然后您的代码将如下所示:
var cmd = Cli.Wrap("cmd")
    .WithArguments(a => a.Add("/c").Add(command));

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

1
我意识到我可能遗漏了一些细节,有些人在未来解决这个问题时可能需要这些信息。
以下是运行时方法参数的值。我对ProcessStartInfo和Process对象需要正确构建有些困惑,我认为其他人也可能会有同样的困惑。
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();

    procStartInfo.FileName = exeDir;
    procStartInfo.Arguments = args;
    procStartInfo.RedirectStandardOutput = true;
    procStartInfo.UseShellExecute = false;
    procStartInfo.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;
  }

在Dmitry的协助和下面的资源之间,

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

我能够拼凑出这个。谢谢!


对于那些可能已经发现我正在尝试自动安装证书到JRE密钥库的人,这里是我正在使用的导入命令:“-import -noprompt -trustcacerts -alias server.us.goodstuffworld -file C:\folder1\mycertname.cer -storepass changeit -keystore keystore.jks”。 - Bryan Harrington

0

试试这个!

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!");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接