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
70 IntPtr mainWindowHandle; // no need to use SafeHandle for window
71 string mainWindowTitle;
73 bool haveWorkingSetLimits;
77 bool haveProcessorAffinity;
78 IntPtr processorAffinity;
80 bool havePriorityClass;
81 ProcessPriorityClass priorityClass;
83 ProcessStartInfo startInfo;
87 EventHandler onExited;
98 bool priorityBoostEnabled;
99 bool havePriorityBoostEnabled;
102 RegisteredWaitHandle registeredWaitHandle;
103 WaitHandle waitHandle;
104 ISynchronizeInvoke synchronizingObject;
105 StreamReader standardOutput;
106 StreamWriter standardInput;
107 StreamReader standardError;
108 OperatingSystem operatingSystem;
111 static object s_CreateProcessLock = new object();
113 // This enum defines the operation mode for redirected process stream.
114 // We don't support switching between synchronous mode and asynchronous mode.
115 private enum StreamReadMode
122 StreamReadMode outputStreamReadMode;
123 StreamReadMode errorStreamReadMode;
126 StreamReadMode inputStreamReadMode;
129 // Support for asynchrously reading streams
130 [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
131 //[System.Runtime.InteropServices.ComVisible(false)]
132 public event DataReceivedEventHandler OutputDataReceived;
133 [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
134 //[System.Runtime.InteropServices.ComVisible(false)]
135 public event DataReceivedEventHandler ErrorDataReceived;
136 // Abstract the stream details
137 internal AsyncStreamReader output;
138 internal AsyncStreamReader error;
139 internal bool pendingOutputRead;
140 internal bool pendingErrorRead;
143 private static SafeFileHandle InvalidPipeHandle = new SafeFileHandle(IntPtr.Zero, false);
145 internal static TraceSwitch processTracing = new TraceSwitch("processTracing", "Controls debug output from Process component");
147 internal static TraceSwitch processTracing = null;
156 /// Initializes a new instance of the <see cref='System.Diagnostics.Process'/> class.
160 this.machineName = ".";
161 this.outputStreamReadMode = StreamReadMode.undefined;
162 this.errorStreamReadMode = StreamReadMode.undefined;
163 this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
166 [ResourceExposure(ResourceScope.Machine)]
167 Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo) : base() {
168 Debug.Assert(SyntaxCheck.CheckMachineName(machineName), "The machine name should be valid!");
170 this.processInfo = processInfo;
172 this.machineName = machineName;
173 this.isRemoteMachine = isRemoteMachine;
174 this.processId = processId;
175 this.haveProcessId = true;
176 this.outputStreamReadMode = StreamReadMode.undefined;
177 this.errorStreamReadMode = StreamReadMode.undefined;
178 this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
186 /// Returns whether this process component is associated with a real process.
189 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessAssociated)]
192 return haveProcessId || haveProcessHandle;
196 #if !FEATURE_PAL && !MONO
199 /// Gets the base priority of
200 /// the associated process.
203 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessBasePriority)]
204 public int BasePriority {
206 EnsureState(State.HaveProcessInfo);
207 return processInfo.basePriority;
210 #endif // !FEATURE_PAL && !MONO
216 /// value that was specified by the associated process when it was terminated.
219 [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitCode)]
220 public int ExitCode {
222 EnsureState(State.Exited);
225 throw new InvalidOperationException ("Cannot get the exit code from a non-child process on Unix");
234 /// value indicating whether the associated process has been terminated.
237 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTerminated)]
238 public bool HasExited {
241 EnsureState(State.Associated);
242 SafeProcessHandle handle = null;
244 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.SYNCHRONIZE, false);
245 if (handle.IsInvalid) {
251 // Although this is the wrong way to check whether the process has exited,
252 // it was historically the way we checked for it, and a lot of code then took a dependency on
253 // the fact that this would always be set before the pipes were closed, so they would read
254 // the exit code out after calling ReadToEnd() or standard output or standard error. In order
255 // to allow 259 to function as a valid exit code and to break as few people as possible that
256 // took the ReadToEnd dependency, we check for an exit code before doing the more correct
257 // check to see if we have been signalled.
258 if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
260 this.exitCode = exitCode;
264 // The best check for exit is that the kernel process object handle is invalid,
265 // or that it is valid and signaled. Checking if the exit code != STILL_ACTIVE
266 // does not guarantee the process is closed,
267 // since some process could return an actual STILL_ACTIVE exit code (259).
268 if (!signaled) // if we just came from WaitForExit, don't repeat
270 ProcessWaitHandle wh = null;
273 wh = new ProcessWaitHandle(handle);
274 this.signaled = wh.WaitOne(0, false);
285 /* If it's a non-child process, it's impossible to get its exit code on
286 * Unix. We don't throw here, but GetExitCodeProcess (in the io-layer)
287 * will set exitCode to -1, and we will throw if we try to call ExitCode */
288 if (!NativeMethods.GetExitCodeProcess(handle, out exitCode))
289 throw new Win32Exception();
292 this.exitCode = exitCode;
299 ReleaseProcessHandle(handle);
310 private ProcessThreadTimes GetProcessTimes() {
311 ProcessThreadTimes processTimes = new ProcessThreadTimes();
312 SafeProcessHandle handle = null;
314 int access = NativeMethods.PROCESS_QUERY_INFORMATION;
316 if (EnvironmentHelpers.IsWindowsVistaOrAbove())
317 access = NativeMethods.PROCESS_QUERY_LIMITED_INFORMATION;
319 handle = GetProcessHandle(access, false);
320 if( handle.IsInvalid) {
321 // On OS older than XP, we will not be able to get the handle for a process
322 // after it terminates.
323 // On Windows XP and newer OS, the information about a process will stay longer.
324 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
327 if (!NativeMethods.GetProcessTimes(handle,
328 out processTimes.create,
329 out processTimes.exit,
330 out processTimes.kernel,
331 out processTimes.user)) {
332 throw new Win32Exception();
337 ReleaseProcessHandle(handle);
345 /// Gets the time that the associated process exited.
348 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitTime)]
349 public DateTime ExitTime {
352 EnsureState(State.IsNt | State.Exited);
353 exitTime = GetProcessTimes().ExitTime;
359 #endif // !FEATURE_PAL
363 /// Returns the native handle for the associated process. The handle is only available
364 /// if this component started the process.
367 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandle)]
368 public IntPtr Handle {
369 [ResourceExposure(ResourceScope.Machine)]
370 [ResourceConsumption(ResourceScope.Machine)]
372 EnsureState(State.Associated);
373 return OpenProcessHandle(this.m_processAccess).DangerousGetHandle();
377 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
378 public SafeProcessHandle SafeHandle {
380 EnsureState(State.Associated);
381 return OpenProcessHandle(this.m_processAccess);
385 #if !FEATURE_PAL && !MONO
388 /// Gets the number of handles that are associated
389 /// with the process.
392 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandleCount)]
393 public int HandleCount {
395 EnsureState(State.HaveProcessInfo);
396 return processInfo.handleCount;
399 #endif // !FEATURE_PAL && !MONO
404 /// the unique identifier for the associated process.
407 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessId)]
410 EnsureState(State.HaveId);
418 /// the name of the computer on which the associated process is running.
421 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMachineName)]
422 public string MachineName {
424 EnsureState(State.Associated);
434 /// Returns the window handle of the main window of the associated process.
437 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowHandle)]
438 public IntPtr MainWindowHandle {
439 [ResourceExposure(ResourceScope.Machine)]
440 [ResourceConsumption(ResourceScope.Machine)]
442 if (!haveMainWindow) {
443 EnsureState(State.IsLocal | State.HaveId);
444 mainWindowHandle = ProcessManager.GetMainWindowHandle(processId);
446 if (mainWindowHandle != (IntPtr)0) {
447 haveMainWindow = true;
449 // 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
450 // we always did this check but have now changed it to just require a ProcessId. In the case where someone has called Refresh()
451 // and the process has exited this call will throw an exception where as the above code would return 0 as the handle.
452 EnsureState(State.HaveProcessInfo);
455 return mainWindowHandle;
461 /// Returns the caption of the <see cref='System.Diagnostics.Process.MainWindowHandle'/> of
462 /// the process. If the handle is zero (0), then an empty string is returned.
465 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowTitle)]
466 public string MainWindowTitle {
467 [ResourceExposure(ResourceScope.None)]
468 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
470 if (mainWindowTitle == null) {
471 IntPtr handle = MainWindowHandle;
472 if (handle == (IntPtr)0) {
473 mainWindowTitle = String.Empty;
476 int length = NativeMethods.GetWindowTextLength(new HandleRef(this, handle)) * 2;
477 StringBuilder builder = new StringBuilder(length);
478 NativeMethods.GetWindowText(new HandleRef(this, handle), builder, builder.Capacity);
479 mainWindowTitle = builder.ToString();
482 return mainWindowTitle;
491 /// the main module for the associated process.
494 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainModule)]
495 public ProcessModule MainModule {
496 [ResourceExposure(ResourceScope.Process)]
497 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
499 // We only return null if we couldn't find a main module.
500 // This could be because
501 // 1. The process hasn't finished loading the main module (most likely)
502 // 2. There are no modules loaded (possible for certain OS processes)
503 // 3. Possibly other?
505 if (OperatingSystem.Platform == PlatformID.Win32NT) {
506 EnsureState(State.HaveId | State.IsLocal);
507 // on NT the first module is the main module
508 ModuleInfo module = NtProcessManager.GetFirstModuleInfo(processId);
509 return new ProcessModule(module);
512 ProcessModuleCollection moduleCollection = Modules;
513 // on 9x we have to do a little more work
514 EnsureState(State.HaveProcessInfo);
515 foreach (ProcessModule pm in moduleCollection) {
516 if (pm.moduleInfo.Id == processInfo.mainModuleId) {
528 /// Gets or sets the maximum allowable working set for the associated
532 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMaxWorkingSet)]
533 public IntPtr MaxWorkingSet {
535 EnsureWorkingSetLimits();
536 return maxWorkingSet;
538 [ResourceExposure(ResourceScope.Process)]
539 [ResourceConsumption(ResourceScope.Process)]
541 SetWorkingSetLimits(null, value);
547 /// Gets or sets the minimum allowable working set for the associated
551 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMinWorkingSet)]
552 public IntPtr MinWorkingSet {
554 EnsureWorkingSetLimits();
555 return minWorkingSet;
557 [ResourceExposure(ResourceScope.Process)]
558 [ResourceConsumption(ResourceScope.Process)]
560 SetWorkingSetLimits(value, null);
568 /// the modules that have been loaded by the associated process.
571 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessModules)]
572 public ProcessModuleCollection Modules {
573 [ResourceExposure(ResourceScope.None)]
574 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
576 if (modules == null) {
577 EnsureState(State.HaveId | State.IsLocal);
578 ModuleInfo[] moduleInfos = ProcessManager.GetModuleInfos(processId);
579 ProcessModule[] newModulesArray = new ProcessModule[moduleInfos.Length];
580 for (int i = 0; i < moduleInfos.Length; i++) {
581 newModulesArray[i] = new ProcessModule(moduleInfos[i]);
583 ProcessModuleCollection newModules = new ProcessModuleCollection(newModulesArray);
584 modules = newModules;
591 /// Returns the amount of memory that the system has allocated on behalf of the
592 /// associated process that can not be written to the virtual memory paging file.
594 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
595 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
596 public int NonpagedSystemMemorySize {
598 EnsureState(State.HaveNtProcessInfo);
599 return unchecked((int)processInfo.poolNonpagedBytes);
603 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
604 [System.Runtime.InteropServices.ComVisible(false)]
605 public long NonpagedSystemMemorySize64 {
607 EnsureState(State.HaveNtProcessInfo);
608 return processInfo.poolNonpagedBytes;
613 /// Returns the amount of memory that the associated process has allocated
614 /// that can be written to the virtual memory paging file.
616 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PagedMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
617 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
618 public int PagedMemorySize {
620 EnsureState(State.HaveNtProcessInfo);
621 return unchecked((int)processInfo.pageFileBytes);
625 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
626 [System.Runtime.InteropServices.ComVisible(false)]
627 public long PagedMemorySize64 {
629 EnsureState(State.HaveNtProcessInfo);
630 return processInfo.pageFileBytes;
636 /// Returns the amount of memory that the system has allocated on behalf of the
637 /// associated process that can be written to the virtual memory paging file.
639 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PagedSystemMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
640 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
641 public int PagedSystemMemorySize {
643 EnsureState(State.HaveNtProcessInfo);
644 return unchecked((int)processInfo.poolPagedBytes);
648 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
649 [System.Runtime.InteropServices.ComVisible(false)]
650 public long PagedSystemMemorySize64 {
652 EnsureState(State.HaveNtProcessInfo);
653 return processInfo.poolPagedBytes;
660 /// Returns the maximum amount of memory that the associated process has
661 /// allocated that could be written to the virtual memory paging file.
664 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakPagedMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
665 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
666 public int PeakPagedMemorySize {
668 EnsureState(State.HaveNtProcessInfo);
669 return unchecked((int)processInfo.pageFileBytesPeak);
673 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
674 [System.Runtime.InteropServices.ComVisible(false)]
675 public long PeakPagedMemorySize64 {
677 EnsureState(State.HaveNtProcessInfo);
678 return processInfo.pageFileBytesPeak;
684 /// Returns the maximum amount of physical memory that the associated
685 /// process required at once.
688 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakWorkingSet64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
689 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
690 public int PeakWorkingSet {
692 EnsureState(State.HaveNtProcessInfo);
693 return unchecked((int)processInfo.workingSetPeak);
697 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
698 [System.Runtime.InteropServices.ComVisible(false)]
699 public long PeakWorkingSet64 {
701 EnsureState(State.HaveNtProcessInfo);
702 return processInfo.workingSetPeak;
707 /// Returns the maximum amount of virtual memory that the associated
708 /// process has requested.
710 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakVirtualMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
711 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
712 public int PeakVirtualMemorySize {
714 EnsureState(State.HaveNtProcessInfo);
715 return unchecked((int)processInfo.virtualBytesPeak);
719 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
720 [System.Runtime.InteropServices.ComVisible(false)]
721 public long PeakVirtualMemorySize64 {
723 EnsureState(State.HaveNtProcessInfo);
724 return processInfo.virtualBytesPeak;
729 private OperatingSystem OperatingSystem {
731 if (operatingSystem == null) {
732 operatingSystem = Environment.OSVersion;
734 return operatingSystem;
741 /// Gets or sets a value indicating whether the associated process priority
742 /// should be temporarily boosted by the operating system when the main window
746 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityBoostEnabled)]
747 public bool PriorityBoostEnabled {
749 EnsureState(State.IsNt);
750 if (!havePriorityBoostEnabled) {
751 SafeProcessHandle handle = null;
753 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
754 bool disabled = false;
755 if (!NativeMethods.GetProcessPriorityBoost(handle, out disabled)) {
756 throw new Win32Exception();
758 priorityBoostEnabled = !disabled;
759 havePriorityBoostEnabled = true;
762 ReleaseProcessHandle(handle);
765 return priorityBoostEnabled;
768 EnsureState(State.IsNt);
769 SafeProcessHandle handle = null;
771 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
772 if (!NativeMethods.SetProcessPriorityBoost(handle, !value))
773 throw new Win32Exception();
774 priorityBoostEnabled = value;
775 havePriorityBoostEnabled = true;
778 ReleaseProcessHandle(handle);
786 /// Gets or sets the overall priority category for the
787 /// associated process.
790 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityClass)]
791 public ProcessPriorityClass PriorityClass {
793 if (!havePriorityClass) {
794 SafeProcessHandle handle = null;
796 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
797 int value = NativeMethods.GetPriorityClass(handle);
799 throw new Win32Exception();
801 priorityClass = (ProcessPriorityClass)value;
802 havePriorityClass = true;
805 ReleaseProcessHandle(handle);
808 return priorityClass;
810 [ResourceExposure(ResourceScope.Machine)]
811 [ResourceConsumption(ResourceScope.Machine)]
813 if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) {
814 throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
818 // BelowNormal and AboveNormal are only available on Win2k and greater.
819 if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0) &&
820 (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) {
821 throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
825 SafeProcessHandle handle = null;
828 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
829 if (!NativeMethods.SetPriorityClass(handle, (int)value)) {
830 throw new Win32Exception();
832 priorityClass = value;
833 havePriorityClass = true;
836 ReleaseProcessHandle(handle);
843 /// Returns the number of bytes that the associated process has allocated that cannot
844 /// be shared with other processes.
846 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PrivateMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
847 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
848 public int PrivateMemorySize {
850 EnsureState(State.HaveNtProcessInfo);
851 return unchecked((int)processInfo.privateBytes);
855 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
856 [System.Runtime.InteropServices.ComVisible(false)]
857 public long PrivateMemorySize64 {
859 EnsureState(State.HaveNtProcessInfo);
860 return processInfo.privateBytes;
866 /// Returns the amount of time the process has spent running code inside the operating
869 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivilegedProcessorTime)]
870 public TimeSpan PrivilegedProcessorTime {
872 EnsureState(State.IsNt);
873 return GetProcessTimes().PrivilegedProcessorTime;
881 /// the friendly name of the process.
884 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessName)]
885 public string ProcessName {
886 [ResourceExposure(ResourceScope.None)]
887 [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
889 EnsureState(State.HaveProcessInfo);
890 String processName = processInfo.processName;
892 // On some old NT-based OS like win2000, the process name from NTQuerySystemInformation is up to 15 characters.
893 // Processes executing notepad_1234567.exe and notepad_12345678.exe will have the same process name.
894 // GetProcessByNames will not be able find the process for notepad_12345678.exe.
895 // So we will try to replace the name of the process by its main module name if the name is 15 characters.
896 // However we can't always get the module name:
897 // (1) Normal user will not be able to get module information about processes.
898 // (2) We can't get module information about remoting process.
899 // We can't get module name for a remote process
901 if (processName.Length == 15 && ProcessManager.IsNt && ProcessManager.IsOSOlderThanXP && !isRemoteMachine) {
903 String mainModuleName = MainModule.ModuleName;
904 if (mainModuleName != null) {
905 processInfo.processName = Path.ChangeExtension(Path.GetFileName(mainModuleName), null);
909 // If we can't access the module information, we can still use the might-be-truncated name.
910 // We could fail for a few reasons:
911 // (1) We don't enough privilege to get module information.
912 // (2) The process could have terminated.
916 return processInfo.processName;
923 /// or sets which processors the threads in this process can be scheduled to run on.
926 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessorAffinity)]
927 public IntPtr ProcessorAffinity {
929 if (!haveProcessorAffinity) {
930 SafeProcessHandle handle = null;
932 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
933 IntPtr processAffinity;
934 IntPtr systemAffinity;
935 if (!NativeMethods.GetProcessAffinityMask(handle, out processAffinity, out systemAffinity))
936 throw new Win32Exception();
937 processorAffinity = processAffinity;
940 ReleaseProcessHandle(handle);
942 haveProcessorAffinity = true;
944 return processorAffinity;
946 [ResourceExposure(ResourceScope.Machine)]
947 [ResourceConsumption(ResourceScope.Machine)]
949 SafeProcessHandle handle = null;
951 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
952 if (!NativeMethods.SetProcessAffinityMask(handle, value))
953 throw new Win32Exception();
955 processorAffinity = value;
956 haveProcessorAffinity = true;
959 ReleaseProcessHandle(handle);
966 /// Gets a value indicating whether or not the user
967 /// interface of the process is responding.
970 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessResponding)]
971 public bool Responding {
972 [ResourceExposure(ResourceScope.None)]
973 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
975 if (!haveResponding) {
976 IntPtr mainWindow = MainWindowHandle;
977 if (mainWindow == (IntPtr)0) {
982 responding = NativeMethods.SendMessageTimeout(new HandleRef(this, mainWindow), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero, NativeMethods.SMTO_ABORTIFHUNG, 5000, out result) != (IntPtr)0;
989 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessSessionId)]
990 public int SessionId {
992 EnsureState(State.HaveNtProcessInfo);
993 return processInfo.sessionId;
998 #endif // !FEATURE_PAL
1000 #if MONO_FEATURE_PROCESS_START
1003 /// Gets or sets the properties to pass into the <see cref='System.Diagnostics.Process.Start'/> method for the <see cref='System.Diagnostics.Process'/>
1007 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MonitoringDescription(SR.ProcessStartInfo)]
1008 public ProcessStartInfo StartInfo {
1010 if (startInfo == null) {
1011 startInfo = new ProcessStartInfo(this);
1015 [ResourceExposure(ResourceScope.Machine)]
1017 if (value == null) {
1018 throw new ArgumentNullException("value");
1027 /// Returns the time the associated process was started.
1029 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStartTime)]
1030 public DateTime StartTime {
1032 EnsureState(State.IsNt);
1033 return GetProcessTimes().StartTime;
1036 #endif // !FEATURE_PAL
1039 /// Represents the object used to marshal the event handler
1040 /// calls issued as a result of a Process exit. Normally
1041 /// this property will be set when the component is placed
1042 /// inside a control or a from, since those components are
1043 /// bound to a specific thread.
1048 MonitoringDescription(SR.ProcessSynchronizingObject)
1050 public ISynchronizeInvoke SynchronizingObject {
1052 if (this.synchronizingObject == null && DesignMode) {
1053 IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
1055 object baseComponent = host.RootComponent;
1056 if (baseComponent != null && baseComponent is ISynchronizeInvoke)
1057 this.synchronizingObject = (ISynchronizeInvoke)baseComponent;
1061 return this.synchronizingObject;
1065 this.synchronizingObject = value;
1074 /// Gets the set of threads that are running in the associated
1078 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessThreads)]
1079 public ProcessThreadCollection Threads {
1080 [ResourceExposure(ResourceScope.Process)]
1081 [ResourceConsumption(ResourceScope.Process)]
1083 if (threads == null) {
1084 EnsureState(State.HaveProcessInfo);
1085 int count = processInfo.threadInfoList.Count;
1086 ProcessThread[] newThreadsArray = new ProcessThread[count];
1087 for (int i = 0; i < count; i++) {
1088 newThreadsArray[i] = new ProcessThread(isRemoteMachine, (ThreadInfo)processInfo.threadInfoList[i]);
1090 ProcessThreadCollection newThreads = new ProcessThreadCollection(newThreadsArray);
1091 threads = newThreads;
1099 /// Returns the amount of time the associated process has spent utilizing the CPU.
1100 /// It is the sum of the <see cref='System.Diagnostics.Process.UserProcessorTime'/> and
1101 /// <see cref='System.Diagnostics.Process.PrivilegedProcessorTime'/>.
1103 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTotalProcessorTime)]
1104 public TimeSpan TotalProcessorTime {
1106 EnsureState(State.IsNt);
1107 return GetProcessTimes().TotalProcessorTime;
1112 /// Returns the amount of time the associated process has spent running code
1113 /// inside the application portion of the process (not the operating system core).
1115 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessUserProcessorTime)]
1116 public TimeSpan UserProcessorTime {
1118 EnsureState(State.IsNt);
1119 return GetProcessTimes().UserProcessorTime;
1125 /// Returns the amount of virtual memory that the associated process has requested.
1127 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.VirtualMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
1128 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1129 public int VirtualMemorySize {
1131 EnsureState(State.HaveNtProcessInfo);
1132 return unchecked((int)processInfo.virtualBytes);
1137 #endif // !FEATURE_PAL
1140 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1141 [System.Runtime.InteropServices.ComVisible(false)]
1142 public long VirtualMemorySize64 {
1144 EnsureState(State.HaveNtProcessInfo);
1145 return processInfo.virtualBytes;
1152 /// Gets or sets whether the <see cref='System.Diagnostics.Process.Exited'/>
1154 /// when the process terminates.
1157 [Browsable(false), DefaultValue(false), MonitoringDescription(SR.ProcessEnableRaisingEvents)]
1158 public bool EnableRaisingEvents {
1160 return watchForExit;
1163 if (value != watchForExit) {
1166 OpenProcessHandle();
1167 EnsureWatchingForExit();
1170 StopWatchingForExit();
1173 watchForExit = value;
1178 #if MONO_FEATURE_PROCESS_START
1180 /// <para>[To be supplied.]</para>
1182 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardInput)]
1183 public StreamWriter StandardInput {
1185 if (standardInput == null) {
1186 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardIn));
1190 inputStreamReadMode = StreamReadMode.syncMode;
1192 return standardInput;
1197 /// <para>[To be supplied.]</para>
1199 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardOutput)]
1200 public StreamReader StandardOutput {
1202 if (standardOutput == null) {
1203 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
1206 if(outputStreamReadMode == StreamReadMode.undefined) {
1207 outputStreamReadMode = StreamReadMode.syncMode;
1209 else if (outputStreamReadMode != StreamReadMode.syncMode) {
1210 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
1213 return standardOutput;
1218 /// <para>[To be supplied.]</para>
1220 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardError)]
1221 public StreamReader StandardError {
1223 if (standardError == null) {
1224 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
1227 if(errorStreamReadMode == StreamReadMode.undefined) {
1228 errorStreamReadMode = StreamReadMode.syncMode;
1230 else if (errorStreamReadMode != StreamReadMode.syncMode) {
1231 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
1234 return standardError;
1239 #if !FEATURE_PAL && !MONO
1241 /// Returns the total amount of physical memory the associated process.
1243 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.WorkingSet64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
1244 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1245 public int WorkingSet {
1247 EnsureState(State.HaveNtProcessInfo);
1248 return unchecked((int)processInfo.workingSet);
1251 #endif // !FEATURE_PAL && !MONO
1254 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1255 [System.Runtime.InteropServices.ComVisible(false)]
1256 public long WorkingSet64 {
1258 EnsureState(State.HaveNtProcessInfo);
1259 return processInfo.workingSet;
1264 [Category("Behavior"), MonitoringDescription(SR.ProcessExited)]
1265 public event EventHandler Exited {
1274 #if !FEATURE_PAL && !MONO
1277 /// Closes a process that has a user interface by sending a close message
1278 /// to its main window.
1281 [ResourceExposure(ResourceScope.Machine)] // Review usages of this.
1282 [ResourceConsumption(ResourceScope.Machine)]
1283 public bool CloseMainWindow() {
1284 IntPtr mainWindowHandle = MainWindowHandle;
1285 if (mainWindowHandle == (IntPtr)0) return false;
1286 int style = NativeMethods.GetWindowLong(new HandleRef(this, mainWindowHandle), NativeMethods.GWL_STYLE);
1287 if ((style & NativeMethods.WS_DISABLED) != 0) return false;
1288 NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
1291 #endif // !FEATURE_PAL && !MONO
1294 /// Release the temporary handle we used to get process information.
1295 /// If we used the process handle stored in the process object (we have all access to the handle,) don't release it.
1298 void ReleaseProcessHandle(SafeProcessHandle handle) {
1299 if (handle == null) {
1303 if (haveProcessHandle && handle == m_processHandle) {
1306 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process)");
1311 /// This is called from the threadpool when a proces exits.
1314 private void CompletionCallback(object context, bool wasSignaled) {
1315 StopWatchingForExit();
1322 /// Free any resources associated with this component.
1325 protected override void Dispose(bool disposing) {
1328 //Dispose managed and unmanaged resources
1331 this.disposed = true;
1332 base.Dispose(disposing);
1338 /// Frees any resources associated with this component.
1341 public void Close() {
1343 if (haveProcessHandle) {
1344 StopWatchingForExit();
1345 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process) in Close()");
1346 m_processHandle.Close();
1347 m_processHandle = null;
1348 haveProcessHandle = false;
1350 haveProcessId = false;
1351 isRemoteMachine = false;
1353 raisedOnExited = false;
1356 //Call close on streams if the user never saw them.
1357 //A stream in the undefined mode was never fetched by the user.
1358 //A stream in the async mode is wrapped on a AsyncStreamReader and we should dispose that instead.
1359 // no way for users to get a hand on a AsyncStreamReader.
1360 var tmpIn = standardInput;
1361 standardInput = null;
1362 if (inputStreamReadMode == StreamReadMode.undefined && tmpIn != null)
1365 var tmpOut = standardOutput;
1366 standardOutput = null;
1367 if (outputStreamReadMode == StreamReadMode.undefined && tmpOut != null)
1370 tmpOut = standardError;
1371 standardError = null;
1372 if (errorStreamReadMode == StreamReadMode.undefined && tmpOut != null)
1375 var tmpAsync = output;
1377 if (outputStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
1378 tmpAsync.CancelOperation ();
1384 if (errorStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
1385 tmpAsync.CancelOperation ();
1389 //Don't call close on the Readers and writers
1390 //since they might be referenced by somebody else while the
1391 //process is still alive but this method called.
1392 standardOutput = null;
1393 standardInput = null;
1394 standardError = null;
1406 /// Helper method for checking preconditions when accessing properties.
1409 [ResourceExposure(ResourceScope.None)]
1410 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1411 void EnsureState(State state) {
1414 if ((state & State.IsWin2k) != (State)0) {
1416 if (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)
1417 #endif // !FEATURE_PAL
1418 throw new PlatformNotSupportedException(SR.GetString(SR.Win2kRequired));
1421 if ((state & State.IsNt) != (State)0) {
1423 if (OperatingSystem.Platform != PlatformID.Win32NT)
1424 #endif // !FEATURE_PAL
1425 throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
1429 if ((state & State.Associated) != (State)0)
1431 throw new InvalidOperationException(SR.GetString(SR.NoAssociatedProcess));
1433 if ((state & State.HaveId) != (State)0) {
1434 if (!haveProcessId) {
1435 #if !FEATURE_PAL && !MONO
1436 if (haveProcessHandle) {
1437 SetProcessId(ProcessManager.GetProcessIdFromHandle(m_processHandle));
1440 EnsureState(State.Associated);
1441 throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1444 EnsureState(State.Associated);
1445 throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1446 #endif // !FEATURE_PAL && !MONO
1450 if ((state & State.IsLocal) != (State)0 && isRemoteMachine) {
1451 throw new NotSupportedException(SR.GetString(SR.NotSupportedRemote));
1454 if ((state & State.HaveProcessInfo) != (State)0) {
1455 #if !FEATURE_PAL && !MONO
1456 if (processInfo == null) {
1457 if ((state & State.HaveId) == (State)0) EnsureState(State.HaveId);
1458 ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1459 for (int i = 0; i < processInfos.Length; i++) {
1460 if (processInfos[i].processId == processId) {
1461 this.processInfo = processInfos[i];
1465 if (processInfo == null) {
1466 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1470 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1471 #endif // !FEATURE_PAL && !MONO
1474 if ((state & State.Exited) != (State)0) {
1476 throw new InvalidOperationException(SR.GetString(SR.WaitTillExit));
1479 if (!haveProcessHandle) {
1480 throw new InvalidOperationException(SR.GetString(SR.NoProcessHandle));
1486 /// Make sure we are watching for a process exit.
1489 void EnsureWatchingForExit() {
1490 if (!watchingForExit) {
1492 if (!watchingForExit) {
1493 Debug.Assert(haveProcessHandle, "Process.EnsureWatchingForExit called with no process handle");
1494 Debug.Assert(Associated, "Process.EnsureWatchingForExit called with no associated process");
1495 watchingForExit = true;
1497 this.waitHandle = new ProcessWaitHandle(m_processHandle);
1498 this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(this.waitHandle,
1499 new WaitOrTimerCallback(this.CompletionCallback), null, -1, true);
1502 watchingForExit = false;
1513 /// Make sure we have obtained the min and max working set limits.
1516 void EnsureWorkingSetLimits() {
1517 EnsureState(State.IsNt);
1518 if (!haveWorkingSetLimits) {
1519 SafeProcessHandle handle = null;
1521 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
1524 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1525 throw new Win32Exception();
1527 minWorkingSet = min;
1528 maxWorkingSet = max;
1529 haveWorkingSetLimits = true;
1532 ReleaseProcessHandle(handle);
1537 public static void EnterDebugMode() {
1539 if (ProcessManager.IsNt) {
1540 SetPrivilege("SeDebugPrivilege", NativeMethods.SE_PRIVILEGE_ENABLED);
1546 [ResourceExposure(ResourceScope.None)]
1547 [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
1548 private static void SetPrivilege(string privilegeName, int attrib) {
1549 IntPtr hToken = (IntPtr)0;
1550 NativeMethods.LUID debugValue = new NativeMethods.LUID();
1552 // this is only a "pseudo handle" to the current process - no need to close it later
1553 IntPtr processHandle = NativeMethods.GetCurrentProcess();
1555 // get the process token so we can adjust the privilege on it. We DO need to
1556 // close the token when we're done with it.
1557 if (!NativeMethods.OpenProcessToken(new HandleRef(null, processHandle), NativeMethods.TOKEN_ADJUST_PRIVILEGES, out hToken)) {
1558 throw new Win32Exception();
1562 if (!NativeMethods.LookupPrivilegeValue(null, privilegeName, out debugValue)) {
1563 throw new Win32Exception();
1566 NativeMethods.TokenPrivileges tkp = new NativeMethods.TokenPrivileges();
1567 tkp.Luid = debugValue;
1568 tkp.Attributes = attrib;
1570 NativeMethods.AdjustTokenPrivileges(new HandleRef(null, hToken), false, tkp, 0, IntPtr.Zero, IntPtr.Zero);
1572 // AdjustTokenPrivileges can return true even if it failed to
1573 // set the privilege, so we need to use GetLastError
1574 if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_SUCCESS) {
1575 throw new Win32Exception();
1579 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(processToken)");
1580 SafeNativeMethods.CloseHandle(hToken);
1586 /// <para>[To be supplied.]</para>
1588 public static void LeaveDebugMode() {
1590 if (ProcessManager.IsNt) {
1591 SetPrivilege("SeDebugPrivilege", 0);
1599 /// Returns a new <see cref='System.Diagnostics.Process'/> component given a process identifier and
1600 /// the name of a computer in the network.
1603 [ResourceExposure(ResourceScope.Machine)]
1604 [ResourceConsumption(ResourceScope.Machine)]
1605 public static Process GetProcessById(int processId, string machineName) {
1606 if (!ProcessManager.IsProcessRunning(processId, machineName)) {
1607 throw new ArgumentException(SR.GetString(SR.MissingProccess, processId.ToString(CultureInfo.CurrentCulture)));
1610 return new Process(machineName, ProcessManager.IsRemoteMachine(machineName), processId, null);
1615 /// Returns a new <see cref='System.Diagnostics.Process'/> component given the
1616 /// identifier of a process on the local computer.
1619 [ResourceExposure(ResourceScope.Machine)]
1620 [ResourceConsumption(ResourceScope.Machine)]
1621 public static Process GetProcessById(int processId) {
1622 return GetProcessById(processId, ".");
1627 /// Creates an array of <see cref='System.Diagnostics.Process'/> components that are
1629 /// with process resources on the
1630 /// local computer. These process resources share the specified process name.
1633 [ResourceExposure(ResourceScope.Machine)]
1634 [ResourceConsumption(ResourceScope.Machine)]
1635 public static Process[] GetProcessesByName(string processName) {
1636 return GetProcessesByName(processName, ".");
1641 /// Creates an array of <see cref='System.Diagnostics.Process'/> components that are associated with process resources on a
1642 /// remote computer. These process resources share the specified process name.
1645 [ResourceExposure(ResourceScope.Machine)]
1646 [ResourceConsumption(ResourceScope.Machine)]
1647 public static Process[] GetProcessesByName(string processName, string machineName) {
1648 if (processName == null) processName = String.Empty;
1649 Process[] procs = GetProcesses(machineName);
1650 ArrayList list = new ArrayList();
1652 for(int i = 0; i < procs.Length; i++) {
1653 if( String.Equals(processName, procs[i].ProcessName, StringComparison.OrdinalIgnoreCase)) {
1654 list.Add( procs[i]);
1660 Process[] temp = new Process[list.Count];
1661 list.CopyTo(temp, 0);
1667 /// Creates a new <see cref='System.Diagnostics.Process'/>
1668 /// component for each process resource on the local computer.
1671 [ResourceExposure(ResourceScope.Machine)]
1672 [ResourceConsumption(ResourceScope.Machine)]
1673 public static Process[] GetProcesses() {
1674 return GetProcesses(".");
1679 /// Creates a new <see cref='System.Diagnostics.Process'/>
1680 /// component for each
1681 /// process resource on the specified computer.
1684 [ResourceExposure(ResourceScope.Machine)]
1685 [ResourceConsumption(ResourceScope.Machine)]
1686 public static Process[] GetProcesses(string machineName) {
1687 bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName);
1688 ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1689 Process[] processes = new Process[processInfos.Length];
1690 for (int i = 0; i < processInfos.Length; i++) {
1691 ProcessInfo processInfo = processInfos[i];
1692 processes[i] = new Process(machineName, isRemoteMachine, processInfo.processId, processInfo);
1694 Debug.WriteLineIf(processTracing.TraceVerbose, "Process.GetProcesses(" + machineName + ")");
1696 if (processTracing.TraceVerbose) {
1698 for (int i = 0; i < processInfos.Length; i++) {
1699 Debug.WriteLine(processes[i].Id + ": " + processes[i].ProcessName);
1708 #endif // !FEATURE_PAL
1712 /// Returns a new <see cref='System.Diagnostics.Process'/>
1713 /// component and associates it with the current active process.
1716 [ResourceExposure(ResourceScope.Process)]
1717 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Process)]
1718 public static Process GetCurrentProcess() {
1719 return new Process(".", false, NativeMethods.GetCurrentProcessId(), null);
1724 /// Raises the <see cref='System.Diagnostics.Process.Exited'/> event.
1727 protected void OnExited() {
1728 EventHandler exited = onExited;
1729 if (exited != null) {
1730 if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired)
1731 this.SynchronizingObject.BeginInvoke(exited, new object[]{this, EventArgs.Empty});
1733 exited(this, EventArgs.Empty);
1738 /// Gets a short-term handle to the process, with the given access.
1739 /// If a handle is stored in current process object, then use it.
1740 /// Note that the handle we stored in current process object will have all access we need.
1743 [ResourceExposure(ResourceScope.None)]
1744 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1745 SafeProcessHandle GetProcessHandle(int access, bool throwIfExited) {
1746 Debug.WriteLineIf(processTracing.TraceVerbose, "GetProcessHandle(access = 0x" + access.ToString("X8", CultureInfo.InvariantCulture) + ", throwIfExited = " + throwIfExited + ")");
1748 if (processTracing.TraceVerbose) {
1749 StackFrame calledFrom = new StackTrace(true).GetFrame(0);
1750 Debug.WriteLine(" called from " + calledFrom.GetFileName() + ", line " + calledFrom.GetFileLineNumber());
1753 if (haveProcessHandle) {
1754 if (throwIfExited) {
1755 // Since haveProcessHandle is true, we know we have the process handle
1756 // open with at least SYNCHRONIZE access, so we can wait on it with
1757 // zero timeout to see if the process has exited.
1758 ProcessWaitHandle waitHandle = null;
1760 waitHandle = new ProcessWaitHandle(m_processHandle);
1761 if (waitHandle.WaitOne(0, false)) {
1763 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1765 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
1769 if( waitHandle != null) {
1774 return m_processHandle;
1777 EnsureState(State.HaveId | State.IsLocal);
1778 SafeProcessHandle handle = SafeProcessHandle.InvalidHandle;
1779 #if !FEATURE_PAL && !MONO
1780 handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
1782 IntPtr pseudohandle = NativeMethods.GetCurrentProcess();
1783 // Get a real handle
1784 if (!NativeMethods.DuplicateHandle (new HandleRef(this, pseudohandle),
1785 new HandleRef(this, pseudohandle),
1786 new HandleRef(this, pseudohandle),
1790 NativeMethods.DUPLICATE_SAME_ACCESS |
1791 NativeMethods.DUPLICATE_CLOSE_SOURCE)) {
1792 throw new Win32Exception();
1794 #endif // !FEATURE_PAL && !MONO
1795 if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) {
1796 if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
1797 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1806 /// Gets a short-term handle to the process, with the given access. If a handle exists,
1807 /// then it is reused. If the process has exited, it throws an exception.
1810 SafeProcessHandle GetProcessHandle(int access) {
1811 return GetProcessHandle(access, true);
1815 /// Opens a long-term handle to the process, with all access. If a handle exists,
1816 /// then it is reused. If the process has exited, it throws an exception.
1819 SafeProcessHandle OpenProcessHandle() {
1820 return OpenProcessHandle(NativeMethods.PROCESS_ALL_ACCESS);
1823 SafeProcessHandle OpenProcessHandle(Int32 access) {
1824 if (!haveProcessHandle) {
1825 //Cannot open a new process handle if the object has been disposed, since finalization has been suppressed.
1826 if (this.disposed) {
1827 throw new ObjectDisposedException(GetType().Name);
1830 SetProcessHandle(GetProcessHandle(access));
1832 return m_processHandle;
1837 /// Raise the Exited event, but make sure we don't do it more than once.
1840 void RaiseOnExited() {
1841 if (!raisedOnExited) {
1843 if (!raisedOnExited) {
1844 raisedOnExited = true;
1854 /// Discards any information about the associated process
1855 /// that has been cached inside the process component. After <see cref='System.Diagnostics.Process.Refresh'/> is called, the
1856 /// first request for information for each property causes the process component
1857 /// to obtain a new value from the associated process.
1860 public void Refresh() {
1867 #endif // !FEATURE_PAL
1868 mainWindowTitle = null;
1871 haveMainWindow = false;
1872 haveWorkingSetLimits = false;
1873 haveProcessorAffinity = false;
1874 havePriorityClass = false;
1875 haveExitTime = false;
1876 haveResponding = false;
1877 havePriorityBoostEnabled = false;
1881 /// Helper to associate a process handle with this component.
1884 void SetProcessHandle(SafeProcessHandle processHandle) {
1885 this.m_processHandle = processHandle;
1886 this.haveProcessHandle = true;
1888 EnsureWatchingForExit();
1893 /// Helper to associate a process id with this component.
1896 [ResourceExposure(ResourceScope.Machine)]
1897 void SetProcessId(int processId) {
1898 this.processId = processId;
1899 this.haveProcessId = true;
1905 /// Helper to set minimum or maximum working set limits.
1908 [ResourceExposure(ResourceScope.Process)]
1909 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1910 void SetWorkingSetLimits(object newMin, object newMax) {
1911 EnsureState(State.IsNt);
1913 SafeProcessHandle handle = null;
1915 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_SET_QUOTA);
1918 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1919 throw new Win32Exception();
1922 if (newMin != null) {
1923 min = (IntPtr)newMin;
1926 if (newMax != null) {
1927 max = (IntPtr)newMax;
1930 if ((long)min > (long)max) {
1931 if (newMin != null) {
1932 throw new ArgumentException(SR.GetString(SR.BadMinWorkset));
1935 throw new ArgumentException(SR.GetString(SR.BadMaxWorkset));
1939 if (!NativeMethods.SetProcessWorkingSetSize(handle, min, max)) {
1940 throw new Win32Exception();
1943 // The value may be rounded/changed by the OS, so go get it
1944 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1945 throw new Win32Exception();
1947 minWorkingSet = min;
1948 maxWorkingSet = max;
1949 haveWorkingSetLimits = true;
1952 ReleaseProcessHandle(handle);
1956 #endif // !FEATURE_PAL
1958 #if MONO_FEATURE_PROCESS_START
1962 /// Starts a process specified by the <see cref='System.Diagnostics.Process.StartInfo'/> property of this <see cref='System.Diagnostics.Process'/>
1963 /// component and associates it with the
1964 /// <see cref='System.Diagnostics.Process'/> . If a process resource is reused
1965 /// rather than started, the reused process is associated with this <see cref='System.Diagnostics.Process'/>
1969 [ResourceExposure(ResourceScope.None)]
1970 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1971 public bool Start() {
1973 ProcessStartInfo startInfo = StartInfo;
1974 if (startInfo.FileName.Length == 0)
1975 throw new InvalidOperationException(SR.GetString(SR.FileNameMissing));
1977 if (startInfo.UseShellExecute) {
1979 return StartWithShellExecuteEx(startInfo);
1981 throw new InvalidOperationException(SR.GetString(SR.net_perm_invalid_val, "StartInfo.UseShellExecute", true));
1982 #endif // !FEATURE_PAL
1984 return StartWithCreateProcess(startInfo);
1989 [ResourceExposure(ResourceScope.Process)]
1990 [ResourceConsumption(ResourceScope.Process)]
1991 private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) {
1992 bool ret = NativeMethods.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize);
1993 if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid) {
1994 throw new Win32Exception();
1998 // Using synchronous Anonymous pipes for process input/output redirection means we would end up
1999 // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
2000 // it will take advantage of the NT IO completion port infrastructure. But we can't really use
2001 // Overlapped I/O for process input/output as it would break Console apps (managed Console class
2002 // methods such as WriteLine as well as native CRT functions like printf) which are making an
2003 // assumption that the console standard handles (obtained via GetStdHandle()) are opened
2004 // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously!
2005 [ResourceExposure(ResourceScope.None)]
2006 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2007 private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) {
2008 NativeMethods.SECURITY_ATTRIBUTES securityAttributesParent = new NativeMethods.SECURITY_ATTRIBUTES();
2009 securityAttributesParent.bInheritHandle = true;
2011 SafeFileHandle hTmp = null;
2014 CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);
2017 CreatePipeWithSecurityAttributes(out hTmp,
2019 securityAttributesParent,
2022 // Duplicate the parent handle to be non-inheritable so that the child process
2023 // doesn't have access. This is done for correctness sake, exact reason is unclear.
2024 // One potential theory is that child process can do something brain dead like
2025 // closing the parent end of the pipe and there by getting into a blocking situation
2026 // as parent will not be draining the pipe at the other end anymore.
2027 if (!NativeMethods.DuplicateHandle(new HandleRef(this, NativeMethods.GetCurrentProcess()),
2029 new HandleRef(this, NativeMethods.GetCurrentProcess()),
2033 NativeMethods.DUPLICATE_SAME_ACCESS)) {
2034 throw new Win32Exception();
2038 if( hTmp != null && !hTmp.IsInvalid) {
2044 private static StringBuilder BuildCommandLine(string executableFileName, string arguments) {
2045 // Construct a StringBuilder with the appropriate command line
2046 // to pass to CreateProcess. If the filename isn't already
2047 // in quotes, we quote it here. This prevents some security
2048 // problems (it specifies exactly which part of the string
2049 // is the file to execute).
2050 StringBuilder commandLine = new StringBuilder();
2051 string fileName = executableFileName.Trim();
2052 bool fileNameIsQuoted = (fileName.StartsWith("\"", StringComparison.Ordinal) && fileName.EndsWith("\"", StringComparison.Ordinal));
2053 if (!fileNameIsQuoted) {
2054 commandLine.Append("\"");
2057 commandLine.Append(fileName);
2059 if (!fileNameIsQuoted) {
2060 commandLine.Append("\"");
2063 if (!String.IsNullOrEmpty(arguments)) {
2064 commandLine.Append(" ");
2065 commandLine.Append(arguments);
2071 [ResourceExposure(ResourceScope.Machine)]
2072 [ResourceConsumption(ResourceScope.Machine)]
2073 private bool StartWithCreateProcess(ProcessStartInfo startInfo) {
2074 if( startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) {
2075 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2078 if( startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) {
2079 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2082 // See knowledge base article Q190351 for an explanation of the following code. Noteworthy tricky points:
2083 // * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
2084 // that the child process can not close them
2085 // * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
2086 // GetStdHandle for the handles that are not being redirected
2088 //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
2089 if (this.disposed) {
2090 throw new ObjectDisposedException(GetType().Name);
2093 StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
2095 NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO();
2096 SafeNativeMethods.PROCESS_INFORMATION processInfo = new SafeNativeMethods.PROCESS_INFORMATION();
2097 SafeProcessHandle procSH = new SafeProcessHandle();
2098 SafeThreadHandle threadSH = new SafeThreadHandle();
2101 // handles used in parent process
2102 SafeFileHandle standardInputWritePipeHandle = null;
2103 SafeFileHandle standardOutputReadPipeHandle = null;
2104 SafeFileHandle standardErrorReadPipeHandle = null;
2105 GCHandle environmentHandle = new GCHandle();
2106 lock (s_CreateProcessLock) {
2108 // set up the streams
2109 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2110 if (startInfo.RedirectStandardInput) {
2111 CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
2113 startupInfo.hStdInput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);
2116 if (startInfo.RedirectStandardOutput) {
2117 CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false);
2119 startupInfo.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_OUTPUT_HANDLE), false);
2122 if (startInfo.RedirectStandardError) {
2123 CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false);
2125 startupInfo.hStdError = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_ERROR_HANDLE), false);
2128 startupInfo.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
2131 // set up the creation flags paramater
2132 int creationFlags = 0;
2134 if (startInfo.CreateNoWindow) creationFlags |= NativeMethods.CREATE_NO_WINDOW;
2135 #endif // !FEATURE_PAL
2137 // set up the environment block parameter
2138 IntPtr environmentPtr = (IntPtr)0;
2139 if (startInfo.environmentVariables != null) {
2140 bool unicode = false;
2142 if (ProcessManager.IsNt) {
2143 creationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
2146 #endif // !FEATURE_PAL
2148 byte[] environmentBytes = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode);
2149 environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
2150 environmentPtr = environmentHandle.AddrOfPinnedObject();
2153 string workingDirectory = startInfo.WorkingDirectory;
2154 if (workingDirectory == string.Empty)
2155 workingDirectory = Environment.CurrentDirectory;
2158 if (startInfo.UserName.Length != 0) {
2159 if (startInfo.Password != null && startInfo.PasswordInClearText != null)
2160 throw new ArgumentException(SR.GetString(SR.CantSetDuplicatePassword));
2162 NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0;
2163 if( startInfo.LoadUserProfile) {
2164 logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
2167 IntPtr password = IntPtr.Zero;
2169 if( startInfo.Password != null) {
2170 password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
2171 } else if( startInfo.PasswordInClearText != null) {
2172 password = Marshal.StringToCoTaskMemUni(startInfo.PasswordInClearText);
2174 password = Marshal.StringToCoTaskMemUni(String.Empty);
2177 RuntimeHelpers.PrepareConstrainedRegions();
2179 retVal = NativeMethods.CreateProcessWithLogonW(
2184 null, // we don't need this since all the info is in commandLine
2189 startupInfo, // pointer to STARTUPINFO
2190 processInfo // pointer to PROCESS_INFORMATION
2193 errorCode = Marshal.GetLastWin32Error();
2194 if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2195 procSH.InitialSetHandle(processInfo.hProcess);
2196 if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2197 threadSH.InitialSetHandle(processInfo.hThread);
2200 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2201 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2204 throw new Win32Exception(errorCode);
2207 if( password != IntPtr.Zero) {
2208 Marshal.ZeroFreeCoTaskMemUnicode(password);
2212 #endif // !FEATURE_PAL
2213 RuntimeHelpers.PrepareConstrainedRegions();
2215 retVal = NativeMethods.CreateProcess (
2216 null, // we don't need this since all the info is in commandLine
2217 commandLine, // pointer to the command line string
2218 null, // pointer to process security attributes, we don't need to inheriat the handle
2219 null, // pointer to thread security attributes
2220 true, // handle inheritance flag
2221 creationFlags, // creation flags
2222 environmentPtr, // pointer to new environment block
2223 workingDirectory, // pointer to current directory name
2224 startupInfo, // pointer to STARTUPINFO
2225 processInfo // pointer to PROCESS_INFORMATION
2228 errorCode = Marshal.GetLastWin32Error();
2229 if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2230 procSH.InitialSetHandle(processInfo.hProcess);
2231 if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2232 threadSH.InitialSetHandle(processInfo.hThread);
2235 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2236 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2238 throw new Win32Exception(errorCode);
2244 // free environment block
2245 if (environmentHandle.IsAllocated) {
2246 environmentHandle.Free();
2249 startupInfo.Dispose();
2253 if (startInfo.RedirectStandardInput) {
2254 standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096);
2255 standardInput.AutoFlush = true;
2257 if (startInfo.RedirectStandardOutput) {
2258 Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
2259 standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2261 if (startInfo.RedirectStandardError) {
2262 Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
2263 standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2267 if (!procSH.IsInvalid) {
2268 SetProcessHandle(procSH);
2269 SetProcessId(processInfo.dwProcessId);
2282 [ResourceExposure(ResourceScope.Machine)]
2283 [ResourceConsumption(ResourceScope.Machine)]
2284 private bool StartWithShellExecuteEx(ProcessStartInfo startInfo) {
2285 //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
2287 throw new ObjectDisposedException(GetType().Name);
2289 if( !String.IsNullOrEmpty(startInfo.UserName) || (startInfo.Password != null) ) {
2290 throw new InvalidOperationException(SR.GetString(SR.CantStartAsUser));
2293 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2294 throw new InvalidOperationException(SR.GetString(SR.CantRedirectStreams));
2297 if (startInfo.StandardErrorEncoding != null) {
2298 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2301 if (startInfo.StandardOutputEncoding != null) {
2302 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2305 // can't set env vars with ShellExecuteEx...
2306 if (startInfo.environmentVariables != null) {
2307 throw new InvalidOperationException(SR.GetString(SR.CantUseEnvVars));
2310 NativeMethods.ShellExecuteInfo shellExecuteInfo = new NativeMethods.ShellExecuteInfo();
2311 shellExecuteInfo.fMask = NativeMethods.SEE_MASK_NOCLOSEPROCESS;
2312 if (startInfo.ErrorDialog) {
2313 shellExecuteInfo.hwnd = startInfo.ErrorDialogParentHandle;
2316 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_NO_UI;
2319 switch (startInfo.WindowStyle) {
2320 case ProcessWindowStyle.Hidden:
2321 shellExecuteInfo.nShow = NativeMethods.SW_HIDE;
2323 case ProcessWindowStyle.Minimized:
2324 shellExecuteInfo.nShow = NativeMethods.SW_SHOWMINIMIZED;
2326 case ProcessWindowStyle.Maximized:
2327 shellExecuteInfo.nShow = NativeMethods.SW_SHOWMAXIMIZED;
2330 shellExecuteInfo.nShow = NativeMethods.SW_SHOWNORMAL;
2336 if (startInfo.FileName.Length != 0)
2337 shellExecuteInfo.lpFile = Marshal.StringToHGlobalAuto(startInfo.FileName);
2338 if (startInfo.Verb.Length != 0)
2339 shellExecuteInfo.lpVerb = Marshal.StringToHGlobalAuto(startInfo.Verb);
2340 if (startInfo.Arguments.Length != 0)
2341 shellExecuteInfo.lpParameters = Marshal.StringToHGlobalAuto(startInfo.Arguments);
2342 if (startInfo.WorkingDirectory.Length != 0)
2343 shellExecuteInfo.lpDirectory = Marshal.StringToHGlobalAuto(startInfo.WorkingDirectory);
2345 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_DDEWAIT;
2347 ShellExecuteHelper executeHelper = new ShellExecuteHelper(shellExecuteInfo);
2348 if (!executeHelper.ShellExecuteOnSTAThread()) {
2349 int error = executeHelper.ErrorCode;
2351 switch ((long)shellExecuteInfo.hInstApp) {
2352 case NativeMethods.SE_ERR_FNF: error = NativeMethods.ERROR_FILE_NOT_FOUND; break;
2353 case NativeMethods.SE_ERR_PNF: error = NativeMethods.ERROR_PATH_NOT_FOUND; break;
2354 case NativeMethods.SE_ERR_ACCESSDENIED: error = NativeMethods.ERROR_ACCESS_DENIED; break;
2355 case NativeMethods.SE_ERR_OOM: error = NativeMethods.ERROR_NOT_ENOUGH_MEMORY; break;
2356 case NativeMethods.SE_ERR_DDEFAIL:
2357 case NativeMethods.SE_ERR_DDEBUSY:
2358 case NativeMethods.SE_ERR_DDETIMEOUT: error = NativeMethods.ERROR_DDE_FAIL; break;
2359 case NativeMethods.SE_ERR_SHARE: error = NativeMethods.ERROR_SHARING_VIOLATION; break;
2360 case NativeMethods.SE_ERR_NOASSOC: error = NativeMethods.ERROR_NO_ASSOCIATION; break;
2361 case NativeMethods.SE_ERR_DLLNOTFOUND: error = NativeMethods.ERROR_DLL_NOT_FOUND; break;
2362 default: error = (int)shellExecuteInfo.hInstApp; break;
2365 if( error == NativeMethods.ERROR_BAD_EXE_FORMAT || error == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2366 throw new Win32Exception(error, SR.GetString(SR.InvalidApplication));
2368 throw new Win32Exception(error);
2373 if (shellExecuteInfo.lpFile != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpFile);
2374 if (shellExecuteInfo.lpVerb != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpVerb);
2375 if (shellExecuteInfo.lpParameters != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpParameters);
2376 if (shellExecuteInfo.lpDirectory != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpDirectory);
2379 if (shellExecuteInfo.hProcess != (IntPtr)0) {
2380 SafeProcessHandle handle = new SafeProcessHandle(shellExecuteInfo.hProcess);
2381 SetProcessHandle(handle);
2389 [ResourceExposure(ResourceScope.Machine)]
2390 [ResourceConsumption(ResourceScope.Machine)]
2391 public static Process Start( string fileName, string userName, SecureString password, string domain ) {
2392 ProcessStartInfo startInfo = new ProcessStartInfo(fileName);
2393 startInfo.UserName = userName;
2394 startInfo.Password = password;
2395 startInfo.Domain = domain;
2396 startInfo.UseShellExecute = false;
2397 return Start(startInfo);
2400 [ResourceExposure(ResourceScope.Machine)]
2401 [ResourceConsumption(ResourceScope.Machine)]
2402 public static Process Start( string fileName, string arguments, string userName, SecureString password, string domain ) {
2403 ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
2404 startInfo.UserName = userName;
2405 startInfo.Password = password;
2406 startInfo.Domain = domain;
2407 startInfo.UseShellExecute = false;
2408 return Start(startInfo);
2412 #endif // !FEATURE_PAL
2416 /// Starts a process resource by specifying the name of a
2417 /// document or application file. Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2421 [ResourceExposure(ResourceScope.Machine)]
2422 [ResourceConsumption(ResourceScope.Machine)]
2423 public static Process Start(string fileName) {
2424 return Start(new ProcessStartInfo(fileName));
2429 /// Starts a process resource by specifying the name of an
2430 /// application and a set of command line arguments. Associates the process resource
2431 /// with a new <see cref='System.Diagnostics.Process'/>
2435 [ResourceExposure(ResourceScope.Machine)]
2436 [ResourceConsumption(ResourceScope.Machine)]
2437 public static Process Start(string fileName, string arguments) {
2438 return Start(new ProcessStartInfo(fileName, arguments));
2443 /// Starts a process resource specified by the process start
2444 /// information passed in, for example the file name of the process to start.
2445 /// Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2449 [ResourceExposure(ResourceScope.Machine)]
2450 [ResourceConsumption(ResourceScope.Machine)]
2451 public static Process Start(ProcessStartInfo startInfo) {
2452 Process process = new Process();
2453 if (startInfo == null) throw new ArgumentNullException("startInfo");
2454 process.StartInfo = startInfo;
2455 if (process.Start()) {
2461 #endif // MONO_FEATURE_PROCESS_START
2466 /// associated process immediately.
2469 [ResourceExposure(ResourceScope.Machine)]
2470 [ResourceConsumption(ResourceScope.Machine)]
2471 public void Kill() {
2472 SafeProcessHandle handle = null;
2474 handle = GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
2475 if (!NativeMethods.TerminateProcess(handle, -1))
2476 throw new Win32Exception();
2479 ReleaseProcessHandle(handle);
2484 /// Make sure we are not watching for process exit.
2487 void StopWatchingForExit() {
2488 if (watchingForExit) {
2490 if (watchingForExit) {
2491 watchingForExit = false;
2492 registeredWaitHandle.Unregister(null);
2495 registeredWaitHandle = null;
2501 public override string ToString() {
2504 string processName = String.Empty;
2506 // On windows 9x, we can't map a handle to an id.
2507 // So ProcessName will throw. We shouldn't throw in Process.ToString though.
2508 // Process.GetProcesses should be used to get all the processes on the machine.
2509 // The processes returned from it will have a nice name.
2512 processName = this.ProcessName;
2514 catch(PlatformNotSupportedException) {
2516 if( processName.Length != 0) {
2517 return String.Format(CultureInfo.CurrentCulture, "{0} ({1})", base.ToString(), processName);
2519 return base.ToString();
2522 #endif // !FEATURE_PAL
2523 return base.ToString();
2528 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait the specified number of milliseconds for the associated process to exit.
2531 public bool WaitForExit(int milliseconds) {
2532 SafeProcessHandle handle = null;
2534 ProcessWaitHandle processWaitHandle = null;
2536 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE, false);
2537 if (handle.IsInvalid) {
2541 processWaitHandle = new ProcessWaitHandle(handle);
2542 if( processWaitHandle.WaitOne(milliseconds, false)) {
2553 if( processWaitHandle != null) {
2554 processWaitHandle.Close();
2557 // If we have a hard timeout, we cannot wait for the streams
2558 if( output != null && milliseconds == -1) {
2559 output.WaitUtilEOF();
2562 if( error != null && milliseconds == -1) {
2563 error.WaitUtilEOF();
2566 ReleaseProcessHandle(handle);
2570 if (exited && watchForExit) {
2579 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2580 /// indefinitely for the associated process to exit.
2583 public void WaitForExit() {
2591 /// Causes the <see cref='System.Diagnostics.Process'/> component to wait the
2592 /// specified number of milliseconds for the associated process to enter an
2594 /// This is only applicable for processes with a user interface,
2595 /// therefore a message loop.
2598 public bool WaitForInputIdle(int milliseconds) {
2599 SafeProcessHandle handle = null;
2602 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE | NativeMethods.PROCESS_QUERY_INFORMATION);
2603 int ret = NativeMethods.WaitForInputIdle(handle, milliseconds);
2605 case NativeMethods.WAIT_OBJECT_0:
2608 case NativeMethods.WAIT_TIMEOUT:
2611 case NativeMethods.WAIT_FAILED:
2613 throw new InvalidOperationException(SR.GetString(SR.InputIdleUnkownError));
2617 ReleaseProcessHandle(handle);
2624 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2625 /// indefinitely for the associated process to enter an idle state. This
2626 /// is only applicable for processes with a user interface, therefore a message loop.
2629 public bool WaitForInputIdle() {
2630 return WaitForInputIdle(Int32.MaxValue);
2633 #endif // !FEATURE_PAL
2635 #if MONO_FEATURE_PROCESS_START
2636 // Support for working asynchronously with streams
2639 /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2640 /// reading the StandardOutput stream asynchronously. The user can register a callback
2641 /// 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
2642 /// then the remaining information is returned. The user can add an event handler to OutputDataReceived.
2645 [System.Runtime.InteropServices.ComVisible(false)]
2646 public void BeginOutputReadLine() {
2648 if(outputStreamReadMode == StreamReadMode.undefined) {
2649 outputStreamReadMode = StreamReadMode.asyncMode;
2651 else if (outputStreamReadMode != StreamReadMode.asyncMode) {
2652 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
2655 if (pendingOutputRead)
2656 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2658 pendingOutputRead = true;
2659 // We can't detect if there's a pending sychronous read, tream also doesn't.
2660 if (output == null) {
2661 if (standardOutput == null) {
2662 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
2665 Stream s = standardOutput.BaseStream;
2666 output = new AsyncStreamReader(this, s, new UserCallBack(this.OutputReadNotifyUser), standardOutput.CurrentEncoding);
2668 output.BeginReadLine();
2674 /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2675 /// reading the StandardError stream asynchronously. The user can register a callback
2676 /// 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
2677 /// then the remaining information is returned. The user can add an event handler to ErrorDataReceived.
2680 [System.Runtime.InteropServices.ComVisible(false)]
2681 public void BeginErrorReadLine() {
2683 if(errorStreamReadMode == StreamReadMode.undefined) {
2684 errorStreamReadMode = StreamReadMode.asyncMode;
2686 else if (errorStreamReadMode != StreamReadMode.asyncMode) {
2687 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
2690 if (pendingErrorRead) {
2691 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2694 pendingErrorRead = true;
2695 // We can't detect if there's a pending sychronous read, stream also doesn't.
2696 if (error == null) {
2697 if (standardError == null) {
2698 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
2701 Stream s = standardError.BaseStream;
2702 error = new AsyncStreamReader(this, s, new UserCallBack(this.ErrorReadNotifyUser), standardError.CurrentEncoding);
2704 error.BeginReadLine();
2709 /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2710 /// specified by BeginOutputReadLine().
2713 [System.Runtime.InteropServices.ComVisible(false)]
2714 public void CancelOutputRead() {
2715 if (output != null) {
2716 output.CancelOperation();
2719 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2722 pendingOutputRead = false;
2727 /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2728 /// specified by BeginErrorReadLine().
2731 [System.Runtime.InteropServices.ComVisible(false)]
2732 public void CancelErrorRead() {
2733 if (error != null) {
2734 error.CancelOperation();
2737 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2740 pendingErrorRead = false;
2743 internal void OutputReadNotifyUser(String data) {
2744 // To avoid ---- between remove handler and raising the event
2745 DataReceivedEventHandler outputDataReceived = OutputDataReceived;
2746 if (outputDataReceived != null) {
2747 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2748 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2749 SynchronizingObject.Invoke(outputDataReceived, new object[] {this, e});
2752 outputDataReceived(this,e); // Call back to user informing data is available.
2757 internal void ErrorReadNotifyUser(String data) {
2758 // To avoid ---- between remove handler and raising the event
2759 DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
2760 if (errorDataReceived != null) {
2761 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2762 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2763 SynchronizingObject.Invoke(errorDataReceived, new object[] {this, e});
2766 errorDataReceived(this,e); // Call back to user informing data is available.
2770 #endif // MONO_FEATURE_PROCESS_START
2773 /// A desired internal state.
2780 HaveProcessInfo = 0x8,
2784 HaveNtProcessInfo = HaveProcessInfo | IsNt
2789 /// This data structure contains information about a process that is collected
2790 /// in bulk by querying the operating system. The reason to make this a separate
2791 /// structure from the process component is so that we can throw it away all at once
2792 /// when Refresh is called on the component.
2795 internal class ProcessInfo {
2797 public ArrayList threadInfoList = new ArrayList();
2798 public int basePriority;
2799 public string processName;
2800 public int processId;
2801 public int handleCount;
2802 public long poolPagedBytes;
2803 public long poolNonpagedBytes;
2804 public long virtualBytes;
2805 public long virtualBytesPeak;
2806 public long workingSetPeak;
2807 public long workingSet;
2808 public long pageFileBytesPeak;
2809 public long pageFileBytes;
2810 public long privateBytes;
2811 public int mainModuleId; // used only for win9x - id is only for use with CreateToolHelp32
2812 public int sessionId;
2818 /// This data structure contains information about a thread in a process that
2819 /// is collected in bulk by querying the operating system. The reason to
2820 /// make this a separate structure from the ProcessThread component is so that we
2821 /// can throw it away all at once when Refresh is called on the component.
2824 internal class ThreadInfo {
2825 public int threadId;
2826 public int processId;
2827 public int basePriority;
2828 public int currentPriority;
2829 public IntPtr startAddress;
2830 public ThreadState threadState;
2832 public ThreadWaitReason threadWaitReason;
2833 #endif // !FEATURE_PAL
2837 /// This data structure contains information about a module in a process that
2838 /// is collected in bulk by querying the operating system. The reason to
2839 /// make this a separate structure from the ProcessModule component is so that we
2840 /// can throw it away all at once when Refresh is called on the component.
2843 internal class ModuleInfo {
2844 public string baseName;
2845 public string fileName;
2846 public IntPtr baseOfDll;
2847 public IntPtr entryPoint;
2848 public int sizeOfImage;
2849 public int Id; // used only on win9x - for matching up with ProcessInfo.mainModuleId
2853 internal static class EnvironmentBlock {
2854 public static byte[] ToByteArray(StringDictionary sd, bool unicode) {
2856 string[] keys = new string[sd.Count];
2857 byte[] envBlock = null;
2858 sd.Keys.CopyTo(keys, 0);
2861 string[] values = new string[sd.Count];
2862 sd.Values.CopyTo(values, 0);
2864 // sort both by the keys
2865 // Windows 2000 requires the environment block to be sorted by the key
2866 // It will first converting the case the strings and do ordinal comparison.
2867 Array.Sort(keys, values, OrdinalCaseInsensitiveComparer.Default);
2869 // create a list of null terminated "key=val" strings
2870 StringBuilder stringBuff = new StringBuilder();
2871 for (int i = 0; i < sd.Count; ++ i) {
2872 stringBuff.Append(keys[i]);
2873 stringBuff.Append('=');
2874 stringBuff.Append(values[i]);
2875 stringBuff.Append('\0');
2877 // an extra null at the end indicates end of list.
2878 stringBuff.Append('\0');
2881 envBlock = Encoding.Unicode.GetBytes(stringBuff.ToString());
2884 envBlock = Encoding.Default.GetBytes(stringBuff.ToString());
2886 if (envBlock.Length > UInt16.MaxValue)
2887 throw new InvalidOperationException(SR.GetString(SR.EnvironmentBlockTooLong, envBlock.Length));
2894 internal class OrdinalCaseInsensitiveComparer : IComparer {
2895 internal static readonly OrdinalCaseInsensitiveComparer Default = new OrdinalCaseInsensitiveComparer();
2897 public int Compare(Object a, Object b) {
2898 String sa = a as String;
2899 String sb = b as String;
2900 if (sa != null && sb != null) {
2901 return String.Compare(sa, sb, StringComparison.OrdinalIgnoreCase);
2903 return Comparer.Default.Compare(a,b);
2907 internal class ProcessThreadTimes {
2908 internal long create;
2910 internal long kernel;
2913 public DateTime StartTime {
2915 return DateTime.FromFileTime(create);
2919 public DateTime ExitTime {
2921 return DateTime.FromFileTime(exit);
2925 public TimeSpan PrivilegedProcessorTime {
2927 return new TimeSpan(kernel);
2931 public TimeSpan UserProcessorTime {
2933 return new TimeSpan(user);
2937 public TimeSpan TotalProcessorTime {
2939 return new TimeSpan(user + kernel);
2945 internal class ShellExecuteHelper {
2946 private NativeMethods.ShellExecuteInfo _executeInfo;
2947 private int _errorCode;
2948 private bool _succeeded;
2950 public ShellExecuteHelper(NativeMethods.ShellExecuteInfo executeInfo) {
2951 _executeInfo = executeInfo;
2954 [ResourceExposure(ResourceScope.None)]
2955 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2956 public void ShellExecuteFunction() {
2957 if (!(_succeeded = NativeMethods.ShellExecuteEx(_executeInfo))) {
2958 _errorCode = Marshal.GetLastWin32Error();
2962 public bool ShellExecuteOnSTAThread() {
2964 // SHELL API ShellExecute() requires STA in order to work correctly.
2965 // If current thread is not a STA thread, we need to call ShellExecute on a new thread.
2967 if( Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) {
2968 ThreadStart threadStart = new ThreadStart(this.ShellExecuteFunction);
2969 Thread executionThread = new Thread(threadStart);
2970 executionThread.SetApartmentState(ApartmentState.STA);
2971 executionThread.Start();
2972 executionThread.Join();
2975 ShellExecuteFunction();
2980 public int ErrorCode {