2017-07-28 133 views
2

我正在将批处理脚本迁移到.Net核心,我试图从当前终端打开另一个终端并运行命令(我不需要stderr o stout)。.Net核心打开外部终端

批量只需要这个命令:start cmd /K gulp。我试图用.Net核心做同样的事情,但只能找到在当前终端内运行命令的方式。

private static string Run(){ 
    var result = ""; 
    try 
    { 
     ProcessStartInfo startInfo = new ProcessStartInfo(); 
     startInfo.FileName = "cmd.exe"; 
     startInfo.Arguments = $"/c \"gulp browserSync\""; 
     startInfo.RedirectStandardOutput = true; 
     startInfo.RedirectStandardError = true; 
     startInfo.UseShellExecute = false; 
     startInfo.CreateNoWindow = true; 

     using (Process process = Process.Start(startInfo)) 
     { 
      result = process.StandardError.ReadToEnd(); 
      process.WaitForExit(); 
     } 
    } 
    catch (Exception Ex) 
    { 
     Console.WriteLine(Ex.Message); 
     Console.ReadKey(); 
    } 
    return result; 
} 

我想,才能在另一端,打开更改此属性:

startInfo.RedirectStandardOutput = false; 
startInfo.RedirectStandardError = false; 
startInfo.UseShellExecute = true; 

但是破例:

UseShellExecute必须始终设置为false。

+0

究竟是什么问题?你想打开一个新的终端,它不会正确吗? –

+0

我在一个终端上,我试图打开一个新终端并运行一个命令。 – Equiman

回答

1

感谢@弯曲弯曲的答案我找到了一种方法来解决它。由于安全限制需要用户/密码凭据以自动授权当前终端打开新的终端。

WorkingDirectory,用户,密码和域是必需的。
创建没有窗口,重定向输出和重定向错误必须为false,以便在新窗口中查看命令结果。

public static void Sample(){ 
    try 
    { 
     Console.Write("Password: "); 
     StringBuilder password = new StringBuilder(); 
     while (true) 
     { 
      var key = System.Console.ReadKey(true); 
      if (key.Key == ConsoleKey.Enter) break; 
      password.Append(key.KeyChar); 
     } 

     ProcessStartInfo startInfo = new ProcessStartInfo 
     { 
      FileName = "cmd.exe", 
      WorkingDirectory = "C:/path_to/Gulp", 
      Arguments = $"/c \"gulp browserSync\"", 
      UseShellExecute = false, 
      RedirectStandardOutput = false, 
      RedirectStandardError = false, 
      UserName = Machine.User(), 
      PasswordInClearText = password.ToString(), 
      Domain = Machine.Domain(), 
      CreateNoWindow = false 
     }; 

     Process proc = new Process(); 
     proc.StartInfo = startInfo; 
     proc.Start(); 
     //proc.WaitForExit(); 
    } catch (Exception ex) 
    { 
     System.Console.WriteLine(ex); 
     System.Console.ReadKey(); 
    } 
} 

.Net Core没有获取用户和域的方法。我们可以使用这个类从环境变量中获取这个值。

public static class Machine 
{ 
    public static string User(){ 
     return Environment.GetEnvironmentVariable("USERNAME") ?? Environment.GetEnvironmentVariable("USER"); 
    } 

    public static string Domain(){ 
     return Environment.GetEnvironmentVariable("USERDOMAIN") ?? Environment.GetEnvironmentVariable("HOSTNAME"); 
    } 
} 

希望它有帮助!

+0

该解决方案仅适用于Windows ...我在macOS上测试了它并说:此平台不支持此操作,如果您需要可在两个平台上运行的解决方案:https://medium.com/@equiman/run-a-command-in-external-terminal-with-net-core-cc24e3cc9839 – Equiman

1

MSDN docs:如果用户名属性不为null或空字符串,或者当的Process.Start(的ProcessStartInfo)方法被调用一个InvalidOperationException将被抛出

UseShellExecute一定是假的。

startInfo.UserName = null; 

编辑:我不知道为什么你的参数传递,但是如果你想要的是一个新的CMD窗口试试这个:

try 
{ 
    ProcessStartInfo startInfo = new ProcessStartInfo 
    { 
     FileName = "cmd.exe", 
     WorkingDirectory = @"C:/users/replace/where_gulp_is_located", 
     Arguments = @"/c gulp", // add /K if its required, I don't know if its for gulp for to open a new cmd window 
     UseShellExecute = false, 
     RedirectStandardOutput = true, 
     RedirectStandardError = true 
    }; 

    Process proc = new Process(); 
    proc.StartInfo = startInfo; 
    proc.Start(); 

    if (showOut) 
    { ///code } 

}catch(Exception ex) 
{ 
    Console.WriteLine(ex); 
} 

你不会需要startInfo.UserName在这种情况是因为你指定了一个工作目录。

+0

执行命令,但没有打开一个新的终端:'( – Equiman