1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.Threading
  9 {
 10     public class Process
 11     {
 12         public enum Redirections : int
 13         {
 14             none = 0
 15             processStdIn = 1 << 0
 16             processStdOut = 1 << 1
 17             processStdErr = 1 << 2
 18         }
 19         public enum StdHandle : int
 20         {
 21             stdOut = 1stdErr = 2
 22         }
 23         public Process(const string& commandRedirections redirections_) : redirections(redirections_)
 24         {
 25             int errorStringHandle = -1;
 26             nativeProcess = RtCreateProcess(command.Chars()cast<int>(redirections)errorStringHandle);
 27             if (nativeProcess == null)
 28             {
 29                 string errorString = RtGetString(errorStringHandle);
 30                 RtDisposeString(errorStringHandle);
 31                 throw ThreadingException("Could not run " + command + ": " + errorString);
 32             }
 33         }
 34         public ~Process()
 35         {
 36             if (nativeProcess != null)
 37             {
 38                 RtDeleteProcess(nativeProcess);
 39             }
 40         }
 41         public bool Running()
 42         {
 43             int errorStringHandle = -1;
 44             if (RtProcessRunning(nativeProcesserrorStringHandle))
 45             {
 46                 return true;
 47             }
 48             if (errorStringHandle != -1)
 49             {
 50                 string errorString = RtGetString(errorStringHandle);
 51                 RtDisposeString(errorStringHandle);
 52                 throw ThreadingException(errorString);
 53             }
 54             return false;
 55         }
 56         public void WaitForExit()
 57         {
 58             int errorStringHandle = -1;
 59             bool result = RtProcessWaitForExit(nativeProcesserrorStringHandle);
 60             if (!result)
 61             {
 62                 string errorString = RtGetString(errorStringHandle);
 63                 RtDisposeString(errorStringHandle);
 64                 throw ThreadingException(errorString);
 65             }
 66         }
 67         public int ExitCode()
 68         {
 69             int errorStringHandle = -1;
 70             int exitCode = RtProcessExitCode(nativeProcesserrorStringHandle);
 71             if (errorStringHandle != -1)
 72             {
 73                 string errorString = RtGetString(errorStringHandle);
 74                 RtDisposeString(errorStringHandle);
 75                 throw ThreadingException(errorString);
 76             }
 77             return exitCode;
 78         }
 79         public void Terminate()
 80         {
 81             int errorStringHandle = -1;
 82             if (!RtProcessTerminate(nativeProcesserrorStringHandle))
 83             {
 84                 if (errorStringHandle != -1)
 85                 {
 86                     string errorString = RtGetString(errorStringHandle);
 87                     RtDisposeString(errorStringHandle);
 88                     throw ThreadingException(errorString);
 89                 }
 90             }
 91         }
 92         public bool Eof(StdHandle handle)
 93         {
 94             int errorStringHandle = -1;
 95             bool eof = RtProcessEof(nativeProcesscast<int>(handle)errorStringHandle);
 96             if (errorStringHandle != -1)
 97             {
 98                 string errorString = RtGetString(errorStringHandle);
 99                 RtDisposeString(errorStringHandle);
100                 throw ThreadingException(errorString);
101             }
102             return eof;
103         }
104         public string ReadLine(StdHandle handle)
105         {
106             int errorStringHandle = -1;
107             int stringHandle = RtProcessReadLine(nativeProcesscast<int>(handle)errorStringHandle);
108             if (errorStringHandle != -1)
109             {
110                 string errorString = RtGetString(errorStringHandle);
111                 RtDisposeString(errorStringHandle);
112                 throw ThreadingException(errorString);
113             }
114             string line = RtGetString(stringHandle);
115             RtDisposeString(stringHandle);
116             return line;
117         }
118         public string ReadToEnd(StdHandle handle)
119         {
120             int errorStringHandle = -1;
121             int stringHandle = RtProcessReadToEnd(nativeProcesscast<int>(handle)errorStringHandle);
122             if (errorStringHandle != -1)
123             {
124                 string errorString = RtGetString(errorStringHandle);
125                 RtDisposeString(errorStringHandle);
126                 throw ThreadingException(errorString);
127             }
128             string content = RtGetString(stringHandle);
129             RtDisposeString(stringHandle);
130             return content;
131         }
132         public void WriteLine(const string& line)
133         {
134             if ((redirections & Redirections.processStdIn) != Redirections.none)
135             {
136                 int errorStringHandle = -1;
137                 if (!RtProcessWriteLine(nativeProcessline.Chars()errorStringHandle))
138                 {
139                     string error = RtGetString(errorStringHandle);
140                     RtDisposeString(errorStringHandle);
141                     throw ThreadingException(error);
142                 }
143             }
144             else
145             {
146                 throw Exception("process stdin not redirected");
147             }
148         }
149         private void* nativeProcess;
150         private Redirections redirections;
151     }
152 }