2 // System.Diagnostics.Process.cs
5 // Dick Porter (dick@ximian.com)
7 // (C) 2002 Ximian, Inc.
12 using System.ComponentModel;
13 using System.Runtime.CompilerServices;
14 using System.Runtime.InteropServices;
15 using System.Collections;
17 namespace System.Diagnostics {
18 public class Process : Component {
19 [StructLayout(LayoutKind.Sequential)]
20 private struct ProcInfo {
21 public IntPtr process_handle;
22 public IntPtr thread_handle;
27 IntPtr process_handle;
30 /* Private constructor called from other methods */
31 private Process(IntPtr handle, int id) {
32 process_handle=handle;
41 public int BasePriority {
48 public bool EnableRaisingEvents {
56 [MethodImplAttribute(MethodImplOptions.InternalCall)]
57 private extern static int ExitCode_internal(IntPtr handle);
61 return(ExitCode_internal(process_handle));
65 /* Returns the process start time in Windows file
66 * times (ticks from DateTime(1/1/1601 00:00 GMT))
68 [MethodImplAttribute(MethodImplOptions.InternalCall)]
69 private extern static long ExitTime_internal(IntPtr handle);
71 public DateTime ExitTime {
73 return(DateTime.FromFileTime(ExitTime_internal(process_handle)));
77 public IntPtr Handle {
79 return(process_handle);
84 public int HandleCount {
91 public bool HasExited {
104 public string MachineName {
110 public ProcessModule MainModule {
112 return(this.Modules[0]);
117 public IntPtr MainWindowHandle {
124 public string MainWindowTitle {
130 [MethodImplAttribute(MethodImplOptions.InternalCall)]
131 private extern static bool GetWorkingSet_internal(IntPtr handle, out int min, out int max);
132 [MethodImplAttribute(MethodImplOptions.InternalCall)]
133 private extern static bool SetWorkingSet_internal(IntPtr handle, int min, int max, bool use_min);
135 /* LAMESPEC: why is this an IntPtr not a plain int? */
136 public IntPtr MaxWorkingSet {
139 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
144 bool ok=GetWorkingSet_internal(process_handle, out min, out max);
146 throw new Win32Exception();
153 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
156 bool ok=SetWorkingSet_internal(process_handle, 0, value.ToInt32(), false);
158 throw new Win32Exception();
163 public IntPtr MinWorkingSet {
166 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
171 bool ok=GetWorkingSet_internal(process_handle, out min, out max);
173 throw new Win32Exception();
180 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
183 bool ok=SetWorkingSet_internal(process_handle, value.ToInt32(), 0, true);
185 throw new Win32Exception();
190 /* Returns the list of process modules. The main module is
193 [MethodImplAttribute(MethodImplOptions.InternalCall)]
194 private extern ProcessModule[] GetModules_internal();
196 private ProcessModuleCollection module_collection;
198 public ProcessModuleCollection Modules {
200 if(module_collection==null) {
201 module_collection=new ProcessModuleCollection(GetModules_internal());
204 return(module_collection);
209 public int NonpagedSystemMemorySize {
216 public int PagedMemorySize {
223 public int PagedSystemMemorySize {
230 public int PeakPagedMemorySize {
237 public int PeakVirtualMemorySize {
244 public int PeakWorkingSet {
251 public bool PriorityBoostEnabled {
260 public ProcessPriorityClass PriorityClass {
262 return(ProcessPriorityClass.Normal);
269 public int PrivateMemorySize {
276 public TimeSpan PrivilegedProcessorTime {
278 return(new TimeSpan(0));
282 [MethodImplAttribute(MethodImplOptions.InternalCall)]
283 private extern static string ProcessName_internal(IntPtr handle);
285 private string process_name=null;
287 public string ProcessName {
289 if(process_name==null) {
290 process_name=ProcessName_internal(process_handle);
291 /* If process_name is _still_
292 * null, assume the process
295 if(process_name==null) {
296 throw new SystemException("The process has exited");
299 /* Strip the suffix (if it
300 * exists) simplistically
301 * instead of removing any
302 * trailing \.???, so we dont
303 * get stupid results on sane
306 if(process_name.EndsWith(".exe") ||
307 process_name.EndsWith(".bat") ||
308 process_name.EndsWith(".com")) {
309 process_name=process_name.Substring(0, process_name.Length-4);
312 return(process_name);
317 public IntPtr ProcessorAffinity {
326 public bool Responding {
332 private StreamReader error_stream=null;
334 public StreamReader StandardError {
336 return(error_stream);
340 private StreamWriter input_stream=null;
342 public StreamWriter StandardInput {
344 return(input_stream);
348 private StreamReader output_stream=null;
350 public StreamReader StandardOutput {
352 return(output_stream);
356 private ProcessStartInfo start_info=null;
358 public ProcessStartInfo StartInfo {
360 if(start_info==null) {
361 start_info=new ProcessStartInfo();
368 throw new ArgumentException("value is null");
375 /* Returns the process start time in Windows file
376 * times (ticks from DateTime(1/1/1601 00:00 GMT))
378 [MethodImplAttribute(MethodImplOptions.InternalCall)]
379 private extern static long StartTime_internal(IntPtr handle);
381 public DateTime StartTime {
383 return(DateTime.FromFileTime(StartTime_internal(process_handle)));
388 public ISynchronizeInvoke SynchronizingObject {
397 public ProcessThreadCollection Threads {
404 public TimeSpan TotalProcessorTime {
406 return(new TimeSpan(0));
411 public TimeSpan UserProcessorTime {
413 return(new TimeSpan(0));
418 public int VirtualMemorySize {
425 public int WorkingSet {
432 public void Close() {
436 public bool CloseMainWindow() {
441 public static void EnterDebugMode() {
444 [MethodImplAttribute(MethodImplOptions.InternalCall)]
445 private extern static IntPtr GetProcess_internal(int pid);
447 [MethodImplAttribute(MethodImplOptions.InternalCall)]
448 private extern static int GetPid_internal();
450 public static Process GetCurrentProcess() {
451 int pid=GetPid_internal();
452 IntPtr proc=GetProcess_internal(pid);
454 if(proc==IntPtr.Zero) {
455 throw new SystemException("Can't find current process");
458 return(new Process(proc, pid));
461 public static Process GetProcessById(int processId) {
462 IntPtr proc=GetProcess_internal(processId);
464 if(proc==IntPtr.Zero) {
465 throw new ArgumentException("Can't find process with ID " + processId.ToString());
468 return(new Process(proc, processId));
472 public static Process GetProcessById(int processId, string machineName) {
473 throw new NotImplementedException();
476 [MethodImplAttribute(MethodImplOptions.InternalCall)]
477 private extern static int[] GetProcesses_internal();
479 public static Process[] GetProcesses() {
480 int[] pids=GetProcesses_internal();
481 ArrayList proclist=new ArrayList();
483 for(int i=0; i<pids.Length; i++) {
485 proclist.Add(GetProcessById(pids[i]));
486 } catch (SystemException) {
487 /* The process might exit
489 * GetProcesses_internal and
495 return((Process[])proclist.ToArray(typeof(Process)));
499 public static Process[] GetProcesses(string machineName) {
500 throw new NotImplementedException();
503 public static Process[] GetProcessesByName(string processName) {
504 Process[] procs=GetProcesses();
505 ArrayList proclist=new ArrayList();
507 for(int i=0; i<procs.Length; i++) {
509 if(String.Compare(processName,
510 procs[i].ProcessName,
512 proclist.Add(procs[i]);
516 return((Process[])proclist.ToArray(typeof(Process)));
520 public static Process[] GetProcessesByName(string processName, string machineName) {
521 throw new NotImplementedException();
529 public static void LeaveDebugMode() {
533 public void Refresh() {
536 [MethodImplAttribute(MethodImplOptions.InternalCall)]
537 private extern static bool Start_internal(string cmd,
542 ref ProcInfo proc_info);
544 private static bool Start_common(ProcessStartInfo startInfo,
546 ProcInfo proc_info=new ProcInfo();
547 IntPtr stdin_rd, stdin_wr;
548 IntPtr stdout_rd, stdout_wr;
549 IntPtr stderr_rd, stderr_wr;
552 if(startInfo.FileName == "") {
553 throw new InvalidOperationException("File name has not been set");
556 if(startInfo.RedirectStandardInput==true) {
557 ret=MonoIO.CreatePipe(out stdin_rd,
560 stdin_rd=MonoIO.ConsoleInput;
561 /* This is required to stop the
562 * &$*£ing stupid compiler moaning
563 * that stdin_wr is unassigned, below.
568 if(startInfo.RedirectStandardOutput==true) {
569 ret=MonoIO.CreatePipe(out stdout_rd,
573 stdout_wr=MonoIO.ConsoleOutput;
576 if(startInfo.RedirectStandardError==true) {
577 ret=MonoIO.CreatePipe(out stderr_rd,
581 stderr_wr=MonoIO.ConsoleError;
584 ret=Start_internal(startInfo.FileName + " " +
586 startInfo.WorkingDirectory,
587 stdin_rd, stdout_wr, stderr_wr,
590 process.process_handle=proc_info.process_handle;
591 process.pid=proc_info.pid;
593 if(startInfo.RedirectStandardInput==true) {
594 MonoIO.Close(stdin_rd);
595 process.input_stream=new StreamWriter(new FileStream(stdin_wr, FileAccess.Write, true));
596 process.input_stream.AutoFlush=true;
599 if(startInfo.RedirectStandardOutput==true) {
600 MonoIO.Close(stdout_wr);
601 process.output_stream=new StreamReader(new FileStream(stdout_rd, FileAccess.Read, true));
604 if(startInfo.RedirectStandardError==true) {
605 MonoIO.Close(stderr_wr);
606 process.error_stream=new StreamReader(new FileStream(stderr_rd, FileAccess.Read, true));
612 public bool Start() {
615 ret=Start_common(start_info, this);
620 public static Process Start(ProcessStartInfo startInfo) {
621 Process process=new Process();
624 ret=Start_common(startInfo, process);
634 public static Process Start(string fileName) {
635 throw new NotImplementedException();
639 public static Process Start(string fileName,
641 throw new NotImplementedException();
644 public override string ToString() {
645 return(base.ToString() +
646 " (" + this.ProcessName + ")");
649 /* Waits up to ms milliseconds for process 'handle' to
650 * exit. ms can be <0 to mean wait forever.
652 [MethodImplAttribute(MethodImplOptions.InternalCall)]
653 private extern bool WaitForExit_internal(IntPtr handle,
656 public void WaitForExit() {
657 WaitForExit_internal(process_handle, -1);
660 public bool WaitForExit(int milliseconds) {
661 return(WaitForExit_internal(process_handle,
666 public bool WaitForInputIdle() {
671 public bool WaitForInputIdle(int milliseconds) {
676 public event EventHandler Exited;
678 // Closes the system process handle
679 [MethodImplAttribute(MethodImplOptions.InternalCall)]
680 private extern void Process_free_internal(IntPtr handle);
682 private bool disposed = false;
684 protected override void Dispose(bool disposing) {
685 // Check to see if Dispose has already been called.
688 // If this is a call to Dispose,
689 // dispose all managed resources.
694 // Release unmanaged resources
697 if(process_handle!=IntPtr.Zero) {
699 Process_free_internal(process_handle);
700 process_handle=IntPtr.Zero;
704 base.Dispose (disposing);
708 protected void OnExited() {