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 // Support for asynchrously reading streams
127 [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
128 //[System.Runtime.InteropServices.ComVisible(false)]
129 public event DataReceivedEventHandler OutputDataReceived;
130 [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
131 //[System.Runtime.InteropServices.ComVisible(false)]
132 public event DataReceivedEventHandler ErrorDataReceived;
133 // Abstract the stream details
134 internal AsyncStreamReader output;
135 internal AsyncStreamReader error;
136 internal bool pendingOutputRead;
137 internal bool pendingErrorRead;
140 private static SafeFileHandle InvalidPipeHandle = new SafeFileHandle(IntPtr.Zero, false);
142 internal static TraceSwitch processTracing = new TraceSwitch("processTracing", "Controls debug output from Process component");
144 internal static TraceSwitch processTracing = null;
153 /// Initializes a new instance of the <see cref='System.Diagnostics.Process'/> class.
157 this.machineName = ".";
158 this.outputStreamReadMode = StreamReadMode.undefined;
159 this.errorStreamReadMode = StreamReadMode.undefined;
160 this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
163 [ResourceExposure(ResourceScope.Machine)]
164 Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo) : base() {
165 Debug.Assert(SyntaxCheck.CheckMachineName(machineName), "The machine name should be valid!");
167 this.processInfo = processInfo;
169 this.machineName = machineName;
170 this.isRemoteMachine = isRemoteMachine;
171 this.processId = processId;
172 this.haveProcessId = true;
173 this.outputStreamReadMode = StreamReadMode.undefined;
174 this.errorStreamReadMode = StreamReadMode.undefined;
175 this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
183 /// Returns whether this process component is associated with a real process.
186 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessAssociated)]
189 return haveProcessId || haveProcessHandle;
193 #if !FEATURE_PAL && !MONO
196 /// Gets the base priority of
197 /// the associated process.
200 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessBasePriority)]
201 public int BasePriority {
203 EnsureState(State.HaveProcessInfo);
204 return processInfo.basePriority;
207 #endif // !FEATURE_PAL && !MONO
213 /// value that was specified by the associated process when it was terminated.
216 [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitCode)]
217 public int ExitCode {
219 EnsureState(State.Exited);
222 throw new InvalidOperationException ("Cannot get the exit code from a non-child process on Unix");
231 /// value indicating whether the associated process has been terminated.
234 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTerminated)]
235 public bool HasExited {
238 EnsureState(State.Associated);
239 SafeProcessHandle handle = null;
241 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.SYNCHRONIZE, false);
242 if (handle.IsInvalid) {
248 // Although this is the wrong way to check whether the process has exited,
249 // it was historically the way we checked for it, and a lot of code then took a dependency on
250 // the fact that this would always be set before the pipes were closed, so they would read
251 // the exit code out after calling ReadToEnd() or standard output or standard error. In order
252 // to allow 259 to function as a valid exit code and to break as few people as possible that
253 // took the ReadToEnd dependency, we check for an exit code before doing the more correct
254 // check to see if we have been signalled.
255 if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
257 this.exitCode = exitCode;
261 // The best check for exit is that the kernel process object handle is invalid,
262 // or that it is valid and signaled. Checking if the exit code != STILL_ACTIVE
263 // does not guarantee the process is closed,
264 // since some process could return an actual STILL_ACTIVE exit code (259).
265 if (!signaled) // if we just came from WaitForExit, don't repeat
267 ProcessWaitHandle wh = null;
270 wh = new ProcessWaitHandle(handle);
271 this.signaled = wh.WaitOne(0, false);
282 /* If it's a non-child process, it's impossible to get its exit code on
283 * Unix. We don't throw here, but GetExitCodeProcess (in the io-layer)
284 * will set exitCode to -1, and we will throw if we try to call ExitCode */
285 if (!NativeMethods.GetExitCodeProcess(handle, out exitCode))
286 throw new Win32Exception();
289 this.exitCode = exitCode;
296 ReleaseProcessHandle(handle);
307 private ProcessThreadTimes GetProcessTimes() {
308 ProcessThreadTimes processTimes = new ProcessThreadTimes();
309 SafeProcessHandle handle = null;
311 int access = NativeMethods.PROCESS_QUERY_INFORMATION;
313 if (EnvironmentHelpers.IsWindowsVistaOrAbove())
314 access = NativeMethods.PROCESS_QUERY_LIMITED_INFORMATION;
316 handle = GetProcessHandle(access, false);
317 if( handle.IsInvalid) {
318 // On OS older than XP, we will not be able to get the handle for a process
319 // after it terminates.
320 // On Windows XP and newer OS, the information about a process will stay longer.
321 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
324 if (!NativeMethods.GetProcessTimes(handle,
325 out processTimes.create,
326 out processTimes.exit,
327 out processTimes.kernel,
328 out processTimes.user)) {
329 throw new Win32Exception();
334 ReleaseProcessHandle(handle);
342 /// Gets the time that the associated process exited.
345 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitTime)]
346 public DateTime ExitTime {
349 EnsureState(State.IsNt | State.Exited);
350 exitTime = GetProcessTimes().ExitTime;
356 #endif // !FEATURE_PAL
360 /// Returns the native handle for the associated process. The handle is only available
361 /// if this component started the process.
364 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandle)]
365 public IntPtr Handle {
366 [ResourceExposure(ResourceScope.Machine)]
367 [ResourceConsumption(ResourceScope.Machine)]
369 EnsureState(State.Associated);
370 return OpenProcessHandle(this.m_processAccess).DangerousGetHandle();
374 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
375 public SafeProcessHandle SafeHandle {
377 EnsureState(State.Associated);
378 return OpenProcessHandle(this.m_processAccess);
382 #if !FEATURE_PAL && !MONO
385 /// Gets the number of handles that are associated
386 /// with the process.
389 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandleCount)]
390 public int HandleCount {
392 EnsureState(State.HaveProcessInfo);
393 return processInfo.handleCount;
396 #endif // !FEATURE_PAL && !MONO
401 /// the unique identifier for the associated process.
404 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessId)]
407 EnsureState(State.HaveId);
415 /// the name of the computer on which the associated process is running.
418 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMachineName)]
419 public string MachineName {
421 EnsureState(State.Associated);
431 /// Returns the window handle of the main window of the associated process.
434 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowHandle)]
435 public IntPtr MainWindowHandle {
436 [ResourceExposure(ResourceScope.Machine)]
437 [ResourceConsumption(ResourceScope.Machine)]
439 if (!haveMainWindow) {
440 EnsureState(State.IsLocal | State.HaveId);
441 mainWindowHandle = ProcessManager.GetMainWindowHandle(processId);
443 if (mainWindowHandle != (IntPtr)0) {
444 haveMainWindow = true;
446 // 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
447 // we always did this check but have now changed it to just require a ProcessId. In the case where someone has called Refresh()
448 // and the process has exited this call will throw an exception where as the above code would return 0 as the handle.
449 EnsureState(State.HaveProcessInfo);
452 return mainWindowHandle;
458 /// Returns the caption of the <see cref='System.Diagnostics.Process.MainWindowHandle'/> of
459 /// the process. If the handle is zero (0), then an empty string is returned.
462 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowTitle)]
463 public string MainWindowTitle {
464 [ResourceExposure(ResourceScope.None)]
465 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
467 if (mainWindowTitle == null) {
468 IntPtr handle = MainWindowHandle;
469 if (handle == (IntPtr)0) {
470 mainWindowTitle = String.Empty;
473 int length = NativeMethods.GetWindowTextLength(new HandleRef(this, handle)) * 2;
474 StringBuilder builder = new StringBuilder(length);
475 NativeMethods.GetWindowText(new HandleRef(this, handle), builder, builder.Capacity);
476 mainWindowTitle = builder.ToString();
479 return mainWindowTitle;
488 /// the main module for the associated process.
491 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainModule)]
492 public ProcessModule MainModule {
493 [ResourceExposure(ResourceScope.Process)]
494 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
496 // We only return null if we couldn't find a main module.
497 // This could be because
498 // 1. The process hasn't finished loading the main module (most likely)
499 // 2. There are no modules loaded (possible for certain OS processes)
500 // 3. Possibly other?
502 if (OperatingSystem.Platform == PlatformID.Win32NT) {
503 EnsureState(State.HaveId | State.IsLocal);
504 // on NT the first module is the main module
505 ModuleInfo module = NtProcessManager.GetFirstModuleInfo(processId);
506 return new ProcessModule(module);
509 ProcessModuleCollection moduleCollection = Modules;
510 // on 9x we have to do a little more work
511 EnsureState(State.HaveProcessInfo);
512 foreach (ProcessModule pm in moduleCollection) {
513 if (pm.moduleInfo.Id == processInfo.mainModuleId) {
525 /// Gets or sets the maximum allowable working set for the associated
529 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMaxWorkingSet)]
530 public IntPtr MaxWorkingSet {
532 EnsureWorkingSetLimits();
533 return maxWorkingSet;
535 [ResourceExposure(ResourceScope.Process)]
536 [ResourceConsumption(ResourceScope.Process)]
538 SetWorkingSetLimits(null, value);
544 /// Gets or sets the minimum allowable working set for the associated
548 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMinWorkingSet)]
549 public IntPtr MinWorkingSet {
551 EnsureWorkingSetLimits();
552 return minWorkingSet;
554 [ResourceExposure(ResourceScope.Process)]
555 [ResourceConsumption(ResourceScope.Process)]
557 SetWorkingSetLimits(value, null);
565 /// the modules that have been loaded by the associated process.
568 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessModules)]
569 public ProcessModuleCollection Modules {
570 [ResourceExposure(ResourceScope.None)]
571 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
573 if (modules == null) {
574 EnsureState(State.HaveId | State.IsLocal);
575 ModuleInfo[] moduleInfos = ProcessManager.GetModuleInfos(processId);
576 ProcessModule[] newModulesArray = new ProcessModule[moduleInfos.Length];
577 for (int i = 0; i < moduleInfos.Length; i++) {
578 newModulesArray[i] = new ProcessModule(moduleInfos[i]);
580 ProcessModuleCollection newModules = new ProcessModuleCollection(newModulesArray);
581 modules = newModules;
588 /// Returns the amount of memory that the system has allocated on behalf of the
589 /// associated process that can not be written to the virtual memory paging file.
591 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
592 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
593 public int NonpagedSystemMemorySize {
595 EnsureState(State.HaveNtProcessInfo);
596 return unchecked((int)processInfo.poolNonpagedBytes);
600 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
601 [System.Runtime.InteropServices.ComVisible(false)]
602 public long NonpagedSystemMemorySize64 {
604 EnsureState(State.HaveNtProcessInfo);
605 return processInfo.poolNonpagedBytes;
610 /// Returns the amount of memory that the associated process has allocated
611 /// that can be written to the virtual memory paging file.
613 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PagedMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
614 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
615 public int PagedMemorySize {
617 EnsureState(State.HaveNtProcessInfo);
618 return unchecked((int)processInfo.pageFileBytes);
622 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
623 [System.Runtime.InteropServices.ComVisible(false)]
624 public long PagedMemorySize64 {
626 EnsureState(State.HaveNtProcessInfo);
627 return processInfo.pageFileBytes;
633 /// Returns the amount of memory that the system has allocated on behalf of the
634 /// associated process that can be written to the virtual memory paging file.
636 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PagedSystemMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
637 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
638 public int PagedSystemMemorySize {
640 EnsureState(State.HaveNtProcessInfo);
641 return unchecked((int)processInfo.poolPagedBytes);
645 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
646 [System.Runtime.InteropServices.ComVisible(false)]
647 public long PagedSystemMemorySize64 {
649 EnsureState(State.HaveNtProcessInfo);
650 return processInfo.poolPagedBytes;
657 /// Returns the maximum amount of memory that the associated process has
658 /// allocated that could be written to the virtual memory paging file.
661 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakPagedMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
662 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
663 public int PeakPagedMemorySize {
665 EnsureState(State.HaveNtProcessInfo);
666 return unchecked((int)processInfo.pageFileBytesPeak);
670 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
671 [System.Runtime.InteropServices.ComVisible(false)]
672 public long PeakPagedMemorySize64 {
674 EnsureState(State.HaveNtProcessInfo);
675 return processInfo.pageFileBytesPeak;
681 /// Returns the maximum amount of physical memory that the associated
682 /// process required at once.
685 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakWorkingSet64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
686 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
687 public int PeakWorkingSet {
689 EnsureState(State.HaveNtProcessInfo);
690 return unchecked((int)processInfo.workingSetPeak);
694 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
695 [System.Runtime.InteropServices.ComVisible(false)]
696 public long PeakWorkingSet64 {
698 EnsureState(State.HaveNtProcessInfo);
699 return processInfo.workingSetPeak;
704 /// Returns the maximum amount of virtual memory that the associated
705 /// process has requested.
707 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PeakVirtualMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
708 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
709 public int PeakVirtualMemorySize {
711 EnsureState(State.HaveNtProcessInfo);
712 return unchecked((int)processInfo.virtualBytesPeak);
716 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
717 [System.Runtime.InteropServices.ComVisible(false)]
718 public long PeakVirtualMemorySize64 {
720 EnsureState(State.HaveNtProcessInfo);
721 return processInfo.virtualBytesPeak;
726 private OperatingSystem OperatingSystem {
728 if (operatingSystem == null) {
729 operatingSystem = Environment.OSVersion;
731 return operatingSystem;
738 /// Gets or sets a value indicating whether the associated process priority
739 /// should be temporarily boosted by the operating system when the main window
743 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityBoostEnabled)]
744 public bool PriorityBoostEnabled {
746 EnsureState(State.IsNt);
747 if (!havePriorityBoostEnabled) {
748 SafeProcessHandle handle = null;
750 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
751 bool disabled = false;
752 if (!NativeMethods.GetProcessPriorityBoost(handle, out disabled)) {
753 throw new Win32Exception();
755 priorityBoostEnabled = !disabled;
756 havePriorityBoostEnabled = true;
759 ReleaseProcessHandle(handle);
762 return priorityBoostEnabled;
765 EnsureState(State.IsNt);
766 SafeProcessHandle handle = null;
768 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
769 if (!NativeMethods.SetProcessPriorityBoost(handle, !value))
770 throw new Win32Exception();
771 priorityBoostEnabled = value;
772 havePriorityBoostEnabled = true;
775 ReleaseProcessHandle(handle);
783 /// Gets or sets the overall priority category for the
784 /// associated process.
787 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityClass)]
788 public ProcessPriorityClass PriorityClass {
790 if (!havePriorityClass) {
791 SafeProcessHandle handle = null;
793 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
794 int value = NativeMethods.GetPriorityClass(handle);
796 throw new Win32Exception();
798 priorityClass = (ProcessPriorityClass)value;
799 havePriorityClass = true;
802 ReleaseProcessHandle(handle);
805 return priorityClass;
807 [ResourceExposure(ResourceScope.Machine)]
808 [ResourceConsumption(ResourceScope.Machine)]
810 if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) {
811 throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
815 // BelowNormal and AboveNormal are only available on Win2k and greater.
816 if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0) &&
817 (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) {
818 throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
822 SafeProcessHandle handle = null;
825 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
826 if (!NativeMethods.SetPriorityClass(handle, (int)value)) {
827 throw new Win32Exception();
829 priorityClass = value;
830 havePriorityClass = true;
833 ReleaseProcessHandle(handle);
840 /// Returns the number of bytes that the associated process has allocated that cannot
841 /// be shared with other processes.
843 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.PrivateMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
844 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
845 public int PrivateMemorySize {
847 EnsureState(State.HaveNtProcessInfo);
848 return unchecked((int)processInfo.privateBytes);
852 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
853 [System.Runtime.InteropServices.ComVisible(false)]
854 public long PrivateMemorySize64 {
856 EnsureState(State.HaveNtProcessInfo);
857 return processInfo.privateBytes;
863 /// Returns the amount of time the process has spent running code inside the operating
866 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivilegedProcessorTime)]
867 public TimeSpan PrivilegedProcessorTime {
869 EnsureState(State.IsNt);
870 return GetProcessTimes().PrivilegedProcessorTime;
878 /// the friendly name of the process.
881 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessName)]
882 public string ProcessName {
883 [ResourceExposure(ResourceScope.None)]
884 [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
886 EnsureState(State.HaveProcessInfo);
887 String processName = processInfo.processName;
889 // On some old NT-based OS like win2000, the process name from NTQuerySystemInformation is up to 15 characters.
890 // Processes executing notepad_1234567.exe and notepad_12345678.exe will have the same process name.
891 // GetProcessByNames will not be able find the process for notepad_12345678.exe.
892 // So we will try to replace the name of the process by its main module name if the name is 15 characters.
893 // However we can't always get the module name:
894 // (1) Normal user will not be able to get module information about processes.
895 // (2) We can't get module information about remoting process.
896 // We can't get module name for a remote process
898 if (processName.Length == 15 && ProcessManager.IsNt && ProcessManager.IsOSOlderThanXP && !isRemoteMachine) {
900 String mainModuleName = MainModule.ModuleName;
901 if (mainModuleName != null) {
902 processInfo.processName = Path.ChangeExtension(Path.GetFileName(mainModuleName), null);
906 // If we can't access the module information, we can still use the might-be-truncated name.
907 // We could fail for a few reasons:
908 // (1) We don't enough privilege to get module information.
909 // (2) The process could have terminated.
913 return processInfo.processName;
920 /// or sets which processors the threads in this process can be scheduled to run on.
923 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessorAffinity)]
924 public IntPtr ProcessorAffinity {
926 if (!haveProcessorAffinity) {
927 SafeProcessHandle handle = null;
929 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
930 IntPtr processAffinity;
931 IntPtr systemAffinity;
932 if (!NativeMethods.GetProcessAffinityMask(handle, out processAffinity, out systemAffinity))
933 throw new Win32Exception();
934 processorAffinity = processAffinity;
937 ReleaseProcessHandle(handle);
939 haveProcessorAffinity = true;
941 return processorAffinity;
943 [ResourceExposure(ResourceScope.Machine)]
944 [ResourceConsumption(ResourceScope.Machine)]
946 SafeProcessHandle handle = null;
948 handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
949 if (!NativeMethods.SetProcessAffinityMask(handle, value))
950 throw new Win32Exception();
952 processorAffinity = value;
953 haveProcessorAffinity = true;
956 ReleaseProcessHandle(handle);
963 /// Gets a value indicating whether or not the user
964 /// interface of the process is responding.
967 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessResponding)]
968 public bool Responding {
969 [ResourceExposure(ResourceScope.None)]
970 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
972 if (!haveResponding) {
973 IntPtr mainWindow = MainWindowHandle;
974 if (mainWindow == (IntPtr)0) {
979 responding = NativeMethods.SendMessageTimeout(new HandleRef(this, mainWindow), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero, NativeMethods.SMTO_ABORTIFHUNG, 5000, out result) != (IntPtr)0;
986 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessSessionId)]
987 public int SessionId {
989 EnsureState(State.HaveNtProcessInfo);
990 return processInfo.sessionId;
995 #endif // !FEATURE_PAL
997 #if MONO_FEATURE_PROCESS_START
1000 /// Gets or sets the properties to pass into the <see cref='System.Diagnostics.Process.Start'/> method for the <see cref='System.Diagnostics.Process'/>
1004 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MonitoringDescription(SR.ProcessStartInfo)]
1005 public ProcessStartInfo StartInfo {
1007 if (startInfo == null) {
1008 startInfo = new ProcessStartInfo(this);
1012 [ResourceExposure(ResourceScope.Machine)]
1014 if (value == null) {
1015 throw new ArgumentNullException("value");
1024 /// Returns the time the associated process was started.
1026 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStartTime)]
1027 public DateTime StartTime {
1029 EnsureState(State.IsNt);
1030 return GetProcessTimes().StartTime;
1033 #endif // !FEATURE_PAL
1036 /// Represents the object used to marshal the event handler
1037 /// calls issued as a result of a Process exit. Normally
1038 /// this property will be set when the component is placed
1039 /// inside a control or a from, since those components are
1040 /// bound to a specific thread.
1045 MonitoringDescription(SR.ProcessSynchronizingObject)
1047 public ISynchronizeInvoke SynchronizingObject {
1049 if (this.synchronizingObject == null && DesignMode) {
1050 IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
1052 object baseComponent = host.RootComponent;
1053 if (baseComponent != null && baseComponent is ISynchronizeInvoke)
1054 this.synchronizingObject = (ISynchronizeInvoke)baseComponent;
1058 return this.synchronizingObject;
1062 this.synchronizingObject = value;
1071 /// Gets the set of threads that are running in the associated
1075 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessThreads)]
1076 public ProcessThreadCollection Threads {
1077 [ResourceExposure(ResourceScope.Process)]
1078 [ResourceConsumption(ResourceScope.Process)]
1080 if (threads == null) {
1081 EnsureState(State.HaveProcessInfo);
1082 int count = processInfo.threadInfoList.Count;
1083 ProcessThread[] newThreadsArray = new ProcessThread[count];
1084 for (int i = 0; i < count; i++) {
1085 newThreadsArray[i] = new ProcessThread(isRemoteMachine, (ThreadInfo)processInfo.threadInfoList[i]);
1087 ProcessThreadCollection newThreads = new ProcessThreadCollection(newThreadsArray);
1088 threads = newThreads;
1096 /// Returns the amount of time the associated process has spent utilizing the CPU.
1097 /// It is the sum of the <see cref='System.Diagnostics.Process.UserProcessorTime'/> and
1098 /// <see cref='System.Diagnostics.Process.PrivilegedProcessorTime'/>.
1100 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTotalProcessorTime)]
1101 public TimeSpan TotalProcessorTime {
1103 EnsureState(State.IsNt);
1104 return GetProcessTimes().TotalProcessorTime;
1109 /// Returns the amount of time the associated process has spent running code
1110 /// inside the application portion of the process (not the operating system core).
1112 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessUserProcessorTime)]
1113 public TimeSpan UserProcessorTime {
1115 EnsureState(State.IsNt);
1116 return GetProcessTimes().UserProcessorTime;
1122 /// Returns the amount of virtual memory that the associated process has requested.
1124 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.VirtualMemorySize64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
1125 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1126 public int VirtualMemorySize {
1128 EnsureState(State.HaveNtProcessInfo);
1129 return unchecked((int)processInfo.virtualBytes);
1134 #endif // !FEATURE_PAL
1137 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1138 [System.Runtime.InteropServices.ComVisible(false)]
1139 public long VirtualMemorySize64 {
1141 EnsureState(State.HaveNtProcessInfo);
1142 return processInfo.virtualBytes;
1149 /// Gets or sets whether the <see cref='System.Diagnostics.Process.Exited'/>
1151 /// when the process terminates.
1154 [Browsable(false), DefaultValue(false), MonitoringDescription(SR.ProcessEnableRaisingEvents)]
1155 public bool EnableRaisingEvents {
1157 return watchForExit;
1160 if (value != watchForExit) {
1163 OpenProcessHandle();
1164 EnsureWatchingForExit();
1167 StopWatchingForExit();
1170 watchForExit = value;
1175 #if MONO_FEATURE_PROCESS_START
1177 /// <para>[To be supplied.]</para>
1179 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardInput)]
1180 public StreamWriter StandardInput {
1182 if (standardInput == null) {
1183 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardIn));
1186 return standardInput;
1191 /// <para>[To be supplied.]</para>
1193 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardOutput)]
1194 public StreamReader StandardOutput {
1196 if (standardOutput == null) {
1197 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
1200 if(outputStreamReadMode == StreamReadMode.undefined) {
1201 outputStreamReadMode = StreamReadMode.syncMode;
1203 else if (outputStreamReadMode != StreamReadMode.syncMode) {
1204 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
1207 return standardOutput;
1212 /// <para>[To be supplied.]</para>
1214 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardError)]
1215 public StreamReader StandardError {
1217 if (standardError == null) {
1218 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
1221 if(errorStreamReadMode == StreamReadMode.undefined) {
1222 errorStreamReadMode = StreamReadMode.syncMode;
1224 else if (errorStreamReadMode != StreamReadMode.syncMode) {
1225 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
1228 return standardError;
1233 #if !FEATURE_PAL && !MONO
1235 /// Returns the total amount of physical memory the associated process.
1237 [Obsolete("This property has been deprecated. Please use System.Diagnostics.Process.WorkingSet64 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
1238 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1239 public int WorkingSet {
1241 EnsureState(State.HaveNtProcessInfo);
1242 return unchecked((int)processInfo.workingSet);
1245 #endif // !FEATURE_PAL && !MONO
1248 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1249 [System.Runtime.InteropServices.ComVisible(false)]
1250 public long WorkingSet64 {
1252 EnsureState(State.HaveNtProcessInfo);
1253 return processInfo.workingSet;
1258 [Category("Behavior"), MonitoringDescription(SR.ProcessExited)]
1259 public event EventHandler Exited {
1268 #if !FEATURE_PAL && !MONO
1271 /// Closes a process that has a user interface by sending a close message
1272 /// to its main window.
1275 [ResourceExposure(ResourceScope.Machine)] // Review usages of this.
1276 [ResourceConsumption(ResourceScope.Machine)]
1277 public bool CloseMainWindow() {
1278 IntPtr mainWindowHandle = MainWindowHandle;
1279 if (mainWindowHandle == (IntPtr)0) return false;
1280 int style = NativeMethods.GetWindowLong(new HandleRef(this, mainWindowHandle), NativeMethods.GWL_STYLE);
1281 if ((style & NativeMethods.WS_DISABLED) != 0) return false;
1282 NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
1285 #endif // !FEATURE_PAL && !MONO
1288 /// Release the temporary handle we used to get process information.
1289 /// If we used the process handle stored in the process object (we have all access to the handle,) don't release it.
1292 void ReleaseProcessHandle(SafeProcessHandle handle) {
1293 if (handle == null) {
1297 if (haveProcessHandle && handle == m_processHandle) {
1300 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process)");
1305 /// This is called from the threadpool when a proces exits.
1308 private void CompletionCallback(object context, bool wasSignaled) {
1309 StopWatchingForExit();
1316 /// Free any resources associated with this component.
1319 protected override void Dispose(bool disposing) {
1322 //Dispose managed and unmanaged resources
1325 this.disposed = true;
1326 base.Dispose(disposing);
1332 /// Frees any resources associated with this component.
1335 public void Close() {
1337 if (haveProcessHandle) {
1338 StopWatchingForExit();
1339 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process) in Close()");
1340 m_processHandle.Close();
1341 m_processHandle = null;
1342 haveProcessHandle = false;
1344 haveProcessId = false;
1345 isRemoteMachine = false;
1347 raisedOnExited = false;
1349 //Don't call close on the Readers and writers
1350 //since they might be referenced by somebody else while the
1351 //process is still alive but this method called.
1352 standardOutput = null;
1353 standardInput = null;
1354 standardError = null;
1365 /// Helper method for checking preconditions when accessing properties.
1368 [ResourceExposure(ResourceScope.None)]
1369 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1370 void EnsureState(State state) {
1373 if ((state & State.IsWin2k) != (State)0) {
1375 if (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)
1376 #endif // !FEATURE_PAL
1377 throw new PlatformNotSupportedException(SR.GetString(SR.Win2kRequired));
1380 if ((state & State.IsNt) != (State)0) {
1382 if (OperatingSystem.Platform != PlatformID.Win32NT)
1383 #endif // !FEATURE_PAL
1384 throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
1388 if ((state & State.Associated) != (State)0)
1390 throw new InvalidOperationException(SR.GetString(SR.NoAssociatedProcess));
1392 if ((state & State.HaveId) != (State)0) {
1393 if (!haveProcessId) {
1394 #if !FEATURE_PAL && !MONO
1395 if (haveProcessHandle) {
1396 SetProcessId(ProcessManager.GetProcessIdFromHandle(m_processHandle));
1399 EnsureState(State.Associated);
1400 throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1403 EnsureState(State.Associated);
1404 throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1405 #endif // !FEATURE_PAL && !MONO
1409 if ((state & State.IsLocal) != (State)0 && isRemoteMachine) {
1410 throw new NotSupportedException(SR.GetString(SR.NotSupportedRemote));
1413 if ((state & State.HaveProcessInfo) != (State)0) {
1414 #if !FEATURE_PAL && !MONO
1415 if (processInfo == null) {
1416 if ((state & State.HaveId) == (State)0) EnsureState(State.HaveId);
1417 ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1418 for (int i = 0; i < processInfos.Length; i++) {
1419 if (processInfos[i].processId == processId) {
1420 this.processInfo = processInfos[i];
1424 if (processInfo == null) {
1425 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1429 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1430 #endif // !FEATURE_PAL && !MONO
1433 if ((state & State.Exited) != (State)0) {
1435 throw new InvalidOperationException(SR.GetString(SR.WaitTillExit));
1438 if (!haveProcessHandle) {
1439 throw new InvalidOperationException(SR.GetString(SR.NoProcessHandle));
1445 /// Make sure we are watching for a process exit.
1448 void EnsureWatchingForExit() {
1449 if (!watchingForExit) {
1451 if (!watchingForExit) {
1452 Debug.Assert(haveProcessHandle, "Process.EnsureWatchingForExit called with no process handle");
1453 Debug.Assert(Associated, "Process.EnsureWatchingForExit called with no associated process");
1454 watchingForExit = true;
1456 this.waitHandle = new ProcessWaitHandle(m_processHandle);
1457 this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(this.waitHandle,
1458 new WaitOrTimerCallback(this.CompletionCallback), null, -1, true);
1461 watchingForExit = false;
1472 /// Make sure we have obtained the min and max working set limits.
1475 void EnsureWorkingSetLimits() {
1476 EnsureState(State.IsNt);
1477 if (!haveWorkingSetLimits) {
1478 SafeProcessHandle handle = null;
1480 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
1483 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1484 throw new Win32Exception();
1486 minWorkingSet = min;
1487 maxWorkingSet = max;
1488 haveWorkingSetLimits = true;
1491 ReleaseProcessHandle(handle);
1496 public static void EnterDebugMode() {
1498 if (ProcessManager.IsNt) {
1499 SetPrivilege("SeDebugPrivilege", NativeMethods.SE_PRIVILEGE_ENABLED);
1505 [ResourceExposure(ResourceScope.None)]
1506 [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
1507 private static void SetPrivilege(string privilegeName, int attrib) {
1508 IntPtr hToken = (IntPtr)0;
1509 NativeMethods.LUID debugValue = new NativeMethods.LUID();
1511 // this is only a "pseudo handle" to the current process - no need to close it later
1512 IntPtr processHandle = NativeMethods.GetCurrentProcess();
1514 // get the process token so we can adjust the privilege on it. We DO need to
1515 // close the token when we're done with it.
1516 if (!NativeMethods.OpenProcessToken(new HandleRef(null, processHandle), NativeMethods.TOKEN_ADJUST_PRIVILEGES, out hToken)) {
1517 throw new Win32Exception();
1521 if (!NativeMethods.LookupPrivilegeValue(null, privilegeName, out debugValue)) {
1522 throw new Win32Exception();
1525 NativeMethods.TokenPrivileges tkp = new NativeMethods.TokenPrivileges();
1526 tkp.Luid = debugValue;
1527 tkp.Attributes = attrib;
1529 NativeMethods.AdjustTokenPrivileges(new HandleRef(null, hToken), false, tkp, 0, IntPtr.Zero, IntPtr.Zero);
1531 // AdjustTokenPrivileges can return true even if it failed to
1532 // set the privilege, so we need to use GetLastError
1533 if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_SUCCESS) {
1534 throw new Win32Exception();
1538 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(processToken)");
1539 SafeNativeMethods.CloseHandle(hToken);
1545 /// <para>[To be supplied.]</para>
1547 public static void LeaveDebugMode() {
1549 if (ProcessManager.IsNt) {
1550 SetPrivilege("SeDebugPrivilege", 0);
1558 /// Returns a new <see cref='System.Diagnostics.Process'/> component given a process identifier and
1559 /// the name of a computer in the network.
1562 [ResourceExposure(ResourceScope.Machine)]
1563 [ResourceConsumption(ResourceScope.Machine)]
1564 public static Process GetProcessById(int processId, string machineName) {
1565 if (!ProcessManager.IsProcessRunning(processId, machineName)) {
1566 throw new ArgumentException(SR.GetString(SR.MissingProccess, processId.ToString(CultureInfo.CurrentCulture)));
1569 return new Process(machineName, ProcessManager.IsRemoteMachine(machineName), processId, null);
1574 /// Returns a new <see cref='System.Diagnostics.Process'/> component given the
1575 /// identifier of a process on the local computer.
1578 [ResourceExposure(ResourceScope.Machine)]
1579 [ResourceConsumption(ResourceScope.Machine)]
1580 public static Process GetProcessById(int processId) {
1581 return GetProcessById(processId, ".");
1586 /// Creates an array of <see cref='System.Diagnostics.Process'/> components that are
1588 /// with process resources on the
1589 /// local computer. These process resources share the specified process name.
1592 [ResourceExposure(ResourceScope.Machine)]
1593 [ResourceConsumption(ResourceScope.Machine)]
1594 public static Process[] GetProcessesByName(string processName) {
1595 return GetProcessesByName(processName, ".");
1600 /// Creates an array of <see cref='System.Diagnostics.Process'/> components that are associated with process resources on a
1601 /// remote computer. These process resources share the specified process name.
1604 [ResourceExposure(ResourceScope.Machine)]
1605 [ResourceConsumption(ResourceScope.Machine)]
1606 public static Process[] GetProcessesByName(string processName, string machineName) {
1607 if (processName == null) processName = String.Empty;
1608 Process[] procs = GetProcesses(machineName);
1609 ArrayList list = new ArrayList();
1611 for(int i = 0; i < procs.Length; i++) {
1612 if( String.Equals(processName, procs[i].ProcessName, StringComparison.OrdinalIgnoreCase)) {
1613 list.Add( procs[i]);
1619 Process[] temp = new Process[list.Count];
1620 list.CopyTo(temp, 0);
1626 /// Creates a new <see cref='System.Diagnostics.Process'/>
1627 /// component for each process resource on the local computer.
1630 [ResourceExposure(ResourceScope.Machine)]
1631 [ResourceConsumption(ResourceScope.Machine)]
1632 public static Process[] GetProcesses() {
1633 return GetProcesses(".");
1638 /// Creates a new <see cref='System.Diagnostics.Process'/>
1639 /// component for each
1640 /// process resource on the specified computer.
1643 [ResourceExposure(ResourceScope.Machine)]
1644 [ResourceConsumption(ResourceScope.Machine)]
1645 public static Process[] GetProcesses(string machineName) {
1646 bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName);
1647 ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1648 Process[] processes = new Process[processInfos.Length];
1649 for (int i = 0; i < processInfos.Length; i++) {
1650 ProcessInfo processInfo = processInfos[i];
1651 processes[i] = new Process(machineName, isRemoteMachine, processInfo.processId, processInfo);
1653 Debug.WriteLineIf(processTracing.TraceVerbose, "Process.GetProcesses(" + machineName + ")");
1655 if (processTracing.TraceVerbose) {
1657 for (int i = 0; i < processInfos.Length; i++) {
1658 Debug.WriteLine(processes[i].Id + ": " + processes[i].ProcessName);
1667 #endif // !FEATURE_PAL
1671 /// Returns a new <see cref='System.Diagnostics.Process'/>
1672 /// component and associates it with the current active process.
1675 [ResourceExposure(ResourceScope.Process)]
1676 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Process)]
1677 public static Process GetCurrentProcess() {
1678 return new Process(".", false, NativeMethods.GetCurrentProcessId(), null);
1683 /// Raises the <see cref='System.Diagnostics.Process.Exited'/> event.
1686 protected void OnExited() {
1687 EventHandler exited = onExited;
1688 if (exited != null) {
1689 if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired)
1690 this.SynchronizingObject.BeginInvoke(exited, new object[]{this, EventArgs.Empty});
1692 exited(this, EventArgs.Empty);
1697 /// Gets a short-term handle to the process, with the given access.
1698 /// If a handle is stored in current process object, then use it.
1699 /// Note that the handle we stored in current process object will have all access we need.
1702 [ResourceExposure(ResourceScope.None)]
1703 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1704 SafeProcessHandle GetProcessHandle(int access, bool throwIfExited) {
1705 Debug.WriteLineIf(processTracing.TraceVerbose, "GetProcessHandle(access = 0x" + access.ToString("X8", CultureInfo.InvariantCulture) + ", throwIfExited = " + throwIfExited + ")");
1707 if (processTracing.TraceVerbose) {
1708 StackFrame calledFrom = new StackTrace(true).GetFrame(0);
1709 Debug.WriteLine(" called from " + calledFrom.GetFileName() + ", line " + calledFrom.GetFileLineNumber());
1712 if (haveProcessHandle) {
1713 if (throwIfExited) {
1714 // Since haveProcessHandle is true, we know we have the process handle
1715 // open with at least SYNCHRONIZE access, so we can wait on it with
1716 // zero timeout to see if the process has exited.
1717 ProcessWaitHandle waitHandle = null;
1719 waitHandle = new ProcessWaitHandle(m_processHandle);
1720 if (waitHandle.WaitOne(0, false)) {
1722 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1724 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
1728 if( waitHandle != null) {
1733 return m_processHandle;
1736 EnsureState(State.HaveId | State.IsLocal);
1737 SafeProcessHandle handle = SafeProcessHandle.InvalidHandle;
1738 #if !FEATURE_PAL && !MONO
1739 handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
1741 IntPtr pseudohandle = NativeMethods.GetCurrentProcess();
1742 // Get a real handle
1743 if (!NativeMethods.DuplicateHandle (new HandleRef(this, pseudohandle),
1744 new HandleRef(this, pseudohandle),
1745 new HandleRef(this, pseudohandle),
1749 NativeMethods.DUPLICATE_SAME_ACCESS |
1750 NativeMethods.DUPLICATE_CLOSE_SOURCE)) {
1751 throw new Win32Exception();
1753 #endif // !FEATURE_PAL && !MONO
1754 if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) {
1755 if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
1756 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1765 /// Gets a short-term handle to the process, with the given access. If a handle exists,
1766 /// then it is reused. If the process has exited, it throws an exception.
1769 SafeProcessHandle GetProcessHandle(int access) {
1770 return GetProcessHandle(access, true);
1774 /// Opens a long-term handle to the process, with all access. If a handle exists,
1775 /// then it is reused. If the process has exited, it throws an exception.
1778 SafeProcessHandle OpenProcessHandle() {
1779 return OpenProcessHandle(NativeMethods.PROCESS_ALL_ACCESS);
1782 SafeProcessHandle OpenProcessHandle(Int32 access) {
1783 if (!haveProcessHandle) {
1784 //Cannot open a new process handle if the object has been disposed, since finalization has been suppressed.
1785 if (this.disposed) {
1786 throw new ObjectDisposedException(GetType().Name);
1789 SetProcessHandle(GetProcessHandle(access));
1791 return m_processHandle;
1796 /// Raise the Exited event, but make sure we don't do it more than once.
1799 void RaiseOnExited() {
1800 if (!raisedOnExited) {
1802 if (!raisedOnExited) {
1803 raisedOnExited = true;
1813 /// Discards any information about the associated process
1814 /// that has been cached inside the process component. After <see cref='System.Diagnostics.Process.Refresh'/> is called, the
1815 /// first request for information for each property causes the process component
1816 /// to obtain a new value from the associated process.
1819 public void Refresh() {
1826 #endif // !FEATURE_PAL
1827 mainWindowTitle = null;
1830 haveMainWindow = false;
1831 haveWorkingSetLimits = false;
1832 haveProcessorAffinity = false;
1833 havePriorityClass = false;
1834 haveExitTime = false;
1835 haveResponding = false;
1836 havePriorityBoostEnabled = false;
1840 /// Helper to associate a process handle with this component.
1843 void SetProcessHandle(SafeProcessHandle processHandle) {
1844 this.m_processHandle = processHandle;
1845 this.haveProcessHandle = true;
1847 EnsureWatchingForExit();
1852 /// Helper to associate a process id with this component.
1855 [ResourceExposure(ResourceScope.Machine)]
1856 void SetProcessId(int processId) {
1857 this.processId = processId;
1858 this.haveProcessId = true;
1864 /// Helper to set minimum or maximum working set limits.
1867 [ResourceExposure(ResourceScope.Process)]
1868 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1869 void SetWorkingSetLimits(object newMin, object newMax) {
1870 EnsureState(State.IsNt);
1872 SafeProcessHandle handle = null;
1874 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_SET_QUOTA);
1877 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1878 throw new Win32Exception();
1881 if (newMin != null) {
1882 min = (IntPtr)newMin;
1885 if (newMax != null) {
1886 max = (IntPtr)newMax;
1889 if ((long)min > (long)max) {
1890 if (newMin != null) {
1891 throw new ArgumentException(SR.GetString(SR.BadMinWorkset));
1894 throw new ArgumentException(SR.GetString(SR.BadMaxWorkset));
1898 if (!NativeMethods.SetProcessWorkingSetSize(handle, min, max)) {
1899 throw new Win32Exception();
1902 // The value may be rounded/changed by the OS, so go get it
1903 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1904 throw new Win32Exception();
1906 minWorkingSet = min;
1907 maxWorkingSet = max;
1908 haveWorkingSetLimits = true;
1911 ReleaseProcessHandle(handle);
1915 #endif // !FEATURE_PAL
1917 #if MONO_FEATURE_PROCESS_START
1921 /// Starts a process specified by the <see cref='System.Diagnostics.Process.StartInfo'/> property of this <see cref='System.Diagnostics.Process'/>
1922 /// component and associates it with the
1923 /// <see cref='System.Diagnostics.Process'/> . If a process resource is reused
1924 /// rather than started, the reused process is associated with this <see cref='System.Diagnostics.Process'/>
1928 [ResourceExposure(ResourceScope.None)]
1929 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1930 public bool Start() {
1932 ProcessStartInfo startInfo = StartInfo;
1933 if (startInfo.FileName.Length == 0)
1934 throw new InvalidOperationException(SR.GetString(SR.FileNameMissing));
1936 if (startInfo.UseShellExecute) {
1938 return StartWithShellExecuteEx(startInfo);
1940 throw new InvalidOperationException(SR.GetString(SR.net_perm_invalid_val, "StartInfo.UseShellExecute", true));
1941 #endif // !FEATURE_PAL
1943 return StartWithCreateProcess(startInfo);
1948 [ResourceExposure(ResourceScope.Process)]
1949 [ResourceConsumption(ResourceScope.Process)]
1950 private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) {
1951 bool ret = NativeMethods.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize);
1952 if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid) {
1953 throw new Win32Exception();
1957 // Using synchronous Anonymous pipes for process input/output redirection means we would end up
1958 // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
1959 // it will take advantage of the NT IO completion port infrastructure. But we can't really use
1960 // Overlapped I/O for process input/output as it would break Console apps (managed Console class
1961 // methods such as WriteLine as well as native CRT functions like printf) which are making an
1962 // assumption that the console standard handles (obtained via GetStdHandle()) are opened
1963 // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously!
1964 [ResourceExposure(ResourceScope.None)]
1965 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1966 private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) {
1967 NativeMethods.SECURITY_ATTRIBUTES securityAttributesParent = new NativeMethods.SECURITY_ATTRIBUTES();
1968 securityAttributesParent.bInheritHandle = true;
1970 SafeFileHandle hTmp = null;
1973 CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);
1976 CreatePipeWithSecurityAttributes(out hTmp,
1978 securityAttributesParent,
1981 // Duplicate the parent handle to be non-inheritable so that the child process
1982 // doesn't have access. This is done for correctness sake, exact reason is unclear.
1983 // One potential theory is that child process can do something brain dead like
1984 // closing the parent end of the pipe and there by getting into a blocking situation
1985 // as parent will not be draining the pipe at the other end anymore.
1986 if (!NativeMethods.DuplicateHandle(new HandleRef(this, NativeMethods.GetCurrentProcess()),
1988 new HandleRef(this, NativeMethods.GetCurrentProcess()),
1992 NativeMethods.DUPLICATE_SAME_ACCESS)) {
1993 throw new Win32Exception();
1997 if( hTmp != null && !hTmp.IsInvalid) {
2003 private static StringBuilder BuildCommandLine(string executableFileName, string arguments) {
2004 // Construct a StringBuilder with the appropriate command line
2005 // to pass to CreateProcess. If the filename isn't already
2006 // in quotes, we quote it here. This prevents some security
2007 // problems (it specifies exactly which part of the string
2008 // is the file to execute).
2009 StringBuilder commandLine = new StringBuilder();
2010 string fileName = executableFileName.Trim();
2011 bool fileNameIsQuoted = (fileName.StartsWith("\"", StringComparison.Ordinal) && fileName.EndsWith("\"", StringComparison.Ordinal));
2012 if (!fileNameIsQuoted) {
2013 commandLine.Append("\"");
2016 commandLine.Append(fileName);
2018 if (!fileNameIsQuoted) {
2019 commandLine.Append("\"");
2022 if (!String.IsNullOrEmpty(arguments)) {
2023 commandLine.Append(" ");
2024 commandLine.Append(arguments);
2030 [ResourceExposure(ResourceScope.Machine)]
2031 [ResourceConsumption(ResourceScope.Machine)]
2032 private bool StartWithCreateProcess(ProcessStartInfo startInfo) {
2033 if( startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) {
2034 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2037 if( startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) {
2038 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2041 // See knowledge base article Q190351 for an explanation of the following code. Noteworthy tricky points:
2042 // * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
2043 // that the child process can not close them
2044 // * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
2045 // GetStdHandle for the handles that are not being redirected
2047 //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
2048 if (this.disposed) {
2049 throw new ObjectDisposedException(GetType().Name);
2052 StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
2054 NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO();
2055 SafeNativeMethods.PROCESS_INFORMATION processInfo = new SafeNativeMethods.PROCESS_INFORMATION();
2056 SafeProcessHandle procSH = new SafeProcessHandle();
2057 SafeThreadHandle threadSH = new SafeThreadHandle();
2060 // handles used in parent process
2061 SafeFileHandle standardInputWritePipeHandle = null;
2062 SafeFileHandle standardOutputReadPipeHandle = null;
2063 SafeFileHandle standardErrorReadPipeHandle = null;
2064 GCHandle environmentHandle = new GCHandle();
2065 lock (s_CreateProcessLock) {
2067 // set up the streams
2068 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2069 if (startInfo.RedirectStandardInput) {
2070 CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
2072 startupInfo.hStdInput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);
2075 if (startInfo.RedirectStandardOutput) {
2076 CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false);
2078 startupInfo.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_OUTPUT_HANDLE), false);
2081 if (startInfo.RedirectStandardError) {
2082 CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false);
2084 startupInfo.hStdError = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_ERROR_HANDLE), false);
2087 startupInfo.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
2090 // set up the creation flags paramater
2091 int creationFlags = 0;
2093 if (startInfo.CreateNoWindow) creationFlags |= NativeMethods.CREATE_NO_WINDOW;
2094 #endif // !FEATURE_PAL
2096 // set up the environment block parameter
2097 IntPtr environmentPtr = (IntPtr)0;
2098 if (startInfo.environmentVariables != null) {
2099 bool unicode = false;
2101 if (ProcessManager.IsNt) {
2102 creationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
2105 #endif // !FEATURE_PAL
2107 byte[] environmentBytes = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode);
2108 environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
2109 environmentPtr = environmentHandle.AddrOfPinnedObject();
2112 string workingDirectory = startInfo.WorkingDirectory;
2113 if (workingDirectory == string.Empty)
2114 workingDirectory = Environment.CurrentDirectory;
2117 if (startInfo.UserName.Length != 0) {
2118 if (startInfo.Password != null && startInfo.PasswordInClearText != null)
2119 throw new ArgumentException(SR.GetString(SR.CantSetDuplicatePassword));
2121 NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0;
2122 if( startInfo.LoadUserProfile) {
2123 logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
2126 IntPtr password = IntPtr.Zero;
2128 if( startInfo.Password != null) {
2129 password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
2130 } else if( startInfo.PasswordInClearText != null) {
2131 password = Marshal.StringToCoTaskMemUni(startInfo.PasswordInClearText);
2133 password = Marshal.StringToCoTaskMemUni(String.Empty);
2136 RuntimeHelpers.PrepareConstrainedRegions();
2138 retVal = NativeMethods.CreateProcessWithLogonW(
2143 null, // we don't need this since all the info is in commandLine
2148 startupInfo, // pointer to STARTUPINFO
2149 processInfo // pointer to PROCESS_INFORMATION
2152 errorCode = Marshal.GetLastWin32Error();
2153 if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2154 procSH.InitialSetHandle(processInfo.hProcess);
2155 if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2156 threadSH.InitialSetHandle(processInfo.hThread);
2159 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2160 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2163 throw new Win32Exception(errorCode);
2166 if( password != IntPtr.Zero) {
2167 Marshal.ZeroFreeCoTaskMemUnicode(password);
2171 #endif // !FEATURE_PAL
2172 RuntimeHelpers.PrepareConstrainedRegions();
2174 retVal = NativeMethods.CreateProcess (
2175 null, // we don't need this since all the info is in commandLine
2176 commandLine, // pointer to the command line string
2177 null, // pointer to process security attributes, we don't need to inheriat the handle
2178 null, // pointer to thread security attributes
2179 true, // handle inheritance flag
2180 creationFlags, // creation flags
2181 environmentPtr, // pointer to new environment block
2182 workingDirectory, // pointer to current directory name
2183 startupInfo, // pointer to STARTUPINFO
2184 processInfo // pointer to PROCESS_INFORMATION
2187 errorCode = Marshal.GetLastWin32Error();
2188 if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2189 procSH.InitialSetHandle(processInfo.hProcess);
2190 if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2191 threadSH.InitialSetHandle(processInfo.hThread);
2194 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2195 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2197 throw new Win32Exception(errorCode);
2203 // free environment block
2204 if (environmentHandle.IsAllocated) {
2205 environmentHandle.Free();
2208 startupInfo.Dispose();
2212 if (startInfo.RedirectStandardInput) {
2213 standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096);
2214 standardInput.AutoFlush = true;
2216 if (startInfo.RedirectStandardOutput) {
2217 Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
2218 standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2220 if (startInfo.RedirectStandardError) {
2221 Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
2222 standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2226 if (!procSH.IsInvalid) {
2227 SetProcessHandle(procSH);
2228 SetProcessId(processInfo.dwProcessId);
2241 [ResourceExposure(ResourceScope.Machine)]
2242 [ResourceConsumption(ResourceScope.Machine)]
2243 private bool StartWithShellExecuteEx(ProcessStartInfo startInfo) {
2244 //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
2246 throw new ObjectDisposedException(GetType().Name);
2248 if( !String.IsNullOrEmpty(startInfo.UserName) || (startInfo.Password != null) ) {
2249 throw new InvalidOperationException(SR.GetString(SR.CantStartAsUser));
2252 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2253 throw new InvalidOperationException(SR.GetString(SR.CantRedirectStreams));
2256 if (startInfo.StandardErrorEncoding != null) {
2257 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2260 if (startInfo.StandardOutputEncoding != null) {
2261 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2264 // can't set env vars with ShellExecuteEx...
2265 if (startInfo.environmentVariables != null) {
2266 throw new InvalidOperationException(SR.GetString(SR.CantUseEnvVars));
2269 NativeMethods.ShellExecuteInfo shellExecuteInfo = new NativeMethods.ShellExecuteInfo();
2270 shellExecuteInfo.fMask = NativeMethods.SEE_MASK_NOCLOSEPROCESS;
2271 if (startInfo.ErrorDialog) {
2272 shellExecuteInfo.hwnd = startInfo.ErrorDialogParentHandle;
2275 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_NO_UI;
2278 switch (startInfo.WindowStyle) {
2279 case ProcessWindowStyle.Hidden:
2280 shellExecuteInfo.nShow = NativeMethods.SW_HIDE;
2282 case ProcessWindowStyle.Minimized:
2283 shellExecuteInfo.nShow = NativeMethods.SW_SHOWMINIMIZED;
2285 case ProcessWindowStyle.Maximized:
2286 shellExecuteInfo.nShow = NativeMethods.SW_SHOWMAXIMIZED;
2289 shellExecuteInfo.nShow = NativeMethods.SW_SHOWNORMAL;
2295 if (startInfo.FileName.Length != 0)
2296 shellExecuteInfo.lpFile = Marshal.StringToHGlobalAuto(startInfo.FileName);
2297 if (startInfo.Verb.Length != 0)
2298 shellExecuteInfo.lpVerb = Marshal.StringToHGlobalAuto(startInfo.Verb);
2299 if (startInfo.Arguments.Length != 0)
2300 shellExecuteInfo.lpParameters = Marshal.StringToHGlobalAuto(startInfo.Arguments);
2301 if (startInfo.WorkingDirectory.Length != 0)
2302 shellExecuteInfo.lpDirectory = Marshal.StringToHGlobalAuto(startInfo.WorkingDirectory);
2304 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_DDEWAIT;
2306 ShellExecuteHelper executeHelper = new ShellExecuteHelper(shellExecuteInfo);
2307 if (!executeHelper.ShellExecuteOnSTAThread()) {
2308 int error = executeHelper.ErrorCode;
2310 switch ((long)shellExecuteInfo.hInstApp) {
2311 case NativeMethods.SE_ERR_FNF: error = NativeMethods.ERROR_FILE_NOT_FOUND; break;
2312 case NativeMethods.SE_ERR_PNF: error = NativeMethods.ERROR_PATH_NOT_FOUND; break;
2313 case NativeMethods.SE_ERR_ACCESSDENIED: error = NativeMethods.ERROR_ACCESS_DENIED; break;
2314 case NativeMethods.SE_ERR_OOM: error = NativeMethods.ERROR_NOT_ENOUGH_MEMORY; break;
2315 case NativeMethods.SE_ERR_DDEFAIL:
2316 case NativeMethods.SE_ERR_DDEBUSY:
2317 case NativeMethods.SE_ERR_DDETIMEOUT: error = NativeMethods.ERROR_DDE_FAIL; break;
2318 case NativeMethods.SE_ERR_SHARE: error = NativeMethods.ERROR_SHARING_VIOLATION; break;
2319 case NativeMethods.SE_ERR_NOASSOC: error = NativeMethods.ERROR_NO_ASSOCIATION; break;
2320 case NativeMethods.SE_ERR_DLLNOTFOUND: error = NativeMethods.ERROR_DLL_NOT_FOUND; break;
2321 default: error = (int)shellExecuteInfo.hInstApp; break;
2324 if( error == NativeMethods.ERROR_BAD_EXE_FORMAT || error == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2325 throw new Win32Exception(error, SR.GetString(SR.InvalidApplication));
2327 throw new Win32Exception(error);
2332 if (shellExecuteInfo.lpFile != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpFile);
2333 if (shellExecuteInfo.lpVerb != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpVerb);
2334 if (shellExecuteInfo.lpParameters != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpParameters);
2335 if (shellExecuteInfo.lpDirectory != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpDirectory);
2338 if (shellExecuteInfo.hProcess != (IntPtr)0) {
2339 SafeProcessHandle handle = new SafeProcessHandle(shellExecuteInfo.hProcess);
2340 SetProcessHandle(handle);
2348 [ResourceExposure(ResourceScope.Machine)]
2349 [ResourceConsumption(ResourceScope.Machine)]
2350 public static Process Start( string fileName, string userName, SecureString password, string domain ) {
2351 ProcessStartInfo startInfo = new ProcessStartInfo(fileName);
2352 startInfo.UserName = userName;
2353 startInfo.Password = password;
2354 startInfo.Domain = domain;
2355 startInfo.UseShellExecute = false;
2356 return Start(startInfo);
2359 [ResourceExposure(ResourceScope.Machine)]
2360 [ResourceConsumption(ResourceScope.Machine)]
2361 public static Process Start( string fileName, string arguments, string userName, SecureString password, string domain ) {
2362 ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
2363 startInfo.UserName = userName;
2364 startInfo.Password = password;
2365 startInfo.Domain = domain;
2366 startInfo.UseShellExecute = false;
2367 return Start(startInfo);
2371 #endif // !FEATURE_PAL
2375 /// Starts a process resource by specifying the name of a
2376 /// document or application file. Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2380 [ResourceExposure(ResourceScope.Machine)]
2381 [ResourceConsumption(ResourceScope.Machine)]
2382 public static Process Start(string fileName) {
2383 return Start(new ProcessStartInfo(fileName));
2388 /// Starts a process resource by specifying the name of an
2389 /// application and a set of command line arguments. Associates the process resource
2390 /// with a new <see cref='System.Diagnostics.Process'/>
2394 [ResourceExposure(ResourceScope.Machine)]
2395 [ResourceConsumption(ResourceScope.Machine)]
2396 public static Process Start(string fileName, string arguments) {
2397 return Start(new ProcessStartInfo(fileName, arguments));
2402 /// Starts a process resource specified by the process start
2403 /// information passed in, for example the file name of the process to start.
2404 /// Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2408 [ResourceExposure(ResourceScope.Machine)]
2409 [ResourceConsumption(ResourceScope.Machine)]
2410 public static Process Start(ProcessStartInfo startInfo) {
2411 Process process = new Process();
2412 if (startInfo == null) throw new ArgumentNullException("startInfo");
2413 process.StartInfo = startInfo;
2414 if (process.Start()) {
2420 #endif // MONO_FEATURE_PROCESS_START
2425 /// associated process immediately.
2428 [ResourceExposure(ResourceScope.Machine)]
2429 [ResourceConsumption(ResourceScope.Machine)]
2430 public void Kill() {
2431 SafeProcessHandle handle = null;
2433 handle = GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
2434 if (!NativeMethods.TerminateProcess(handle, -1))
2435 throw new Win32Exception();
2438 ReleaseProcessHandle(handle);
2443 /// Make sure we are not watching for process exit.
2446 void StopWatchingForExit() {
2447 if (watchingForExit) {
2449 if (watchingForExit) {
2450 watchingForExit = false;
2451 registeredWaitHandle.Unregister(null);
2454 registeredWaitHandle = null;
2460 public override string ToString() {
2463 string processName = String.Empty;
2465 // On windows 9x, we can't map a handle to an id.
2466 // So ProcessName will throw. We shouldn't throw in Process.ToString though.
2467 // Process.GetProcesses should be used to get all the processes on the machine.
2468 // The processes returned from it will have a nice name.
2471 processName = this.ProcessName;
2473 catch(PlatformNotSupportedException) {
2475 if( processName.Length != 0) {
2476 return String.Format(CultureInfo.CurrentCulture, "{0} ({1})", base.ToString(), processName);
2478 return base.ToString();
2481 #endif // !FEATURE_PAL
2482 return base.ToString();
2487 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait the specified number of milliseconds for the associated process to exit.
2490 public bool WaitForExit(int milliseconds) {
2491 SafeProcessHandle handle = null;
2493 ProcessWaitHandle processWaitHandle = null;
2495 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE, false);
2496 if (handle.IsInvalid) {
2500 processWaitHandle = new ProcessWaitHandle(handle);
2501 if( processWaitHandle.WaitOne(milliseconds, false)) {
2512 if( processWaitHandle != null) {
2513 processWaitHandle.Close();
2516 // If we have a hard timeout, we cannot wait for the streams
2517 if( output != null && milliseconds == -1) {
2518 output.WaitUtilEOF();
2521 if( error != null && milliseconds == -1) {
2522 error.WaitUtilEOF();
2525 ReleaseProcessHandle(handle);
2529 if (exited && watchForExit) {
2538 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2539 /// indefinitely for the associated process to exit.
2542 public void WaitForExit() {
2550 /// Causes the <see cref='System.Diagnostics.Process'/> component to wait the
2551 /// specified number of milliseconds for the associated process to enter an
2553 /// This is only applicable for processes with a user interface,
2554 /// therefore a message loop.
2557 public bool WaitForInputIdle(int milliseconds) {
2558 SafeProcessHandle handle = null;
2561 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE | NativeMethods.PROCESS_QUERY_INFORMATION);
2562 int ret = NativeMethods.WaitForInputIdle(handle, milliseconds);
2564 case NativeMethods.WAIT_OBJECT_0:
2567 case NativeMethods.WAIT_TIMEOUT:
2570 case NativeMethods.WAIT_FAILED:
2572 throw new InvalidOperationException(SR.GetString(SR.InputIdleUnkownError));
2576 ReleaseProcessHandle(handle);
2583 /// Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2584 /// indefinitely for the associated process to enter an idle state. This
2585 /// is only applicable for processes with a user interface, therefore a message loop.
2588 public bool WaitForInputIdle() {
2589 return WaitForInputIdle(Int32.MaxValue);
2592 #endif // !FEATURE_PAL
2594 #if MONO_FEATURE_PROCESS_START
2595 // Support for working asynchronously with streams
2598 /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2599 /// reading the StandardOutput stream asynchronously. The user can register a callback
2600 /// 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
2601 /// then the remaining information is returned. The user can add an event handler to OutputDataReceived.
2604 [System.Runtime.InteropServices.ComVisible(false)]
2605 public void BeginOutputReadLine() {
2607 if(outputStreamReadMode == StreamReadMode.undefined) {
2608 outputStreamReadMode = StreamReadMode.asyncMode;
2610 else if (outputStreamReadMode != StreamReadMode.asyncMode) {
2611 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
2614 if (pendingOutputRead)
2615 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2617 pendingOutputRead = true;
2618 // We can't detect if there's a pending sychronous read, tream also doesn't.
2619 if (output == null) {
2620 if (standardOutput == null) {
2621 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
2624 Stream s = standardOutput.BaseStream;
2625 output = new AsyncStreamReader(this, s, new UserCallBack(this.OutputReadNotifyUser), standardOutput.CurrentEncoding);
2627 output.BeginReadLine();
2633 /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2634 /// reading the StandardError stream asynchronously. The user can register a callback
2635 /// 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
2636 /// then the remaining information is returned. The user can add an event handler to ErrorDataReceived.
2639 [System.Runtime.InteropServices.ComVisible(false)]
2640 public void BeginErrorReadLine() {
2642 if(errorStreamReadMode == StreamReadMode.undefined) {
2643 errorStreamReadMode = StreamReadMode.asyncMode;
2645 else if (errorStreamReadMode != StreamReadMode.asyncMode) {
2646 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
2649 if (pendingErrorRead) {
2650 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2653 pendingErrorRead = true;
2654 // We can't detect if there's a pending sychronous read, stream also doesn't.
2655 if (error == null) {
2656 if (standardError == null) {
2657 throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
2660 Stream s = standardError.BaseStream;
2661 error = new AsyncStreamReader(this, s, new UserCallBack(this.ErrorReadNotifyUser), standardError.CurrentEncoding);
2663 error.BeginReadLine();
2668 /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2669 /// specified by BeginOutputReadLine().
2672 [System.Runtime.InteropServices.ComVisible(false)]
2673 public void CancelOutputRead() {
2674 if (output != null) {
2675 output.CancelOperation();
2678 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2681 pendingOutputRead = false;
2686 /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2687 /// specified by BeginErrorReadLine().
2690 [System.Runtime.InteropServices.ComVisible(false)]
2691 public void CancelErrorRead() {
2692 if (error != null) {
2693 error.CancelOperation();
2696 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2699 pendingErrorRead = false;
2702 internal void OutputReadNotifyUser(String data) {
2703 // To avoid ---- between remove handler and raising the event
2704 DataReceivedEventHandler outputDataReceived = OutputDataReceived;
2705 if (outputDataReceived != null) {
2706 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2707 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2708 SynchronizingObject.Invoke(outputDataReceived, new object[] {this, e});
2711 outputDataReceived(this,e); // Call back to user informing data is available.
2716 internal void ErrorReadNotifyUser(String data) {
2717 // To avoid ---- between remove handler and raising the event
2718 DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
2719 if (errorDataReceived != null) {
2720 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2721 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2722 SynchronizingObject.Invoke(errorDataReceived, new object[] {this, e});
2725 errorDataReceived(this,e); // Call back to user informing data is available.
2729 #endif // MONO_FEATURE_PROCESS_START
2732 /// A desired internal state.
2739 HaveProcessInfo = 0x8,
2743 HaveNtProcessInfo = HaveProcessInfo | IsNt
2748 /// This data structure contains information about a process that is collected
2749 /// in bulk by querying the operating system. The reason to make this a separate
2750 /// structure from the process component is so that we can throw it away all at once
2751 /// when Refresh is called on the component.
2754 internal class ProcessInfo {
2756 public ArrayList threadInfoList = new ArrayList();
2757 public int basePriority;
2758 public string processName;
2759 public int processId;
2760 public int handleCount;
2761 public long poolPagedBytes;
2762 public long poolNonpagedBytes;
2763 public long virtualBytes;
2764 public long virtualBytesPeak;
2765 public long workingSetPeak;
2766 public long workingSet;
2767 public long pageFileBytesPeak;
2768 public long pageFileBytes;
2769 public long privateBytes;
2770 public int mainModuleId; // used only for win9x - id is only for use with CreateToolHelp32
2771 public int sessionId;
2777 /// This data structure contains information about a thread in a process that
2778 /// is collected in bulk by querying the operating system. The reason to
2779 /// make this a separate structure from the ProcessThread component is so that we
2780 /// can throw it away all at once when Refresh is called on the component.
2783 internal class ThreadInfo {
2784 public int threadId;
2785 public int processId;
2786 public int basePriority;
2787 public int currentPriority;
2788 public IntPtr startAddress;
2789 public ThreadState threadState;
2791 public ThreadWaitReason threadWaitReason;
2792 #endif // !FEATURE_PAL
2796 /// This data structure contains information about a module in a process that
2797 /// is collected in bulk by querying the operating system. The reason to
2798 /// make this a separate structure from the ProcessModule component is so that we
2799 /// can throw it away all at once when Refresh is called on the component.
2802 internal class ModuleInfo {
2803 public string baseName;
2804 public string fileName;
2805 public IntPtr baseOfDll;
2806 public IntPtr entryPoint;
2807 public int sizeOfImage;
2808 public int Id; // used only on win9x - for matching up with ProcessInfo.mainModuleId
2812 internal static class EnvironmentBlock {
2813 public static byte[] ToByteArray(StringDictionary sd, bool unicode) {
2815 string[] keys = new string[sd.Count];
2816 byte[] envBlock = null;
2817 sd.Keys.CopyTo(keys, 0);
2820 string[] values = new string[sd.Count];
2821 sd.Values.CopyTo(values, 0);
2823 // sort both by the keys
2824 // Windows 2000 requires the environment block to be sorted by the key
2825 // It will first converting the case the strings and do ordinal comparison.
2826 Array.Sort(keys, values, OrdinalCaseInsensitiveComparer.Default);
2828 // create a list of null terminated "key=val" strings
2829 StringBuilder stringBuff = new StringBuilder();
2830 for (int i = 0; i < sd.Count; ++ i) {
2831 stringBuff.Append(keys[i]);
2832 stringBuff.Append('=');
2833 stringBuff.Append(values[i]);
2834 stringBuff.Append('\0');
2836 // an extra null at the end indicates end of list.
2837 stringBuff.Append('\0');
2840 envBlock = Encoding.Unicode.GetBytes(stringBuff.ToString());
2843 envBlock = Encoding.Default.GetBytes(stringBuff.ToString());
2845 if (envBlock.Length > UInt16.MaxValue)
2846 throw new InvalidOperationException(SR.GetString(SR.EnvironmentBlockTooLong, envBlock.Length));
2853 internal class OrdinalCaseInsensitiveComparer : IComparer {
2854 internal static readonly OrdinalCaseInsensitiveComparer Default = new OrdinalCaseInsensitiveComparer();
2856 public int Compare(Object a, Object b) {
2857 String sa = a as String;
2858 String sb = b as String;
2859 if (sa != null && sb != null) {
2860 return String.Compare(sa, sb, StringComparison.OrdinalIgnoreCase);
2862 return Comparer.Default.Compare(a,b);
2866 internal class ProcessThreadTimes {
2867 internal long create;
2869 internal long kernel;
2872 public DateTime StartTime {
2874 return DateTime.FromFileTime(create);
2878 public DateTime ExitTime {
2880 return DateTime.FromFileTime(exit);
2884 public TimeSpan PrivilegedProcessorTime {
2886 return new TimeSpan(kernel);
2890 public TimeSpan UserProcessorTime {
2892 return new TimeSpan(user);
2896 public TimeSpan TotalProcessorTime {
2898 return new TimeSpan(user + kernel);
2904 internal class ShellExecuteHelper {
2905 private NativeMethods.ShellExecuteInfo _executeInfo;
2906 private int _errorCode;
2907 private bool _succeeded;
2909 public ShellExecuteHelper(NativeMethods.ShellExecuteInfo executeInfo) {
2910 _executeInfo = executeInfo;
2913 [ResourceExposure(ResourceScope.None)]
2914 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2915 public void ShellExecuteFunction() {
2916 if (!(_succeeded = NativeMethods.ShellExecuteEx(_executeInfo))) {
2917 _errorCode = Marshal.GetLastWin32Error();
2921 public bool ShellExecuteOnSTAThread() {
2923 // SHELL API ShellExecute() requires STA in order to work correctly.
2924 // If current thread is not a STA thread, we need to call ShellExecute on a new thread.
2926 if( Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) {
2927 ThreadStart threadStart = new ThreadStart(this.ShellExecuteFunction);
2928 Thread executionThread = new Thread(threadStart);
2929 executionThread.SetApartmentState(ApartmentState.STA);
2930 executionThread.Start();
2931 executionThread.Join();
2934 ShellExecuteFunction();
2939 public int ErrorCode {