1 //------------------------------------------------------------------------------
2 // <copyright file="Process.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
11 namespace System.Diagnostics {
13 using System.Threading;
14 using System.Runtime.InteropServices;
15 using System.ComponentModel;
16 using System.ComponentModel.Design;
17 using System.Runtime.CompilerServices;
18 using System.Runtime.ConstrainedExecution;
19 using System.Diagnostics;
21 using System.Collections;
23 using Microsoft.Win32;
24 using Microsoft.Win32.SafeHandles;
25 using System.Collections.Specialized;
26 using System.Globalization;
27 using System.Security;
28 using System.Security.Permissions;
29 using System.Security.Principal;
30 using System.Runtime.Versioning;
34 /// Provides access to local and remote
35 /// processes. Enables you to start and stop system processes.
39 MonitoringDescription(SR.ProcessDesc),
40 DefaultEvent("Exited"),
41 DefaultProperty("StartInfo"),
42 Designer("System.Diagnostics.Design.ProcessDesigner, " + AssemblyRef.SystemDesign),
43 // Disabling partial trust scenarios
44 PermissionSet(SecurityAction.LinkDemand, Name="FullTrust"),
45 PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust"),
46 HostProtection(SharedState=true, Synchronization=true, ExternalProcessMgmt=true, SelfAffectingProcessMgmt=true)
48 public partial class Process : Component {
55 bool haveProcessHandle;
56 SafeProcessHandle m_processHandle;
60 ProcessInfo processInfo;
62 Int32 m_processAccess;
65 ProcessThreadCollection threads;
66 ProcessModuleCollection modules;
67 #endif // !FEATURE_PAL
71 IntPtr mainWindowHandle; // no need to use SafeHandle for window
72 string mainWindowTitle;
75 bool haveWorkingSetLimits;
80 bool haveProcessorAffinity;
81 IntPtr processorAffinity;
84 bool havePriorityClass;
85 ProcessPriorityClass priorityClass;
87 ProcessStartInfo startInfo;
91 EventHandler onExited;
103 bool priorityBoostEnabled;
104 bool havePriorityBoostEnabled;
108 RegisteredWaitHandle registeredWaitHandle;
109 WaitHandle waitHandle;
110 ISynchronizeInvoke synchronizingObject;
111 StreamReader standardOutput;
112 StreamWriter standardInput;
113 StreamReader standardError;
114 OperatingSystem operatingSystem;
118 static object s_CreateProcessLock = new object();
121 // This enum defines the operation mode for redirected process stream.
122 // We don't support switching between synchronous mode and asynchronous mode.
123 private enum StreamReadMode
130 StreamReadMode outputStreamReadMode;
131 StreamReadMode errorStreamReadMode;
134 StreamReadMode inputStreamReadMode;
137 // Support for asynchrously reading streams
138 [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
139 //[System.Runtime.InteropServices.ComVisible(false)]
140 public event DataReceivedEventHandler OutputDataReceived;
141 [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
142 //[System.Runtime.InteropServices.ComVisible(false)]
143 public event DataReceivedEventHandler ErrorDataReceived;
144 // Abstract the stream details
145 internal AsyncStreamReader output;
146 internal AsyncStreamReader error;
147 internal bool pendingOutputRead;
148 internal bool pendingErrorRead;
151 private static SafeFileHandle InvalidPipeHandle = new SafeFileHandle(IntPtr.Zero, false);
154 internal static TraceSwitch processTracing = new TraceSwitch("processTracing", "Controls debug output from Process component");
156 internal static TraceSwitch processTracing = null;
165 /// Initializes a new instance of the <see cref='System.Diagnostics.Process'/> class.
169 this.machineName = ".";
170 this.outputStreamReadMode = StreamReadMode.undefined;
171 this.errorStreamReadMode = StreamReadMode.undefined;
172 this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
175 [ResourceExposure(ResourceScope.Machine)]
176 Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo) : base() {
177 Debug.Assert(SyntaxCheck.CheckMachineName(machineName), "The machine name should be valid!");
179 this.processInfo = processInfo;
181 this.machineName = machineName;
182 this.isRemoteMachine = isRemoteMachine;
183 this.processId = processId;
184 this.haveProcessId = true;
185 this.outputStreamReadMode = StreamReadMode.undefined;
186 this.errorStreamReadMode = StreamReadMode.undefined;
187 this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
195 /// Returns whether this process component is associated with a real process.
198 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessAssociated)]
201 return haveProcessId || haveProcessHandle;
205 #if !FEATURE_PAL && !MONO
208 /// Gets the base priority of
209 /// the associated process.
212 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessBasePriority)]
213 public int BasePriority {
215 EnsureState(State.HaveProcessInfo);
216 return processInfo.basePriority;
219 #endif // !FEATURE_PAL && !MONO
225 /// value that was specified by the associated process when it was terminated.
228 [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitCode)]
229 public int ExitCode {
231 EnsureState(State.Exited);
234 throw new InvalidOperationException ("Cannot get the exit code from a non-child process on Unix");
243 /// value indicating whether the associated process has been terminated.
246 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTerminated)]
247 public bool HasExited {
250 EnsureState(State.Associated);
251 SafeProcessHandle handle = null;
253 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.SYNCHRONIZE, false);
254 if (handle.IsInvalid) {
260 // Although this is the wrong way to check whether the process has exited,
261 // it was historically the way we checked for it, and a lot of code then took a dependency on
262 // the fact that this would always be set before the pipes were closed, so they would read
263 // the exit code out after calling ReadToEnd() or standard output or standard error. In order
264 // to allow 259 to function as a valid exit code and to break as few people as possible that
265 // took the ReadToEnd dependency, we check for an exit code before doing the more correct
266 // check to see if we have been signalled.
267 if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
269 this.exitCode = exitCode;
273 // The best check for exit is that the kernel process object handle is invalid,
274 // or that it is valid and signaled. Checking if the exit code != STILL_ACTIVE
275 // does not guarantee the process is closed,
276 // since some process could return an actual STILL_ACTIVE exit code (259).
277 if (!signaled) // if we just came from WaitForExit, don't repeat
279 ProcessWaitHandle wh = null;
282 wh = new ProcessWaitHandle(handle);
283 this.signaled = wh.WaitOne(0, false);
294 /* If it's a non-child process, it's impossible to get its exit code on
295 * Unix. We don't throw here, but GetExitCodeProcess (in the io-layer)
296 * will set exitCode to -1, and we will throw if we try to call ExitCode */
297 if (!NativeMethods.GetExitCodeProcess(handle, out exitCode))
298 throw new Win32Exception();
301 this.exitCode = exitCode;
308 ReleaseProcessHandle(handle);
319 private ProcessThreadTimes GetProcessTimes() {
320 ProcessThreadTimes processTimes = new ProcessThreadTimes();
321 SafeProcessHandle handle = null;
323 int access = NativeMethods.PROCESS_QUERY_INFORMATION;
325 if (EnvironmentHelpers.IsWindowsVistaOrAbove())
326 access = NativeMethods.PROCESS_QUERY_LIMITED_INFORMATION;
328 handle = GetProcessHandle(access, false);
329 if( handle.IsInvalid) {
330 // On OS older than XP, we will not be able to get the handle for a process
331 // after it terminates.
332 // On Windows XP and newer OS, the information about a process will stay longer.
333 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
336 if (!NativeMethods.GetProcessTimes(handle,
337 out processTimes.create,
338 out processTimes.exit,
339 out processTimes.kernel,
340 out processTimes.user)) {
341 throw new Win32Exception();
346 ReleaseProcessHandle(handle);
354 /// Gets the time that the associated process exited.
357 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitTime)]
358 public DateTime ExitTime {
361 EnsureState(State.IsNt | State.Exited);
362 exitTime = GetProcessTimes().ExitTime;
368 #endif // !FEATURE_PAL
372 /// Returns the native handle for the associated process. The handle is only available
373 /// if this component started the process.
376 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandle)]
377 public IntPtr Handle {
378 [ResourceExposure(ResourceScope.Machine)]
379 [ResourceConsumption(ResourceScope.Machine)]
381 EnsureState(State.Associated);
382 return OpenProcessHandle(this.m_processAccess).DangerousGetHandle();
386 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
387 public SafeProcessHandle SafeHandle {
389 EnsureState(State.Associated);
390 return OpenProcessHandle(this.m_processAccess);
394 #if !FEATURE_PAL && !MONO
397 /// Gets the number of handles that are associated
398 /// with the process.
401 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandleCount)]
402 public int HandleCount {
404 EnsureState(State.HaveProcessInfo);
405 return processInfo.handleCount;
408 #endif // !FEATURE_PAL && !MONO
413 /// the unique identifier for the associated process.
416 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessId)]
419 EnsureState(State.HaveId);
427 /// the name of the computer on which the associated process is running.
430 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMachineName)]
431 public string MachineName {
433 EnsureState(State.Associated);
443 /// Returns the window handle of the main window of the associated process.
446 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowHandle)]
447 public IntPtr MainWindowHandle {
448 [ResourceExposure(ResourceScope.Machine)]
449 [ResourceConsumption(ResourceScope.Machine)]
451 if (!haveMainWindow) {
452 EnsureState(State.IsLocal | State.HaveId);
453 mainWindowHandle = ProcessManager.GetMainWindowHandle(processId);
455 if (mainWindowHandle != (IntPtr)0) {
456 haveMainWindow = true;
458 // We do the following only for the side-effect that it will throw when if the process no longer exists on the system. In Whidbey
459 // we always did this check but have now changed it to just require a ProcessId. In the case where someone has called Refresh()
460 // and the process has exited this call will throw an exception where as the above code would return 0 as the handle.
461 EnsureState(State.HaveProcessInfo);
464 return mainWindowHandle;
470 /// Returns the caption of the <see cref='System.Diagnostics.Process.MainWindowHandle'/> of
471 /// the process. If the handle is zero (0), then an empty string is returned.
474 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowTitle)]
475 public string MainWindowTitle {
476 [ResourceExposure(ResourceScope.None)]
477 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
479 if (mainWindowTitle == null) {
480 IntPtr handle = MainWindowHandle;
481 if (handle == (IntPtr)0) {
482 mainWindowTitle = String.Empty;
485 int length = NativeMethods.GetWindowTextLength(new HandleRef(this, handle)) * 2;
486 StringBuilder builder = new StringBuilder(length);
487 NativeMethods.GetWindowText(new HandleRef(this, handle), builder, builder.Capacity);
488 mainWindowTitle = builder.ToString();
491 return mainWindowTitle;
500 /// the main module for the associated process.
503 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainModule)]
504 public ProcessModule MainModule {
505 [ResourceExposure(ResourceScope.Process)]
506 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
508 // We only return null if we couldn't find a main module.
509 // This could be because
510 // 1. The process hasn't finished loading the main module (most likely)
511 // 2. There are no modules loaded (possible for certain OS processes)
512 // 3. Possibly other?
514 if (OperatingSystem.Platform == PlatformID.Win32NT) {
515 EnsureState(State.HaveId | State.IsLocal);
516 // on NT the first module is the main module
517 ModuleInfo module = NtProcessManager.GetFirstModuleInfo(processId);
518 return new ProcessModule(module);
521 ProcessModuleCollection moduleCollection = Modules;
522 // on 9x we have to do a little more work
523 EnsureState(State.HaveProcessInfo);
524 foreach (ProcessModule pm in moduleCollection) {
525 if (pm.moduleInfo.Id == processInfo.mainModuleId) {
537 /// Gets or sets the maximum allowable working set for the associated
541 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMaxWorkingSet)]
542 public IntPtr MaxWorkingSet {
544 EnsureWorkingSetLimits();
545 return maxWorkingSet;
547 [ResourceExposure(ResourceScope.Process)]
548 [ResourceConsumption(ResourceScope.Process)]
550 SetWorkingSetLimits(null, value);
556 /// Gets or sets the minimum allowable working set for the associated
560 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMinWorkingSet)]
561 public IntPtr MinWorkingSet {
563 EnsureWorkingSetLimits();
564 return minWorkingSet;
566 [ResourceExposure(ResourceScope.Process)]
567 [ResourceConsumption(ResourceScope.Process)]
569 SetWorkingSetLimits(value, null);
577 /// the modules that have been loaded by the associated process.
580 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessModules)]
581 public ProcessModuleCollection Modules {
582 [ResourceExposure(ResourceScope.None)]
583 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
585 if (modules == null) {
586 EnsureState(State.HaveId | State.IsLocal);
587 ModuleInfo[] moduleInfos = ProcessManager.GetModuleInfos(processId);
588 ProcessModule[] newModulesArray = new ProcessModule[moduleInfos.Length];
589 for (int i = 0; i < moduleInfos.Length; i++) {
590 newModulesArray[i] = new ProcessModule(moduleInfos[i]);
592 ProcessModuleCollection newModules = new ProcessModuleCollection(newModulesArray);
593 modules = newModules;
600 /// Returns the amount of memory that the system has allocated on behalf of the
601 /// associated process that can not be written to the virtual memory paging file.
603 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
604 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
605 public int NonpagedSystemMemorySize {
607 EnsureState(State.HaveNtProcessInfo);
608 return unchecked((int)processInfo.poolNonpagedBytes);
612 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
613 [System.Runtime.InteropServices.ComVisible(false)]
614 public long NonpagedSystemMemorySize64 {
616 EnsureState(State.HaveNtProcessInfo);
617 return processInfo.poolNonpagedBytes;
622 /// Returns the amount of memory that the associated process has allocated
623 /// that can be written to the virtual memory paging file.
625 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PagedMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
626 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
627 public int PagedMemorySize {
629 EnsureState(State.HaveNtProcessInfo);
630 return unchecked((int)processInfo.pageFileBytes);
634 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
635 [System.Runtime.InteropServices.ComVisible(false)]
636 public long PagedMemorySize64 {
638 EnsureState(State.HaveNtProcessInfo);
639 return processInfo.pageFileBytes;
645 /// Returns the amount of memory that the system has allocated on behalf of the
646 /// associated process that can be written to the virtual memory paging file.
648 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PagedSystemMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
649 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
650 public int PagedSystemMemorySize {
652 EnsureState(State.HaveNtProcessInfo);
653 return unchecked((int)processInfo.poolPagedBytes);
657 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
658 [System.Runtime.InteropServices.ComVisible(false)]
659 public long PagedSystemMemorySize64 {
661 EnsureState(State.HaveNtProcessInfo);
662 return processInfo.poolPagedBytes;
669 /// Returns the maximum amount of memory that the associated process has
670 /// allocated that could be written to the virtual memory paging file.
673 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakPagedMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
674 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
675 public int PeakPagedMemorySize {
677 EnsureState(State.HaveNtProcessInfo);
678 return unchecked((int)processInfo.pageFileBytesPeak);
682 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
683 [System.Runtime.InteropServices.ComVisible(false)]
684 public long PeakPagedMemorySize64 {
686 EnsureState(State.HaveNtProcessInfo);
687 return processInfo.pageFileBytesPeak;
693 /// Returns the maximum amount of physical memory that the associated
694 /// process required at once.
697 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakWorkingSet64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
698 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
699 public int PeakWorkingSet {
701 EnsureState(State.HaveNtProcessInfo);
702 return unchecked((int)processInfo.workingSetPeak);
706 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
707 [System.Runtime.InteropServices.ComVisible(false)]
708 public long PeakWorkingSet64 {
710 EnsureState(State.HaveNtProcessInfo);
711 return processInfo.workingSetPeak;
716 /// Returns the maximum amount of virtual memory that the associated
717 /// process has requested.
719 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakVirtualMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
720 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
721 public int PeakVirtualMemorySize {
723 EnsureState(State.HaveNtProcessInfo);
724 return unchecked((int)processInfo.virtualBytesPeak);
728 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
729 [System.Runtime.InteropServices.ComVisible(false)]
730 public long PeakVirtualMemorySize64 {
732 EnsureState(State.HaveNtProcessInfo);
733 return processInfo.virtualBytesPeak;
738 private OperatingSystem OperatingSystem {
740 if (operatingSystem == null) {
741 operatingSystem = Environment.OSVersion;
743 return operatingSystem;
750 /// Gets or sets a value indicating whether the associated process priority
751 /// should be temporarily boosted by the operating system when the main window
755 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityBoostEnabled)]
756 public bool PriorityBoostEnabled {
758 EnsureState(State.IsNt);
759 if (!havePriorityBoostEnabled) {
760 SafeProcessHandle handle = null;
762 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
763 bool disabled = false;
764 if (!NativeMethods.GetProcessPriorityBoost(handle, out disabled)) {
765 throw new Win32Exception();
767 priorityBoostEnabled = !disabled;
768 havePriorityBoostEnabled = true;
771 ReleaseProcessHandle(handle);
774 return priorityBoostEnabled;
777 EnsureState(State.IsNt);
778 SafeProcessHandle handle = null;
780 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
781 if (!NativeMethods.SetProcessPriorityBoost(handle, !value))
782 throw new Win32Exception();
783 priorityBoostEnabled = value;
784 havePriorityBoostEnabled = true;
787 ReleaseProcessHandle(handle);
795 /// Gets or sets the overall priority category for the
796 /// associated process.
799 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityClass)]
800 public ProcessPriorityClass PriorityClass {
802 if (!havePriorityClass) {
803 SafeProcessHandle handle = null;
805 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
806 int value = NativeMethods.GetPriorityClass(handle);
808 throw new Win32Exception();
810 priorityClass = (ProcessPriorityClass)value;
811 havePriorityClass = true;
814 ReleaseProcessHandle(handle);
817 return priorityClass;
819 [ResourceExposure(ResourceScope.Machine)]
820 [ResourceConsumption(ResourceScope.Machine)]
822 if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) {
823 throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
827 // BelowNormal and AboveNormal are only available on Win2k and greater.
828 if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0) &&
829 (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) {
830 throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
834 SafeProcessHandle handle = null;
837 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
838 if (!NativeMethods.SetPriorityClass(handle, (int)value)) {
839 throw new Win32Exception();
841 priorityClass = value;
842 havePriorityClass = true;
845 ReleaseProcessHandle(handle);
852 /// Returns the number of bytes that the associated process has allocated that cannot
853 /// be shared with other processes.
855 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PrivateMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
856 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
857 public int PrivateMemorySize {
859 EnsureState(State.HaveNtProcessInfo);
860 return unchecked((int)processInfo.privateBytes);
864 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
865 [System.Runtime.InteropServices.ComVisible(false)]
866 public long PrivateMemorySize64 {
868 EnsureState(State.HaveNtProcessInfo);
869 return processInfo.privateBytes;
875 /// Returns the amount of time the process has spent running code inside the operating
878 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivilegedProcessorTime)]
879 public TimeSpan PrivilegedProcessorTime {
881 EnsureState(State.IsNt);
882 return GetProcessTimes().PrivilegedProcessorTime;
890 /// the friendly name of the process.
893 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessName)]
894 public string ProcessName {
895 [ResourceExposure(ResourceScope.None)]
896 [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
898 EnsureState(State.HaveProcessInfo);
899 String processName = processInfo.processName;
901 // On some old NT-based OS like win2000, the process name from NTQuerySystemInformation is up to 15 characters.
902 // Processes executing notepad_1234567.exe and notepad_12345678.exe will have the same process name.
903 // GetProcessByNames will not be able find the process for notepad_12345678.exe.
904 // So we will try to replace the name of the process by its main module name if the name is 15 characters.
905 // However we can't always get the module name:
906 // (1) Normal user will not be able to get module information about processes.
907 // (2) We can't get module information about remoting process.
908 // We can't get module name for a remote process
910 if (processName.Length == 15 && ProcessManager.IsNt && ProcessManager.IsOSOlderThanXP && !isRemoteMachine) {
912 String mainModuleName = MainModule.ModuleName;
913 if (mainModuleName != null) {
914 processInfo.processName = Path.ChangeExtension(Path.GetFileName(mainModuleName), null);
918 // If we can't access the module information, we can still use the might-be-truncated name.
919 // We could fail for a few reasons:
920 // (1) We don't enough privilege to get module information.
921 // (2) The process could have terminated.
925 return processInfo.processName;
932 /// or sets which processors the threads in this process can be scheduled to run on.
935 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessorAffinity)]
936 public IntPtr ProcessorAffinity {
938 if (!haveProcessorAffinity) {
939 SafeProcessHandle handle = null;
941 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
942 IntPtr processAffinity;
943 IntPtr systemAffinity;
944 if (!NativeMethods.GetProcessAffinityMask(handle, out processAffinity, out systemAffinity))
945 throw new Win32Exception();
946 processorAffinity = processAffinity;
949 ReleaseProcessHandle(handle);
951 haveProcessorAffinity = true;
953 return processorAffinity;
955 [ResourceExposure(ResourceScope.Machine)]
956 [ResourceConsumption(ResourceScope.Machine)]
958 SafeProcessHandle handle = null;
960 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
961 if (!NativeMethods.SetProcessAffinityMask(handle, value))
962 throw new Win32Exception();
964 processorAffinity = value;
965 haveProcessorAffinity = true;
968 ReleaseProcessHandle(handle);
975 /// Gets a value indicating whether or not the user
976 /// interface of the process is responding.
979 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessResponding)]
980 public bool Responding {
981 [ResourceExposure(ResourceScope.None)]
982 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
984 if (!haveResponding) {
985 IntPtr mainWindow = MainWindowHandle;
986 if (mainWindow == (IntPtr)0) {
991 responding = NativeMethods.SendMessageTimeout(new HandleRef(this, mainWindow), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero, NativeMethods.SMTO_ABORTIFHUNG, 5000, out result) != (IntPtr)0;
998 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessSessionId)]
999 public int SessionId {
1001 EnsureState(State.HaveNtProcessInfo);
1002 return processInfo.sessionId;
1007 #endif // !FEATURE_PAL
1009 #if MONO_FEATURE_PROCESS_START
1012 /// Gets or sets the properties to pass into the <see cref='System.Diagnostics.Process.Start'/> method for the <see cref='System.Diagnostics.Process'/>
1016 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MonitoringDescription(SR.ProcessStartInfo)]
1017 public ProcessStartInfo StartInfo {
1019 if (startInfo == null) {
1020 startInfo = new ProcessStartInfo(this);
1024 [ResourceExposure(ResourceScope.Machine)]
1026 if (value == null) {
1027 throw new ArgumentNullException("value");
1036 /// Returns the time the associated process was started.
1038 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStartTime)]
1039 public DateTime StartTime {
1041 EnsureState(State.IsNt);
1042 return GetProcessTimes().StartTime;
1045 #endif // !FEATURE_PAL
1048 /// Represents the object used to marshal the event handler
1049 /// calls issued as a result of a Process exit. Normally
1050 /// this property will be set when the component is placed
1051 /// inside a control or a from, since those components are
1052 /// bound to a specific thread.
1057 MonitoringDescription(SR.ProcessSynchronizingObject)
1059 public ISynchronizeInvoke SynchronizingObject {
1061 if (this.synchronizingObject == null && DesignMode) {
1062 IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
1064 object baseComponent = host.RootComponent;
1065 if (baseComponent != null && baseComponent is ISynchronizeInvoke)
1066 this.synchronizingObject = (ISynchronizeInvoke)baseComponent;
1070 return this.synchronizingObject;
1074 this.synchronizingObject = value;
1083 /// Gets the set of threads that are running in the associated
1087 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessThreads)]
1088 public ProcessThreadCollection Threads {
1089 [ResourceExposure(ResourceScope.Process)]
1090 [ResourceConsumption(ResourceScope.Process)]
1092 if (threads == null) {
1093 EnsureState(State.HaveProcessInfo);
1094 int count = processInfo.threadInfoList.Count;
1095 ProcessThread[] newThreadsArray = new ProcessThread[count];
1096 for (int i = 0; i < count; i++) {
1097 newThreadsArray[i] = new ProcessThread(isRemoteMachine, (ThreadInfo)processInfo.threadInfoList[i]);
1099 ProcessThreadCollection newThreads = new ProcessThreadCollection(newThreadsArray);
1100 threads = newThreads;
1108 /// Returns the amount of time the associated process has spent utilizing the CPU.
1109 /// It is the sum of the <see cref='System.Diagnostics.Process.UserProcessorTime'/> and
1110 /// <see cref='System.Diagnostics.Process.PrivilegedProcessorTime'/>.
1112 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTotalProcessorTime)]
1113 public TimeSpan TotalProcessorTime {
1115 EnsureState(State.IsNt);
1116 return GetProcessTimes().TotalProcessorTime;
1121 /// Returns the amount of time the associated process has spent running code
1122 /// inside the application portion of the process (not the operating system core).
1124 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessUserProcessorTime)]
1125 public TimeSpan UserProcessorTime {
1127 EnsureState(State.IsNt);
1128 return GetProcessTimes().UserProcessorTime;
1134 /// Returns the amount of virtual memory that the associated process has requested.
1136 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.VirtualMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
1137 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1138 public int VirtualMemorySize {
1140 EnsureState(State.HaveNtProcessInfo);
1141 return unchecked((int)processInfo.virtualBytes);
1146 #endif // !FEATURE_PAL
1149 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1150 [System.Runtime.InteropServices.ComVisible(false)]
1151 public long VirtualMemorySize64 {
1153 EnsureState(State.HaveNtProcessInfo);
1154 return processInfo.virtualBytes;
1161 /// Gets or sets whether the <see cref='System.Diagnostics.Process.Exited'/>
1163 /// when the process terminates.
1166 [Browsable(false), DefaultValue(false), MonitoringDescription(SR.ProcessEnableRaisingEvents)]
1167 public bool EnableRaisingEvents {
1169 return watchForExit;
1172 if (value != watchForExit) {
1175 OpenProcessHandle();
1176 EnsureWatchingForExit();
1179 StopWatchingForExit();
1182 watchForExit = value;
1187 #if MONO_FEATURE_PROCESS_START
1189 /// <para>[To be supplied.]</para>
1191 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardInput)]
1192 public StreamWriter StandardInput {
1194 if (standardInput == null) {
1195 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardIn));
1199 inputStreamReadMode = StreamReadMode.syncMode;
1201 return standardInput;
1206 /// <para>[To be supplied.]</para>
1208 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardOutput)]
1209 public StreamReader StandardOutput {
1211 if (standardOutput == null) {
1212 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
1215 if(outputStreamReadMode == StreamReadMode.undefined) {
1216 outputStreamReadMode = StreamReadMode.syncMode;
1218 else if (outputStreamReadMode != StreamReadMode.syncMode) {
1219 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
1222 return standardOutput;
1227 /// <para>[To be supplied.]</para>
1229 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardError)]
1230 public StreamReader StandardError {
1232 if (standardError == null) {
1233 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
1236 if(errorStreamReadMode == StreamReadMode.undefined) {
1237 errorStreamReadMode = StreamReadMode.syncMode;
1239 else if (errorStreamReadMode != StreamReadMode.syncMode) {
1240 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
1243 return standardError;
1248 #if !FEATURE_PAL && !MONO
1250 /// Returns the total amount of physical memory the associated process.
1252 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.WorkingSet64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
1253 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1254 public int WorkingSet {
1256 EnsureState(State.HaveNtProcessInfo);
1257 return unchecked((int)processInfo.workingSet);
1260 #endif // !FEATURE_PAL && !MONO
1263 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1264 [System.Runtime.InteropServices.ComVisible(false)]
1265 public long WorkingSet64 {
1267 EnsureState(State.HaveNtProcessInfo);
1268 return processInfo.workingSet;
1273 [Category("Behavior"), MonitoringDescription(SR.ProcessExited)]
1274 public event EventHandler Exited {
1283 #if !FEATURE_PAL && !MONO
1286 /// Closes a process that has a user interface by sending a close message
1287 /// to its main window.
1290 [ResourceExposure(ResourceScope.Machine)] // Review usages of this.
1291 [ResourceConsumption(ResourceScope.Machine)]
1292 public bool CloseMainWindow() {
1293 IntPtr mainWindowHandle = MainWindowHandle;
1294 if (mainWindowHandle == (IntPtr)0) return false;
1295 int style = NativeMethods.GetWindowLong(new HandleRef(this, mainWindowHandle), NativeMethods.GWL_STYLE);
1296 if ((style & NativeMethods.WS_DISABLED) != 0) return false;
1297 NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
1300 #endif // !FEATURE_PAL && !MONO
1303 /// Release the temporary handle we used to get process information.
1304 /// If we used the process handle stored in the process object (we have all access to the handle,) don't release it.
1307 void ReleaseProcessHandle(SafeProcessHandle handle) {
1308 if (handle == null) {
1312 if (haveProcessHandle && handle == m_processHandle) {
1315 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process)");
1320 /// This is called from the threadpool when a proces exits.
1323 private void CompletionCallback(object context, bool wasSignaled) {
1324 StopWatchingForExit();
1331 /// Free any resources associated with this component.
1334 protected override void Dispose(bool disposing) {
1337 //Dispose managed and unmanaged resources
1340 this.disposed = true;
1341 base.Dispose(disposing);
1347 /// Frees any resources associated with this component.
1350 public void Close() {
1352 if (haveProcessHandle) {
1353 StopWatchingForExit();
1354 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process) in Close()");
1355 m_processHandle.Close();
1356 m_processHandle = null;
1357 haveProcessHandle = false;
1359 haveProcessId = false;
1360 isRemoteMachine = false;
1362 raisedOnExited = false;
1365 //Call close on streams if the user never saw them.
1366 //A stream in the undefined mode was never fetched by the user.
1367 //A stream in the async mode is wrapped on a AsyncStreamReader and we should dispose that instead.
1368 // no way for users to get a hand on a AsyncStreamReader.
1369 var tmpIn = standardInput;
1370 standardInput = null;
1371 if (inputStreamReadMode == StreamReadMode.undefined && tmpIn != null)
1374 var tmpOut = standardOutput;
1375 standardOutput = null;
1376 if (outputStreamReadMode == StreamReadMode.undefined && tmpOut != null)
1379 tmpOut = standardError;
1380 standardError = null;
1381 if (errorStreamReadMode == StreamReadMode.undefined && tmpOut != null)
1384 var tmpAsync = output;
1386 if (outputStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
1387 tmpAsync.CancelOperation ();
1393 if (errorStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
1394 tmpAsync.CancelOperation ();
1398 //Don't call close on the Readers and writers
1399 //since they might be referenced by somebody else while the
1400 //process is still alive but this method called.
1401 standardOutput = null;
1402 standardInput = null;
1403 standardError = null;
1415 /// Helper method for checking preconditions when accessing properties.
1418 [ResourceExposure(ResourceScope.None)]
1419 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1420 void EnsureState(State state) {
1423 if ((state & State.IsWin2k) != (State)0) {
1425 if (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)
1426 #endif // !FEATURE_PAL
1427 throw new PlatformNotSupportedException(SR.GetString(SR.Win2kRequired));
1430 if ((state & State.IsNt) != (State)0) {
1432 if (OperatingSystem.Platform != PlatformID.Win32NT)
1433 #endif // !FEATURE_PAL
1434 throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
1438 if ((state & State.Associated) != (State)0)
1440 throw new InvalidOperationException(SR.GetString(SR.NoAssociatedProcess));
1442 if ((state & State.HaveId) != (State)0) {
1443 if (!haveProcessId) {
1444 #if !FEATURE_PAL && !MONO
1445 if (haveProcessHandle) {
1446 SetProcessId(ProcessManager.GetProcessIdFromHandle(m_processHandle));
1449 EnsureState(State.Associated);
1450 throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1453 EnsureState(State.Associated);
1454 throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1455 #endif // !FEATURE_PAL && !MONO
1459 if ((state & State.IsLocal) != (State)0 && isRemoteMachine) {
1460 throw new NotSupportedException(SR.GetString(SR.NotSupportedRemote));
1463 if ((state & State.HaveProcessInfo) != (State)0) {
1464 #if !FEATURE_PAL && !MONO
1465 if (processInfo == null) {
1466 if ((state & State.HaveId) == (State)0) EnsureState(State.HaveId);
1467 ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1468 for (int i = 0; i < processInfos.Length; i++) {
1469 if (processInfos[i].processId == processId) {
1470 this.processInfo = processInfos[i];
1474 if (processInfo == null) {
1475 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1479 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1480 #endif // !FEATURE_PAL && !MONO
1483 if ((state & State.Exited) != (State)0) {
1485 throw new InvalidOperationException(SR.GetString(SR.WaitTillExit));
1488 if (!haveProcessHandle) {
1489 throw new InvalidOperationException(SR.GetString(SR.NoProcessHandle));
1495 /// Make sure we are watching for a process exit.
1498 void EnsureWatchingForExit() {
1499 if (!watchingForExit) {
1501 if (!watchingForExit) {
1502 Debug.Assert(haveProcessHandle, "Process.EnsureWatchingForExit called with no process handle");
1503 Debug.Assert(Associated, "Process.EnsureWatchingForExit called with no associated process");
1504 watchingForExit = true;
1506 this.waitHandle = new ProcessWaitHandle(m_processHandle);
1507 this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(this.waitHandle,
1508 new WaitOrTimerCallback(this.CompletionCallback), null, -1, true);
1511 watchingForExit = false;
1522 /// Make sure we have obtained the min and max working set limits.
1525 void EnsureWorkingSetLimits() {
1526 EnsureState(State.IsNt);
1527 if (!haveWorkingSetLimits) {
1528 SafeProcessHandle handle = null;
1530 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
1533 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1534 throw new Win32Exception();
1536 minWorkingSet = min;
1537 maxWorkingSet = max;
1538 haveWorkingSetLimits = true;
1541 ReleaseProcessHandle(handle);
1546 public static void EnterDebugMode() {
1548 if (ProcessManager.IsNt) {
1549 SetPrivilege("SeDebugPrivilege", NativeMethods.SE_PRIVILEGE_ENABLED);
1555 [ResourceExposure(ResourceScope.None)]
1556 [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
1557 private static void SetPrivilege(string privilegeName, int attrib) {
1558 IntPtr hToken = (IntPtr)0;
1559 NativeMethods.LUID debugValue = new NativeMethods.LUID();
1561 // this is only a "pseudo handle" to the current process - no need to close it later
1562 IntPtr processHandle = NativeMethods.GetCurrentProcess();
1564 // get the process token so we can adjust the privilege on it. We DO need to
1565 // close the token when we're done with it.
1566 if (!NativeMethods.OpenProcessToken(new HandleRef(null, processHandle), NativeMethods.TOKEN_ADJUST_PRIVILEGES, out hToken)) {
1567 throw new Win32Exception();
1571 if (!NativeMethods.LookupPrivilegeValue(null, privilegeName, out debugValue)) {
1572 throw new Win32Exception();
1575 NativeMethods.TokenPrivileges tkp = new NativeMethods.TokenPrivileges();
1576 tkp.Luid = debugValue;
1577 tkp.Attributes = attrib;
1579 NativeMethods.AdjustTokenPrivileges(new HandleRef(null, hToken), false, tkp, 0, IntPtr.Zero, IntPtr.Zero);
1581 // AdjustTokenPrivileges can return true even if it failed to
1582 // set the privilege, so we need to use GetLastError
1583 if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_SUCCESS) {
1584 throw new Win32Exception();
1588 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(processToken)");
1589 SafeNativeMethods.CloseHandle(hToken);
1595 /// <para>[To be supplied.]</para>
1597 public static void LeaveDebugMode() {
1599 if (ProcessManager.IsNt) {
1600 SetPrivilege("SeDebugPrivilege", 0);
1608 /// Returns a new <see cref='System.Diagnostics.Process'/> component given a process identifier and
1609 /// the name of a computer in the network.
1612 [ResourceExposure(ResourceScope.Machine)]
1613 [ResourceConsumption(ResourceScope.Machine)]
1614 public static Process GetProcessById(int processId, string machineName) {
1615 if (!ProcessManager.IsProcessRunning(processId, machineName)) {
1616 throw new ArgumentException(SR.GetString(SR.MissingProccess, processId.ToString(CultureInfo.CurrentCulture)));
1619 return new Process(machineName, ProcessManager.IsRemoteMachine(machineName), processId, null);
1625 /// Returns a new <see cref='System.Diagnostics.Process'/> component given the
1626 /// identifier of a process on the local computer.
1629 [ResourceExposure(ResourceScope.Machine)]
1630 [ResourceConsumption(ResourceScope.Machine)]
1631 public static Process GetProcessById(int processId) {
1632 return GetProcessById(processId, ".");
1637 /// Creates an array of <see cref='System.Diagnostics.Process'/> components that are
1639 /// with process resources on the
1640 /// local computer. These process resources share the specified process name.
1643 [ResourceExposure(ResourceScope.Machine)]
1644 [ResourceConsumption(ResourceScope.Machine)]
1645 public static Process[] GetProcessesByName(string processName) {
1646 return GetProcessesByName(processName, ".");
1652 /// Creates an array of <see cref='System.Diagnostics.Process'/> components that are associated with process resources on a
1653 /// remote computer. These process resources share the specified process name.
1656 [ResourceExposure(ResourceScope.Machine)]
1657 [ResourceConsumption(ResourceScope.Machine)]
1658 public static Process[] GetProcessesByName(string processName, string machineName) {
1659 if (processName == null) processName = String.Empty;
1660 Process[] procs = GetProcesses(machineName);
1661 ArrayList list = new ArrayList();
1663 for(int i = 0; i < procs.Length; i++) {
1664 if( String.Equals(processName, procs[i].ProcessName, StringComparison.OrdinalIgnoreCase)) {
1665 list.Add( procs[i]);
1671 Process[] temp = new Process[list.Count];
1672 list.CopyTo(temp, 0);
1679 /// Creates a new <see cref='System.Diagnostics.Process'/>
1680 /// component for each process resource on the local computer.
1683 [ResourceExposure(ResourceScope.Machine)]
1684 [ResourceConsumption(ResourceScope.Machine)]
1685 public static Process[] GetProcesses() {
1686 return GetProcesses(".");
1692 /// Creates a new <see cref='System.Diagnostics.Process'/>
1693 /// component for each
1694 /// process resource on the specified computer.
1697 [ResourceExposure(ResourceScope.Machine)]
1698 [ResourceConsumption(ResourceScope.Machine)]
1699 public static Process[] GetProcesses(string machineName) {
1700 bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName);
1701 ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1702 Process[] processes = new Process[processInfos.Length];
1703 for (int i = 0; i < processInfos.Length; i++) {
1704 ProcessInfo processInfo = processInfos[i];
1705 processes[i] = new Process(machineName, isRemoteMachine, processInfo.processId, processInfo);
1707 Debug.WriteLineIf(processTracing.TraceVerbose, "Process.GetProcesses(" + machineName + ")");
1709 if (processTracing.TraceVerbose) {
1711 for (int i = 0; i < processInfos.Length; i++) {
1712 Debug.WriteLine(processes[i].Id + ": " + processes[i].ProcessName);
1721 #endif // !FEATURE_PAL
1725 /// Returns a new <see cref='System.Diagnostics.Process'/>
1726 /// component and associates it with the current active process.
1729 [ResourceExposure(ResourceScope.Process)]
1730 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Process)]
1731 public static Process GetCurrentProcess() {
1732 return new Process(".", false, NativeMethods.GetCurrentProcessId(), null);
1737 /// Raises the <see cref='System.Diagnostics.Process.Exited'/> event.
1740 protected void OnExited() {
1741 EventHandler exited = onExited;
1742 if (exited != null) {
1743 if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired)
1744 this.SynchronizingObject.BeginInvoke(exited, new object[]{this, EventArgs.Empty});
1746 exited(this, EventArgs.Empty);
1751 /// Gets a short-term handle to the process, with the given access.
1752 /// If a handle is stored in current process object, then use it.
1753 /// Note that the handle we stored in current process object will have all access we need.
1756 [ResourceExposure(ResourceScope.None)]
1757 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1758 SafeProcessHandle GetProcessHandle(int access, bool throwIfExited) {
1759 Debug.WriteLineIf(processTracing.TraceVerbose, "GetProcessHandle(access = 0x" + access.ToString("X8", CultureInfo.InvariantCulture) + ", throwIfExited = " + throwIfExited + ")");
1761 if (processTracing.TraceVerbose) {
1762 StackFrame calledFrom = new StackTrace(true).GetFrame(0);
1763 Debug.WriteLine(" called from " + calledFrom.GetFileName() + ", line " + calledFrom.GetFileLineNumber());
1766 if (haveProcessHandle) {
1767 if (throwIfExited) {
1768 // Since haveProcessHandle is true, we know we have the process handle
1769 // open with at least SYNCHRONIZE access, so we can wait on it with
1770 // zero timeout to see if the process has exited.
1771 ProcessWaitHandle waitHandle = null;
1773 waitHandle = new ProcessWaitHandle(m_processHandle);
1774 if (waitHandle.WaitOne(0, false)) {
1776 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1778 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
1782 if( waitHandle != null) {
1787 return m_processHandle;
1790 EnsureState(State.HaveId | State.IsLocal);
1791 SafeProcessHandle handle = SafeProcessHandle.InvalidHandle;
1792 #if !FEATURE_PAL && !MONO
1793 handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
1795 IntPtr pseudohandle = NativeMethods.GetCurrentProcess();
1796 // Get a real handle
1797 if (!NativeMethods.DuplicateHandle (new HandleRef(this, pseudohandle),
1798 new HandleRef(this, pseudohandle),
1799 new HandleRef(this, pseudohandle),
1803 NativeMethods.DUPLICATE_SAME_ACCESS |
1804 NativeMethods.DUPLICATE_CLOSE_SOURCE)) {
1805 throw new Win32Exception();
1807 #endif // !FEATURE_PAL && !MONO
1808 if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) {
1809 if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
1810 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1819 /// Gets a short-term handle to the process, with the given access. If a handle exists,
1820 /// then it is reused. If the process has exited, it throws an exception.
1823 SafeProcessHandle GetProcessHandle(int access) {
1824 return GetProcessHandle(access, true);
1828 /// Opens a long-term handle to the process, with all access. If a handle exists,
1829 /// then it is reused. If the process has exited, it throws an exception.
1832 SafeProcessHandle OpenProcessHandle() {
1833 return OpenProcessHandle(NativeMethods.PROCESS_ALL_ACCESS);
1836 SafeProcessHandle OpenProcessHandle(Int32 access) {
1837 if (!haveProcessHandle) {
1838 //Cannot open a new process handle if the object has been disposed, since finalization has been suppressed.
1839 if (this.disposed) {
1840 throw new ObjectDisposedException(GetType().Name);
1843 SetProcessHandle(GetProcessHandle(access));
1845 return m_processHandle;
1850 /// Raise the Exited event, but make sure we don't do it more than once.
1853 void RaiseOnExited() {
1854 if (!raisedOnExited) {
1856 if (!raisedOnExited) {
1857 raisedOnExited = true;
1867 /// Discards any information about the associated process
1868 /// that has been cached inside the process component. After <see cref='System.Diagnostics.Process.Refresh'/> is called, the
1869 /// first request for information for each property causes the process component
1870 /// to obtain a new value from the associated process.
1873 public void Refresh() {
1880 #endif // !FEATURE_PAL
1882 mainWindowTitle = null;
1887 haveMainWindow = false;
1889 haveWorkingSetLimits = false;
1891 haveProcessorAffinity = false;
1893 havePriorityClass = false;
1894 haveExitTime = false;
1896 haveResponding = false;
1897 havePriorityBoostEnabled = false;
1902 /// Helper to associate a process handle with this component.
1905 void SetProcessHandle(SafeProcessHandle processHandle) {
1906 this.m_processHandle = processHandle;
1907 this.haveProcessHandle = true;
1909 EnsureWatchingForExit();
1914 /// Helper to associate a process id with this component.
1917 [ResourceExposure(ResourceScope.Machine)]
1918 void SetProcessId(int processId) {
1919 this.processId = processId;
1920 this.haveProcessId = true;
1926 /// Helper to set minimum or maximum working set limits.
1929 [ResourceExposure(ResourceScope.Process)]
1930 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1931 void SetWorkingSetLimits(object newMin, object newMax) {
1932 EnsureState(State.IsNt);
1934 SafeProcessHandle handle = null;
1936 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_SET_QUOTA);
1939 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1940 throw new Win32Exception();
1943 if (newMin != null) {
1944 min = (IntPtr)newMin;
1947 if (newMax != null) {
1948 max = (IntPtr)newMax;
1951 if ((long)min > (long)max) {
1952 if (newMin != null) {
1953 throw new ArgumentException(SR.GetString(SR.BadMinWorkset));
1956 throw new ArgumentException(SR.GetString(SR.BadMaxWorkset));
1960 if (!NativeMethods.SetProcessWorkingSetSize(handle, min, max)) {
1961 throw new Win32Exception();
1964 // The value may be rounded/changed by the OS, so go get it
1965 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1966 throw new Win32Exception();
1968 minWorkingSet = min;
1969 maxWorkingSet = max;
1970 haveWorkingSetLimits = true;
1973 ReleaseProcessHandle(handle);
1977 #endif // !FEATURE_PAL
1979 #if MONO_FEATURE_PROCESS_START
1983 /// Starts a process specified by the <see cref='System.Diagnostics.Process.StartInfo'/> property of this <see cref='System.Diagnostics.Process'/>
1984 /// component and associates it with the
1985 /// <see cref='System.Diagnostics.Process'/> . If a process resource is reused
1986 /// rather than started, the reused process is associated with this <see cref='System.Diagnostics.Process'/>
1990 [ResourceExposure(ResourceScope.None)]
1991 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1992 public bool Start() {
1994 ProcessStartInfo startInfo = StartInfo;
1995 if (startInfo.FileName.Length == 0)
1996 throw new InvalidOperationException(SR.GetString(SR.FileNameMissing));
1998 if (startInfo.UseShellExecute) {
2000 return StartWithShellExecuteEx(startInfo);
2002 throw new InvalidOperationException(SR.GetString(SR.net_perm_invalid_val, "StartInfo.UseShellExecute", true));
2003 #endif // !FEATURE_PAL
2005 return StartWithCreateProcess(startInfo);
2010 [ResourceExposure(ResourceScope.Process)]
2011 [ResourceConsumption(ResourceScope.Process)]
2012 private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) {
2013 bool ret = NativeMethods.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize);
2014 if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid) {
2015 throw new Win32Exception();
2019 // Using synchronous Anonymous pipes for process input/output redirection means we would end up
2020 // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
2021 // it will take advantage of the NT IO completion port infrastructure. But we can't really use
2022 // Overlapped I/O for process input/output as it would break Console apps (managed Console class
2023 // methods such as WriteLine as well as native CRT functions like printf) which are making an
2024 // assumption that the console standard handles (obtained via GetStdHandle()) are opened
2025 // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously!
2026 [ResourceExposure(ResourceScope.None)]
2027 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2028 private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) {
2029 NativeMethods.SECURITY_ATTRIBUTES securityAttributesParent = new NativeMethods.SECURITY_ATTRIBUTES();
2030 securityAttributesParent.bInheritHandle = true;
2032 SafeFileHandle hTmp = null;
2035 CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);
2038 CreatePipeWithSecurityAttributes(out hTmp,
2040 securityAttributesParent,
2043 // Duplicate the parent handle to be non-inheritable so that the child process
2044 // doesn't have access. This is done for correctness sake, exact reason is unclear.
2045 // One potential theory is that child process can do something brain dead like
2046 // closing the parent end of the pipe and there by getting into a blocking situation
2047 // as parent will not be draining the pipe at the other end anymore.
2048 if (!NativeMethods.DuplicateHandle(new HandleRef(this, NativeMethods.GetCurrentProcess()),
2050 new HandleRef(this, NativeMethods.GetCurrentProcess()),
2054 NativeMethods.DUPLICATE_SAME_ACCESS)) {
2055 throw new Win32Exception();
2059 if( hTmp != null && !hTmp.IsInvalid) {
2065 private static StringBuilder BuildCommandLine(string executableFileName, string arguments) {
2066 // Construct a StringBuilder with the appropriate command line
2067 // to pass to CreateProcess. If the filename isn't already
2068 // in quotes, we quote it here. This prevents some security
2069 // problems (it specifies exactly which part of the string
2070 // is the file to execute).
2071 StringBuilder commandLine = new StringBuilder();
2072 string fileName = executableFileName.Trim();
2073 bool fileNameIsQuoted = (fileName.StartsWith("\"", StringComparison.Ordinal) && fileName.EndsWith("\"", StringComparison.Ordinal));
2074 if (!fileNameIsQuoted) {
2075 commandLine.Append("\"");
2078 commandLine.Append(fileName);
2080 if (!fileNameIsQuoted) {
2081 commandLine.Append("\"");
2084 if (!String.IsNullOrEmpty(arguments)) {
2085 commandLine.Append(" ");
2086 commandLine.Append(arguments);
2092 [ResourceExposure(ResourceScope.Machine)]
2093 [ResourceConsumption(ResourceScope.Machine)]
2094 private bool StartWithCreateProcess(ProcessStartInfo startInfo) {
2095 if( startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) {
2096 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2099 if( startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) {
2100 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2103 // See knowledge base article Q190351 for an explanation of the following code. Noteworthy tricky points:
2104 // * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
2105 // that the child process can not close them
2106 // * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
2107 // GetStdHandle for the handles that are not being redirected
2109 //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
2110 if (this.disposed) {
2111 throw new ObjectDisposedException(GetType().Name);
2114 StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
2116 NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO();
2117 SafeNativeMethods.PROCESS_INFORMATION processInfo = new SafeNativeMethods.PROCESS_INFORMATION();
2118 SafeProcessHandle procSH = new SafeProcessHandle();
2119 SafeThreadHandle threadSH = new SafeThreadHandle();
2122 // handles used in parent process
2123 SafeFileHandle standardInputWritePipeHandle = null;
2124 SafeFileHandle standardOutputReadPipeHandle = null;
2125 SafeFileHandle standardErrorReadPipeHandle = null;
2126 GCHandle environmentHandle = new GCHandle();
2127 lock (s_CreateProcessLock) {
2129 // set up the streams
2130 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2131 if (startInfo.RedirectStandardInput) {
2132 CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
2134 startupInfo.hStdInput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);
2137 if (startInfo.RedirectStandardOutput) {
2138 CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false);
2140 startupInfo.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_OUTPUT_HANDLE), false);
2143 if (startInfo.RedirectStandardError) {
2144 CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false);
2146 startupInfo.hStdError = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_ERROR_HANDLE), false);
2149 startupInfo.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
2152 // set up the creation flags paramater
2153 int creationFlags = 0;
2155 if (startInfo.CreateNoWindow) creationFlags |= NativeMethods.CREATE_NO_WINDOW;
2156 #endif // !FEATURE_PAL
2158 // set up the environment block parameter
2159 IntPtr environmentPtr = (IntPtr)0;
2160 if (startInfo.environmentVariables != null) {
2161 bool unicode = false;
2163 if (ProcessManager.IsNt) {
2164 creationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
2167 #endif // !FEATURE_PAL
2169 byte[] environmentBytes = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode);
2170 environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
2171 environmentPtr = environmentHandle.AddrOfPinnedObject();
2174 string workingDirectory = startInfo.WorkingDirectory;
2175 if (workingDirectory == string.Empty)
2176 workingDirectory = Environment.CurrentDirectory;
2179 if (startInfo.UserName.Length != 0) {
2180 if (startInfo.Password != null && startInfo.PasswordInClearText != null)
2181 throw new ArgumentException(SR.GetString(SR.CantSetDuplicatePassword));
2183 NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0;
2184 if( startInfo.LoadUserProfile) {
2185 logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
2188 IntPtr password = IntPtr.Zero;
2190 if( startInfo.Password != null) {
2191 password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
2192 } else if( startInfo.PasswordInClearText != null) {
2193 password = Marshal.StringToCoTaskMemUni(startInfo.PasswordInClearText);
2195 password = Marshal.StringToCoTaskMemUni(String.Empty);
2198 RuntimeHelpers.PrepareConstrainedRegions();
2200 retVal = NativeMethods.CreateProcessWithLogonW(
2205 null, // we don't need this since all the info is in commandLine
2210 startupInfo, // pointer to STARTUPINFO
2211 processInfo // pointer to PROCESS_INFORMATION
2214 errorCode = Marshal.GetLastWin32Error();
2215 if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2216 procSH.InitialSetHandle(processInfo.hProcess);
2217 if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2218 threadSH.InitialSetHandle(processInfo.hThread);
2221 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2222 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2225 throw new Win32Exception(errorCode);
2228 if( password != IntPtr.Zero) {
2229 Marshal.ZeroFreeCoTaskMemUnicode(password);
2233 #endif // !FEATURE_PAL
2234 RuntimeHelpers.PrepareConstrainedRegions();
2236 retVal = NativeMethods.CreateProcess (
2237 null, // we don't need this since all the info is in commandLine
2238 commandLine, // pointer to the command line string
2239 null, // pointer to process security attributes, we don't need to inheriat the handle
2240 null, // pointer to thread security attributes
2241 true, // handle inheritance flag
2242 creationFlags, // creation flags
2243 environmentPtr, // pointer to new environment block
2244 workingDirectory, // pointer to current directory name
2245 startupInfo, // pointer to STARTUPINFO
2246 processInfo // pointer to PROCESS_INFORMATION
2249 errorCode = Marshal.GetLastWin32Error();
2250 if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2251 procSH.InitialSetHandle(processInfo.hProcess);
2252 if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2253 threadSH.InitialSetHandle(processInfo.hThread);
2256 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2257 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2259 throw new Win32Exception(errorCode);
2265 // free environment block
2266 if (environmentHandle.IsAllocated) {
2267 environmentHandle.Free();
2270 startupInfo.Dispose();
2274 if (startInfo.RedirectStandardInput) {
2275 standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096);
2276 standardInput.AutoFlush = true;
2278 if (startInfo.RedirectStandardOutput) {
2279 Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
2280 standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2282 if (startInfo.RedirectStandardError) {
2283 Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
2284 standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2288 if (!procSH.IsInvalid) {
2289 SetProcessHandle(procSH);
2290 SetProcessId(processInfo.dwProcessId);
2303 [ResourceExposure(ResourceScope.Machine)]
2304 [ResourceConsumption(ResourceScope.Machine)]
2305 private bool StartWithShellExecuteEx(ProcessStartInfo startInfo) {
2306 //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
2308 throw new ObjectDisposedException(GetType().Name);
2310 if( !String.IsNullOrEmpty(startInfo.UserName) || (startInfo.Password != null) ) {
2311 throw new InvalidOperationException(SR.GetString(SR.CantStartAsUser));
2314 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2315 throw new InvalidOperationException(SR.GetString(SR.CantRedirectStreams));
2318 if (startInfo.StandardErrorEncoding != null) {
2319 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2322 if (startInfo.StandardOutputEncoding != null) {
2323 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2326 // can't set env vars with ShellExecuteEx...
2327 if (startInfo.environmentVariables != null) {
2328 throw new InvalidOperationException(SR.GetString(SR.CantUseEnvVars));
2331 NativeMethods.ShellExecuteInfo shellExecuteInfo = new NativeMethods.ShellExecuteInfo();
2332 shellExecuteInfo.fMask = NativeMethods.SEE_MASK_NOCLOSEPROCESS;
2333 if (startInfo.ErrorDialog) {
2334 shellExecuteInfo.hwnd = startInfo.ErrorDialogParentHandle;
2337 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_NO_UI;
2340 switch (startInfo.WindowStyle) {
2341 case ProcessWindowStyle.Hidden:
2342 shellExecuteInfo.nShow = NativeMethods.SW_HIDE;
2344 case ProcessWindowStyle.Minimized:
2345 shellExecuteInfo.nShow = NativeMethods.SW_SHOWMINIMIZED;
2347 case ProcessWindowStyle.Maximized:
2348 shellExecuteInfo.nShow = NativeMethods.SW_SHOWMAXIMIZED;
2351 shellExecuteInfo.nShow = NativeMethods.SW_SHOWNORMAL;
2357 if (startInfo.FileName.Length != 0)
2358 shellExecuteInfo.lpFile = Marshal.StringToHGlobalAuto(startInfo.FileName);
2359 if (startInfo.Verb.Length != 0)
2360 shellExecuteInfo.lpVerb = Marshal.StringToHGlobalAuto(startInfo.Verb);
2361 if (startInfo.Arguments.Length != 0)
2362 shellExecuteInfo.lpParameters = Marshal.StringToHGlobalAuto(startInfo.Arguments);
2363 if (startInfo.WorkingDirectory.Length != 0)
2364 shellExecuteInfo.lpDirectory = Marshal.StringToHGlobalAuto(startInfo.WorkingDirectory);
2366 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_DDEWAIT;
2368 ShellExecuteHelper executeHelper = new ShellExecuteHelper(shellExecuteInfo);
2369 if (!executeHelper.ShellExecuteOnSTAThread()) {
2370 int error = executeHelper.ErrorCode;
2372 switch ((long)shellExecuteInfo.hInstApp) {
2373 case NativeMethods.SE_ERR_FNF: error = NativeMethods.ERROR_FILE_NOT_FOUND; break;
2374 case NativeMethods.SE_ERR_PNF: error = NativeMethods.ERROR_PATH_NOT_FOUND; break;
2375 case NativeMethods.SE_ERR_ACCESSDENIED: error = NativeMethods.ERROR_ACCESS_DENIED; break;
2376 case NativeMethods.SE_ERR_OOM: error = NativeMethods.ERROR_NOT_ENOUGH_MEMORY; break;
2377 case NativeMethods.SE_ERR_DDEFAIL:
2378 case NativeMethods.SE_ERR_DDEBUSY:
2379 case NativeMethods.SE_ERR_DDETIMEOUT: error = NativeMethods.ERROR_DDE_FAIL; break;
2380 case NativeMethods.SE_ERR_SHARE: error = NativeMethods.ERROR_SHARING_VIOLATION; break;
2381 case NativeMethods.SE_ERR_NOASSOC: error = NativeMethods.ERROR_NO_ASSOCIATION; break;
2382 case NativeMethods.SE_ERR_DLLNOTFOUND: error = NativeMethods.ERROR_DLL_NOT_FOUND; break;
2383 default: error = (int)shellExecuteInfo.hInstApp; break;
2386 if( error == NativeMethods.ERROR_BAD_EXE_FORMAT || error == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2387 throw new Win32Exception(error, SR.GetString(SR.InvalidApplication));
2389 throw new Win32Exception(error);
2394 if (shellExecuteInfo.lpFile != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpFile);
2395 if (shellExecuteInfo.lpVerb != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpVerb);
2396 if (shellExecuteInfo.lpParameters != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpParameters);
2397 if (shellExecuteInfo.lpDirectory != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpDirectory);
2400 if (shellExecuteInfo.hProcess != (IntPtr)0) {
2401 SafeProcessHandle handle = new SafeProcessHandle(shellExecuteInfo.hProcess);
2402 SetProcessHandle(handle);
2410 [ResourceExposure(ResourceScope.Machine)]
2411 [ResourceConsumption(ResourceScope.Machine)]
2412 public static Process Start( string fileName, string userName, SecureString password, string domain ) {
2413 ProcessStartInfo startInfo = new ProcessStartInfo(fileName);
2414 startInfo.UserName = userName;
2415 startInfo.Password = password;
2416 startInfo.Domain = domain;
2417 startInfo.UseShellExecute = false;
2418 return Start(startInfo);
2421 [ResourceExposure(ResourceScope.Machine)]
2422 [ResourceConsumption(ResourceScope.Machine)]
2423 public static Process Start( string fileName, string arguments, string userName, SecureString password, string domain ) {
2424 ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
2425 startInfo.UserName = userName;
2426 startInfo.Password = password;
2427 startInfo.Domain = domain;
2428 startInfo.UseShellExecute = false;
2429 return Start(startInfo);
2433 #endif // !FEATURE_PAL
2437 /// Starts a process resource by specifying the name of a
2438 /// document or application file. Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2442 [ResourceExposure(ResourceScope.Machine)]
2443 [ResourceConsumption(ResourceScope.Machine)]
2444 public static Process Start(string fileName) {
2445 return Start(new ProcessStartInfo(fileName));
2450 /// Starts a process resource by specifying the name of an
2451 /// application and a set of command line arguments. Associates the process resource
2452 /// with a new <see cref='System.Diagnostics.Process'/>
2456 [ResourceExposure(ResourceScope.Machine)]
2457 [ResourceConsumption(ResourceScope.Machine)]
2458 public static Process Start(string fileName, string arguments) {
2459 return Start(new ProcessStartInfo(fileName, arguments));
2464 /// Starts a process resource specified by the process start
2465 /// information passed in, for example the file name of the process to start.
2466 /// Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2470 [ResourceExposure(ResourceScope.Machine)]
2471 [ResourceConsumption(ResourceScope.Machine)]
2472 public static Process Start(ProcessStartInfo startInfo) {
2473 Process process = new Process();
2474 if (startInfo == null) throw new ArgumentNullException("startInfo");
2475 process.StartInfo = startInfo;
2476 if (process.Start()) {
2482 #endif // MONO_FEATURE_PROCESS_START
2487 /// associated process immediately.
2490 [ResourceExposure(ResourceScope.Machine)]
2491 [ResourceConsumption(ResourceScope.Machine)]
2492 public void Kill() {
2493 SafeProcessHandle handle = null;
2495 handle = GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
2496 if (!NativeMethods.TerminateProcess(handle, -1))
2497 throw new Win32Exception();
2500 ReleaseProcessHandle(handle);
2505 /// Make sure we are not watching for process exit.
2508 void StopWatchingForExit() {
2509 if (watchingForExit) {
2511 if (watchingForExit) {
2512 watchingForExit = false;
2513 registeredWaitHandle.Unregister(null);
2516 registeredWaitHandle = null;
2522 public override string ToString() {
2525 string processName = String.Empty;
2527 // On windows 9x, we can't map a handle to an id.
2528 // So ProcessName will throw. We shouldn't throw in Process.ToString though.
2529 // Process.GetProcesses should be used to get all the processes on the machine.
2530 // The processes returned from it will have a nice name.
2533 processName = this.ProcessName;
2535 catch(PlatformNotSupportedException) {
2537 if( processName.Length != 0) {
2538 return String.Format(CultureInfo.CurrentCulture, "{0} ({1})", base.ToString(), processName);
2540 return base.ToString();
2543 #endif // !FEATURE_PAL
2544 return base.ToString();
2549 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait the specified number of milliseconds for the associated process to exit.
2552 public bool WaitForExit(int milliseconds) {
2553 SafeProcessHandle handle = null;
2555 ProcessWaitHandle processWaitHandle = null;
2557 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE, false);
2558 if (handle.IsInvalid) {
2562 processWaitHandle = new ProcessWaitHandle(handle);
2563 if( processWaitHandle.WaitOne(milliseconds, false)) {
2574 if( processWaitHandle != null) {
2575 processWaitHandle.Close();
2578 // If we have a hard timeout, we cannot wait for the streams
2579 if( output != null && milliseconds == -1) {
2580 output.WaitUtilEOF();
2583 if( error != null && milliseconds == -1) {
2584 error.WaitUtilEOF();
2587 ReleaseProcessHandle(handle);
2591 if (exited && watchForExit) {
2600 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2601 /// indefinitely for the associated process to exit.
2604 public void WaitForExit() {
2612 /// Causes the <see cref='System.Diagnostics.Process'/> component to wait the
2613 /// specified number of milliseconds for the associated process to enter an
2615 /// This is only applicable for processes with a user interface,
2616 /// therefore a message loop.
2619 public bool WaitForInputIdle(int milliseconds) {
2620 SafeProcessHandle handle = null;
2623 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE | NativeMethods.PROCESS_QUERY_INFORMATION);
2624 int ret = NativeMethods.WaitForInputIdle(handle, milliseconds);
2626 case NativeMethods.WAIT_OBJECT_0:
2629 case NativeMethods.WAIT_TIMEOUT:
2632 case NativeMethods.WAIT_FAILED:
2634 throw new InvalidOperationException(SR.GetString(SR.InputIdleUnkownError));
2638 ReleaseProcessHandle(handle);
2645 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2646 /// indefinitely for the associated process to enter an idle state. This
2647 /// is only applicable for processes with a user interface, therefore a message loop.
2650 public bool WaitForInputIdle() {
2651 return WaitForInputIdle(Int32.MaxValue);
2654 #endif // !FEATURE_PAL
2656 #if MONO_FEATURE_PROCESS_START
2657 // Support for working asynchronously with streams
2660 /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2661 /// reading the StandardOutput stream asynchronously. The user can register a callback
2662 /// that will be called when a line of data terminated by \n,\r or \r\n is reached, or the end of stream is reached
2663 /// then the remaining information is returned. The user can add an event handler to OutputDataReceived.
2666 [System.Runtime.InteropServices.ComVisible(false)]
2667 public void BeginOutputReadLine() {
2669 if(outputStreamReadMode == StreamReadMode.undefined) {
2670 outputStreamReadMode = StreamReadMode.asyncMode;
2672 else if (outputStreamReadMode != StreamReadMode.asyncMode) {
2673 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
2676 if (pendingOutputRead)
2677 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2679 pendingOutputRead = true;
2680 // We can't detect if there's a pending sychronous read, tream also doesn't.
2681 if (output == null) {
2682 if (standardOutput == null) {
2683 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
2686 Stream s = standardOutput.BaseStream;
2687 output = new AsyncStreamReader(this, s, new UserCallBack(this.OutputReadNotifyUser), standardOutput.CurrentEncoding);
2689 output.BeginReadLine();
2695 /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2696 /// reading the StandardError stream asynchronously. The user can register a callback
2697 /// that will be called when a line of data terminated by \n,\r or \r\n is reached, or the end of stream is reached
2698 /// then the remaining information is returned. The user can add an event handler to ErrorDataReceived.
2701 [System.Runtime.InteropServices.ComVisible(false)]
2702 public void BeginErrorReadLine() {
2704 if(errorStreamReadMode == StreamReadMode.undefined) {
2705 errorStreamReadMode = StreamReadMode.asyncMode;
2707 else if (errorStreamReadMode != StreamReadMode.asyncMode) {
2708 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
2711 if (pendingErrorRead) {
2712 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2715 pendingErrorRead = true;
2716 // We can't detect if there's a pending sychronous read, stream also doesn't.
2717 if (error == null) {
2718 if (standardError == null) {
2719 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
2722 Stream s = standardError.BaseStream;
2723 error = new AsyncStreamReader(this, s, new UserCallBack(this.ErrorReadNotifyUser), standardError.CurrentEncoding);
2725 error.BeginReadLine();
2730 /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2731 /// specified by BeginOutputReadLine().
2734 [System.Runtime.InteropServices.ComVisible(false)]
2735 public void CancelOutputRead() {
2736 if (output != null) {
2737 output.CancelOperation();
2740 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2743 pendingOutputRead = false;
2748 /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2749 /// specified by BeginErrorReadLine().
2752 [System.Runtime.InteropServices.ComVisible(false)]
2753 public void CancelErrorRead() {
2754 if (error != null) {
2755 error.CancelOperation();
2758 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2761 pendingErrorRead = false;
2764 internal void OutputReadNotifyUser(String data) {
2765 // To avoid ---- between remove handler and raising the event
2766 DataReceivedEventHandler outputDataReceived = OutputDataReceived;
2767 if (outputDataReceived != null) {
2768 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2769 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2770 SynchronizingObject.Invoke(outputDataReceived, new object[] {this, e});
2773 outputDataReceived(this,e); // Call back to user informing data is available.
2778 internal void ErrorReadNotifyUser(String data) {
2779 // To avoid ---- between remove handler and raising the event
2780 DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
2781 if (errorDataReceived != null) {
2782 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2783 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2784 SynchronizingObject.Invoke(errorDataReceived, new object[] {this, e});
2787 errorDataReceived(this,e); // Call back to user informing data is available.
2791 #endif // MONO_FEATURE_PROCESS_START
2794 /// A desired internal state.
2801 HaveProcessInfo = 0x8,
2805 HaveNtProcessInfo = HaveProcessInfo | IsNt
2810 /// This data structure contains information about a process that is collected
2811 /// in bulk by querying the operating system. The reason to make this a separate
2812 /// structure from the process component is so that we can throw it away all at once
2813 /// when Refresh is called on the component.
2816 internal class ProcessInfo {
2818 public ArrayList threadInfoList = new ArrayList();
2819 public int basePriority;
2820 public string processName;
2821 public int processId;
2822 public int handleCount;
2823 public long poolPagedBytes;
2824 public long poolNonpagedBytes;
2825 public long virtualBytes;
2826 public long virtualBytesPeak;
2827 public long workingSetPeak;
2828 public long workingSet;
2829 public long pageFileBytesPeak;
2830 public long pageFileBytes;
2831 public long privateBytes;
2832 public int mainModuleId; // used only for win9x - id is only for use with CreateToolHelp32
2833 public int sessionId;
2839 /// This data structure contains information about a thread in a process that
2840 /// is collected in bulk by querying the operating system. The reason to
2841 /// make this a separate structure from the ProcessThread component is so that we
2842 /// can throw it away all at once when Refresh is called on the component.
2845 internal class ThreadInfo {
2846 public int threadId;
2847 public int processId;
2848 public int basePriority;
2849 public int currentPriority;
2850 public IntPtr startAddress;
2851 public ThreadState threadState;
2853 public ThreadWaitReason threadWaitReason;
2854 #endif // !FEATURE_PAL
2858 /// This data structure contains information about a module in a process that
2859 /// is collected in bulk by querying the operating system. The reason to
2860 /// make this a separate structure from the ProcessModule component is so that we
2861 /// can throw it away all at once when Refresh is called on the component.
2864 internal class ModuleInfo {
2865 public string baseName;
2866 public string fileName;
2867 public IntPtr baseOfDll;
2868 public IntPtr entryPoint;
2869 public int sizeOfImage;
2870 public int Id; // used only on win9x - for matching up with ProcessInfo.mainModuleId
2874 internal static class EnvironmentBlock {
2875 public static byte[] ToByteArray(StringDictionary sd, bool unicode) {
2877 string[] keys = new string[sd.Count];
2878 byte[] envBlock = null;
2879 sd.Keys.CopyTo(keys, 0);
2882 string[] values = new string[sd.Count];
2883 sd.Values.CopyTo(values, 0);
2885 // sort both by the keys
2886 // Windows 2000 requires the environment block to be sorted by the key
2887 // It will first converting the case the strings and do ordinal comparison.
2888 Array.Sort(keys, values, OrdinalCaseInsensitiveComparer.Default);
2890 // create a list of null terminated "key=val" strings
2891 StringBuilder stringBuff = new StringBuilder();
2892 for (int i = 0; i < sd.Count; ++ i) {
2893 stringBuff.Append(keys[i]);
2894 stringBuff.Append('=');
2895 stringBuff.Append(values[i]);
2896 stringBuff.Append('\0');
2898 // an extra null at the end indicates end of list.
2899 stringBuff.Append('\0');
2902 envBlock = Encoding.Unicode.GetBytes(stringBuff.ToString());
2905 envBlock = Encoding.Default.GetBytes(stringBuff.ToString());
2907 if (envBlock.Length > UInt16.MaxValue)
2908 throw new InvalidOperationException(SR.GetString(SR.EnvironmentBlockTooLong, envBlock.Length));
2915 internal class OrdinalCaseInsensitiveComparer : IComparer {
2916 internal static readonly OrdinalCaseInsensitiveComparer Default = new OrdinalCaseInsensitiveComparer();
2918 public int Compare(Object a, Object b) {
2919 String sa = a as String;
2920 String sb = b as String;
2921 if (sa != null && sb != null) {
2922 return String.Compare(sa, sb, StringComparison.OrdinalIgnoreCase);
2924 return Comparer.Default.Compare(a,b);
2928 internal class ProcessThreadTimes {
2929 internal long create;
2931 internal long kernel;
2934 public DateTime StartTime {
2936 return DateTime.FromFileTime(create);
2940 public DateTime ExitTime {
2942 return DateTime.FromFileTime(exit);
2946 public TimeSpan PrivilegedProcessorTime {
2948 return new TimeSpan(kernel);
2952 public TimeSpan UserProcessorTime {
2954 return new TimeSpan(user);
2958 public TimeSpan TotalProcessorTime {
2960 return new TimeSpan(user + kernel);
2966 internal class ShellExecuteHelper {
2967 private NativeMethods.ShellExecuteInfo _executeInfo;
2968 private int _errorCode;
2969 private bool _succeeded;
2971 public ShellExecuteHelper(NativeMethods.ShellExecuteInfo executeInfo) {
2972 _executeInfo = executeInfo;
2975 [ResourceExposure(ResourceScope.None)]
2976 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2977 public void ShellExecuteFunction() {
2978 if (!(_succeeded = NativeMethods.ShellExecuteEx(_executeInfo))) {
2979 _errorCode = Marshal.GetLastWin32Error();
2983 public bool ShellExecuteOnSTAThread() {
2985 // SHELL API ShellExecute() requires STA in order to work correctly.
2986 // If current thread is not a STA thread, we need to call ShellExecute on a new thread.
2988 if( Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) {
2989 ThreadStart threadStart = new ThreadStart(this.ShellExecuteFunction);
2990 Thread executionThread = new Thread(threadStart);
2991 executionThread.SetApartmentState(ApartmentState.STA);
2992 executionThread.Start();
2993 executionThread.Join();
2996 ShellExecuteFunction();
3001 public int ErrorCode {