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;
99 bool priorityBoostEnabled;
100 bool havePriorityBoostEnabled;
104 RegisteredWaitHandle registeredWaitHandle;
105 WaitHandle waitHandle;
106 ISynchronizeInvoke synchronizingObject;
107 StreamReader standardOutput;
108 StreamWriter standardInput;
109 StreamReader standardError;
110 OperatingSystem operatingSystem;
114 static object s_CreateProcessLock = new object();
117 // This enum defines the operation mode for redirected process stream.
118 // We don't support switching between synchronous mode and asynchronous mode.
119 private enum StreamReadMode
126 StreamReadMode outputStreamReadMode;
127 StreamReadMode errorStreamReadMode;
130 StreamReadMode inputStreamReadMode;
133 // Support for asynchrously reading streams
134 [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
135 //[System.Runtime.InteropServices.ComVisible(false)]
136 public event DataReceivedEventHandler OutputDataReceived;
137 [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
138 //[System.Runtime.InteropServices.ComVisible(false)]
139 public event DataReceivedEventHandler ErrorDataReceived;
140 // Abstract the stream details
141 internal AsyncStreamReader output;
142 internal AsyncStreamReader error;
143 internal bool pendingOutputRead;
144 internal bool pendingErrorRead;
147 private static SafeFileHandle InvalidPipeHandle = new SafeFileHandle(IntPtr.Zero, false);
150 internal static TraceSwitch processTracing = new TraceSwitch("processTracing", "Controls debug output from Process component");
152 internal static TraceSwitch processTracing = null;
161 /// Initializes a new instance of the <see cref='System.Diagnostics.Process'/> class.
165 this.machineName = ".";
166 this.outputStreamReadMode = StreamReadMode.undefined;
167 this.errorStreamReadMode = StreamReadMode.undefined;
168 this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
171 [ResourceExposure(ResourceScope.Machine)]
172 Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo) : base() {
173 Debug.Assert(SyntaxCheck.CheckMachineName(machineName), "The machine name should be valid!");
175 this.processInfo = processInfo;
177 this.machineName = machineName;
178 this.isRemoteMachine = isRemoteMachine;
179 this.processId = processId;
180 this.haveProcessId = true;
181 this.outputStreamReadMode = StreamReadMode.undefined;
182 this.errorStreamReadMode = StreamReadMode.undefined;
183 this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
191 /// Returns whether this process component is associated with a real process.
194 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessAssociated)]
197 return haveProcessId || haveProcessHandle;
201 #if !FEATURE_PAL && !MONO
204 /// Gets the base priority of
205 /// the associated process.
208 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessBasePriority)]
209 public int BasePriority {
211 EnsureState(State.HaveProcessInfo);
212 return processInfo.basePriority;
215 #endif // !FEATURE_PAL && !MONO
221 /// value that was specified by the associated process when it was terminated.
224 [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitCode)]
225 public int ExitCode {
227 EnsureState(State.Exited);
230 throw new InvalidOperationException ("Cannot get the exit code from a non-child process on Unix");
239 /// value indicating whether the associated process has been terminated.
242 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTerminated)]
243 public bool HasExited {
246 EnsureState(State.Associated);
247 SafeProcessHandle handle = null;
249 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.SYNCHRONIZE, false);
250 if (handle.IsInvalid) {
256 // Although this is the wrong way to check whether the process has exited,
257 // it was historically the way we checked for it, and a lot of code then took a dependency on
258 // the fact that this would always be set before the pipes were closed, so they would read
259 // the exit code out after calling ReadToEnd() or standard output or standard error. In order
260 // to allow 259 to function as a valid exit code and to break as few people as possible that
261 // took the ReadToEnd dependency, we check for an exit code before doing the more correct
262 // check to see if we have been signalled.
263 if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
265 this.exitCode = exitCode;
269 // The best check for exit is that the kernel process object handle is invalid,
270 // or that it is valid and signaled. Checking if the exit code != STILL_ACTIVE
271 // does not guarantee the process is closed,
272 // since some process could return an actual STILL_ACTIVE exit code (259).
273 if (!signaled) // if we just came from WaitForExit, don't repeat
275 ProcessWaitHandle wh = null;
278 wh = new ProcessWaitHandle(handle);
279 this.signaled = wh.WaitOne(0, false);
290 /* If it's a non-child process, it's impossible to get its exit code on
291 * Unix. We don't throw here, but GetExitCodeProcess (in the io-layer)
292 * will set exitCode to -1, and we will throw if we try to call ExitCode */
293 if (!NativeMethods.GetExitCodeProcess(handle, out exitCode))
294 throw new Win32Exception();
297 this.exitCode = exitCode;
304 ReleaseProcessHandle(handle);
315 private ProcessThreadTimes GetProcessTimes() {
316 ProcessThreadTimes processTimes = new ProcessThreadTimes();
317 SafeProcessHandle handle = null;
319 int access = NativeMethods.PROCESS_QUERY_INFORMATION;
321 if (EnvironmentHelpers.IsWindowsVistaOrAbove())
322 access = NativeMethods.PROCESS_QUERY_LIMITED_INFORMATION;
324 handle = GetProcessHandle(access, false);
325 if( handle.IsInvalid) {
326 // On OS older than XP, we will not be able to get the handle for a process
327 // after it terminates.
328 // On Windows XP and newer OS, the information about a process will stay longer.
329 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
332 if (!NativeMethods.GetProcessTimes(handle,
333 out processTimes.create,
334 out processTimes.exit,
335 out processTimes.kernel,
336 out processTimes.user)) {
337 throw new Win32Exception();
342 ReleaseProcessHandle(handle);
350 /// Gets the time that the associated process exited.
353 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitTime)]
354 public DateTime ExitTime {
357 EnsureState(State.IsNt | State.Exited);
358 exitTime = GetProcessTimes().ExitTime;
364 #endif // !FEATURE_PAL
368 /// Returns the native handle for the associated process. The handle is only available
369 /// if this component started the process.
372 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandle)]
373 public IntPtr Handle {
374 [ResourceExposure(ResourceScope.Machine)]
375 [ResourceConsumption(ResourceScope.Machine)]
377 EnsureState(State.Associated);
378 return OpenProcessHandle(this.m_processAccess).DangerousGetHandle();
382 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
383 public SafeProcessHandle SafeHandle {
385 EnsureState(State.Associated);
386 return OpenProcessHandle(this.m_processAccess);
390 #if !FEATURE_PAL && !MONO
393 /// Gets the number of handles that are associated
394 /// with the process.
397 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandleCount)]
398 public int HandleCount {
400 EnsureState(State.HaveProcessInfo);
401 return processInfo.handleCount;
404 #endif // !FEATURE_PAL && !MONO
409 /// the unique identifier for the associated process.
412 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessId)]
415 EnsureState(State.HaveId);
423 /// the name of the computer on which the associated process is running.
426 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMachineName)]
427 public string MachineName {
429 EnsureState(State.Associated);
439 /// Returns the window handle of the main window of the associated process.
442 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowHandle)]
443 public IntPtr MainWindowHandle {
444 [ResourceExposure(ResourceScope.Machine)]
445 [ResourceConsumption(ResourceScope.Machine)]
447 if (!haveMainWindow) {
448 EnsureState(State.IsLocal | State.HaveId);
449 mainWindowHandle = ProcessManager.GetMainWindowHandle(processId);
451 if (mainWindowHandle != (IntPtr)0) {
452 haveMainWindow = true;
454 // 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
455 // we always did this check but have now changed it to just require a ProcessId. In the case where someone has called Refresh()
456 // and the process has exited this call will throw an exception where as the above code would return 0 as the handle.
457 EnsureState(State.HaveProcessInfo);
460 return mainWindowHandle;
466 /// Returns the caption of the <see cref='System.Diagnostics.Process.MainWindowHandle'/> of
467 /// the process. If the handle is zero (0), then an empty string is returned.
470 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowTitle)]
471 public string MainWindowTitle {
472 [ResourceExposure(ResourceScope.None)]
473 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
475 if (mainWindowTitle == null) {
476 IntPtr handle = MainWindowHandle;
477 if (handle == (IntPtr)0) {
478 mainWindowTitle = String.Empty;
481 int length = NativeMethods.GetWindowTextLength(new HandleRef(this, handle)) * 2;
482 StringBuilder builder = new StringBuilder(length);
483 NativeMethods.GetWindowText(new HandleRef(this, handle), builder, builder.Capacity);
484 mainWindowTitle = builder.ToString();
487 return mainWindowTitle;
496 /// the main module for the associated process.
499 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainModule)]
500 public ProcessModule MainModule {
501 [ResourceExposure(ResourceScope.Process)]
502 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
504 // We only return null if we couldn't find a main module.
505 // This could be because
506 // 1. The process hasn't finished loading the main module (most likely)
507 // 2. There are no modules loaded (possible for certain OS processes)
508 // 3. Possibly other?
510 if (OperatingSystem.Platform == PlatformID.Win32NT) {
511 EnsureState(State.HaveId | State.IsLocal);
512 // on NT the first module is the main module
513 ModuleInfo module = NtProcessManager.GetFirstModuleInfo(processId);
514 return new ProcessModule(module);
517 ProcessModuleCollection moduleCollection = Modules;
518 // on 9x we have to do a little more work
519 EnsureState(State.HaveProcessInfo);
520 foreach (ProcessModule pm in moduleCollection) {
521 if (pm.moduleInfo.Id == processInfo.mainModuleId) {
533 /// Gets or sets the maximum allowable working set for the associated
537 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMaxWorkingSet)]
538 public IntPtr MaxWorkingSet {
540 EnsureWorkingSetLimits();
541 return maxWorkingSet;
543 [ResourceExposure(ResourceScope.Process)]
544 [ResourceConsumption(ResourceScope.Process)]
546 SetWorkingSetLimits(null, value);
552 /// Gets or sets the minimum allowable working set for the associated
556 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMinWorkingSet)]
557 public IntPtr MinWorkingSet {
559 EnsureWorkingSetLimits();
560 return minWorkingSet;
562 [ResourceExposure(ResourceScope.Process)]
563 [ResourceConsumption(ResourceScope.Process)]
565 SetWorkingSetLimits(value, null);
573 /// the modules that have been loaded by the associated process.
576 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessModules)]
577 public ProcessModuleCollection Modules {
578 [ResourceExposure(ResourceScope.None)]
579 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
581 if (modules == null) {
582 EnsureState(State.HaveId | State.IsLocal);
583 ModuleInfo[] moduleInfos = ProcessManager.GetModuleInfos(processId);
584 ProcessModule[] newModulesArray = new ProcessModule[moduleInfos.Length];
585 for (int i = 0; i < moduleInfos.Length; i++) {
586 newModulesArray[i] = new ProcessModule(moduleInfos[i]);
588 ProcessModuleCollection newModules = new ProcessModuleCollection(newModulesArray);
589 modules = newModules;
596 /// Returns the amount of memory that the system has allocated on behalf of the
597 /// associated process that can not be written to the virtual memory paging file.
599 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
600 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
601 public int NonpagedSystemMemorySize {
603 EnsureState(State.HaveNtProcessInfo);
604 return unchecked((int)processInfo.poolNonpagedBytes);
608 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
609 [System.Runtime.InteropServices.ComVisible(false)]
610 public long NonpagedSystemMemorySize64 {
612 EnsureState(State.HaveNtProcessInfo);
613 return processInfo.poolNonpagedBytes;
618 /// Returns the amount of memory that the associated process has allocated
619 /// that can be written to the virtual memory paging file.
621 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PagedMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
622 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
623 public int PagedMemorySize {
625 EnsureState(State.HaveNtProcessInfo);
626 return unchecked((int)processInfo.pageFileBytes);
630 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
631 [System.Runtime.InteropServices.ComVisible(false)]
632 public long PagedMemorySize64 {
634 EnsureState(State.HaveNtProcessInfo);
635 return processInfo.pageFileBytes;
641 /// Returns the amount of memory that the system has allocated on behalf of the
642 /// associated process that can be written to the virtual memory paging file.
644 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PagedSystemMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
645 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
646 public int PagedSystemMemorySize {
648 EnsureState(State.HaveNtProcessInfo);
649 return unchecked((int)processInfo.poolPagedBytes);
653 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
654 [System.Runtime.InteropServices.ComVisible(false)]
655 public long PagedSystemMemorySize64 {
657 EnsureState(State.HaveNtProcessInfo);
658 return processInfo.poolPagedBytes;
665 /// Returns the maximum amount of memory that the associated process has
666 /// allocated that could be written to the virtual memory paging file.
669 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakPagedMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
670 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
671 public int PeakPagedMemorySize {
673 EnsureState(State.HaveNtProcessInfo);
674 return unchecked((int)processInfo.pageFileBytesPeak);
678 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
679 [System.Runtime.InteropServices.ComVisible(false)]
680 public long PeakPagedMemorySize64 {
682 EnsureState(State.HaveNtProcessInfo);
683 return processInfo.pageFileBytesPeak;
689 /// Returns the maximum amount of physical memory that the associated
690 /// process required at once.
693 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakWorkingSet64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
694 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
695 public int PeakWorkingSet {
697 EnsureState(State.HaveNtProcessInfo);
698 return unchecked((int)processInfo.workingSetPeak);
702 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
703 [System.Runtime.InteropServices.ComVisible(false)]
704 public long PeakWorkingSet64 {
706 EnsureState(State.HaveNtProcessInfo);
707 return processInfo.workingSetPeak;
712 /// Returns the maximum amount of virtual memory that the associated
713 /// process has requested.
715 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakVirtualMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
716 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
717 public int PeakVirtualMemorySize {
719 EnsureState(State.HaveNtProcessInfo);
720 return unchecked((int)processInfo.virtualBytesPeak);
724 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
725 [System.Runtime.InteropServices.ComVisible(false)]
726 public long PeakVirtualMemorySize64 {
728 EnsureState(State.HaveNtProcessInfo);
729 return processInfo.virtualBytesPeak;
734 private OperatingSystem OperatingSystem {
736 if (operatingSystem == null) {
737 operatingSystem = Environment.OSVersion;
739 return operatingSystem;
746 /// Gets or sets a value indicating whether the associated process priority
747 /// should be temporarily boosted by the operating system when the main window
751 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityBoostEnabled)]
752 public bool PriorityBoostEnabled {
754 EnsureState(State.IsNt);
755 if (!havePriorityBoostEnabled) {
756 SafeProcessHandle handle = null;
758 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
759 bool disabled = false;
760 if (!NativeMethods.GetProcessPriorityBoost(handle, out disabled)) {
761 throw new Win32Exception();
763 priorityBoostEnabled = !disabled;
764 havePriorityBoostEnabled = true;
767 ReleaseProcessHandle(handle);
770 return priorityBoostEnabled;
773 EnsureState(State.IsNt);
774 SafeProcessHandle handle = null;
776 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
777 if (!NativeMethods.SetProcessPriorityBoost(handle, !value))
778 throw new Win32Exception();
779 priorityBoostEnabled = value;
780 havePriorityBoostEnabled = true;
783 ReleaseProcessHandle(handle);
791 /// Gets or sets the overall priority category for the
792 /// associated process.
795 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityClass)]
796 public ProcessPriorityClass PriorityClass {
798 if (!havePriorityClass) {
799 SafeProcessHandle handle = null;
801 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
802 int value = NativeMethods.GetPriorityClass(handle);
804 throw new Win32Exception();
806 priorityClass = (ProcessPriorityClass)value;
807 havePriorityClass = true;
810 ReleaseProcessHandle(handle);
813 return priorityClass;
815 [ResourceExposure(ResourceScope.Machine)]
816 [ResourceConsumption(ResourceScope.Machine)]
818 if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) {
819 throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
823 // BelowNormal and AboveNormal are only available on Win2k and greater.
824 if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0) &&
825 (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) {
826 throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
830 SafeProcessHandle handle = null;
833 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
834 if (!NativeMethods.SetPriorityClass(handle, (int)value)) {
835 throw new Win32Exception();
837 priorityClass = value;
838 havePriorityClass = true;
841 ReleaseProcessHandle(handle);
848 /// Returns the number of bytes that the associated process has allocated that cannot
849 /// be shared with other processes.
851 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PrivateMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
852 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
853 public int PrivateMemorySize {
855 EnsureState(State.HaveNtProcessInfo);
856 return unchecked((int)processInfo.privateBytes);
860 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
861 [System.Runtime.InteropServices.ComVisible(false)]
862 public long PrivateMemorySize64 {
864 EnsureState(State.HaveNtProcessInfo);
865 return processInfo.privateBytes;
871 /// Returns the amount of time the process has spent running code inside the operating
874 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivilegedProcessorTime)]
875 public TimeSpan PrivilegedProcessorTime {
877 EnsureState(State.IsNt);
878 return GetProcessTimes().PrivilegedProcessorTime;
886 /// the friendly name of the process.
889 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessName)]
890 public string ProcessName {
891 [ResourceExposure(ResourceScope.None)]
892 [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
894 EnsureState(State.HaveProcessInfo);
895 String processName = processInfo.processName;
897 // On some old NT-based OS like win2000, the process name from NTQuerySystemInformation is up to 15 characters.
898 // Processes executing notepad_1234567.exe and notepad_12345678.exe will have the same process name.
899 // GetProcessByNames will not be able find the process for notepad_12345678.exe.
900 // So we will try to replace the name of the process by its main module name if the name is 15 characters.
901 // However we can't always get the module name:
902 // (1) Normal user will not be able to get module information about processes.
903 // (2) We can't get module information about remoting process.
904 // We can't get module name for a remote process
906 if (processName.Length == 15 && ProcessManager.IsNt && ProcessManager.IsOSOlderThanXP && !isRemoteMachine) {
908 String mainModuleName = MainModule.ModuleName;
909 if (mainModuleName != null) {
910 processInfo.processName = Path.ChangeExtension(Path.GetFileName(mainModuleName), null);
914 // If we can't access the module information, we can still use the might-be-truncated name.
915 // We could fail for a few reasons:
916 // (1) We don't enough privilege to get module information.
917 // (2) The process could have terminated.
921 return processInfo.processName;
928 /// or sets which processors the threads in this process can be scheduled to run on.
931 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessorAffinity)]
932 public IntPtr ProcessorAffinity {
934 if (!haveProcessorAffinity) {
935 SafeProcessHandle handle = null;
937 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
938 IntPtr processAffinity;
939 IntPtr systemAffinity;
940 if (!NativeMethods.GetProcessAffinityMask(handle, out processAffinity, out systemAffinity))
941 throw new Win32Exception();
942 processorAffinity = processAffinity;
945 ReleaseProcessHandle(handle);
947 haveProcessorAffinity = true;
949 return processorAffinity;
951 [ResourceExposure(ResourceScope.Machine)]
952 [ResourceConsumption(ResourceScope.Machine)]
954 SafeProcessHandle handle = null;
956 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
957 if (!NativeMethods.SetProcessAffinityMask(handle, value))
958 throw new Win32Exception();
960 processorAffinity = value;
961 haveProcessorAffinity = true;
964 ReleaseProcessHandle(handle);
971 /// Gets a value indicating whether or not the user
972 /// interface of the process is responding.
975 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessResponding)]
976 public bool Responding {
977 [ResourceExposure(ResourceScope.None)]
978 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
980 if (!haveResponding) {
981 IntPtr mainWindow = MainWindowHandle;
982 if (mainWindow == (IntPtr)0) {
987 responding = NativeMethods.SendMessageTimeout(new HandleRef(this, mainWindow), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero, NativeMethods.SMTO_ABORTIFHUNG, 5000, out result) != (IntPtr)0;
994 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessSessionId)]
995 public int SessionId {
997 EnsureState(State.HaveNtProcessInfo);
998 return processInfo.sessionId;
1003 #endif // !FEATURE_PAL
1005 #if MONO_FEATURE_PROCESS_START
1008 /// Gets or sets the properties to pass into the <see cref='System.Diagnostics.Process.Start'/> method for the <see cref='System.Diagnostics.Process'/>
1012 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MonitoringDescription(SR.ProcessStartInfo)]
1013 public ProcessStartInfo StartInfo {
1015 if (startInfo == null) {
1016 startInfo = new ProcessStartInfo(this);
1020 [ResourceExposure(ResourceScope.Machine)]
1022 if (value == null) {
1023 throw new ArgumentNullException("value");
1032 /// Returns the time the associated process was started.
1034 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStartTime)]
1035 public DateTime StartTime {
1037 EnsureState(State.IsNt);
1038 return GetProcessTimes().StartTime;
1041 #endif // !FEATURE_PAL
1044 /// Represents the object used to marshal the event handler
1045 /// calls issued as a result of a Process exit. Normally
1046 /// this property will be set when the component is placed
1047 /// inside a control or a from, since those components are
1048 /// bound to a specific thread.
1053 MonitoringDescription(SR.ProcessSynchronizingObject)
1055 public ISynchronizeInvoke SynchronizingObject {
1057 if (this.synchronizingObject == null && DesignMode) {
1058 IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
1060 object baseComponent = host.RootComponent;
1061 if (baseComponent != null && baseComponent is ISynchronizeInvoke)
1062 this.synchronizingObject = (ISynchronizeInvoke)baseComponent;
1066 return this.synchronizingObject;
1070 this.synchronizingObject = value;
1079 /// Gets the set of threads that are running in the associated
1083 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessThreads)]
1084 public ProcessThreadCollection Threads {
1085 [ResourceExposure(ResourceScope.Process)]
1086 [ResourceConsumption(ResourceScope.Process)]
1088 if (threads == null) {
1089 EnsureState(State.HaveProcessInfo);
1090 int count = processInfo.threadInfoList.Count;
1091 ProcessThread[] newThreadsArray = new ProcessThread[count];
1092 for (int i = 0; i < count; i++) {
1093 newThreadsArray[i] = new ProcessThread(isRemoteMachine, (ThreadInfo)processInfo.threadInfoList[i]);
1095 ProcessThreadCollection newThreads = new ProcessThreadCollection(newThreadsArray);
1096 threads = newThreads;
1104 /// Returns the amount of time the associated process has spent utilizing the CPU.
1105 /// It is the sum of the <see cref='System.Diagnostics.Process.UserProcessorTime'/> and
1106 /// <see cref='System.Diagnostics.Process.PrivilegedProcessorTime'/>.
1108 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTotalProcessorTime)]
1109 public TimeSpan TotalProcessorTime {
1111 EnsureState(State.IsNt);
1112 return GetProcessTimes().TotalProcessorTime;
1117 /// Returns the amount of time the associated process has spent running code
1118 /// inside the application portion of the process (not the operating system core).
1120 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessUserProcessorTime)]
1121 public TimeSpan UserProcessorTime {
1123 EnsureState(State.IsNt);
1124 return GetProcessTimes().UserProcessorTime;
1130 /// Returns the amount of virtual memory that the associated process has requested.
1132 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.VirtualMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
1133 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1134 public int VirtualMemorySize {
1136 EnsureState(State.HaveNtProcessInfo);
1137 return unchecked((int)processInfo.virtualBytes);
1142 #endif // !FEATURE_PAL
1145 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1146 [System.Runtime.InteropServices.ComVisible(false)]
1147 public long VirtualMemorySize64 {
1149 EnsureState(State.HaveNtProcessInfo);
1150 return processInfo.virtualBytes;
1157 /// Gets or sets whether the <see cref='System.Diagnostics.Process.Exited'/>
1159 /// when the process terminates.
1162 [Browsable(false), DefaultValue(false), MonitoringDescription(SR.ProcessEnableRaisingEvents)]
1163 public bool EnableRaisingEvents {
1165 return watchForExit;
1168 if (value != watchForExit) {
1171 OpenProcessHandle();
1172 EnsureWatchingForExit();
1175 StopWatchingForExit();
1178 watchForExit = value;
1183 #if MONO_FEATURE_PROCESS_START
1185 /// <para>[To be supplied.]</para>
1187 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardInput)]
1188 public StreamWriter StandardInput {
1190 if (standardInput == null) {
1191 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardIn));
1195 inputStreamReadMode = StreamReadMode.syncMode;
1197 return standardInput;
1202 /// <para>[To be supplied.]</para>
1204 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardOutput)]
1205 public StreamReader StandardOutput {
1207 if (standardOutput == null) {
1208 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
1211 if(outputStreamReadMode == StreamReadMode.undefined) {
1212 outputStreamReadMode = StreamReadMode.syncMode;
1214 else if (outputStreamReadMode != StreamReadMode.syncMode) {
1215 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
1218 return standardOutput;
1223 /// <para>[To be supplied.]</para>
1225 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardError)]
1226 public StreamReader StandardError {
1228 if (standardError == null) {
1229 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
1232 if(errorStreamReadMode == StreamReadMode.undefined) {
1233 errorStreamReadMode = StreamReadMode.syncMode;
1235 else if (errorStreamReadMode != StreamReadMode.syncMode) {
1236 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
1239 return standardError;
1244 #if !FEATURE_PAL && !MONO
1246 /// Returns the total amount of physical memory the associated process.
1248 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.WorkingSet64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
1249 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1250 public int WorkingSet {
1252 EnsureState(State.HaveNtProcessInfo);
1253 return unchecked((int)processInfo.workingSet);
1256 #endif // !FEATURE_PAL && !MONO
1259 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1260 [System.Runtime.InteropServices.ComVisible(false)]
1261 public long WorkingSet64 {
1263 EnsureState(State.HaveNtProcessInfo);
1264 return processInfo.workingSet;
1269 [Category("Behavior"), MonitoringDescription(SR.ProcessExited)]
1270 public event EventHandler Exited {
1279 #if !FEATURE_PAL && !MONO
1282 /// Closes a process that has a user interface by sending a close message
1283 /// to its main window.
1286 [ResourceExposure(ResourceScope.Machine)] // Review usages of this.
1287 [ResourceConsumption(ResourceScope.Machine)]
1288 public bool CloseMainWindow() {
1289 IntPtr mainWindowHandle = MainWindowHandle;
1290 if (mainWindowHandle == (IntPtr)0) return false;
1291 int style = NativeMethods.GetWindowLong(new HandleRef(this, mainWindowHandle), NativeMethods.GWL_STYLE);
1292 if ((style & NativeMethods.WS_DISABLED) != 0) return false;
1293 NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
1296 #endif // !FEATURE_PAL && !MONO
1299 /// Release the temporary handle we used to get process information.
1300 /// If we used the process handle stored in the process object (we have all access to the handle,) don't release it.
1303 void ReleaseProcessHandle(SafeProcessHandle handle) {
1304 if (handle == null) {
1308 if (haveProcessHandle && handle == m_processHandle) {
1311 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process)");
1316 /// This is called from the threadpool when a proces exits.
1319 private void CompletionCallback(object context, bool wasSignaled) {
1320 StopWatchingForExit();
1327 /// Free any resources associated with this component.
1330 protected override void Dispose(bool disposing) {
1333 //Dispose managed and unmanaged resources
1336 this.disposed = true;
1337 base.Dispose(disposing);
1343 /// Frees any resources associated with this component.
1346 public void Close() {
1348 if (haveProcessHandle) {
1349 StopWatchingForExit();
1350 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process) in Close()");
1351 m_processHandle.Close();
1352 m_processHandle = null;
1353 haveProcessHandle = false;
1355 haveProcessId = false;
1356 isRemoteMachine = false;
1358 raisedOnExited = false;
1361 //Call close on streams if the user never saw them.
1362 //A stream in the undefined mode was never fetched by the user.
1363 //A stream in the async mode is wrapped on a AsyncStreamReader and we should dispose that instead.
1364 // no way for users to get a hand on a AsyncStreamReader.
1365 var tmpIn = standardInput;
1366 standardInput = null;
1367 if (inputStreamReadMode == StreamReadMode.undefined && tmpIn != null)
1370 var tmpOut = standardOutput;
1371 standardOutput = null;
1372 if (outputStreamReadMode == StreamReadMode.undefined && tmpOut != null)
1375 tmpOut = standardError;
1376 standardError = null;
1377 if (errorStreamReadMode == StreamReadMode.undefined && tmpOut != null)
1380 var tmpAsync = output;
1382 if (outputStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
1383 tmpAsync.CancelOperation ();
1389 if (errorStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
1390 tmpAsync.CancelOperation ();
1394 //Don't call close on the Readers and writers
1395 //since they might be referenced by somebody else while the
1396 //process is still alive but this method called.
1397 standardOutput = null;
1398 standardInput = null;
1399 standardError = null;
1411 /// Helper method for checking preconditions when accessing properties.
1414 [ResourceExposure(ResourceScope.None)]
1415 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1416 void EnsureState(State state) {
1419 if ((state & State.IsWin2k) != (State)0) {
1421 if (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)
1422 #endif // !FEATURE_PAL
1423 throw new PlatformNotSupportedException(SR.GetString(SR.Win2kRequired));
1426 if ((state & State.IsNt) != (State)0) {
1428 if (OperatingSystem.Platform != PlatformID.Win32NT)
1429 #endif // !FEATURE_PAL
1430 throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
1434 if ((state & State.Associated) != (State)0)
1436 throw new InvalidOperationException(SR.GetString(SR.NoAssociatedProcess));
1438 if ((state & State.HaveId) != (State)0) {
1439 if (!haveProcessId) {
1440 #if !FEATURE_PAL && !MONO
1441 if (haveProcessHandle) {
1442 SetProcessId(ProcessManager.GetProcessIdFromHandle(m_processHandle));
1445 EnsureState(State.Associated);
1446 throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1449 EnsureState(State.Associated);
1450 throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1451 #endif // !FEATURE_PAL && !MONO
1455 if ((state & State.IsLocal) != (State)0 && isRemoteMachine) {
1456 throw new NotSupportedException(SR.GetString(SR.NotSupportedRemote));
1459 if ((state & State.HaveProcessInfo) != (State)0) {
1460 #if !FEATURE_PAL && !MONO
1461 if (processInfo == null) {
1462 if ((state & State.HaveId) == (State)0) EnsureState(State.HaveId);
1463 ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1464 for (int i = 0; i < processInfos.Length; i++) {
1465 if (processInfos[i].processId == processId) {
1466 this.processInfo = processInfos[i];
1470 if (processInfo == null) {
1471 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1475 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1476 #endif // !FEATURE_PAL && !MONO
1479 if ((state & State.Exited) != (State)0) {
1481 throw new InvalidOperationException(SR.GetString(SR.WaitTillExit));
1484 if (!haveProcessHandle) {
1485 throw new InvalidOperationException(SR.GetString(SR.NoProcessHandle));
1491 /// Make sure we are watching for a process exit.
1494 void EnsureWatchingForExit() {
1495 if (!watchingForExit) {
1497 if (!watchingForExit) {
1498 Debug.Assert(haveProcessHandle, "Process.EnsureWatchingForExit called with no process handle");
1499 Debug.Assert(Associated, "Process.EnsureWatchingForExit called with no associated process");
1500 watchingForExit = true;
1502 this.waitHandle = new ProcessWaitHandle(m_processHandle);
1503 this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(this.waitHandle,
1504 new WaitOrTimerCallback(this.CompletionCallback), null, -1, true);
1507 watchingForExit = false;
1518 /// Make sure we have obtained the min and max working set limits.
1521 void EnsureWorkingSetLimits() {
1522 EnsureState(State.IsNt);
1523 if (!haveWorkingSetLimits) {
1524 SafeProcessHandle handle = null;
1526 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
1529 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1530 throw new Win32Exception();
1532 minWorkingSet = min;
1533 maxWorkingSet = max;
1534 haveWorkingSetLimits = true;
1537 ReleaseProcessHandle(handle);
1542 public static void EnterDebugMode() {
1544 if (ProcessManager.IsNt) {
1545 SetPrivilege("SeDebugPrivilege", NativeMethods.SE_PRIVILEGE_ENABLED);
1551 [ResourceExposure(ResourceScope.None)]
1552 [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
1553 private static void SetPrivilege(string privilegeName, int attrib) {
1554 IntPtr hToken = (IntPtr)0;
1555 NativeMethods.LUID debugValue = new NativeMethods.LUID();
1557 // this is only a "pseudo handle" to the current process - no need to close it later
1558 IntPtr processHandle = NativeMethods.GetCurrentProcess();
1560 // get the process token so we can adjust the privilege on it. We DO need to
1561 // close the token when we're done with it.
1562 if (!NativeMethods.OpenProcessToken(new HandleRef(null, processHandle), NativeMethods.TOKEN_ADJUST_PRIVILEGES, out hToken)) {
1563 throw new Win32Exception();
1567 if (!NativeMethods.LookupPrivilegeValue(null, privilegeName, out debugValue)) {
1568 throw new Win32Exception();
1571 NativeMethods.TokenPrivileges tkp = new NativeMethods.TokenPrivileges();
1572 tkp.Luid = debugValue;
1573 tkp.Attributes = attrib;
1575 NativeMethods.AdjustTokenPrivileges(new HandleRef(null, hToken), false, tkp, 0, IntPtr.Zero, IntPtr.Zero);
1577 // AdjustTokenPrivileges can return true even if it failed to
1578 // set the privilege, so we need to use GetLastError
1579 if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_SUCCESS) {
1580 throw new Win32Exception();
1584 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(processToken)");
1585 SafeNativeMethods.CloseHandle(hToken);
1591 /// <para>[To be supplied.]</para>
1593 public static void LeaveDebugMode() {
1595 if (ProcessManager.IsNt) {
1596 SetPrivilege("SeDebugPrivilege", 0);
1604 /// Returns a new <see cref='System.Diagnostics.Process'/> component given a process identifier and
1605 /// the name of a computer in the network.
1608 [ResourceExposure(ResourceScope.Machine)]
1609 [ResourceConsumption(ResourceScope.Machine)]
1610 public static Process GetProcessById(int processId, string machineName) {
1611 if (!ProcessManager.IsProcessRunning(processId, machineName)) {
1612 throw new ArgumentException(SR.GetString(SR.MissingProccess, processId.ToString(CultureInfo.CurrentCulture)));
1615 return new Process(machineName, ProcessManager.IsRemoteMachine(machineName), processId, null);
1620 /// Returns a new <see cref='System.Diagnostics.Process'/> component given the
1621 /// identifier of a process on the local computer.
1624 [ResourceExposure(ResourceScope.Machine)]
1625 [ResourceConsumption(ResourceScope.Machine)]
1626 public static Process GetProcessById(int processId) {
1627 return GetProcessById(processId, ".");
1632 /// Creates an array of <see cref='System.Diagnostics.Process'/> components that are
1634 /// with process resources on the
1635 /// local computer. These process resources share the specified process name.
1638 [ResourceExposure(ResourceScope.Machine)]
1639 [ResourceConsumption(ResourceScope.Machine)]
1640 public static Process[] GetProcessesByName(string processName) {
1641 return GetProcessesByName(processName, ".");
1646 /// Creates an array of <see cref='System.Diagnostics.Process'/> components that are associated with process resources on a
1647 /// remote computer. These process resources share the specified process name.
1650 [ResourceExposure(ResourceScope.Machine)]
1651 [ResourceConsumption(ResourceScope.Machine)]
1652 public static Process[] GetProcessesByName(string processName, string machineName) {
1653 if (processName == null) processName = String.Empty;
1654 Process[] procs = GetProcesses(machineName);
1655 ArrayList list = new ArrayList();
1657 for(int i = 0; i < procs.Length; i++) {
1658 if( String.Equals(processName, procs[i].ProcessName, StringComparison.OrdinalIgnoreCase)) {
1659 list.Add( procs[i]);
1665 Process[] temp = new Process[list.Count];
1666 list.CopyTo(temp, 0);
1672 /// Creates a new <see cref='System.Diagnostics.Process'/>
1673 /// component for each process resource on the local computer.
1676 [ResourceExposure(ResourceScope.Machine)]
1677 [ResourceConsumption(ResourceScope.Machine)]
1678 public static Process[] GetProcesses() {
1679 return GetProcesses(".");
1684 /// Creates a new <see cref='System.Diagnostics.Process'/>
1685 /// component for each
1686 /// process resource on the specified computer.
1689 [ResourceExposure(ResourceScope.Machine)]
1690 [ResourceConsumption(ResourceScope.Machine)]
1691 public static Process[] GetProcesses(string machineName) {
1692 bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName);
1693 ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1694 Process[] processes = new Process[processInfos.Length];
1695 for (int i = 0; i < processInfos.Length; i++) {
1696 ProcessInfo processInfo = processInfos[i];
1697 processes[i] = new Process(machineName, isRemoteMachine, processInfo.processId, processInfo);
1699 Debug.WriteLineIf(processTracing.TraceVerbose, "Process.GetProcesses(" + machineName + ")");
1701 if (processTracing.TraceVerbose) {
1703 for (int i = 0; i < processInfos.Length; i++) {
1704 Debug.WriteLine(processes[i].Id + ": " + processes[i].ProcessName);
1713 #endif // !FEATURE_PAL
1717 /// Returns a new <see cref='System.Diagnostics.Process'/>
1718 /// component and associates it with the current active process.
1721 [ResourceExposure(ResourceScope.Process)]
1722 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Process)]
1723 public static Process GetCurrentProcess() {
1724 return new Process(".", false, NativeMethods.GetCurrentProcessId(), null);
1729 /// Raises the <see cref='System.Diagnostics.Process.Exited'/> event.
1732 protected void OnExited() {
1733 EventHandler exited = onExited;
1734 if (exited != null) {
1735 if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired)
1736 this.SynchronizingObject.BeginInvoke(exited, new object[]{this, EventArgs.Empty});
1738 exited(this, EventArgs.Empty);
1743 /// Gets a short-term handle to the process, with the given access.
1744 /// If a handle is stored in current process object, then use it.
1745 /// Note that the handle we stored in current process object will have all access we need.
1748 [ResourceExposure(ResourceScope.None)]
1749 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1750 SafeProcessHandle GetProcessHandle(int access, bool throwIfExited) {
1751 Debug.WriteLineIf(processTracing.TraceVerbose, "GetProcessHandle(access = 0x" + access.ToString("X8", CultureInfo.InvariantCulture) + ", throwIfExited = " + throwIfExited + ")");
1753 if (processTracing.TraceVerbose) {
1754 StackFrame calledFrom = new StackTrace(true).GetFrame(0);
1755 Debug.WriteLine(" called from " + calledFrom.GetFileName() + ", line " + calledFrom.GetFileLineNumber());
1758 if (haveProcessHandle) {
1759 if (throwIfExited) {
1760 // Since haveProcessHandle is true, we know we have the process handle
1761 // open with at least SYNCHRONIZE access, so we can wait on it with
1762 // zero timeout to see if the process has exited.
1763 ProcessWaitHandle waitHandle = null;
1765 waitHandle = new ProcessWaitHandle(m_processHandle);
1766 if (waitHandle.WaitOne(0, false)) {
1768 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1770 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
1774 if( waitHandle != null) {
1779 return m_processHandle;
1782 EnsureState(State.HaveId | State.IsLocal);
1783 SafeProcessHandle handle = SafeProcessHandle.InvalidHandle;
1784 #if !FEATURE_PAL && !MONO
1785 handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
1787 IntPtr pseudohandle = NativeMethods.GetCurrentProcess();
1788 // Get a real handle
1789 if (!NativeMethods.DuplicateHandle (new HandleRef(this, pseudohandle),
1790 new HandleRef(this, pseudohandle),
1791 new HandleRef(this, pseudohandle),
1795 NativeMethods.DUPLICATE_SAME_ACCESS |
1796 NativeMethods.DUPLICATE_CLOSE_SOURCE)) {
1797 throw new Win32Exception();
1799 #endif // !FEATURE_PAL && !MONO
1800 if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) {
1801 if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
1802 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1811 /// Gets a short-term handle to the process, with the given access. If a handle exists,
1812 /// then it is reused. If the process has exited, it throws an exception.
1815 SafeProcessHandle GetProcessHandle(int access) {
1816 return GetProcessHandle(access, true);
1820 /// Opens a long-term handle to the process, with all access. If a handle exists,
1821 /// then it is reused. If the process has exited, it throws an exception.
1824 SafeProcessHandle OpenProcessHandle() {
1825 return OpenProcessHandle(NativeMethods.PROCESS_ALL_ACCESS);
1828 SafeProcessHandle OpenProcessHandle(Int32 access) {
1829 if (!haveProcessHandle) {
1830 //Cannot open a new process handle if the object has been disposed, since finalization has been suppressed.
1831 if (this.disposed) {
1832 throw new ObjectDisposedException(GetType().Name);
1835 SetProcessHandle(GetProcessHandle(access));
1837 return m_processHandle;
1842 /// Raise the Exited event, but make sure we don't do it more than once.
1845 void RaiseOnExited() {
1846 if (!raisedOnExited) {
1848 if (!raisedOnExited) {
1849 raisedOnExited = true;
1859 /// Discards any information about the associated process
1860 /// that has been cached inside the process component. After <see cref='System.Diagnostics.Process.Refresh'/> is called, the
1861 /// first request for information for each property causes the process component
1862 /// to obtain a new value from the associated process.
1865 public void Refresh() {
1872 #endif // !FEATURE_PAL
1873 mainWindowTitle = null;
1876 haveMainWindow = false;
1877 haveWorkingSetLimits = false;
1878 haveProcessorAffinity = false;
1879 havePriorityClass = false;
1880 haveExitTime = false;
1882 haveResponding = false;
1883 havePriorityBoostEnabled = false;
1888 /// Helper to associate a process handle with this component.
1891 void SetProcessHandle(SafeProcessHandle processHandle) {
1892 this.m_processHandle = processHandle;
1893 this.haveProcessHandle = true;
1895 EnsureWatchingForExit();
1900 /// Helper to associate a process id with this component.
1903 [ResourceExposure(ResourceScope.Machine)]
1904 void SetProcessId(int processId) {
1905 this.processId = processId;
1906 this.haveProcessId = true;
1912 /// Helper to set minimum or maximum working set limits.
1915 [ResourceExposure(ResourceScope.Process)]
1916 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1917 void SetWorkingSetLimits(object newMin, object newMax) {
1918 EnsureState(State.IsNt);
1920 SafeProcessHandle handle = null;
1922 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_SET_QUOTA);
1925 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1926 throw new Win32Exception();
1929 if (newMin != null) {
1930 min = (IntPtr)newMin;
1933 if (newMax != null) {
1934 max = (IntPtr)newMax;
1937 if ((long)min > (long)max) {
1938 if (newMin != null) {
1939 throw new ArgumentException(SR.GetString(SR.BadMinWorkset));
1942 throw new ArgumentException(SR.GetString(SR.BadMaxWorkset));
1946 if (!NativeMethods.SetProcessWorkingSetSize(handle, min, max)) {
1947 throw new Win32Exception();
1950 // The value may be rounded/changed by the OS, so go get it
1951 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1952 throw new Win32Exception();
1954 minWorkingSet = min;
1955 maxWorkingSet = max;
1956 haveWorkingSetLimits = true;
1959 ReleaseProcessHandle(handle);
1963 #endif // !FEATURE_PAL
1965 #if MONO_FEATURE_PROCESS_START
1969 /// Starts a process specified by the <see cref='System.Diagnostics.Process.StartInfo'/> property of this <see cref='System.Diagnostics.Process'/>
1970 /// component and associates it with the
1971 /// <see cref='System.Diagnostics.Process'/> . If a process resource is reused
1972 /// rather than started, the reused process is associated with this <see cref='System.Diagnostics.Process'/>
1976 [ResourceExposure(ResourceScope.None)]
1977 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1978 public bool Start() {
1980 ProcessStartInfo startInfo = StartInfo;
1981 if (startInfo.FileName.Length == 0)
1982 throw new InvalidOperationException(SR.GetString(SR.FileNameMissing));
1984 if (startInfo.UseShellExecute) {
1986 return StartWithShellExecuteEx(startInfo);
1988 throw new InvalidOperationException(SR.GetString(SR.net_perm_invalid_val, "StartInfo.UseShellExecute", true));
1989 #endif // !FEATURE_PAL
1991 return StartWithCreateProcess(startInfo);
1996 [ResourceExposure(ResourceScope.Process)]
1997 [ResourceConsumption(ResourceScope.Process)]
1998 private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) {
1999 bool ret = NativeMethods.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize);
2000 if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid) {
2001 throw new Win32Exception();
2005 // Using synchronous Anonymous pipes for process input/output redirection means we would end up
2006 // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
2007 // it will take advantage of the NT IO completion port infrastructure. But we can't really use
2008 // Overlapped I/O for process input/output as it would break Console apps (managed Console class
2009 // methods such as WriteLine as well as native CRT functions like printf) which are making an
2010 // assumption that the console standard handles (obtained via GetStdHandle()) are opened
2011 // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously!
2012 [ResourceExposure(ResourceScope.None)]
2013 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2014 private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) {
2015 NativeMethods.SECURITY_ATTRIBUTES securityAttributesParent = new NativeMethods.SECURITY_ATTRIBUTES();
2016 securityAttributesParent.bInheritHandle = true;
2018 SafeFileHandle hTmp = null;
2021 CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);
2024 CreatePipeWithSecurityAttributes(out hTmp,
2026 securityAttributesParent,
2029 // Duplicate the parent handle to be non-inheritable so that the child process
2030 // doesn't have access. This is done for correctness sake, exact reason is unclear.
2031 // One potential theory is that child process can do something brain dead like
2032 // closing the parent end of the pipe and there by getting into a blocking situation
2033 // as parent will not be draining the pipe at the other end anymore.
2034 if (!NativeMethods.DuplicateHandle(new HandleRef(this, NativeMethods.GetCurrentProcess()),
2036 new HandleRef(this, NativeMethods.GetCurrentProcess()),
2040 NativeMethods.DUPLICATE_SAME_ACCESS)) {
2041 throw new Win32Exception();
2045 if( hTmp != null && !hTmp.IsInvalid) {
2051 private static StringBuilder BuildCommandLine(string executableFileName, string arguments) {
2052 // Construct a StringBuilder with the appropriate command line
2053 // to pass to CreateProcess. If the filename isn't already
2054 // in quotes, we quote it here. This prevents some security
2055 // problems (it specifies exactly which part of the string
2056 // is the file to execute).
2057 StringBuilder commandLine = new StringBuilder();
2058 string fileName = executableFileName.Trim();
2059 bool fileNameIsQuoted = (fileName.StartsWith("\"", StringComparison.Ordinal) && fileName.EndsWith("\"", StringComparison.Ordinal));
2060 if (!fileNameIsQuoted) {
2061 commandLine.Append("\"");
2064 commandLine.Append(fileName);
2066 if (!fileNameIsQuoted) {
2067 commandLine.Append("\"");
2070 if (!String.IsNullOrEmpty(arguments)) {
2071 commandLine.Append(" ");
2072 commandLine.Append(arguments);
2078 [ResourceExposure(ResourceScope.Machine)]
2079 [ResourceConsumption(ResourceScope.Machine)]
2080 private bool StartWithCreateProcess(ProcessStartInfo startInfo) {
2081 if( startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) {
2082 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2085 if( startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) {
2086 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2089 // See knowledge base article Q190351 for an explanation of the following code. Noteworthy tricky points:
2090 // * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
2091 // that the child process can not close them
2092 // * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
2093 // GetStdHandle for the handles that are not being redirected
2095 //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
2096 if (this.disposed) {
2097 throw new ObjectDisposedException(GetType().Name);
2100 StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
2102 NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO();
2103 SafeNativeMethods.PROCESS_INFORMATION processInfo = new SafeNativeMethods.PROCESS_INFORMATION();
2104 SafeProcessHandle procSH = new SafeProcessHandle();
2105 SafeThreadHandle threadSH = new SafeThreadHandle();
2108 // handles used in parent process
2109 SafeFileHandle standardInputWritePipeHandle = null;
2110 SafeFileHandle standardOutputReadPipeHandle = null;
2111 SafeFileHandle standardErrorReadPipeHandle = null;
2112 GCHandle environmentHandle = new GCHandle();
2113 lock (s_CreateProcessLock) {
2115 // set up the streams
2116 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2117 if (startInfo.RedirectStandardInput) {
2118 CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
2120 startupInfo.hStdInput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);
2123 if (startInfo.RedirectStandardOutput) {
2124 CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false);
2126 startupInfo.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_OUTPUT_HANDLE), false);
2129 if (startInfo.RedirectStandardError) {
2130 CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false);
2132 startupInfo.hStdError = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_ERROR_HANDLE), false);
2135 startupInfo.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
2138 // set up the creation flags paramater
2139 int creationFlags = 0;
2141 if (startInfo.CreateNoWindow) creationFlags |= NativeMethods.CREATE_NO_WINDOW;
2142 #endif // !FEATURE_PAL
2144 // set up the environment block parameter
2145 IntPtr environmentPtr = (IntPtr)0;
2146 if (startInfo.environmentVariables != null) {
2147 bool unicode = false;
2149 if (ProcessManager.IsNt) {
2150 creationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
2153 #endif // !FEATURE_PAL
2155 byte[] environmentBytes = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode);
2156 environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
2157 environmentPtr = environmentHandle.AddrOfPinnedObject();
2160 string workingDirectory = startInfo.WorkingDirectory;
2161 if (workingDirectory == string.Empty)
2162 workingDirectory = Environment.CurrentDirectory;
2165 if (startInfo.UserName.Length != 0) {
2166 if (startInfo.Password != null && startInfo.PasswordInClearText != null)
2167 throw new ArgumentException(SR.GetString(SR.CantSetDuplicatePassword));
2169 NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0;
2170 if( startInfo.LoadUserProfile) {
2171 logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
2174 IntPtr password = IntPtr.Zero;
2176 if( startInfo.Password != null) {
2177 password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
2178 } else if( startInfo.PasswordInClearText != null) {
2179 password = Marshal.StringToCoTaskMemUni(startInfo.PasswordInClearText);
2181 password = Marshal.StringToCoTaskMemUni(String.Empty);
2184 RuntimeHelpers.PrepareConstrainedRegions();
2186 retVal = NativeMethods.CreateProcessWithLogonW(
2191 null, // we don't need this since all the info is in commandLine
2196 startupInfo, // pointer to STARTUPINFO
2197 processInfo // pointer to PROCESS_INFORMATION
2200 errorCode = Marshal.GetLastWin32Error();
2201 if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2202 procSH.InitialSetHandle(processInfo.hProcess);
2203 if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2204 threadSH.InitialSetHandle(processInfo.hThread);
2207 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2208 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2211 throw new Win32Exception(errorCode);
2214 if( password != IntPtr.Zero) {
2215 Marshal.ZeroFreeCoTaskMemUnicode(password);
2219 #endif // !FEATURE_PAL
2220 RuntimeHelpers.PrepareConstrainedRegions();
2222 retVal = NativeMethods.CreateProcess (
2223 null, // we don't need this since all the info is in commandLine
2224 commandLine, // pointer to the command line string
2225 null, // pointer to process security attributes, we don't need to inheriat the handle
2226 null, // pointer to thread security attributes
2227 true, // handle inheritance flag
2228 creationFlags, // creation flags
2229 environmentPtr, // pointer to new environment block
2230 workingDirectory, // pointer to current directory name
2231 startupInfo, // pointer to STARTUPINFO
2232 processInfo // pointer to PROCESS_INFORMATION
2235 errorCode = Marshal.GetLastWin32Error();
2236 if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2237 procSH.InitialSetHandle(processInfo.hProcess);
2238 if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2239 threadSH.InitialSetHandle(processInfo.hThread);
2242 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2243 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2245 throw new Win32Exception(errorCode);
2251 // free environment block
2252 if (environmentHandle.IsAllocated) {
2253 environmentHandle.Free();
2256 startupInfo.Dispose();
2260 if (startInfo.RedirectStandardInput) {
2261 standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096);
2262 standardInput.AutoFlush = true;
2264 if (startInfo.RedirectStandardOutput) {
2265 Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
2266 standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2268 if (startInfo.RedirectStandardError) {
2269 Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
2270 standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2274 if (!procSH.IsInvalid) {
2275 SetProcessHandle(procSH);
2276 SetProcessId(processInfo.dwProcessId);
2289 [ResourceExposure(ResourceScope.Machine)]
2290 [ResourceConsumption(ResourceScope.Machine)]
2291 private bool StartWithShellExecuteEx(ProcessStartInfo startInfo) {
2292 //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
2294 throw new ObjectDisposedException(GetType().Name);
2296 if( !String.IsNullOrEmpty(startInfo.UserName) || (startInfo.Password != null) ) {
2297 throw new InvalidOperationException(SR.GetString(SR.CantStartAsUser));
2300 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2301 throw new InvalidOperationException(SR.GetString(SR.CantRedirectStreams));
2304 if (startInfo.StandardErrorEncoding != null) {
2305 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2308 if (startInfo.StandardOutputEncoding != null) {
2309 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2312 // can't set env vars with ShellExecuteEx...
2313 if (startInfo.environmentVariables != null) {
2314 throw new InvalidOperationException(SR.GetString(SR.CantUseEnvVars));
2317 NativeMethods.ShellExecuteInfo shellExecuteInfo = new NativeMethods.ShellExecuteInfo();
2318 shellExecuteInfo.fMask = NativeMethods.SEE_MASK_NOCLOSEPROCESS;
2319 if (startInfo.ErrorDialog) {
2320 shellExecuteInfo.hwnd = startInfo.ErrorDialogParentHandle;
2323 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_NO_UI;
2326 switch (startInfo.WindowStyle) {
2327 case ProcessWindowStyle.Hidden:
2328 shellExecuteInfo.nShow = NativeMethods.SW_HIDE;
2330 case ProcessWindowStyle.Minimized:
2331 shellExecuteInfo.nShow = NativeMethods.SW_SHOWMINIMIZED;
2333 case ProcessWindowStyle.Maximized:
2334 shellExecuteInfo.nShow = NativeMethods.SW_SHOWMAXIMIZED;
2337 shellExecuteInfo.nShow = NativeMethods.SW_SHOWNORMAL;
2343 if (startInfo.FileName.Length != 0)
2344 shellExecuteInfo.lpFile = Marshal.StringToHGlobalAuto(startInfo.FileName);
2345 if (startInfo.Verb.Length != 0)
2346 shellExecuteInfo.lpVerb = Marshal.StringToHGlobalAuto(startInfo.Verb);
2347 if (startInfo.Arguments.Length != 0)
2348 shellExecuteInfo.lpParameters = Marshal.StringToHGlobalAuto(startInfo.Arguments);
2349 if (startInfo.WorkingDirectory.Length != 0)
2350 shellExecuteInfo.lpDirectory = Marshal.StringToHGlobalAuto(startInfo.WorkingDirectory);
2352 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_DDEWAIT;
2354 ShellExecuteHelper executeHelper = new ShellExecuteHelper(shellExecuteInfo);
2355 if (!executeHelper.ShellExecuteOnSTAThread()) {
2356 int error = executeHelper.ErrorCode;
2358 switch ((long)shellExecuteInfo.hInstApp) {
2359 case NativeMethods.SE_ERR_FNF: error = NativeMethods.ERROR_FILE_NOT_FOUND; break;
2360 case NativeMethods.SE_ERR_PNF: error = NativeMethods.ERROR_PATH_NOT_FOUND; break;
2361 case NativeMethods.SE_ERR_ACCESSDENIED: error = NativeMethods.ERROR_ACCESS_DENIED; break;
2362 case NativeMethods.SE_ERR_OOM: error = NativeMethods.ERROR_NOT_ENOUGH_MEMORY; break;
2363 case NativeMethods.SE_ERR_DDEFAIL:
2364 case NativeMethods.SE_ERR_DDEBUSY:
2365 case NativeMethods.SE_ERR_DDETIMEOUT: error = NativeMethods.ERROR_DDE_FAIL; break;
2366 case NativeMethods.SE_ERR_SHARE: error = NativeMethods.ERROR_SHARING_VIOLATION; break;
2367 case NativeMethods.SE_ERR_NOASSOC: error = NativeMethods.ERROR_NO_ASSOCIATION; break;
2368 case NativeMethods.SE_ERR_DLLNOTFOUND: error = NativeMethods.ERROR_DLL_NOT_FOUND; break;
2369 default: error = (int)shellExecuteInfo.hInstApp; break;
2372 if( error == NativeMethods.ERROR_BAD_EXE_FORMAT || error == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2373 throw new Win32Exception(error, SR.GetString(SR.InvalidApplication));
2375 throw new Win32Exception(error);
2380 if (shellExecuteInfo.lpFile != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpFile);
2381 if (shellExecuteInfo.lpVerb != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpVerb);
2382 if (shellExecuteInfo.lpParameters != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpParameters);
2383 if (shellExecuteInfo.lpDirectory != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpDirectory);
2386 if (shellExecuteInfo.hProcess != (IntPtr)0) {
2387 SafeProcessHandle handle = new SafeProcessHandle(shellExecuteInfo.hProcess);
2388 SetProcessHandle(handle);
2396 [ResourceExposure(ResourceScope.Machine)]
2397 [ResourceConsumption(ResourceScope.Machine)]
2398 public static Process Start( string fileName, string userName, SecureString password, string domain ) {
2399 ProcessStartInfo startInfo = new ProcessStartInfo(fileName);
2400 startInfo.UserName = userName;
2401 startInfo.Password = password;
2402 startInfo.Domain = domain;
2403 startInfo.UseShellExecute = false;
2404 return Start(startInfo);
2407 [ResourceExposure(ResourceScope.Machine)]
2408 [ResourceConsumption(ResourceScope.Machine)]
2409 public static Process Start( string fileName, string arguments, string userName, SecureString password, string domain ) {
2410 ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
2411 startInfo.UserName = userName;
2412 startInfo.Password = password;
2413 startInfo.Domain = domain;
2414 startInfo.UseShellExecute = false;
2415 return Start(startInfo);
2419 #endif // !FEATURE_PAL
2423 /// Starts a process resource by specifying the name of a
2424 /// document or application file. Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2428 [ResourceExposure(ResourceScope.Machine)]
2429 [ResourceConsumption(ResourceScope.Machine)]
2430 public static Process Start(string fileName) {
2431 return Start(new ProcessStartInfo(fileName));
2436 /// Starts a process resource by specifying the name of an
2437 /// application and a set of command line arguments. Associates the process resource
2438 /// with a new <see cref='System.Diagnostics.Process'/>
2442 [ResourceExposure(ResourceScope.Machine)]
2443 [ResourceConsumption(ResourceScope.Machine)]
2444 public static Process Start(string fileName, string arguments) {
2445 return Start(new ProcessStartInfo(fileName, arguments));
2450 /// Starts a process resource specified by the process start
2451 /// information passed in, for example the file name of the process to start.
2452 /// Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2456 [ResourceExposure(ResourceScope.Machine)]
2457 [ResourceConsumption(ResourceScope.Machine)]
2458 public static Process Start(ProcessStartInfo startInfo) {
2459 Process process = new Process();
2460 if (startInfo == null) throw new ArgumentNullException("startInfo");
2461 process.StartInfo = startInfo;
2462 if (process.Start()) {
2468 #endif // MONO_FEATURE_PROCESS_START
2473 /// associated process immediately.
2476 [ResourceExposure(ResourceScope.Machine)]
2477 [ResourceConsumption(ResourceScope.Machine)]
2478 public void Kill() {
2479 SafeProcessHandle handle = null;
2481 handle = GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
2482 if (!NativeMethods.TerminateProcess(handle, -1))
2483 throw new Win32Exception();
2486 ReleaseProcessHandle(handle);
2491 /// Make sure we are not watching for process exit.
2494 void StopWatchingForExit() {
2495 if (watchingForExit) {
2497 if (watchingForExit) {
2498 watchingForExit = false;
2499 registeredWaitHandle.Unregister(null);
2502 registeredWaitHandle = null;
2508 public override string ToString() {
2511 string processName = String.Empty;
2513 // On windows 9x, we can't map a handle to an id.
2514 // So ProcessName will throw. We shouldn't throw in Process.ToString though.
2515 // Process.GetProcesses should be used to get all the processes on the machine.
2516 // The processes returned from it will have a nice name.
2519 processName = this.ProcessName;
2521 catch(PlatformNotSupportedException) {
2523 if( processName.Length != 0) {
2524 return String.Format(CultureInfo.CurrentCulture, "{0} ({1})", base.ToString(), processName);
2526 return base.ToString();
2529 #endif // !FEATURE_PAL
2530 return base.ToString();
2535 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait the specified number of milliseconds for the associated process to exit.
2538 public bool WaitForExit(int milliseconds) {
2539 SafeProcessHandle handle = null;
2541 ProcessWaitHandle processWaitHandle = null;
2543 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE, false);
2544 if (handle.IsInvalid) {
2548 processWaitHandle = new ProcessWaitHandle(handle);
2549 if( processWaitHandle.WaitOne(milliseconds, false)) {
2560 if( processWaitHandle != null) {
2561 processWaitHandle.Close();
2564 // If we have a hard timeout, we cannot wait for the streams
2565 if( output != null && milliseconds == -1) {
2566 output.WaitUtilEOF();
2569 if( error != null && milliseconds == -1) {
2570 error.WaitUtilEOF();
2573 ReleaseProcessHandle(handle);
2577 if (exited && watchForExit) {
2586 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2587 /// indefinitely for the associated process to exit.
2590 public void WaitForExit() {
2598 /// Causes the <see cref='System.Diagnostics.Process'/> component to wait the
2599 /// specified number of milliseconds for the associated process to enter an
2601 /// This is only applicable for processes with a user interface,
2602 /// therefore a message loop.
2605 public bool WaitForInputIdle(int milliseconds) {
2606 SafeProcessHandle handle = null;
2609 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE | NativeMethods.PROCESS_QUERY_INFORMATION);
2610 int ret = NativeMethods.WaitForInputIdle(handle, milliseconds);
2612 case NativeMethods.WAIT_OBJECT_0:
2615 case NativeMethods.WAIT_TIMEOUT:
2618 case NativeMethods.WAIT_FAILED:
2620 throw new InvalidOperationException(SR.GetString(SR.InputIdleUnkownError));
2624 ReleaseProcessHandle(handle);
2631 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2632 /// indefinitely for the associated process to enter an idle state. This
2633 /// is only applicable for processes with a user interface, therefore a message loop.
2636 public bool WaitForInputIdle() {
2637 return WaitForInputIdle(Int32.MaxValue);
2640 #endif // !FEATURE_PAL
2642 #if MONO_FEATURE_PROCESS_START
2643 // Support for working asynchronously with streams
2646 /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2647 /// reading the StandardOutput stream asynchronously. The user can register a callback
2648 /// 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
2649 /// then the remaining information is returned. The user can add an event handler to OutputDataReceived.
2652 [System.Runtime.InteropServices.ComVisible(false)]
2653 public void BeginOutputReadLine() {
2655 if(outputStreamReadMode == StreamReadMode.undefined) {
2656 outputStreamReadMode = StreamReadMode.asyncMode;
2658 else if (outputStreamReadMode != StreamReadMode.asyncMode) {
2659 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
2662 if (pendingOutputRead)
2663 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2665 pendingOutputRead = true;
2666 // We can't detect if there's a pending sychronous read, tream also doesn't.
2667 if (output == null) {
2668 if (standardOutput == null) {
2669 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
2672 Stream s = standardOutput.BaseStream;
2673 output = new AsyncStreamReader(this, s, new UserCallBack(this.OutputReadNotifyUser), standardOutput.CurrentEncoding);
2675 output.BeginReadLine();
2681 /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2682 /// reading the StandardError stream asynchronously. The user can register a callback
2683 /// 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
2684 /// then the remaining information is returned. The user can add an event handler to ErrorDataReceived.
2687 [System.Runtime.InteropServices.ComVisible(false)]
2688 public void BeginErrorReadLine() {
2690 if(errorStreamReadMode == StreamReadMode.undefined) {
2691 errorStreamReadMode = StreamReadMode.asyncMode;
2693 else if (errorStreamReadMode != StreamReadMode.asyncMode) {
2694 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
2697 if (pendingErrorRead) {
2698 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2701 pendingErrorRead = true;
2702 // We can't detect if there's a pending sychronous read, stream also doesn't.
2703 if (error == null) {
2704 if (standardError == null) {
2705 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
2708 Stream s = standardError.BaseStream;
2709 error = new AsyncStreamReader(this, s, new UserCallBack(this.ErrorReadNotifyUser), standardError.CurrentEncoding);
2711 error.BeginReadLine();
2716 /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2717 /// specified by BeginOutputReadLine().
2720 [System.Runtime.InteropServices.ComVisible(false)]
2721 public void CancelOutputRead() {
2722 if (output != null) {
2723 output.CancelOperation();
2726 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2729 pendingOutputRead = false;
2734 /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2735 /// specified by BeginErrorReadLine().
2738 [System.Runtime.InteropServices.ComVisible(false)]
2739 public void CancelErrorRead() {
2740 if (error != null) {
2741 error.CancelOperation();
2744 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2747 pendingErrorRead = false;
2750 internal void OutputReadNotifyUser(String data) {
2751 // To avoid ---- between remove handler and raising the event
2752 DataReceivedEventHandler outputDataReceived = OutputDataReceived;
2753 if (outputDataReceived != null) {
2754 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2755 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2756 SynchronizingObject.Invoke(outputDataReceived, new object[] {this, e});
2759 outputDataReceived(this,e); // Call back to user informing data is available.
2764 internal void ErrorReadNotifyUser(String data) {
2765 // To avoid ---- between remove handler and raising the event
2766 DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
2767 if (errorDataReceived != null) {
2768 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2769 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2770 SynchronizingObject.Invoke(errorDataReceived, new object[] {this, e});
2773 errorDataReceived(this,e); // Call back to user informing data is available.
2777 #endif // MONO_FEATURE_PROCESS_START
2780 /// A desired internal state.
2787 HaveProcessInfo = 0x8,
2791 HaveNtProcessInfo = HaveProcessInfo | IsNt
2796 /// This data structure contains information about a process that is collected
2797 /// in bulk by querying the operating system. The reason to make this a separate
2798 /// structure from the process component is so that we can throw it away all at once
2799 /// when Refresh is called on the component.
2802 internal class ProcessInfo {
2804 public ArrayList threadInfoList = new ArrayList();
2805 public int basePriority;
2806 public string processName;
2807 public int processId;
2808 public int handleCount;
2809 public long poolPagedBytes;
2810 public long poolNonpagedBytes;
2811 public long virtualBytes;
2812 public long virtualBytesPeak;
2813 public long workingSetPeak;
2814 public long workingSet;
2815 public long pageFileBytesPeak;
2816 public long pageFileBytes;
2817 public long privateBytes;
2818 public int mainModuleId; // used only for win9x - id is only for use with CreateToolHelp32
2819 public int sessionId;
2825 /// This data structure contains information about a thread in a process that
2826 /// is collected in bulk by querying the operating system. The reason to
2827 /// make this a separate structure from the ProcessThread component is so that we
2828 /// can throw it away all at once when Refresh is called on the component.
2831 internal class ThreadInfo {
2832 public int threadId;
2833 public int processId;
2834 public int basePriority;
2835 public int currentPriority;
2836 public IntPtr startAddress;
2837 public ThreadState threadState;
2839 public ThreadWaitReason threadWaitReason;
2840 #endif // !FEATURE_PAL
2844 /// This data structure contains information about a module in a process that
2845 /// is collected in bulk by querying the operating system. The reason to
2846 /// make this a separate structure from the ProcessModule component is so that we
2847 /// can throw it away all at once when Refresh is called on the component.
2850 internal class ModuleInfo {
2851 public string baseName;
2852 public string fileName;
2853 public IntPtr baseOfDll;
2854 public IntPtr entryPoint;
2855 public int sizeOfImage;
2856 public int Id; // used only on win9x - for matching up with ProcessInfo.mainModuleId
2860 internal static class EnvironmentBlock {
2861 public static byte[] ToByteArray(StringDictionary sd, bool unicode) {
2863 string[] keys = new string[sd.Count];
2864 byte[] envBlock = null;
2865 sd.Keys.CopyTo(keys, 0);
2868 string[] values = new string[sd.Count];
2869 sd.Values.CopyTo(values, 0);
2871 // sort both by the keys
2872 // Windows 2000 requires the environment block to be sorted by the key
2873 // It will first converting the case the strings and do ordinal comparison.
2874 Array.Sort(keys, values, OrdinalCaseInsensitiveComparer.Default);
2876 // create a list of null terminated "key=val" strings
2877 StringBuilder stringBuff = new StringBuilder();
2878 for (int i = 0; i < sd.Count; ++ i) {
2879 stringBuff.Append(keys[i]);
2880 stringBuff.Append('=');
2881 stringBuff.Append(values[i]);
2882 stringBuff.Append('\0');
2884 // an extra null at the end indicates end of list.
2885 stringBuff.Append('\0');
2888 envBlock = Encoding.Unicode.GetBytes(stringBuff.ToString());
2891 envBlock = Encoding.Default.GetBytes(stringBuff.ToString());
2893 if (envBlock.Length > UInt16.MaxValue)
2894 throw new InvalidOperationException(SR.GetString(SR.EnvironmentBlockTooLong, envBlock.Length));
2901 internal class OrdinalCaseInsensitiveComparer : IComparer {
2902 internal static readonly OrdinalCaseInsensitiveComparer Default = new OrdinalCaseInsensitiveComparer();
2904 public int Compare(Object a, Object b) {
2905 String sa = a as String;
2906 String sb = b as String;
2907 if (sa != null && sb != null) {
2908 return String.Compare(sa, sb, StringComparison.OrdinalIgnoreCase);
2910 return Comparer.Default.Compare(a,b);
2914 internal class ProcessThreadTimes {
2915 internal long create;
2917 internal long kernel;
2920 public DateTime StartTime {
2922 return DateTime.FromFileTime(create);
2926 public DateTime ExitTime {
2928 return DateTime.FromFileTime(exit);
2932 public TimeSpan PrivilegedProcessorTime {
2934 return new TimeSpan(kernel);
2938 public TimeSpan UserProcessorTime {
2940 return new TimeSpan(user);
2944 public TimeSpan TotalProcessorTime {
2946 return new TimeSpan(user + kernel);
2952 internal class ShellExecuteHelper {
2953 private NativeMethods.ShellExecuteInfo _executeInfo;
2954 private int _errorCode;
2955 private bool _succeeded;
2957 public ShellExecuteHelper(NativeMethods.ShellExecuteInfo executeInfo) {
2958 _executeInfo = executeInfo;
2961 [ResourceExposure(ResourceScope.None)]
2962 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2963 public void ShellExecuteFunction() {
2964 if (!(_succeeded = NativeMethods.ShellExecuteEx(_executeInfo))) {
2965 _errorCode = Marshal.GetLastWin32Error();
2969 public bool ShellExecuteOnSTAThread() {
2971 // SHELL API ShellExecute() requires STA in order to work correctly.
2972 // If current thread is not a STA thread, we need to call ShellExecute on a new thread.
2974 if( Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) {
2975 ThreadStart threadStart = new ThreadStart(this.ShellExecuteFunction);
2976 Thread executionThread = new Thread(threadStart);
2977 executionThread.SetApartmentState(ApartmentState.STA);
2978 executionThread.Start();
2979 executionThread.Join();
2982 ShellExecuteFunction();
2987 public int ErrorCode {