title: Process.Start() differences between Windows and Linux
body: <p>I'm experiencing some differences in <code>Process.Start()</code> in a .NET Core 2.2 project.  You can find the full source in this gist: <a href="https://gist.github.com/jchristn/5a2a301baedeed787a2e57cd528e46d6" rel="nofollow noreferrer">https://gist.github.com/jchristn/5a2a301baedeed787a2e57cd528e46d6</a></p>
  
  <p>I have a method for starting processes:</p>
  
  <pre><code>private static void ExecuteShell(
      string filename, 
      string args, 
      bool useShellExecute,
      bool redirectStdOut,
      bool redirectStdErr,
      out int returnCode, 
      out string consoleOutput)
  {
      returnCode = 0;
      consoleOutput = null;
  
      if (String.IsNullOrEmpty(filename)) throw new ArgumentNullException(nameof(filename));
  
      // fileName, i.e. "cmd.exe"
      // args, i.e.     "/c dir /w"
  
      Process process = new Process();
      process.StartInfo.FileName = filename;
      process.StartInfo.Arguments = args;
      process.StartInfo.UseShellExecute = useShellExecute;
      process.StartInfo.RedirectStandardOutput = redirectStdOut;
      process.StartInfo.RedirectStandardError = redirectStdErr;
      process.Start();
      if (process.StartInfo.RedirectStandardOutput) consoleOutput = process.StandardOutput.ReadToEnd();
      process.WaitForExit();
      returnCode = process.ExitCode;
  }
  </code></pre>
  
  <p>And the caller looks like this:</p>
  
  <pre><code>while (true)
  {
      try
      {
          Console.WriteLine("");
          Console.WriteLine("Example: cmd.exe /c dir /w");
          Console.Write("Command: ");
          string userInput = Console.ReadLine();
          if (String.IsNullOrEmpty(userInput)) break;
  
          string[] parts = userInput.Split(new char[] { ' ' }, 2);
  
          string filename = parts[0];
          string arg = null;
          if (parts.Length &gt; 1) arg = parts[1];
  
          bool useShellExecute = InputBoolean("  Use shell execute  : ", false);
          bool redirectStdOut =  InputBoolean("  Redirect stdout    : ", false);
          bool redirectStdErr =  InputBoolean("  Redirect stderr    : ", false);
  
          int returnCode;
          string consoleOutput;
  
          ExecuteShell(
              filename,
              arg,
              useShellExecute,
              redirectStdOut,
              redirectStdErr,
              out returnCode, out consoleOutput);
  
          Console.WriteLine("Return code    : " + returnCode);
          Console.WriteLine("Console output : " + consoleOutput);
      }
      catch (Exception e)
      {
          Console.WriteLine("Exception: " + Environment.NewLine + SerializeJson(e, true));
      }
  }
  </code></pre>
  
  <p>The simplest way to reproduce the larger issue I'm having is this.  Assume there is a file on the file system and I want to <code>type testfile &gt; testfile2</code>, i.e. to pipe to another file.</p>
  
  <p>On Windows, if I use <code>cmd.exe /c type testfile &gt; testfile2</code> it works great (with the three Boolean values set to <code>false</code>).</p>
  
  <p>i.e.</p>
  
  <pre><code>C:\Code\ExecuteShell\ExecuteShell\bin\Debug\netcoreapp2.2&gt;dotnet ExecuteShell.dll
  
  Example: cmd.exe /c dir /w
  Command: cmd.exe /c type testfile &gt; testfile2
    Use shell execute  :  [y/N]?
    Redirect stdout    :  [y/N]?
    Redirect stderr    :  [y/N]?
  Return code    : 0
  Console output :
  
  Example: cmd.exe /c dir /w
  Command:
  C:\Code\ExecuteShell\ExecuteShell\bin\Debug\netcoreapp2.2&gt;dir
   Volume in drive C is OS
   Volume Serial Number is 72E2-466A
  
   Directory of C:\Code\ExecuteShell\ExecuteShell\bin\Debug\netcoreapp2.2
  
  ... portions removed ...
  04/09/2020  05:41 PM                15 testfile
  04/09/2020  05:41 PM                15 testfile2
  </code></pre>
  
  <p>When I try this on Ubuntu 14.04 it fails.</p>
  
  <pre><code>~/code/ExecuteShell/ExecuteShell/bin/Debug/netcoreapp2.2/publish$ dotnet ExecuteShell.dll
  
  Example: cmd.exe /c dir /w
  Command: cat testfile &gt; testfile2
    Use shell execute  :  [y/N]?
    Redirect stdout    :  [y/N]?
    Redirect stderr    :  [y/N]?
  Hello, world!
  
  cat: &gt;: No such file or directory
  cat: testfile2: No such file or directory
  Return code    : 1
  Console output :
  </code></pre>
  
  <p>If I try it with <code>useShellExecute</code> set to <code>true</code>, I get this strange <code>xdg-open</code> issue:</p>
  
  <pre><code>~/code/ExecuteShell/ExecuteShell/bin/Debug/netcoreapp2.2/publish$ dotnet ExecuteShell.dll
  
  Example: cmd.exe /c dir /w
  Command: cat testfile &gt; testfile2
    Use shell execute  :  [y/N]? y
    Redirect stdout    :  [y/N]?
    Redirect stderr    :  [y/N]?
  xdg-open: unexpected argument 'testfile'
  Try 'xdg-open --help' for more information.
  Return code    : 1
  Console output :
  </code></pre>
  
  <p>Any idea how to make this work?</p>