(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System / System.Diagnostics / Process.cs
blobe46ab5b07300effce282e37ee77d8cbad19d1a05
1 //
2 // System.Diagnostics.Process.cs
3 //
4 // Authors:
5 // Dick Porter (dick@ximian.com)
6 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //
9 // (C) 2002 Ximian, Inc.
10 // (C) 2003 Andreas Nahr
11 // (c) 2004 Novell, Inc. (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 //
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System;
36 using System.IO;
37 using System.ComponentModel;
38 using System.ComponentModel.Design;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Collections;
42 using System.Threading;
44 namespace System.Diagnostics {
45 [DefaultEvent ("Exited"), DefaultProperty ("StartInfo")]
46 [Designer ("System.Diagnostics.Design.ProcessDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
47 public class Process : Component
49 [StructLayout(LayoutKind.Sequential)]
50 private struct ProcInfo
52 public IntPtr process_handle;
53 /* If thread_handle is ever needed for
54 * something, take out the CloseHandle() in
55 * the Start_internal icall in
56 * mono/metadata/process.c
58 public IntPtr thread_handle;
59 public int pid; // Contains -GetLastError () on failure.
60 public int tid;
61 public string [] envKeys;
62 public string [] envValues;
63 public bool useShellExecute;
66 IntPtr process_handle;
67 int pid;
68 bool enableRaisingEvents;
69 ISynchronizeInvoke synchronizingObject;
71 /* Private constructor called from other methods */
72 private Process(IntPtr handle, int id) {
73 process_handle=handle;
74 pid=id;
77 [MonoTODO]
78 public Process() {
81 [MonoTODO]
82 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
83 [MonitoringDescription ("Base process priority.")]
84 public int BasePriority {
85 get {
86 return(0);
90 [DefaultValue (false), Browsable (false)]
91 [MonitoringDescription ("Check for exiting of the process to raise the apropriate event.")]
92 public bool EnableRaisingEvents {
93 get {
94 return enableRaisingEvents;
96 set {
97 if (process_handle != IntPtr.Zero)
98 throw new InvalidOperationException ("The process is already started.");
100 enableRaisingEvents = value;
105 [MethodImplAttribute(MethodImplOptions.InternalCall)]
106 private extern static int ExitCode_internal(IntPtr handle);
108 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
109 [MonitoringDescription ("The exit code of the process.")]
110 public int ExitCode {
111 get {
112 if (process_handle == IntPtr.Zero)
113 throw new InvalidOperationException ("Process has not been started.");
115 int code = ExitCode_internal (process_handle);
116 if (code == 259)
117 throw new InvalidOperationException ("The process must exit before " +
118 "getting the requested information.");
120 return code;
124 /* Returns the process start time in Windows file
125 * times (ticks from DateTime(1/1/1601 00:00 GMT))
127 [MethodImplAttribute(MethodImplOptions.InternalCall)]
128 private extern static long ExitTime_internal(IntPtr handle);
130 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
131 [MonitoringDescription ("The exit time of the process.")]
132 public DateTime ExitTime {
133 get {
134 if (process_handle == IntPtr.Zero)
135 throw new InvalidOperationException ("Process has not been started.");
137 if (!HasExited)
138 throw new InvalidOperationException ("The process must exit before " +
139 "getting the requested information.");
141 return(DateTime.FromFileTime(ExitTime_internal(process_handle)));
145 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
146 [MonitoringDescription ("Handle for this process.")]
147 public IntPtr Handle {
148 get {
149 return(process_handle);
153 [MonoTODO]
154 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
155 [MonitoringDescription ("Handles for this process.")]
156 public int HandleCount {
157 get {
158 return(0);
162 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
163 [MonitoringDescription ("Determines if the process is still running.")]
164 public bool HasExited {
165 get {
166 if (process_handle == IntPtr.Zero)
167 throw new InvalidOperationException ("Process has not been started.");
169 int exitcode = ExitCode_internal (process_handle);
171 if(exitcode==259) {
172 /* STILL_ACTIVE */
173 return(false);
174 } else {
175 return(true);
180 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
181 [MonitoringDescription ("Process identifier.")]
182 public int Id {
183 get {
184 return(pid);
188 [MonoTODO]
189 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
190 [MonitoringDescription ("The name of the computer running the process.")]
191 public string MachineName {
192 get {
193 return("localhost");
197 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
198 [MonitoringDescription ("The main module of the process.")]
199 public ProcessModule MainModule {
200 get {
201 return(this.Modules[0]);
205 [MonoTODO]
206 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
207 [MonitoringDescription ("The handle of the main window of the process.")]
208 public IntPtr MainWindowHandle {
209 get {
210 return((IntPtr)0);
214 [MonoTODO]
215 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
216 [MonitoringDescription ("The title of the main window of the process.")]
217 public string MainWindowTitle {
218 get {
219 return("null");
223 [MethodImplAttribute(MethodImplOptions.InternalCall)]
224 private extern static bool GetWorkingSet_internal(IntPtr handle, out int min, out int max);
225 [MethodImplAttribute(MethodImplOptions.InternalCall)]
226 private extern static bool SetWorkingSet_internal(IntPtr handle, int min, int max, bool use_min);
228 /* LAMESPEC: why is this an IntPtr not a plain int? */
229 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
230 [MonitoringDescription ("The maximum working set for this process.")]
231 public IntPtr MaxWorkingSet {
232 get {
233 if(HasExited) {
234 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
237 int min;
238 int max;
239 bool ok=GetWorkingSet_internal(process_handle, out min, out max);
240 if(ok==false) {
241 throw new Win32Exception();
244 return((IntPtr)max);
246 set {
247 if(HasExited) {
248 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
251 bool ok=SetWorkingSet_internal(process_handle, 0, value.ToInt32(), false);
252 if(ok==false) {
253 throw new Win32Exception();
258 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
259 [MonitoringDescription ("The minimum working set for this process.")]
260 public IntPtr MinWorkingSet {
261 get {
262 if(HasExited) {
263 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
266 int min;
267 int max;
268 bool ok=GetWorkingSet_internal(process_handle, out min, out max);
269 if(ok==false) {
270 throw new Win32Exception();
273 return((IntPtr)min);
275 set {
276 if(HasExited) {
277 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
280 bool ok=SetWorkingSet_internal(process_handle, value.ToInt32(), 0, true);
281 if(ok==false) {
282 throw new Win32Exception();
287 /* Returns the list of process modules. The main module is
288 * element 0.
290 [MethodImplAttribute(MethodImplOptions.InternalCall)]
291 private extern ProcessModule[] GetModules_internal();
293 private ProcessModuleCollection module_collection;
295 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
296 [MonitoringDescription ("The modules that are loaded as part of this process.")]
297 public ProcessModuleCollection Modules {
298 get {
299 if(module_collection==null) {
300 module_collection=new ProcessModuleCollection(GetModules_internal());
303 return(module_collection);
307 [MonoTODO]
308 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
309 [MonitoringDescription ("The number of bytes that are not pageable.")]
310 public int NonpagedSystemMemorySize {
311 get {
312 return(0);
316 [MonoTODO]
317 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
318 [MonitoringDescription ("The number of bytes that are paged.")]
319 public int PagedMemorySize {
320 get {
321 return(0);
325 [MonoTODO]
326 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
327 [MonitoringDescription ("The amount of paged system memory in bytes.")]
328 public int PagedSystemMemorySize {
329 get {
330 return(0);
334 [MonoTODO]
335 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
336 [MonitoringDescription ("The maximum amount of paged memory used by this process.")]
337 public int PeakPagedMemorySize {
338 get {
339 return(0);
343 [MonoTODO]
344 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
345 [MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
346 public int PeakVirtualMemorySize {
347 get {
348 return(0);
352 [MonoTODO]
353 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
354 [MonitoringDescription ("The maximum amount of system memory used by this process.")]
355 public int PeakWorkingSet {
356 get {
357 return(0);
361 [MonoTODO]
362 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
363 [MonitoringDescription ("Process will be of higher priority while it is actively used.")]
364 public bool PriorityBoostEnabled {
365 get {
366 return(false);
368 set {
372 [MonoTODO]
373 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
374 [MonitoringDescription ("The relative process priority.")]
375 public ProcessPriorityClass PriorityClass {
376 get {
377 return(ProcessPriorityClass.Normal);
379 set {
383 [MonoTODO]
384 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
385 [MonitoringDescription ("The amount of memory exclusively used by this process.")]
386 public int PrivateMemorySize {
387 get {
388 return(0);
392 [MonoTODO]
393 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
394 [MonitoringDescription ("The amount of processing time spent in the OS core for this process.")]
395 public TimeSpan PrivilegedProcessorTime {
396 get {
397 return(new TimeSpan(0));
401 [MethodImplAttribute(MethodImplOptions.InternalCall)]
402 private extern static string ProcessName_internal(IntPtr handle);
404 private string process_name=null;
406 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
407 [MonitoringDescription ("The name of this process.")]
408 public string ProcessName {
409 get {
410 if(process_name==null) {
411 process_name=ProcessName_internal(process_handle);
412 /* If process_name is _still_
413 * null, assume the process
414 * has exited
416 if(process_name==null) {
417 throw new SystemException("The process has exited");
420 /* Strip the suffix (if it
421 * exists) simplistically
422 * instead of removing any
423 * trailing \.???, so we dont
424 * get stupid results on sane
425 * systems
427 if(process_name.EndsWith(".exe") ||
428 process_name.EndsWith(".bat") ||
429 process_name.EndsWith(".com")) {
430 process_name=process_name.Substring(0, process_name.Length-4);
433 return(process_name);
437 [MonoTODO]
438 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
439 [MonitoringDescription ("Allowed processor that can be used by this process.")]
440 public IntPtr ProcessorAffinity {
441 get {
442 return((IntPtr)0);
444 set {
448 [MonoTODO]
449 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
450 [MonitoringDescription ("Is this process responsive.")]
451 public bool Responding {
452 get {
453 return(false);
457 private StreamReader error_stream=null;
459 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
460 [MonitoringDescription ("The standard error stream of this process.")]
461 public StreamReader StandardError {
462 get {
463 if (error_stream == null) {
464 throw new InvalidOperationException("Standard error has not been redirected");
467 return(error_stream);
471 private StreamWriter input_stream=null;
473 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
474 [MonitoringDescription ("The standard input stream of this process.")]
475 public StreamWriter StandardInput {
476 get {
477 if (input_stream == null) {
478 throw new InvalidOperationException("Standard input has not been redirected");
481 return(input_stream);
485 private StreamReader output_stream=null;
487 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
488 [MonitoringDescription ("The standard output stream of this process.")]
489 public StreamReader StandardOutput {
490 get {
491 if (output_stream == null) {
492 throw new InvalidOperationException("Standard output has not been redirected");
495 return(output_stream);
499 private ProcessStartInfo start_info=null;
501 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
502 [MonitoringDescription ("Information for the start of this process.")]
503 public ProcessStartInfo StartInfo {
504 get {
505 if(start_info==null) {
506 start_info=new ProcessStartInfo();
509 return(start_info);
511 set {
512 if(value==null) {
513 throw new ArgumentException("value is null");
516 start_info=value;
520 /* Returns the process start time in Windows file
521 * times (ticks from DateTime(1/1/1601 00:00 GMT))
523 [MethodImplAttribute(MethodImplOptions.InternalCall)]
524 private extern static long StartTime_internal(IntPtr handle);
526 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
527 [MonitoringDescription ("The time this process started.")]
528 public DateTime StartTime {
529 get {
530 return(DateTime.FromFileTime(StartTime_internal(process_handle)));
534 [DefaultValue (null), Browsable (false)]
535 [MonitoringDescription ("The object that is used to synchronize event handler calls for this process.")]
536 public ISynchronizeInvoke SynchronizingObject {
537 get { return synchronizingObject; }
538 set { synchronizingObject = value; }
541 [MonoTODO]
542 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
543 [MonitoringDescription ("The number of threads of this process.")]
544 public ProcessThreadCollection Threads {
545 get {
546 return(null);
550 [MonoTODO]
551 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
552 [MonitoringDescription ("The total CPU time spent for this process.")]
553 public TimeSpan TotalProcessorTime {
554 get {
555 return(new TimeSpan(0));
559 [MonoTODO]
560 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
561 [MonitoringDescription ("The CPU time spent for this process in user mode.")]
562 public TimeSpan UserProcessorTime {
563 get {
564 return(new TimeSpan(0));
568 [MonoTODO]
569 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
570 [MonitoringDescription ("The amount of virtual memory currently used for this process.")]
571 public int VirtualMemorySize {
572 get {
573 return(0);
577 [MonoTODO]
578 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
579 [MonitoringDescription ("The amount of physical memory currently used for this process.")]
580 public int WorkingSet {
581 get {
582 return(0);
586 public void Close()
588 Dispose (true);
591 [MethodImplAttribute(MethodImplOptions.InternalCall)]
592 extern static bool Kill_internal (IntPtr handle, int signo);
594 /* int kill -> 1 KILL, 2 CloseMainWindow */
595 bool Close (int signo)
597 if (process_handle == IntPtr.Zero)
598 throw new SystemException ("No process to kill.");
600 int exitcode = ExitCode_internal (process_handle);
601 if (exitcode != 259)
602 throw new InvalidOperationException ("The process already finished.");
604 return Kill_internal (process_handle, signo);
607 public bool CloseMainWindow ()
609 return Close (2);
612 [MonoTODO]
613 public static void EnterDebugMode() {
616 [MethodImplAttribute(MethodImplOptions.InternalCall)]
617 private extern static IntPtr GetProcess_internal(int pid);
619 [MethodImplAttribute(MethodImplOptions.InternalCall)]
620 private extern static int GetPid_internal();
622 public static Process GetCurrentProcess() {
623 int pid=GetPid_internal();
624 IntPtr proc=GetProcess_internal(pid);
626 if(proc==IntPtr.Zero) {
627 throw new SystemException("Can't find current process");
630 return(new Process(proc, pid));
633 public static Process GetProcessById(int processId) {
634 IntPtr proc=GetProcess_internal(processId);
636 if(proc==IntPtr.Zero) {
637 throw new ArgumentException("Can't find process with ID " + processId.ToString());
640 return(new Process(proc, processId));
643 [MonoTODO]
644 public static Process GetProcessById(int processId, string machineName) {
645 throw new NotImplementedException();
648 [MethodImplAttribute(MethodImplOptions.InternalCall)]
649 private extern static int[] GetProcesses_internal();
651 public static Process[] GetProcesses() {
652 int[] pids=GetProcesses_internal();
653 ArrayList proclist=new ArrayList();
655 for(int i=0; i<pids.Length; i++) {
656 try {
657 proclist.Add(GetProcessById(pids[i]));
658 } catch (SystemException) {
659 /* The process might exit
660 * between
661 * GetProcesses_internal and
662 * GetProcessById
667 return((Process[])proclist.ToArray(typeof(Process)));
670 [MonoTODO]
671 public static Process[] GetProcesses(string machineName) {
672 throw new NotImplementedException();
675 public static Process[] GetProcessesByName(string processName) {
676 Process[] procs=GetProcesses();
677 ArrayList proclist=new ArrayList();
679 for(int i=0; i<procs.Length; i++) {
680 /* Ignore case */
681 if(String.Compare(processName,
682 procs[i].ProcessName,
683 true)==0) {
684 proclist.Add(procs[i]);
688 return((Process[])proclist.ToArray(typeof(Process)));
691 [MonoTODO]
692 public static Process[] GetProcessesByName(string processName, string machineName) {
693 throw new NotImplementedException();
696 public void Kill ()
698 Close (1);
701 [MonoTODO]
702 public static void LeaveDebugMode() {
705 [MonoTODO]
706 public void Refresh() {
709 [MethodImplAttribute(MethodImplOptions.InternalCall)]
710 private extern static bool Start_internal(string appname,
711 string cmdline,
712 string dir,
713 IntPtr stdin,
714 IntPtr stdout,
715 IntPtr stderr,
716 ref ProcInfo proc_info);
718 private static bool Start_common(ProcessStartInfo startInfo,
719 Process process) {
720 ProcInfo proc_info=new ProcInfo();
721 IntPtr stdin_rd, stdin_wr;
722 IntPtr stdout_rd, stdout_wr;
723 IntPtr stderr_rd, stderr_wr;
724 bool ret;
726 if(startInfo.FileName == null || startInfo.FileName == "") {
727 throw new InvalidOperationException("File name has not been set");
730 proc_info.useShellExecute = startInfo.UseShellExecute;
731 if (proc_info.useShellExecute && (startInfo.RedirectStandardInput ||
732 startInfo.RedirectStandardOutput || startInfo.RedirectStandardError)) {
733 throw new InvalidOperationException ("UseShellExecute must be false when " +
734 "redirecting I/O.");
737 if (startInfo.HaveEnvVars) {
738 if (startInfo.UseShellExecute)
739 throw new InvalidOperationException ("UseShellExecute must be false in order " +
740 "to use environment variables.");
742 string [] strs = new string [startInfo.EnvironmentVariables.Count];
743 startInfo.EnvironmentVariables.Keys.CopyTo (strs, 0);
744 proc_info.envKeys = strs;
746 strs = new string [startInfo.EnvironmentVariables.Count];
747 startInfo.EnvironmentVariables.Values.CopyTo (strs, 0);
748 proc_info.envValues = strs;
751 if(startInfo.RedirectStandardInput==true) {
752 ret=MonoIO.CreatePipe(out stdin_rd,
753 out stdin_wr);
754 if (ret == false) {
755 throw new IOException("Error creating standard input pipe");
757 } else {
758 stdin_rd=MonoIO.ConsoleInput;
759 /* This is required to stop the
760 * &$*£ing stupid compiler moaning
761 * that stdin_wr is unassigned, below.
763 stdin_wr=(IntPtr)0;
766 if(startInfo.RedirectStandardOutput==true) {
767 ret=MonoIO.CreatePipe(out stdout_rd,
768 out stdout_wr);
769 if (ret == false) {
770 throw new IOException("Error creating standard output pipe");
772 } else {
773 stdout_rd=(IntPtr)0;
774 stdout_wr=MonoIO.ConsoleOutput;
777 if(startInfo.RedirectStandardError==true) {
778 ret=MonoIO.CreatePipe(out stderr_rd,
779 out stderr_wr);
780 if (ret == false) {
781 throw new IOException("Error creating standard error pipe");
783 } else {
784 stderr_rd=(IntPtr)0;
785 stderr_wr=MonoIO.ConsoleError;
788 string cmdline;
789 string appname;
790 if (startInfo.UseShellExecute) {
791 appname = null;
792 string args = startInfo.Arguments;
793 if (args == null || args.Trim () == "")
794 cmdline = startInfo.FileName;
795 else
796 cmdline = startInfo.FileName + " " + startInfo.Arguments.Trim ();
797 } else {
798 appname = startInfo.FileName;
799 // FIXME: There seems something wrong in process.c. We should not require extraneous command line
800 if (Path.DirectorySeparatorChar == '\\')
801 cmdline = appname + " " + startInfo.Arguments.Trim ();
802 else
803 cmdline = startInfo.Arguments.Trim ();
806 ret=Start_internal(appname,
807 cmdline,
808 startInfo.WorkingDirectory,
809 stdin_rd, stdout_wr, stderr_wr,
810 ref proc_info);
812 MonoIOError error;
814 if (!ret) {
815 if (startInfo.RedirectStandardInput == true)
816 MonoIO.Close (stdin_rd, out error);
818 if (startInfo.RedirectStandardOutput == true)
819 MonoIO.Close (stdout_wr, out error);
821 if (startInfo.RedirectStandardError == true)
822 MonoIO.Close (stderr_wr, out error);
824 throw new Win32Exception (-proc_info.pid);
827 if (process.enableRaisingEvents && process.Exited != null) {
828 WaitOrTimerCallback cb = new WaitOrTimerCallback (CBOnExit);
829 ProcessWaitHandle h = new ProcessWaitHandle (proc_info.process_handle);
830 ThreadPool.RegisterWaitForSingleObject (h, cb, process, -1, true);
833 process.process_handle=proc_info.process_handle;
834 process.pid=proc_info.pid;
836 if(startInfo.RedirectStandardInput==true) {
837 MonoIO.Close(stdin_rd, out error);
838 process.input_stream=new StreamWriter(new FileStream(stdin_wr, FileAccess.Write, true));
839 process.input_stream.AutoFlush=true;
842 if(startInfo.RedirectStandardOutput==true) {
843 MonoIO.Close(stdout_wr, out error);
844 process.output_stream=new StreamReader(new FileStream(stdout_rd, FileAccess.Read, true));
847 if(startInfo.RedirectStandardError==true) {
848 MonoIO.Close(stderr_wr, out error);
849 process.error_stream=new StreamReader(new FileStream(stderr_rd, FileAccess.Read, true));
852 return(ret);
855 public bool Start() {
856 bool ret;
858 ret=Start_common(start_info, this);
860 return(ret);
863 public static Process Start(ProcessStartInfo startInfo) {
864 Process process=new Process();
865 bool ret;
867 ret=Start_common(startInfo, process);
869 if(ret==true) {
870 return(process);
871 } else {
872 return(null);
876 public static Process Start(string fileName) {
877 return Start(new ProcessStartInfo(fileName));
880 public static Process Start(string fileName,
881 string arguments) {
882 return Start(new ProcessStartInfo(fileName, arguments));
885 public override string ToString() {
886 return(base.ToString() +
887 " (" + this.ProcessName + ")");
890 /* Waits up to ms milliseconds for process 'handle' to
891 * exit. ms can be <0 to mean wait forever.
893 [MethodImplAttribute(MethodImplOptions.InternalCall)]
894 private extern bool WaitForExit_internal(IntPtr handle,
895 int ms);
897 public void WaitForExit() {
898 WaitForExit_internal(process_handle, -1);
901 public bool WaitForExit(int milliseconds) {
902 if (milliseconds == int.MaxValue)
903 milliseconds = -1;
905 return WaitForExit_internal (process_handle, milliseconds);
908 [MonoTODO]
909 public bool WaitForInputIdle() {
910 return(false);
913 [MonoTODO]
914 public bool WaitForInputIdle(int milliseconds) {
915 return(false);
918 [Category ()]
919 [MonitoringDescription ("Raised when this process exits.")]
920 public event EventHandler Exited;
922 // Closes the system process handle
923 [MethodImplAttribute(MethodImplOptions.InternalCall)]
924 private extern void Process_free_internal(IntPtr handle);
926 private bool disposed = false;
928 protected override void Dispose(bool disposing) {
929 // Check to see if Dispose has already been called.
930 if(this.disposed == false) {
931 this.disposed=true;
932 // If this is a call to Dispose,
933 // dispose all managed resources.
934 if(disposing) {
935 // Do stuff here
938 // Release unmanaged resources
940 lock(this) {
941 if(process_handle!=IntPtr.Zero) {
943 Process_free_internal(process_handle);
944 process_handle=IntPtr.Zero;
947 if (input_stream != null) {
948 input_stream.Close();
949 input_stream = null;
952 if (output_stream != null) {
953 output_stream.Close();
954 output_stream = null;
957 if (error_stream != null) {
958 error_stream.Close();
959 error_stream = null;
963 base.Dispose (disposing);
966 static void CBOnExit (object state, bool unused)
968 Process p = (Process) state;
969 p.OnExited ();
972 protected void OnExited()
974 if (Exited == null)
975 return;
977 if (synchronizingObject == null) {
978 Exited (this, EventArgs.Empty);
979 return;
982 object [] args = new object [] {this, EventArgs.Empty};
983 synchronizingObject.BeginInvoke (Exited, args);
986 class ProcessWaitHandle : WaitHandle
988 public ProcessWaitHandle (IntPtr handle)
990 Handle = handle;
993 protected override void Dispose (bool explicitDisposing)
995 // Do nothing, we don't own the handle and we won't close it.