2 // System.Diagnostics.Process.cs
5 // Dick Porter (dick@ximian.com)
6 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 // (C) 2002 Ximian, Inc.
9 // (C) 2003 Andreas Nahr
14 using System.ComponentModel;
15 using System.ComponentModel.Design;
16 using System.Runtime.CompilerServices;
17 using System.Runtime.InteropServices;
18 using System.Collections;
20 namespace System.Diagnostics {
21 [DefaultEvent ("Exited"), DefaultProperty ("StartInfo")]
22 [Designer ("System.Diagnostics.Design.ProcessDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
23 public class Process : Component
25 [StructLayout(LayoutKind.Sequential)]
26 private struct ProcInfo
28 public IntPtr process_handle;
29 public IntPtr thread_handle;
30 public int pid; // Contains -GetLastError () on failure.
34 IntPtr process_handle;
37 /* Private constructor called from other methods */
38 private Process(IntPtr handle, int id) {
39 process_handle=handle;
48 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
49 [MonitoringDescription ("Base process priority.")]
50 public int BasePriority {
57 [DefaultValue (false), Browsable (false)]
58 [MonitoringDescription ("Check for exiting of the process to raise the apropriate event.")]
59 public bool EnableRaisingEvents {
67 [MethodImplAttribute(MethodImplOptions.InternalCall)]
68 private extern static int ExitCode_internal(IntPtr handle);
70 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
71 [MonitoringDescription ("The exit code of the process.")]
74 return(ExitCode_internal(process_handle));
78 /* Returns the process start time in Windows file
79 * times (ticks from DateTime(1/1/1601 00:00 GMT))
81 [MethodImplAttribute(MethodImplOptions.InternalCall)]
82 private extern static long ExitTime_internal(IntPtr handle);
84 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
85 [MonitoringDescription ("The exit time of the process.")]
86 public DateTime ExitTime {
88 return(DateTime.FromFileTime(ExitTime_internal(process_handle)));
92 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
93 [MonitoringDescription ("Handle for this process.")]
94 public IntPtr Handle {
96 return(process_handle);
101 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
102 [MonitoringDescription ("Handles for this process.")]
103 public int HandleCount {
109 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
110 [MonitoringDescription ("Determines if the process is still running.")]
111 public bool HasExited {
113 int exitcode=ExitCode;
124 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
125 [MonitoringDescription ("Process identifier.")]
133 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
134 [MonitoringDescription ("The name of the computer running the process.")]
135 public string MachineName {
141 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
142 [MonitoringDescription ("The main module of the process.")]
143 public ProcessModule MainModule {
145 return(this.Modules[0]);
150 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
151 [MonitoringDescription ("The handle of the main window of the process.")]
152 public IntPtr MainWindowHandle {
159 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
160 [MonitoringDescription ("The title of the main window of the process.")]
161 public string MainWindowTitle {
167 [MethodImplAttribute(MethodImplOptions.InternalCall)]
168 private extern static bool GetWorkingSet_internal(IntPtr handle, out int min, out int max);
169 [MethodImplAttribute(MethodImplOptions.InternalCall)]
170 private extern static bool SetWorkingSet_internal(IntPtr handle, int min, int max, bool use_min);
172 /* LAMESPEC: why is this an IntPtr not a plain int? */
173 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
174 [MonitoringDescription ("The maximum working set for this process.")]
175 public IntPtr MaxWorkingSet {
178 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
183 bool ok=GetWorkingSet_internal(process_handle, out min, out max);
185 throw new Win32Exception();
192 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
195 bool ok=SetWorkingSet_internal(process_handle, 0, value.ToInt32(), false);
197 throw new Win32Exception();
202 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
203 [MonitoringDescription ("The minimum working set for this process.")]
204 public IntPtr MinWorkingSet {
207 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
212 bool ok=GetWorkingSet_internal(process_handle, out min, out max);
214 throw new Win32Exception();
221 throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
224 bool ok=SetWorkingSet_internal(process_handle, value.ToInt32(), 0, true);
226 throw new Win32Exception();
231 /* Returns the list of process modules. The main module is
234 [MethodImplAttribute(MethodImplOptions.InternalCall)]
235 private extern ProcessModule[] GetModules_internal();
237 private ProcessModuleCollection module_collection;
239 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
240 [MonitoringDescription ("The modules that are loaded as part of this process.")]
241 public ProcessModuleCollection Modules {
243 if(module_collection==null) {
244 module_collection=new ProcessModuleCollection(GetModules_internal());
247 return(module_collection);
252 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
253 [MonitoringDescription ("The number of bytes that are not pageable.")]
254 public int NonpagedSystemMemorySize {
261 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
262 [MonitoringDescription ("The number of bytes that are paged.")]
263 public int PagedMemorySize {
270 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
271 [MonitoringDescription ("The amount of paged system memory in bytes.")]
272 public int PagedSystemMemorySize {
279 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
280 [MonitoringDescription ("The maximum amount of paged memory used by this process.")]
281 public int PeakPagedMemorySize {
288 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
289 [MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
290 public int PeakVirtualMemorySize {
297 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
298 [MonitoringDescription ("The maximum amount of system memory used by this process.")]
299 public int PeakWorkingSet {
306 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
307 [MonitoringDescription ("Process will be of higher priority while it is actively used.")]
308 public bool PriorityBoostEnabled {
317 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
318 [MonitoringDescription ("The relative process priority.")]
319 public ProcessPriorityClass PriorityClass {
321 return(ProcessPriorityClass.Normal);
328 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
329 [MonitoringDescription ("The amount of memory exclusively used by this process.")]
330 public int PrivateMemorySize {
337 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
338 [MonitoringDescription ("The amount of processing time spent is the OS core for this process.")]
339 public TimeSpan PrivilegedProcessorTime {
341 return(new TimeSpan(0));
345 [MethodImplAttribute(MethodImplOptions.InternalCall)]
346 private extern static string ProcessName_internal(IntPtr handle);
348 private string process_name=null;
350 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
351 [MonitoringDescription ("The name of this process.")]
352 public string ProcessName {
354 if(process_name==null) {
355 process_name=ProcessName_internal(process_handle);
356 /* If process_name is _still_
357 * null, assume the process
360 if(process_name==null) {
361 throw new SystemException("The process has exited");
364 /* Strip the suffix (if it
365 * exists) simplistically
366 * instead of removing any
367 * trailing \.???, so we dont
368 * get stupid results on sane
371 if(process_name.EndsWith(".exe") ||
372 process_name.EndsWith(".bat") ||
373 process_name.EndsWith(".com")) {
374 process_name=process_name.Substring(0, process_name.Length-4);
377 return(process_name);
382 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
383 [MonitoringDescription ("Allowed processor that can be used by this process.")]
384 public IntPtr ProcessorAffinity {
393 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
394 [MonitoringDescription ("Is this process responsive.")]
395 public bool Responding {
401 private StreamReader error_stream=null;
403 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
404 [MonitoringDescription ("The standard error stream of this process.")]
405 public StreamReader StandardError {
407 return(error_stream);
411 private StreamWriter input_stream=null;
413 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
414 [MonitoringDescription ("The standard input stream of this process.")]
415 public StreamWriter StandardInput {
417 return(input_stream);
421 private StreamReader output_stream=null;
423 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
424 [MonitoringDescription ("The standard output stream of this process.")]
425 public StreamReader StandardOutput {
427 return(output_stream);
431 private ProcessStartInfo start_info=null;
433 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
434 [MonitoringDescription ("Information for the start of this process.")]
435 public ProcessStartInfo StartInfo {
437 if(start_info==null) {
438 start_info=new ProcessStartInfo();
445 throw new ArgumentException("value is null");
452 /* Returns the process start time in Windows file
453 * times (ticks from DateTime(1/1/1601 00:00 GMT))
455 [MethodImplAttribute(MethodImplOptions.InternalCall)]
456 private extern static long StartTime_internal(IntPtr handle);
458 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
459 [MonitoringDescription ("The time this process started.")]
460 public DateTime StartTime {
462 return(DateTime.FromFileTime(StartTime_internal(process_handle)));
467 [DefaultValue (null), Browsable (false)]
468 [MonitoringDescription ("The object that is used to synchronize event handler calls for this process.")]
469 public ISynchronizeInvoke SynchronizingObject {
478 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
479 [MonitoringDescription ("The number of threads of this process.")]
480 public ProcessThreadCollection Threads {
487 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
488 [MonitoringDescription ("The total CPU time spent for this process.")]
489 public TimeSpan TotalProcessorTime {
491 return(new TimeSpan(0));
496 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
497 [MonitoringDescription ("The CPU time spent for this process in user mode.")]
498 public TimeSpan UserProcessorTime {
500 return(new TimeSpan(0));
505 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
506 [MonitoringDescription ("The amount of virtual memory currently used for this process.")]
507 public int VirtualMemorySize {
514 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
515 [MonitoringDescription ("The amount of physical memory currently used for this process.")]
516 public int WorkingSet {
523 public void Close() {
527 public bool CloseMainWindow() {
532 public static void EnterDebugMode() {
535 [MethodImplAttribute(MethodImplOptions.InternalCall)]
536 private extern static IntPtr GetProcess_internal(int pid);
538 [MethodImplAttribute(MethodImplOptions.InternalCall)]
539 private extern static int GetPid_internal();
541 public static Process GetCurrentProcess() {
542 int pid=GetPid_internal();
543 IntPtr proc=GetProcess_internal(pid);
545 if(proc==IntPtr.Zero) {
546 throw new SystemException("Can't find current process");
549 return(new Process(proc, pid));
552 public static Process GetProcessById(int processId) {
553 IntPtr proc=GetProcess_internal(processId);
555 if(proc==IntPtr.Zero) {
556 throw new ArgumentException("Can't find process with ID " + processId.ToString());
559 return(new Process(proc, processId));
563 public static Process GetProcessById(int processId, string machineName) {
564 throw new NotImplementedException();
567 [MethodImplAttribute(MethodImplOptions.InternalCall)]
568 private extern static int[] GetProcesses_internal();
570 public static Process[] GetProcesses() {
571 int[] pids=GetProcesses_internal();
572 ArrayList proclist=new ArrayList();
574 for(int i=0; i<pids.Length; i++) {
576 proclist.Add(GetProcessById(pids[i]));
577 } catch (SystemException) {
578 /* The process might exit
580 * GetProcesses_internal and
586 return((Process[])proclist.ToArray(typeof(Process)));
590 public static Process[] GetProcesses(string machineName) {
591 throw new NotImplementedException();
594 public static Process[] GetProcessesByName(string processName) {
595 Process[] procs=GetProcesses();
596 ArrayList proclist=new ArrayList();
598 for(int i=0; i<procs.Length; i++) {
600 if(String.Compare(processName,
601 procs[i].ProcessName,
603 proclist.Add(procs[i]);
607 return((Process[])proclist.ToArray(typeof(Process)));
611 public static Process[] GetProcessesByName(string processName, string machineName) {
612 throw new NotImplementedException();
620 public static void LeaveDebugMode() {
624 public void Refresh() {
627 [MethodImplAttribute(MethodImplOptions.InternalCall)]
628 private extern static bool Start_internal(string cmd,
633 ref ProcInfo proc_info);
635 private static bool Start_common(ProcessStartInfo startInfo,
637 ProcInfo proc_info=new ProcInfo();
638 IntPtr stdin_rd, stdin_wr;
639 IntPtr stdout_rd, stdout_wr;
640 IntPtr stderr_rd, stderr_wr;
643 if(startInfo.FileName == "") {
644 throw new InvalidOperationException("File name has not been set");
647 if(startInfo.RedirectStandardInput==true) {
648 ret=MonoIO.CreatePipe(out stdin_rd,
651 stdin_rd=MonoIO.ConsoleInput;
652 /* This is required to stop the
653 * &$*£ing stupid compiler moaning
654 * that stdin_wr is unassigned, below.
659 if(startInfo.RedirectStandardOutput==true) {
660 ret=MonoIO.CreatePipe(out stdout_rd,
664 stdout_wr=MonoIO.ConsoleOutput;
667 if(startInfo.RedirectStandardError==true) {
668 ret=MonoIO.CreatePipe(out stderr_rd,
672 stderr_wr=MonoIO.ConsoleError;
675 ret=Start_internal(startInfo.FileName + " " +
677 startInfo.WorkingDirectory,
678 stdin_rd, stdout_wr, stderr_wr,
684 if (startInfo.RedirectStandardInput == true)
685 MonoIO.Close (stdin_rd, out error);
687 if (startInfo.RedirectStandardOutput == true)
688 MonoIO.Close (stdout_wr, out error);
690 if (startInfo.RedirectStandardError == true)
691 MonoIO.Close (stderr_wr, out error);
693 throw new Win32Exception (-proc_info.pid);
696 process.process_handle=proc_info.process_handle;
697 process.pid=proc_info.pid;
699 if(startInfo.RedirectStandardInput==true) {
700 MonoIO.Close(stdin_rd, out error);
701 process.input_stream=new StreamWriter(new FileStream(stdin_wr, FileAccess.Write, true));
702 process.input_stream.AutoFlush=true;
705 if(startInfo.RedirectStandardOutput==true) {
706 MonoIO.Close(stdout_wr, out error);
707 process.output_stream=new StreamReader(new FileStream(stdout_rd, FileAccess.Read, true));
710 if(startInfo.RedirectStandardError==true) {
711 MonoIO.Close(stderr_wr, out error);
712 process.error_stream=new StreamReader(new FileStream(stderr_rd, FileAccess.Read, true));
718 public bool Start() {
721 ret=Start_common(start_info, this);
726 public static Process Start(ProcessStartInfo startInfo) {
727 Process process=new Process();
730 ret=Start_common(startInfo, process);
739 public static Process Start(string fileName) {
740 return Start(new ProcessStartInfo(fileName));
743 public static Process Start(string fileName,
745 return Start(new ProcessStartInfo(fileName, arguments));
748 public override string ToString() {
749 return(base.ToString() +
750 " (" + this.ProcessName + ")");
753 /* Waits up to ms milliseconds for process 'handle' to
754 * exit. ms can be <0 to mean wait forever.
756 [MethodImplAttribute(MethodImplOptions.InternalCall)]
757 private extern bool WaitForExit_internal(IntPtr handle,
760 public void WaitForExit() {
761 WaitForExit_internal(process_handle, -1);
764 public bool WaitForExit(int milliseconds) {
765 return(WaitForExit_internal(process_handle,
770 public bool WaitForInputIdle() {
775 public bool WaitForInputIdle(int milliseconds) {
780 [MonitoringDescription ("Raised when this process exits.")]
781 public event EventHandler Exited;
783 // Closes the system process handle
784 [MethodImplAttribute(MethodImplOptions.InternalCall)]
785 private extern void Process_free_internal(IntPtr handle);
787 private bool disposed = false;
789 protected override void Dispose(bool disposing) {
790 // Check to see if Dispose has already been called.
793 // If this is a call to Dispose,
794 // dispose all managed resources.
799 // Release unmanaged resources
802 if(process_handle!=IntPtr.Zero) {
804 Process_free_internal(process_handle);
805 process_handle=IntPtr.Zero;
809 base.Dispose (disposing);
812 protected void OnExited()
815 Exited (this, EventArgs.Empty);