[process] Fix Process.GetProcessesByName (#4351)
[mono.git] / mcs / class / referencesource / System / services / monitoring / system / diagnosticts / Process.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="Process.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 #if MONO
8 #undef FEATURE_PAL
9 #endif
10
11 namespace System.Diagnostics {
12     using System.Text;
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;
20     using System;
21     using System.Collections;
22     using System.IO;
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;
31     
32     /// <devdoc>
33     ///    <para>
34     ///       Provides access to local and remote
35     ///       processes. Enables you to start and stop system processes.
36     ///    </para>
37     /// </devdoc>
38     [
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)
47     ]
48     public partial class Process : Component {
49         //
50         // FIELDS
51         //
52
53         bool haveProcessId;
54         int processId;
55         bool haveProcessHandle;
56         SafeProcessHandle m_processHandle;
57         bool isRemoteMachine;
58         string machineName;
59 #if !MONO
60         ProcessInfo processInfo;
61 #endif
62         Int32 m_processAccess;
63
64 #if !FEATURE_PAL        
65         ProcessThreadCollection threads;
66         ProcessModuleCollection modules;
67 #endif // !FEATURE_PAL        
68
69 #if !MONO
70         bool haveMainWindow;
71         IntPtr mainWindowHandle;  // no need to use SafeHandle for window        
72         string mainWindowTitle;
73 #endif
74         
75         bool haveWorkingSetLimits;
76         IntPtr minWorkingSet;
77         IntPtr maxWorkingSet;
78
79 #if !MONO
80         bool haveProcessorAffinity;
81         IntPtr processorAffinity;
82 #endif
83
84         bool havePriorityClass;
85         ProcessPriorityClass priorityClass;
86
87         ProcessStartInfo startInfo;
88         
89         bool watchForExit;
90         bool watchingForExit;
91         EventHandler onExited;
92         bool exited;
93         int exitCode;
94         bool signaled;
95                 
96         DateTime exitTime;
97         bool haveExitTime;
98
99 #if !MONO
100         bool responding;
101         bool haveResponding;
102         
103         bool priorityBoostEnabled;
104         bool havePriorityBoostEnabled;
105 #endif
106         
107         bool raisedOnExited;
108         RegisteredWaitHandle registeredWaitHandle;
109         WaitHandle waitHandle;
110         ISynchronizeInvoke synchronizingObject;
111         StreamReader standardOutput;
112         StreamWriter standardInput;
113         StreamReader standardError;
114         OperatingSystem operatingSystem;
115         bool disposed;
116         
117 #if !MONO
118         static object s_CreateProcessLock = new object();
119 #endif
120         
121         // This enum defines the operation mode for redirected process stream.
122         // We don't support switching between synchronous mode and asynchronous mode.
123         private enum StreamReadMode 
124         {
125             undefined, 
126             syncMode, 
127             asyncMode
128         }
129         
130         StreamReadMode outputStreamReadMode;
131         StreamReadMode errorStreamReadMode;
132         
133 #if MONO
134         StreamReadMode inputStreamReadMode;
135 #endif
136        
137         // Support for asynchrously reading streams
138         [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
139         //[System.Runtime.InteropServices.ComVisible(false)]        
140         public event DataReceivedEventHandler OutputDataReceived;
141         [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
142         //[System.Runtime.InteropServices.ComVisible(false)]        
143         public event DataReceivedEventHandler ErrorDataReceived;
144         // Abstract the stream details
145         internal AsyncStreamReader output;
146         internal AsyncStreamReader error;
147         internal bool pendingOutputRead;
148         internal bool pendingErrorRead;
149
150 #if !MONO
151         private static SafeFileHandle InvalidPipeHandle = new SafeFileHandle(IntPtr.Zero, false);
152 #endif
153 #if DEBUG
154         internal static TraceSwitch processTracing = new TraceSwitch("processTracing", "Controls debug output from Process component");
155 #else
156         internal static TraceSwitch processTracing = null;
157 #endif
158
159         //
160         // CONSTRUCTORS
161         //
162
163         /// <devdoc>
164         ///    <para>
165         ///       Initializes a new instance of the <see cref='System.Diagnostics.Process'/> class.
166         ///    </para>
167         /// </devdoc>
168         public Process() {
169             this.machineName = ".";
170             this.outputStreamReadMode = StreamReadMode.undefined;
171             this.errorStreamReadMode = StreamReadMode.undefined;            
172             this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
173         }        
174         
175         [ResourceExposure(ResourceScope.Machine)]
176         Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo) : base() {
177             Debug.Assert(SyntaxCheck.CheckMachineName(machineName), "The machine name should be valid!");
178 #if !MONO
179             this.processInfo = processInfo;
180 #endif
181             this.machineName = machineName;
182             this.isRemoteMachine = isRemoteMachine;
183             this.processId = processId;
184             this.haveProcessId = true;
185             this.outputStreamReadMode = StreamReadMode.undefined;
186             this.errorStreamReadMode = StreamReadMode.undefined;
187             this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS;
188         }
189
190         //
191         // PROPERTIES
192         //
193
194         /// <devdoc>
195         ///     Returns whether this process component is associated with a real process.
196         /// </devdoc>
197         /// <internalonly/>
198         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessAssociated)]
199         bool Associated {
200             get {
201                 return haveProcessId || haveProcessHandle;
202             }
203         }
204
205  #if !FEATURE_PAL && !MONO
206         /// <devdoc>
207         ///    <para>
208         ///       Gets the base priority of
209         ///       the associated process.
210         ///    </para>
211         /// </devdoc>
212         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessBasePriority)]
213         public int BasePriority {
214             get {
215                 EnsureState(State.HaveProcessInfo);
216                 return processInfo.basePriority;
217             }
218         }
219 #endif // !FEATURE_PAL && !MONO
220
221         /// <devdoc>
222         ///    <para>
223         ///       Gets
224         ///       the
225         ///       value that was specified by the associated process when it was terminated.
226         ///    </para>
227         /// </devdoc>
228         [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitCode)]
229         public int ExitCode {
230             get {
231                 EnsureState(State.Exited);
232 #if MONO
233                 if (exitCode == -1)
234                     throw new InvalidOperationException ("Cannot get the exit code from a non-child process on Unix");
235 #endif
236                 return exitCode;
237             }
238           }
239
240         /// <devdoc>
241         ///    <para>
242         ///       Gets a
243         ///       value indicating whether the associated process has been terminated.
244         ///    </para>
245         /// </devdoc>
246         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTerminated)]
247         public bool HasExited {
248             get {
249                 if (!exited) {
250                     EnsureState(State.Associated);
251                     SafeProcessHandle handle = null;
252                     try {
253                         handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.SYNCHRONIZE, false);
254                         if (handle.IsInvalid) {
255                             exited = true;
256                         }
257                         else {
258                             int exitCode;
259                             
260                             // Although this is the wrong way to check whether the process has exited,
261                             // it was historically the way we checked for it, and a lot of code then took a dependency on
262                             // the fact that this would always be set before the pipes were closed, so they would read
263                             // the exit code out after calling ReadToEnd() or standard output or standard error. In order
264                             // to allow 259 to function as a valid exit code and to break as few people as possible that
265                             // took the ReadToEnd dependency, we check for an exit code before doing the more correct
266                             // check to see if we have been signalled.
267                             if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
268                                 this.exited = true;
269                                 this.exitCode = exitCode;                                
270                             }
271                             else {                                                        
272
273                                 // The best check for exit is that the kernel process object handle is invalid, 
274                                 // or that it is valid and signaled.  Checking if the exit code != STILL_ACTIVE 
275                                 // does not guarantee the process is closed,
276                                 // since some process could return an actual STILL_ACTIVE exit code (259).
277                                 if (!signaled) // if we just came from WaitForExit, don't repeat
278                                 {
279                                     ProcessWaitHandle wh = null;
280                                     try 
281                                     {
282                                         wh = new ProcessWaitHandle(handle);
283                                         this.signaled = wh.WaitOne(0, false);                                   
284                                     }
285                                     finally
286                                     {
287
288                                         if (wh != null)
289                                         wh.Close();
290                                     }
291                                 }
292                                 if (signaled) 
293                                 {
294                                     /* If it's a non-child process, it's impossible to get its exit code on
295                                      * Unix. We don't throw here, but GetExitCodeProcess (in the io-layer)
296                                      * will set exitCode to -1, and we will throw if we try to call ExitCode */
297                                     if (!NativeMethods.GetExitCodeProcess(handle, out exitCode))                               
298                                         throw new Win32Exception();
299                                 
300                                     this.exited = true;
301                                     this.exitCode = exitCode;
302                                 }
303                             }
304                         }       
305                     }
306                     finally 
307                     {
308                         ReleaseProcessHandle(handle);
309                     }
310
311                     if (exited) {
312                         RaiseOnExited();
313                     }
314                 }
315                 return exited;
316             }
317         }
318
319         private ProcessThreadTimes GetProcessTimes() {
320             ProcessThreadTimes processTimes = new ProcessThreadTimes();
321             SafeProcessHandle handle = null;
322             try {
323                 int access = NativeMethods.PROCESS_QUERY_INFORMATION;
324
325                 if (EnvironmentHelpers.IsWindowsVistaOrAbove()) 
326                     access = NativeMethods.PROCESS_QUERY_LIMITED_INFORMATION;
327
328                 handle = GetProcessHandle(access, false);
329                 if( handle.IsInvalid) {
330                     // On OS older than XP, we will not be able to get the handle for a process
331                     // after it terminates. 
332                     // On Windows XP and newer OS, the information about a process will stay longer. 
333                     throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
334                 }
335
336                 if (!NativeMethods.GetProcessTimes(handle, 
337                                                    out processTimes.create, 
338                                                    out processTimes.exit, 
339                                                    out processTimes.kernel, 
340                                                    out processTimes.user)) {
341                     throw new Win32Exception();
342                 }
343
344             }
345             finally {
346                 ReleaseProcessHandle(handle);                
347             }
348             return processTimes;
349         }
350
351  #if !FEATURE_PAL
352         /// <devdoc>
353         ///    <para>
354         ///       Gets the time that the associated process exited.
355         ///    </para>
356         /// </devdoc>
357         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitTime)]
358         public DateTime ExitTime {
359             get {
360                 if (!haveExitTime) {
361                     EnsureState(State.IsNt | State.Exited);
362                     exitTime = GetProcessTimes().ExitTime;
363                     haveExitTime = true;
364                 }
365                 return exitTime;
366             }
367         }
368 #endif // !FEATURE_PAL
369
370         /// <devdoc>
371         ///    <para>
372         ///       Returns the native handle for the associated process. The handle is only available
373         ///       if this component started the process.
374         ///    </para>
375         /// </devdoc>
376         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandle)]
377         public IntPtr Handle {
378             [ResourceExposure(ResourceScope.Machine)]
379             [ResourceConsumption(ResourceScope.Machine)]
380             get {
381                 EnsureState(State.Associated);
382                 return OpenProcessHandle(this.m_processAccess).DangerousGetHandle();
383             }
384         }
385
386         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]  
387         public SafeProcessHandle SafeHandle {
388             get {
389                 EnsureState(State.Associated);
390                 return OpenProcessHandle(this.m_processAccess);
391             }
392         }
393
394 #if !FEATURE_PAL && !MONO
395         /// <devdoc>
396         ///    <para>
397         ///       Gets the number of handles that are associated
398         ///       with the process.
399         ///    </para>
400         /// </devdoc>
401         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandleCount)]
402         public int HandleCount {
403             get {
404                 EnsureState(State.HaveProcessInfo);
405                 return processInfo.handleCount;
406             }
407         }
408 #endif // !FEATURE_PAL && !MONO
409
410         /// <devdoc>
411         ///    <para>
412         ///       Gets
413         ///       the unique identifier for the associated process.
414         ///    </para>
415         /// </devdoc>
416         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessId)]
417         public int Id {
418             get {
419                 EnsureState(State.HaveId);
420                 return processId;
421             }
422         }
423
424         /// <devdoc>
425         ///    <para>
426         ///       Gets
427         ///       the name of the computer on which the associated process is running.
428         ///    </para>
429         /// </devdoc>
430         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMachineName)]
431         public string MachineName {
432             get {
433                 EnsureState(State.Associated);
434                 return machineName;
435             }
436         }
437
438  #if !FEATURE_PAL
439
440 #if !MONO
441         /// <devdoc>
442         ///    <para>
443         ///       Returns the window handle of the main window of the associated process.
444         ///    </para>
445         /// </devdoc>
446         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowHandle)]
447         public IntPtr MainWindowHandle {
448             [ResourceExposure(ResourceScope.Machine)]
449             [ResourceConsumption(ResourceScope.Machine)]
450             get {
451                 if (!haveMainWindow) {
452                     EnsureState(State.IsLocal | State.HaveId);
453                     mainWindowHandle = ProcessManager.GetMainWindowHandle(processId);
454
455                     if (mainWindowHandle != (IntPtr)0) {
456                         haveMainWindow = true;
457                     } else {
458                         // We do the following only for the side-effect that it will throw when if the process no longer exists on the system.  In Whidbey
459                         // we always did this check but have now changed it to just require a ProcessId. In the case where someone has called Refresh() 
460                         // and the process has exited this call will throw an exception where as the above code would return 0 as the handle.
461                         EnsureState(State.HaveProcessInfo);
462                     }
463                 }
464                 return mainWindowHandle;
465             }
466         }
467
468         /// <devdoc>
469         ///    <para>
470         ///       Returns the caption of the <see cref='System.Diagnostics.Process.MainWindowHandle'/> of
471         ///       the process. If the handle is zero (0), then an empty string is returned.
472         ///    </para>
473         /// </devdoc>
474         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowTitle)]
475         public string MainWindowTitle {
476             [ResourceExposure(ResourceScope.None)]
477             [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
478             get {
479                 if (mainWindowTitle == null) {
480                     IntPtr handle = MainWindowHandle;
481                     if (handle == (IntPtr)0) {
482                         mainWindowTitle = String.Empty;
483                     }
484                     else {
485                         int length = NativeMethods.GetWindowTextLength(new HandleRef(this, handle)) * 2;
486                         StringBuilder builder = new StringBuilder(length);
487                         NativeMethods.GetWindowText(new HandleRef(this, handle), builder, builder.Capacity);
488                         mainWindowTitle = builder.ToString();
489                     }
490                 }
491                 return mainWindowTitle;
492             }
493         }
494
495
496
497         /// <devdoc>
498         ///    <para>
499         ///       Gets
500         ///       the main module for the associated process.
501         ///    </para>
502         /// </devdoc>
503         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainModule)]
504         public ProcessModule MainModule {
505             [ResourceExposure(ResourceScope.Process)]
506             [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
507             get {
508                 // We only return null if we couldn't find a main module.
509                 // This could be because
510                 //      1. The process hasn't finished loading the main module (most likely)
511                 //      2. There are no modules loaded (possible for certain OS processes)
512                 //      3. Possibly other?
513                 
514                 if (OperatingSystem.Platform == PlatformID.Win32NT) {
515                     EnsureState(State.HaveId | State.IsLocal);
516                     // on NT the first module is the main module                    
517                     ModuleInfo module = NtProcessManager.GetFirstModuleInfo(processId);
518                     return new ProcessModule(module);
519                 }
520                 else {
521                     ProcessModuleCollection moduleCollection = Modules;                        
522                     // on 9x we have to do a little more work
523                     EnsureState(State.HaveProcessInfo);
524                     foreach (ProcessModule pm in moduleCollection) {
525                         if (pm.moduleInfo.Id == processInfo.mainModuleId) {
526                             return pm;
527                         }
528                     }
529                     return null;
530                 }
531             }
532         }
533 #endif
534
535         /// <devdoc>
536         ///    <para>
537         ///       Gets or sets the maximum allowable working set for the associated
538         ///       process.
539         ///    </para>
540         /// </devdoc>
541         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMaxWorkingSet)]
542         public IntPtr MaxWorkingSet {
543             get {
544                 EnsureWorkingSetLimits();
545                 return maxWorkingSet;
546             }
547             [ResourceExposure(ResourceScope.Process)]
548             [ResourceConsumption(ResourceScope.Process)]
549             set {
550                 SetWorkingSetLimits(null, value);
551             }
552         }
553
554         /// <devdoc>
555         ///    <para>
556         ///       Gets or sets the minimum allowable working set for the associated
557         ///       process.
558         ///    </para>
559         /// </devdoc>
560         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMinWorkingSet)]
561         public IntPtr MinWorkingSet {
562             get {
563                 EnsureWorkingSetLimits();
564                 return minWorkingSet;
565             }
566             [ResourceExposure(ResourceScope.Process)]
567             [ResourceConsumption(ResourceScope.Process)]
568             set {
569                 SetWorkingSetLimits(value, null);
570             }
571         }
572
573 #if !MONO
574         /// <devdoc>
575         ///    <para>
576         ///       Gets
577         ///       the modules that have been loaded by the associated process.
578         ///    </para>
579         /// </devdoc>
580         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessModules)]
581         public ProcessModuleCollection Modules {
582             [ResourceExposure(ResourceScope.None)]
583             [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
584             get {
585                 if (modules == null) {
586                     EnsureState(State.HaveId | State.IsLocal);
587                     ModuleInfo[] moduleInfos = ProcessManager.GetModuleInfos(processId);
588                     ProcessModule[] newModulesArray = new ProcessModule[moduleInfos.Length];
589                     for (int i = 0; i < moduleInfos.Length; i++) {
590                         newModulesArray[i] = new ProcessModule(moduleInfos[i]);
591                     }
592                     ProcessModuleCollection newModules = new ProcessModuleCollection(newModulesArray);
593                     modules = newModules;
594                 }
595                 return modules;
596             }
597         }
598
599         /// <devdoc>
600         ///     Returns the amount of memory that the system has allocated on behalf of the
601         ///     associated process that can not be written to the virtual memory paging file.
602         /// </devdoc>
603         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
604         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
605         public int NonpagedSystemMemorySize {
606             get {
607                 EnsureState(State.HaveNtProcessInfo);
608                 return unchecked((int)processInfo.poolNonpagedBytes);
609             }
610         }
611
612         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
613         [System.Runtime.InteropServices.ComVisible(false)]            
614         public long NonpagedSystemMemorySize64 {
615             get {
616                 EnsureState(State.HaveNtProcessInfo);
617                 return processInfo.poolNonpagedBytes;
618             }
619         }
620
621         /// <devdoc>
622         ///     Returns the amount of memory that the associated process has allocated
623         ///     that can be written to the virtual memory paging file.
624         /// </devdoc>
625         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PagedMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
626         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
627         public int PagedMemorySize {
628             get {
629                 EnsureState(State.HaveNtProcessInfo);
630                 return unchecked((int)processInfo.pageFileBytes);
631             }
632         }
633
634         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
635         [System.Runtime.InteropServices.ComVisible(false)]
636         public long PagedMemorySize64 {
637             get {
638                 EnsureState(State.HaveNtProcessInfo);
639                 return processInfo.pageFileBytes;
640             }
641         }
642
643
644         /// <devdoc>
645         ///     Returns the amount of memory that the system has allocated on behalf of the
646         ///     associated process that can be written to the virtual memory paging file.
647         /// </devdoc>
648         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PagedSystemMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
649         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
650         public int PagedSystemMemorySize {
651             get {
652                 EnsureState(State.HaveNtProcessInfo);
653                 return unchecked((int)processInfo.poolPagedBytes);
654             }
655         }
656
657         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
658         [System.Runtime.InteropServices.ComVisible(false)]
659         public long PagedSystemMemorySize64 {
660             get {
661                 EnsureState(State.HaveNtProcessInfo);
662                 return processInfo.poolPagedBytes;
663             }
664         }
665
666
667         /// <devdoc>
668         ///    <para>
669         ///       Returns the maximum amount of memory that the associated process has
670         ///       allocated that could be written to the virtual memory paging file.
671         ///    </para>
672         /// </devdoc>
673         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakPagedMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
674         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
675         public int PeakPagedMemorySize {
676             get {
677                 EnsureState(State.HaveNtProcessInfo);
678                 return unchecked((int)processInfo.pageFileBytesPeak);
679             }
680         }
681
682         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
683         [System.Runtime.InteropServices.ComVisible(false)]
684         public long PeakPagedMemorySize64 {
685             get {
686                 EnsureState(State.HaveNtProcessInfo);
687                 return processInfo.pageFileBytesPeak;
688             }
689         }
690         
691         /// <devdoc>
692         ///    <para>
693         ///       Returns the maximum amount of physical memory that the associated
694         ///       process required at once.
695         ///    </para>
696         /// </devdoc>
697         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakWorkingSet64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
698         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
699         public int PeakWorkingSet {
700             get {
701                 EnsureState(State.HaveNtProcessInfo);
702                 return unchecked((int)processInfo.workingSetPeak);
703             }
704         }
705
706         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
707         [System.Runtime.InteropServices.ComVisible(false)]
708         public long PeakWorkingSet64 {
709             get {
710                 EnsureState(State.HaveNtProcessInfo);
711                 return processInfo.workingSetPeak;
712             }
713         }
714
715         /// <devdoc>
716         ///     Returns the maximum amount of virtual memory that the associated
717         ///     process has requested.
718         /// </devdoc>
719         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakVirtualMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
720         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
721         public int PeakVirtualMemorySize {
722             get {
723                 EnsureState(State.HaveNtProcessInfo);
724                 return unchecked((int)processInfo.virtualBytesPeak);
725             }
726         }
727
728         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
729         [System.Runtime.InteropServices.ComVisible(false)]
730         public long PeakVirtualMemorySize64 {
731             get {
732                 EnsureState(State.HaveNtProcessInfo);
733                 return processInfo.virtualBytesPeak;
734             }
735         }
736 #endif
737
738         private OperatingSystem OperatingSystem {
739             get {
740                 if (operatingSystem == null) {
741                     operatingSystem = Environment.OSVersion;
742                 }                
743                 return operatingSystem;
744             }
745         }
746
747 #if !MONO
748         /// <devdoc>
749         ///    <para>
750         ///       Gets or sets a value indicating whether the associated process priority
751         ///       should be temporarily boosted by the operating system when the main window
752         ///       has focus.
753         ///    </para>
754         /// </devdoc>
755         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityBoostEnabled)]
756         public bool PriorityBoostEnabled {
757             get {
758                 EnsureState(State.IsNt);
759                 if (!havePriorityBoostEnabled) {
760                     SafeProcessHandle handle = null;
761                     try {
762                         handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
763                         bool disabled = false;
764                         if (!NativeMethods.GetProcessPriorityBoost(handle, out disabled)) {
765                             throw new Win32Exception();
766                         }
767                         priorityBoostEnabled = !disabled;
768                         havePriorityBoostEnabled = true;
769                     }
770                     finally {
771                         ReleaseProcessHandle(handle);
772                     }
773                 }
774                 return priorityBoostEnabled;
775             }
776             set {
777                 EnsureState(State.IsNt);
778                 SafeProcessHandle handle = null;
779                 try {
780                     handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
781                     if (!NativeMethods.SetProcessPriorityBoost(handle, !value))
782                         throw new Win32Exception();
783                     priorityBoostEnabled = value;
784                     havePriorityBoostEnabled = true;
785                 }
786                 finally {
787                     ReleaseProcessHandle(handle);
788                 }
789             }
790         }
791 #endif
792
793         /// <devdoc>
794         ///    <para>
795         ///       Gets or sets the overall priority category for the
796         ///       associated process.
797         ///    </para>
798         /// </devdoc>
799         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityClass)]
800         public ProcessPriorityClass PriorityClass {
801             get {
802                 if (!havePriorityClass) {
803                     SafeProcessHandle handle = null;
804                     try {
805                         handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
806                         int value = NativeMethods.GetPriorityClass(handle);
807                         if (value == 0) {
808                             throw new Win32Exception();
809                         }
810                         priorityClass = (ProcessPriorityClass)value;
811                         havePriorityClass = true;
812                     }
813                     finally {
814                         ReleaseProcessHandle(handle);
815                     }
816                 }
817                 return priorityClass;
818             }
819             [ResourceExposure(ResourceScope.Machine)]
820             [ResourceConsumption(ResourceScope.Machine)]
821             set {
822                 if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) { 
823                     throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
824                 }
825
826 #if !MONO
827                 // BelowNormal and AboveNormal are only available on Win2k and greater.
828                 if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0)   && 
829                     (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) {
830                     throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
831                 }                
832 #endif // !MONO
833                                     
834                 SafeProcessHandle handle = null;
835
836                 try {
837                     handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
838                     if (!NativeMethods.SetPriorityClass(handle, (int)value)) {
839                         throw new Win32Exception();
840                     }
841                     priorityClass = value;
842                     havePriorityClass = true;
843                 }
844                 finally {
845                     ReleaseProcessHandle(handle);
846                 }
847             }
848         }
849
850 #if !MONO
851         /// <devdoc>
852         ///     Returns the number of bytes that the associated process has allocated that cannot
853         ///     be shared with other processes.
854         /// </devdoc>
855         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PrivateMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
856         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
857         public int PrivateMemorySize {
858             get {
859                 EnsureState(State.HaveNtProcessInfo);
860                 return unchecked((int)processInfo.privateBytes);
861             }
862         }
863
864         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
865         [System.Runtime.InteropServices.ComVisible(false)]            
866         public long PrivateMemorySize64 {
867             get {
868                 EnsureState(State.HaveNtProcessInfo);
869                 return processInfo.privateBytes;
870             }
871         }
872 #endif
873
874         /// <devdoc>
875         ///     Returns the amount of time the process has spent running code inside the operating
876         ///     system core.
877         /// </devdoc>
878         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivilegedProcessorTime)]
879         public TimeSpan PrivilegedProcessorTime {
880             get {
881                 EnsureState(State.IsNt);
882                 return GetProcessTimes().PrivilegedProcessorTime;
883             }
884         }
885
886 #if !MONO
887         /// <devdoc>
888         ///    <para>
889         ///       Gets
890         ///       the friendly name of the process.
891         ///    </para>
892         /// </devdoc>
893         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessName)]
894         public string ProcessName {
895             [ResourceExposure(ResourceScope.None)]
896             [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
897             get {
898                 EnsureState(State.HaveProcessInfo);
899                 String processName =  processInfo.processName;
900                 //
901                 // On some old NT-based OS like win2000, the process name from NTQuerySystemInformation is up to 15 characters.
902                 // Processes executing notepad_1234567.exe and notepad_12345678.exe will have the same process name.
903                 // GetProcessByNames will not be able find the process for notepad_12345678.exe.
904                 // So we will try to replace the name of the process by its main module name if the name is 15 characters.
905                 // However we can't always get the module name:
906                 //     (1) Normal user will not be able to get module information about processes. 
907                 //     (2) We can't get module information about remoting process.
908                 // We can't get module name for a remote process
909                 // 
910                 if (processName.Length == 15 && ProcessManager.IsNt && ProcessManager.IsOSOlderThanXP && !isRemoteMachine) { 
911                     try {
912                         String mainModuleName = MainModule.ModuleName;
913                         if (mainModuleName != null) {
914                             processInfo.processName = Path.ChangeExtension(Path.GetFileName(mainModuleName), null);
915                         }
916                     }
917                     catch(Exception) {
918                         // If we can't access the module information, we can still use the might-be-truncated name. 
919                         // We could fail for a few reasons:
920                         // (1) We don't enough privilege to get module information.
921                         // (2) The process could have terminated.
922                     }
923                 }
924                 
925                 return processInfo.processName;
926             }
927         }
928
929         /// <devdoc>
930         ///    <para>
931         ///       Gets
932         ///       or sets which processors the threads in this process can be scheduled to run on.
933         ///    </para>
934         /// </devdoc>
935         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessorAffinity)]
936         public IntPtr ProcessorAffinity {
937             get {
938                 if (!haveProcessorAffinity) {
939                     SafeProcessHandle handle = null;
940                     try {
941                         handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
942                         IntPtr processAffinity;
943                         IntPtr systemAffinity;
944                         if (!NativeMethods.GetProcessAffinityMask(handle, out processAffinity, out systemAffinity))
945                             throw new Win32Exception();
946                         processorAffinity = processAffinity;
947                     }
948                     finally {
949                         ReleaseProcessHandle(handle);
950                     }
951                     haveProcessorAffinity = true;
952                 }
953                 return processorAffinity;
954             }
955             [ResourceExposure(ResourceScope.Machine)]
956             [ResourceConsumption(ResourceScope.Machine)]
957             set {
958                 SafeProcessHandle handle = null;
959                 try {
960                     handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
961                     if (!NativeMethods.SetProcessAffinityMask(handle, value)) 
962                         throw new Win32Exception();
963                         
964                     processorAffinity = value;
965                     haveProcessorAffinity = true;
966                 }
967                 finally {
968                     ReleaseProcessHandle(handle);
969                 }
970             }
971         }
972
973         /// <devdoc>
974         ///    <para>
975         ///       Gets a value indicating whether or not the user
976         ///       interface of the process is responding.
977         ///    </para>
978         /// </devdoc>
979         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessResponding)]
980         public bool Responding {
981             [ResourceExposure(ResourceScope.None)]
982             [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
983             get {
984                 if (!haveResponding) {
985                     IntPtr mainWindow = MainWindowHandle;
986                     if (mainWindow == (IntPtr)0) {
987                         responding = true;
988                     }
989                     else {
990                         IntPtr result;
991                         responding = NativeMethods.SendMessageTimeout(new HandleRef(this, mainWindow), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero, NativeMethods.SMTO_ABORTIFHUNG, 5000, out result) != (IntPtr)0;
992                     }
993                 }
994                 return responding;
995             }
996         }
997
998         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessSessionId)]
999         public int SessionId {
1000             get {
1001                 EnsureState(State.HaveNtProcessInfo);
1002                 return processInfo.sessionId;                
1003             }
1004         }
1005 #endif // !MONO
1006
1007 #endif // !FEATURE_PAL
1008
1009 #if MONO_FEATURE_PROCESS_START
1010         /// <devdoc>
1011         ///    <para>
1012         ///       Gets or sets the properties to pass into the <see cref='System.Diagnostics.Process.Start'/> method for the <see cref='System.Diagnostics.Process'/>
1013         ///       .
1014         ///    </para>
1015         /// </devdoc>
1016         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MonitoringDescription(SR.ProcessStartInfo)]
1017         public ProcessStartInfo StartInfo {
1018             get {
1019                 if (startInfo == null) {
1020                     startInfo = new ProcessStartInfo(this);
1021                 }                
1022                 return startInfo;
1023             }
1024             [ResourceExposure(ResourceScope.Machine)]
1025             set {
1026                 if (value == null) { 
1027                     throw new ArgumentNullException("value");
1028                 }
1029                 startInfo = value;
1030             }
1031         }
1032 #endif
1033
1034 #if !FEATURE_PAL        
1035         /// <devdoc>
1036         ///     Returns the time the associated process was started.
1037         /// </devdoc>
1038         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStartTime)]
1039         public DateTime StartTime {
1040             get {
1041                 EnsureState(State.IsNt);
1042                 return GetProcessTimes().StartTime;
1043             }
1044         }
1045 #endif // !FEATURE_PAL
1046
1047         /// <devdoc>
1048         ///   Represents the object used to marshal the event handler
1049         ///   calls issued as a result of a Process exit. Normally 
1050         ///   this property will  be set when the component is placed 
1051         ///   inside a control or  a from, since those components are 
1052         ///   bound to a specific thread.
1053         /// </devdoc>
1054         [
1055         Browsable(false),
1056         DefaultValue(null),         
1057         MonitoringDescription(SR.ProcessSynchronizingObject)
1058         ]
1059         public ISynchronizeInvoke SynchronizingObject {
1060             get {
1061                if (this.synchronizingObject == null && DesignMode) {
1062                     IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
1063                     if (host != null) {
1064                         object baseComponent = host.RootComponent;
1065                         if (baseComponent != null && baseComponent is ISynchronizeInvoke)
1066                             this.synchronizingObject = (ISynchronizeInvoke)baseComponent;
1067                     }                        
1068                 }
1069
1070                 return this.synchronizingObject;
1071             }
1072             
1073             set {
1074                 this.synchronizingObject = value;
1075             }
1076         }
1077
1078 #if !FEATURE_PAL        
1079         
1080 #if !MONO
1081         /// <devdoc>
1082         ///    <para>
1083         ///       Gets the set of threads that are running in the associated
1084         ///       process.
1085         ///    </para>
1086         /// </devdoc>
1087         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessThreads)]
1088         public ProcessThreadCollection Threads {
1089             [ResourceExposure(ResourceScope.Process)]
1090             [ResourceConsumption(ResourceScope.Process)]
1091             get {
1092                 if (threads == null) {
1093                     EnsureState(State.HaveProcessInfo);
1094                     int count = processInfo.threadInfoList.Count;
1095                     ProcessThread[] newThreadsArray = new ProcessThread[count];
1096                     for (int i = 0; i < count; i++) {
1097                         newThreadsArray[i] = new ProcessThread(isRemoteMachine, (ThreadInfo)processInfo.threadInfoList[i]);
1098                     }
1099                     ProcessThreadCollection newThreads = new ProcessThreadCollection(newThreadsArray);
1100                     threads = newThreads;
1101                 }
1102                 return threads;
1103             }
1104         }
1105 #endif
1106
1107         /// <devdoc>
1108         ///     Returns the amount of time the associated process has spent utilizing the CPU.
1109         ///     It is the sum of the <see cref='System.Diagnostics.Process.UserProcessorTime'/> and
1110         ///     <see cref='System.Diagnostics.Process.PrivilegedProcessorTime'/>.
1111         /// </devdoc>
1112         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTotalProcessorTime)]
1113         public TimeSpan TotalProcessorTime {
1114             get {
1115                 EnsureState(State.IsNt);
1116                 return GetProcessTimes().TotalProcessorTime;
1117             }
1118         }
1119
1120         /// <devdoc>
1121         ///     Returns the amount of time the associated process has spent running code
1122         ///     inside the application portion of the process (not the operating system core).
1123         /// </devdoc>
1124         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessUserProcessorTime)]
1125         public TimeSpan UserProcessorTime {
1126             get {
1127                 EnsureState(State.IsNt);
1128                 return GetProcessTimes().UserProcessorTime;
1129             }
1130         }
1131
1132 #if !MONO
1133         /// <devdoc>
1134         ///     Returns the amount of virtual memory that the associated process has requested.
1135         /// </devdoc>
1136         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.VirtualMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]        
1137         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1138         public int VirtualMemorySize {
1139             get {
1140                 EnsureState(State.HaveNtProcessInfo);
1141                 return unchecked((int)processInfo.virtualBytes);
1142             }
1143         }
1144 #endif // !MONO
1145
1146 #endif // !FEATURE_PAL
1147
1148 #if !MONO
1149         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
1150         [System.Runtime.InteropServices.ComVisible(false)]        
1151         public long VirtualMemorySize64 {
1152             get {
1153                 EnsureState(State.HaveNtProcessInfo);
1154                 return processInfo.virtualBytes;
1155             }
1156         }
1157 #endif
1158
1159         /// <devdoc>
1160         ///    <para>
1161         ///       Gets or sets whether the <see cref='System.Diagnostics.Process.Exited'/>
1162         ///       event is fired
1163         ///       when the process terminates.
1164         ///    </para>
1165         /// </devdoc>
1166         [Browsable(false), DefaultValue(false), MonitoringDescription(SR.ProcessEnableRaisingEvents)]
1167         public bool EnableRaisingEvents {
1168             get {
1169                 return watchForExit;
1170             }
1171             set {
1172                 if (value != watchForExit) {
1173                     if (Associated) {
1174                         if (value) {
1175                             OpenProcessHandle();
1176                             EnsureWatchingForExit();
1177                         }
1178                         else {
1179                             StopWatchingForExit();
1180                         }
1181                     }
1182                     watchForExit = value;
1183                 }
1184             }
1185         }
1186
1187 #if MONO_FEATURE_PROCESS_START
1188         /// <devdoc>
1189         ///    <para>[To be supplied.]</para>
1190         /// </devdoc>
1191         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardInput)]
1192         public StreamWriter StandardInput {
1193             get { 
1194                 if (standardInput == null) {
1195                     throw new InvalidOperationException(SR.GetString(SR.CantGetStandardIn));
1196                 }
1197
1198 #if MONO
1199                 inputStreamReadMode = StreamReadMode.syncMode;
1200 #endif
1201                 return standardInput;
1202             }
1203         }
1204
1205         /// <devdoc>
1206         ///    <para>[To be supplied.]</para>
1207         /// </devdoc>
1208         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardOutput)]
1209         public StreamReader StandardOutput {
1210             get {
1211                 if (standardOutput == null) {
1212                     throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
1213                 }
1214
1215                 if(outputStreamReadMode == StreamReadMode.undefined) {
1216                     outputStreamReadMode = StreamReadMode.syncMode;
1217                 }
1218                 else if (outputStreamReadMode != StreamReadMode.syncMode) {
1219                     throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));                    
1220                 }
1221                     
1222                 return standardOutput;
1223             }
1224         }
1225
1226         /// <devdoc>
1227         ///    <para>[To be supplied.]</para>
1228         /// </devdoc>
1229         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardError)]
1230         public StreamReader StandardError {
1231             get { 
1232                 if (standardError == null) {
1233                     throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
1234                 }
1235
1236                 if(errorStreamReadMode == StreamReadMode.undefined) {
1237                     errorStreamReadMode = StreamReadMode.syncMode;
1238                 }
1239                 else if (errorStreamReadMode != StreamReadMode.syncMode) {
1240                     throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));                    
1241                 }
1242
1243                 return standardError;
1244             }
1245         }
1246 #endif
1247
1248 #if !FEATURE_PAL && !MONO
1249         /// <devdoc>
1250         ///     Returns the total amount of physical memory the associated process.
1251         /// </devdoc>
1252         [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.WorkingSet64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]        
1253         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1254         public int WorkingSet {
1255             get {
1256                 EnsureState(State.HaveNtProcessInfo);
1257                 return unchecked((int)processInfo.workingSet);
1258             }
1259         }
1260 #endif // !FEATURE_PAL && !MONO
1261
1262 #if !MONO
1263         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
1264         [System.Runtime.InteropServices.ComVisible(false)]        
1265         public long WorkingSet64 {
1266             get {
1267                 EnsureState(State.HaveNtProcessInfo);
1268                 return processInfo.workingSet;
1269             }
1270         }
1271 #endif
1272
1273         [Category("Behavior"), MonitoringDescription(SR.ProcessExited)]
1274         public event EventHandler Exited {
1275             add {
1276                 onExited += value;
1277             }
1278             remove {
1279                 onExited -= value;
1280             }
1281         }
1282
1283 #if !FEATURE_PAL && !MONO
1284         /// <devdoc>
1285         ///    <para>
1286         ///       Closes a process that has a user interface by sending a close message
1287         ///       to its main window.
1288         ///    </para>
1289         /// </devdoc>
1290         [ResourceExposure(ResourceScope.Machine)]  // Review usages of this.
1291         [ResourceConsumption(ResourceScope.Machine)]
1292         public bool CloseMainWindow() {
1293             IntPtr mainWindowHandle = MainWindowHandle;
1294             if (mainWindowHandle == (IntPtr)0) return false;
1295             int style = NativeMethods.GetWindowLong(new HandleRef(this, mainWindowHandle), NativeMethods.GWL_STYLE);
1296             if ((style & NativeMethods.WS_DISABLED) != 0) return false;
1297             NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
1298             return true;
1299         }
1300 #endif // !FEATURE_PAL && !MONO
1301
1302         /// <devdoc>
1303         ///     Release the temporary handle we used to get process information.
1304         ///     If we used the process handle stored in the process object (we have all access to the handle,) don't release it.
1305         /// </devdoc>
1306         /// <internalonly/>
1307         void ReleaseProcessHandle(SafeProcessHandle handle) {
1308             if (handle == null) { 
1309                 return; 
1310             }
1311
1312             if (haveProcessHandle && handle == m_processHandle) {
1313                 return;
1314             }
1315             Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process)");
1316             handle.Close();
1317         }
1318
1319         /// <devdoc>
1320         ///     This is called from the threadpool when a proces exits.
1321         /// </devdoc>
1322         /// <internalonly/>
1323         private void CompletionCallback(object context, bool wasSignaled) {
1324             StopWatchingForExit();
1325             RaiseOnExited();      
1326         }
1327
1328         /// <internalonly/>
1329         /// <devdoc>
1330         ///    <para>
1331         ///       Free any resources associated with this component.
1332         ///    </para>
1333         /// </devdoc>
1334         protected override void Dispose(bool disposing) {
1335             if( !disposed) {
1336                 if (disposing) {
1337                     //Dispose managed and unmanaged resources
1338                     Close();
1339                 }
1340                 this.disposed = true;
1341                 base.Dispose(disposing);                
1342             }            
1343         }
1344
1345         /// <devdoc>
1346         ///    <para>
1347         ///       Frees any resources associated with this component.
1348         ///    </para>
1349         /// </devdoc>
1350         public void Close() {
1351             if (Associated) {
1352                 if (haveProcessHandle) {
1353                     StopWatchingForExit();
1354                     Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process) in Close()");
1355                     m_processHandle.Close();
1356                     m_processHandle = null;
1357                     haveProcessHandle = false;
1358                 }
1359                 haveProcessId = false;
1360                 isRemoteMachine = false;
1361                 machineName = ".";
1362                 raisedOnExited = false;
1363
1364 #if MONO
1365                 //Call close on streams if the user never saw them.
1366                 //A stream in the undefined mode was never fetched by the user.
1367                 //A stream in the async mode is wrapped on a AsyncStreamReader and we should dispose that instead.
1368                 //  no way for users to get a hand on a AsyncStreamReader.
1369                 var tmpIn = standardInput;
1370                 standardInput = null;
1371                 if (inputStreamReadMode == StreamReadMode.undefined && tmpIn != null)
1372                     tmpIn.Close ();
1373
1374                 var tmpOut = standardOutput;
1375                 standardOutput = null;
1376                 if (outputStreamReadMode == StreamReadMode.undefined && tmpOut != null)
1377                     tmpOut.Close ();
1378
1379                 tmpOut = standardError;
1380                 standardError = null;
1381                 if (errorStreamReadMode == StreamReadMode.undefined && tmpOut != null)
1382                     tmpOut.Close ();
1383
1384                 var tmpAsync = output;
1385                 output = null;
1386                 if (outputStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
1387                     tmpAsync.CancelOperation ();
1388                     tmpAsync.Close ();
1389                 }
1390
1391                 tmpAsync = error;
1392                 error = null;
1393                 if (errorStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
1394                     tmpAsync.CancelOperation ();
1395                     tmpAsync.Close ();
1396                 }
1397 #else
1398                 //Don't call close on the Readers and writers
1399                 //since they might be referenced by somebody else while the 
1400                 //process is still alive but this method called.
1401                 standardOutput = null;
1402                 standardInput = null;
1403                 standardError = null;
1404
1405                 output = null;
1406                 error = null;
1407         
1408 #endif
1409
1410                 Refresh();
1411             }
1412         }
1413
1414         /// <devdoc>
1415         ///     Helper method for checking preconditions when accessing properties.
1416         /// </devdoc>
1417         /// <internalonly/>
1418         [ResourceExposure(ResourceScope.None)]
1419         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1420         void EnsureState(State state) {
1421
1422 #if !MONO
1423             if ((state & State.IsWin2k) != (State)0) {
1424 #if !FEATURE_PAL
1425                 if (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)
1426 #endif // !FEATURE_PAL
1427                     throw new PlatformNotSupportedException(SR.GetString(SR.Win2kRequired));
1428             }
1429
1430             if ((state & State.IsNt) != (State)0) {
1431 #if !FEATURE_PAL
1432                 if (OperatingSystem.Platform != PlatformID.Win32NT)
1433 #endif // !FEATURE_PAL                    
1434                     throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
1435             }
1436 #endif // !MONO
1437
1438             if ((state & State.Associated) != (State)0)
1439                 if (!Associated)
1440                     throw new InvalidOperationException(SR.GetString(SR.NoAssociatedProcess));
1441
1442             if ((state & State.HaveId) != (State)0) {
1443                 if (!haveProcessId) {
1444 #if !FEATURE_PAL && !MONO
1445                     if (haveProcessHandle) {
1446                         SetProcessId(ProcessManager.GetProcessIdFromHandle(m_processHandle));
1447                      }
1448                     else {                     
1449                         EnsureState(State.Associated);
1450                         throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1451                     }
1452 #else
1453                     EnsureState(State.Associated);
1454                     throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
1455 #endif // !FEATURE_PAL && !MONO
1456                 }
1457             }
1458
1459             if ((state & State.IsLocal) != (State)0 && isRemoteMachine) {
1460                     throw new NotSupportedException(SR.GetString(SR.NotSupportedRemote));
1461             }
1462             
1463             if ((state & State.HaveProcessInfo) != (State)0) {
1464 #if !FEATURE_PAL && !MONO
1465                 if (processInfo == null) {
1466                     if ((state & State.HaveId) == (State)0) EnsureState(State.HaveId);
1467                     ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1468                     for (int i = 0; i < processInfos.Length; i++) {
1469                         if (processInfos[i].processId == processId) {
1470                             this.processInfo = processInfos[i];
1471                             break;
1472                         }
1473                     }
1474                     if (processInfo == null) {
1475                         throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1476                     }
1477                 }
1478 #else
1479                 throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
1480 #endif // !FEATURE_PAL && !MONO
1481             }
1482
1483             if ((state & State.Exited) != (State)0) {
1484                 if (!HasExited) {
1485                     throw new InvalidOperationException(SR.GetString(SR.WaitTillExit));
1486                 }
1487                 
1488                 if (!haveProcessHandle) {
1489                     throw new InvalidOperationException(SR.GetString(SR.NoProcessHandle));
1490                 }
1491             }
1492         }
1493             
1494         /// <devdoc>
1495         ///     Make sure we are watching for a process exit.
1496         /// </devdoc>
1497         /// <internalonly/>
1498         void EnsureWatchingForExit() {
1499             if (!watchingForExit) {
1500                 lock (this) {
1501                     if (!watchingForExit) {
1502                         Debug.Assert(haveProcessHandle, "Process.EnsureWatchingForExit called with no process handle");
1503                         Debug.Assert(Associated, "Process.EnsureWatchingForExit called with no associated process");
1504                         watchingForExit = true;
1505                         try {
1506                             this.waitHandle = new ProcessWaitHandle(m_processHandle);
1507                             this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(this.waitHandle,
1508                                 new WaitOrTimerCallback(this.CompletionCallback), null, -1, true);                    
1509                         }
1510                         catch {
1511                             watchingForExit = false;
1512                             throw;
1513                         }
1514                     }
1515                 }
1516             }
1517         }
1518
1519 #if !FEATURE_PAL    
1520
1521         /// <devdoc>
1522         ///     Make sure we have obtained the min and max working set limits.
1523         /// </devdoc>
1524         /// <internalonly/>
1525         void EnsureWorkingSetLimits() {
1526             EnsureState(State.IsNt);
1527             if (!haveWorkingSetLimits) {
1528                 SafeProcessHandle handle = null;
1529                 try {
1530                     handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
1531                     IntPtr min;
1532                     IntPtr max;
1533                     if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1534                         throw new Win32Exception();
1535                     }
1536                     minWorkingSet = min;
1537                     maxWorkingSet = max;
1538                     haveWorkingSetLimits = true;
1539                 }
1540                 finally {
1541                     ReleaseProcessHandle(handle);
1542                 }
1543             }
1544         }
1545
1546         public static void EnterDebugMode() {
1547 #if !MONO
1548             if (ProcessManager.IsNt) {
1549                 SetPrivilege("SeDebugPrivilege", NativeMethods.SE_PRIVILEGE_ENABLED);
1550             }
1551 #endif
1552         }
1553
1554 #if !MONO
1555         [ResourceExposure(ResourceScope.None)]
1556         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
1557         private static void SetPrivilege(string privilegeName, int attrib) {
1558             IntPtr hToken = (IntPtr)0;
1559             NativeMethods.LUID debugValue = new NativeMethods.LUID();
1560
1561             // this is only a "pseudo handle" to the current process - no need to close it later
1562             IntPtr processHandle = NativeMethods.GetCurrentProcess();
1563
1564             // get the process token so we can adjust the privilege on it.  We DO need to
1565             // close the token when we're done with it.
1566             if (!NativeMethods.OpenProcessToken(new HandleRef(null, processHandle), NativeMethods.TOKEN_ADJUST_PRIVILEGES, out hToken)) {
1567                 throw new Win32Exception();
1568             }
1569
1570             try {
1571                 if (!NativeMethods.LookupPrivilegeValue(null, privilegeName, out debugValue)) {
1572                     throw new Win32Exception();
1573                 }
1574                 
1575                 NativeMethods.TokenPrivileges tkp = new NativeMethods.TokenPrivileges();
1576                 tkp.Luid = debugValue;
1577                 tkp.Attributes = attrib;
1578     
1579                 NativeMethods.AdjustTokenPrivileges(new HandleRef(null, hToken), false, tkp, 0, IntPtr.Zero, IntPtr.Zero);
1580     
1581                 // AdjustTokenPrivileges can return true even if it failed to
1582                 // set the privilege, so we need to use GetLastError
1583                 if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_SUCCESS) {
1584                     throw new Win32Exception();
1585                 }
1586             }
1587             finally {
1588                 Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(processToken)");
1589                 SafeNativeMethods.CloseHandle(hToken);
1590             }
1591         }
1592 #endif
1593
1594         /// <devdoc>
1595         ///    <para>[To be supplied.]</para>
1596         /// </devdoc>
1597         public static void LeaveDebugMode() {
1598 #if !MONO
1599             if (ProcessManager.IsNt) {
1600                 SetPrivilege("SeDebugPrivilege", 0);
1601             }
1602 #endif
1603         }     
1604
1605 #if !MONO
1606         /// <devdoc>
1607         ///    <para>
1608         ///       Returns a new <see cref='System.Diagnostics.Process'/> component given a process identifier and
1609         ///       the name of a computer in the network.
1610         ///    </para>
1611         /// </devdoc>
1612         [ResourceExposure(ResourceScope.Machine)]
1613         [ResourceConsumption(ResourceScope.Machine)]
1614         public static Process GetProcessById(int processId, string machineName) {
1615             if (!ProcessManager.IsProcessRunning(processId, machineName)) {
1616                 throw new ArgumentException(SR.GetString(SR.MissingProccess, processId.ToString(CultureInfo.CurrentCulture)));
1617             }
1618             
1619             return new Process(machineName, ProcessManager.IsRemoteMachine(machineName), processId, null);
1620         }
1621 #endif
1622
1623         /// <devdoc>
1624         ///    <para>
1625         ///       Returns a new <see cref='System.Diagnostics.Process'/> component given the
1626         ///       identifier of a process on the local computer.
1627         ///    </para>
1628         /// </devdoc>
1629         [ResourceExposure(ResourceScope.Machine)]
1630         [ResourceConsumption(ResourceScope.Machine)]
1631         public static Process GetProcessById(int processId) {
1632             return GetProcessById(processId, ".");
1633         }
1634
1635         /// <devdoc>
1636         ///    <para>
1637         ///       Creates an array of <see cref='System.Diagnostics.Process'/> components that are
1638         ///       associated
1639         ///       with process resources on the
1640         ///       local computer. These process resources share the specified process name.
1641         ///    </para>
1642         /// </devdoc>
1643         [ResourceExposure(ResourceScope.Machine)]
1644         [ResourceConsumption(ResourceScope.Machine)]
1645         public static Process[] GetProcessesByName(string processName) {
1646             return GetProcessesByName(processName, ".");
1647         }
1648
1649 #if !MONO
1650         /// <devdoc>
1651         ///    <para>
1652         ///       Creates an array of <see cref='System.Diagnostics.Process'/> components that are associated with process resources on a
1653         ///       remote computer. These process resources share the specified process name.
1654         ///    </para>
1655         /// </devdoc>
1656         [ResourceExposure(ResourceScope.Machine)]
1657         [ResourceConsumption(ResourceScope.Machine)]
1658         public static Process[] GetProcessesByName(string processName, string machineName) {
1659             if (processName == null) processName = String.Empty;
1660             Process[] procs = GetProcesses(machineName);
1661             ArrayList list = new ArrayList();
1662
1663             for(int i = 0; i < procs.Length; i++) {                
1664                 if( String.Equals(processName, procs[i].ProcessName, StringComparison.OrdinalIgnoreCase)) {
1665                     list.Add( procs[i]);                    
1666                 } else {
1667                     procs[i].Dispose();
1668                 }
1669             }
1670             
1671             Process[] temp = new Process[list.Count];
1672             list.CopyTo(temp, 0);
1673             return temp;
1674         }
1675 #endif
1676
1677         /// <devdoc>
1678         ///    <para>
1679         ///       Creates a new <see cref='System.Diagnostics.Process'/>
1680         ///       component for each process resource on the local computer.
1681         ///    </para>
1682         /// </devdoc>
1683         [ResourceExposure(ResourceScope.Machine)]
1684         [ResourceConsumption(ResourceScope.Machine)]
1685         public static Process[] GetProcesses() {
1686             return GetProcesses(".");
1687         }
1688
1689 #if !MONO
1690         /// <devdoc>
1691         ///    <para>
1692         ///       Creates a new <see cref='System.Diagnostics.Process'/>
1693         ///       component for each
1694         ///       process resource on the specified computer.
1695         ///    </para>
1696         /// </devdoc>
1697         [ResourceExposure(ResourceScope.Machine)]
1698         [ResourceConsumption(ResourceScope.Machine)]
1699         public static Process[] GetProcesses(string machineName) {
1700             bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName);
1701             ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
1702             Process[] processes = new Process[processInfos.Length];
1703             for (int i = 0; i < processInfos.Length; i++) {
1704                 ProcessInfo processInfo = processInfos[i];
1705                 processes[i] = new Process(machineName, isRemoteMachine, processInfo.processId, processInfo);
1706             }
1707             Debug.WriteLineIf(processTracing.TraceVerbose, "Process.GetProcesses(" + machineName + ")");
1708 #if DEBUG
1709             if (processTracing.TraceVerbose) {
1710                 Debug.Indent();
1711                 for (int i = 0; i < processInfos.Length; i++) {
1712                     Debug.WriteLine(processes[i].Id + ": " + processes[i].ProcessName);
1713                 }
1714                 Debug.Unindent();
1715             }
1716 #endif // DEBUG
1717             return processes;
1718         }
1719 #endif // !MONO
1720
1721 #endif // !FEATURE_PAL        
1722
1723         /// <devdoc>
1724         ///    <para>
1725         ///       Returns a new <see cref='System.Diagnostics.Process'/>
1726         ///       component and associates it with the current active process.
1727         ///    </para>
1728         /// </devdoc>
1729         [ResourceExposure(ResourceScope.Process)]
1730         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Process)]
1731         public static Process GetCurrentProcess() {
1732             return new Process(".", false, NativeMethods.GetCurrentProcessId(), null);
1733         }
1734
1735         /// <devdoc>
1736         ///    <para>
1737         ///       Raises the <see cref='System.Diagnostics.Process.Exited'/> event.
1738         ///    </para>
1739         /// </devdoc>
1740         protected void OnExited() {
1741             EventHandler exited = onExited;
1742             if (exited != null) {
1743                 if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired)
1744                     this.SynchronizingObject.BeginInvoke(exited, new object[]{this, EventArgs.Empty});
1745                 else                        
1746                    exited(this, EventArgs.Empty);                
1747             }               
1748         }
1749
1750         /// <devdoc>
1751         ///     Gets a short-term handle to the process, with the given access.  
1752         ///     If a handle is stored in current process object, then use it.
1753         ///     Note that the handle we stored in current process object will have all access we need.
1754         /// </devdoc>
1755         /// <internalonly/>
1756         [ResourceExposure(ResourceScope.None)]
1757         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1758         SafeProcessHandle GetProcessHandle(int access, bool throwIfExited) {
1759             Debug.WriteLineIf(processTracing.TraceVerbose, "GetProcessHandle(access = 0x" + access.ToString("X8", CultureInfo.InvariantCulture) + ", throwIfExited = " + throwIfExited + ")");
1760 #if DEBUG
1761             if (processTracing.TraceVerbose) {
1762                 StackFrame calledFrom = new StackTrace(true).GetFrame(0);
1763                 Debug.WriteLine("   called from " + calledFrom.GetFileName() + ", line " + calledFrom.GetFileLineNumber());
1764             }
1765 #endif
1766             if (haveProcessHandle) {
1767                 if (throwIfExited) {
1768                     // Since haveProcessHandle is true, we know we have the process handle
1769                     // open with at least SYNCHRONIZE access, so we can wait on it with 
1770                     // zero timeout to see if the process has exited.
1771                     ProcessWaitHandle waitHandle = null;
1772                     try {
1773                         waitHandle = new ProcessWaitHandle(m_processHandle);             
1774                         if (waitHandle.WaitOne(0, false)) {
1775                             if (haveProcessId)
1776                                 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1777                             else
1778                                 throw new InvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
1779                         }
1780                     }
1781                     finally {
1782                         if( waitHandle != null) {
1783                             waitHandle.Close();
1784                         }
1785                     }            
1786                 }
1787                 return m_processHandle;
1788             }
1789             else {
1790                 EnsureState(State.HaveId | State.IsLocal);
1791                 SafeProcessHandle handle = SafeProcessHandle.InvalidHandle;
1792 #if !FEATURE_PAL && !MONO
1793                 handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
1794 #else
1795                 IntPtr pseudohandle = NativeMethods.GetCurrentProcess();
1796                 // Get a real handle
1797                 if (!NativeMethods.DuplicateHandle (new HandleRef(this, pseudohandle), 
1798                                                     new HandleRef(this, pseudohandle), 
1799                                                     new HandleRef(this, pseudohandle), 
1800                                                     out handle,
1801                                                     0, 
1802                                                     false, 
1803                                                     NativeMethods.DUPLICATE_SAME_ACCESS | 
1804                                                     NativeMethods.DUPLICATE_CLOSE_SOURCE)) {
1805                     throw new Win32Exception();
1806                 }
1807 #endif // !FEATURE_PAL && !MONO
1808                 if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) {         
1809                     if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
1810                         throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
1811                     }
1812                 }
1813                 return handle;
1814             }
1815
1816         }
1817
1818         /// <devdoc>
1819         ///     Gets a short-term handle to the process, with the given access.  If a handle exists,
1820         ///     then it is reused.  If the process has exited, it throws an exception.
1821         /// </devdoc>
1822         /// <internalonly/>
1823         SafeProcessHandle GetProcessHandle(int access) {
1824             return GetProcessHandle(access, true);
1825         }
1826
1827         /// <devdoc>
1828         ///     Opens a long-term handle to the process, with all access.  If a handle exists,
1829         ///     then it is reused.  If the process has exited, it throws an exception.
1830         /// </devdoc>
1831         /// <internalonly/>
1832         SafeProcessHandle OpenProcessHandle() {
1833             return OpenProcessHandle(NativeMethods.PROCESS_ALL_ACCESS);
1834         }
1835
1836         SafeProcessHandle OpenProcessHandle(Int32 access) {
1837             if (!haveProcessHandle) {
1838                 //Cannot open a new process handle if the object has been disposed, since finalization has been suppressed.            
1839                 if (this.disposed) {
1840                     throw new ObjectDisposedException(GetType().Name);
1841                 }
1842                         
1843                 SetProcessHandle(GetProcessHandle(access));
1844             }                
1845             return m_processHandle;
1846         }
1847
1848 #if !MONO
1849         /// <devdoc>
1850         ///     Raise the Exited event, but make sure we don't do it more than once.
1851         /// </devdoc>
1852         /// <internalonly/>
1853         void RaiseOnExited() {
1854             if (!raisedOnExited) {
1855                 lock (this) {
1856                     if (!raisedOnExited) {
1857                         raisedOnExited = true;
1858                         OnExited();
1859                     }
1860                 }
1861             }
1862         }
1863 #endif
1864
1865         /// <devdoc>
1866         ///    <para>
1867         ///       Discards any information about the associated process
1868         ///       that has been cached inside the process component. After <see cref='System.Diagnostics.Process.Refresh'/> is called, the
1869         ///       first request for information for each property causes the process component
1870         ///       to obtain a new value from the associated process.
1871         ///    </para>
1872         /// </devdoc>
1873         public void Refresh() {
1874 #if !MONO
1875             processInfo = null;
1876 #endif
1877 #if !FEATURE_PAL            
1878             threads = null;
1879             modules = null;
1880 #endif // !FEATURE_PAL            
1881 #if !MONO
1882             mainWindowTitle = null;
1883 #endif
1884             exited = false;
1885             signaled = false;
1886 #if !MONO
1887             haveMainWindow = false;
1888 #endif
1889             haveWorkingSetLimits = false;
1890 #if !MONO
1891             haveProcessorAffinity = false;
1892 #endif
1893             havePriorityClass = false;
1894             haveExitTime = false;
1895 #if !MONO
1896             haveResponding = false;
1897             havePriorityBoostEnabled = false;
1898 #endif
1899         }
1900
1901         /// <devdoc>
1902         ///     Helper to associate a process handle with this component.
1903         /// </devdoc>
1904         /// <internalonly/>
1905         void SetProcessHandle(SafeProcessHandle processHandle) {
1906             this.m_processHandle = processHandle;
1907             this.haveProcessHandle = true;
1908             if (watchForExit) {
1909                 EnsureWatchingForExit();
1910             }
1911         }
1912
1913         /// <devdoc>
1914         ///     Helper to associate a process id with this component.
1915         /// </devdoc>
1916         /// <internalonly/>
1917         [ResourceExposure(ResourceScope.Machine)]
1918         void SetProcessId(int processId) {
1919             this.processId = processId;
1920             this.haveProcessId = true;
1921         }
1922
1923 #if !FEATURE_PAL        
1924
1925         /// <devdoc>
1926         ///     Helper to set minimum or maximum working set limits.
1927         /// </devdoc>
1928         /// <internalonly/>
1929         [ResourceExposure(ResourceScope.Process)]
1930         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1931         void SetWorkingSetLimits(object newMin, object newMax) {
1932             EnsureState(State.IsNt);
1933
1934             SafeProcessHandle handle = null;
1935             try {
1936                 handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_SET_QUOTA);
1937                 IntPtr min;
1938                 IntPtr max;
1939                 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1940                     throw new Win32Exception();
1941                 }
1942                 
1943                 if (newMin != null) {
1944                     min = (IntPtr)newMin;
1945                 }
1946                 
1947                 if (newMax != null) { 
1948                     max = (IntPtr)newMax;
1949                 }
1950                 
1951                 if ((long)min > (long)max) {
1952                     if (newMin != null) {
1953                         throw new ArgumentException(SR.GetString(SR.BadMinWorkset));
1954                     }
1955                     else {
1956                         throw new ArgumentException(SR.GetString(SR.BadMaxWorkset));
1957                     }
1958                 }
1959                 
1960                 if (!NativeMethods.SetProcessWorkingSetSize(handle, min, max)) {
1961                     throw new Win32Exception();
1962                 }
1963                 
1964                 // The value may be rounded/changed by the OS, so go get it
1965                 if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
1966                     throw new Win32Exception();
1967                 }
1968                 minWorkingSet = min;
1969                 maxWorkingSet = max;
1970                 haveWorkingSetLimits = true;
1971             }
1972             finally {
1973                 ReleaseProcessHandle(handle);
1974             }
1975         }
1976
1977 #endif // !FEATURE_PAL
1978
1979 #if MONO_FEATURE_PROCESS_START
1980
1981         /// <devdoc>
1982         ///    <para>
1983         ///       Starts a process specified by the <see cref='System.Diagnostics.Process.StartInfo'/> property of this <see cref='System.Diagnostics.Process'/>
1984         ///       component and associates it with the
1985         ///    <see cref='System.Diagnostics.Process'/> . If a process resource is reused 
1986         ///       rather than started, the reused process is associated with this <see cref='System.Diagnostics.Process'/>
1987         ///       component.
1988         ///    </para>
1989         /// </devdoc>
1990         [ResourceExposure(ResourceScope.None)]
1991         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1992         public bool Start() {
1993             Close();
1994             ProcessStartInfo startInfo = StartInfo;
1995             if (startInfo.FileName.Length == 0) 
1996                 throw new InvalidOperationException(SR.GetString(SR.FileNameMissing));
1997
1998             if (startInfo.UseShellExecute) {
1999 #if !FEATURE_PAL                
2000                 return StartWithShellExecuteEx(startInfo);
2001 #else
2002                 throw new InvalidOperationException(SR.GetString(SR.net_perm_invalid_val, "StartInfo.UseShellExecute", true));
2003 #endif // !FEATURE_PAL
2004             } else {
2005                 return StartWithCreateProcess(startInfo);
2006             }
2007         }
2008
2009 #if !MONO
2010         [ResourceExposure(ResourceScope.Process)]
2011         [ResourceConsumption(ResourceScope.Process)]
2012         private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) {
2013             bool ret = NativeMethods.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize);
2014             if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid) {
2015                 throw new Win32Exception();
2016             }
2017         }
2018
2019         // Using synchronous Anonymous pipes for process input/output redirection means we would end up 
2020         // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since 
2021         // it will take advantage of the NT IO completion port infrastructure. But we can't really use 
2022         // Overlapped I/O for process input/output as it would break Console apps (managed Console class 
2023         // methods such as WriteLine as well as native CRT functions like printf) which are making an
2024         // assumption that the console standard handles (obtained via GetStdHandle()) are opened
2025         // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously!
2026         [ResourceExposure(ResourceScope.None)]
2027         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2028         private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) {
2029             NativeMethods.SECURITY_ATTRIBUTES securityAttributesParent = new NativeMethods.SECURITY_ATTRIBUTES();
2030             securityAttributesParent.bInheritHandle = true;
2031             
2032             SafeFileHandle hTmp = null;
2033             try {
2034                 if (parentInputs) {
2035                     CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);                                                          
2036                 } 
2037                 else {
2038                     CreatePipeWithSecurityAttributes(out hTmp, 
2039                                                           out childHandle, 
2040                                                           securityAttributesParent, 
2041                                                           0);                                                                              
2042                 }
2043                 // Duplicate the parent handle to be non-inheritable so that the child process 
2044                 // doesn't have access. This is done for correctness sake, exact reason is unclear.
2045                 // One potential theory is that child process can do something brain dead like 
2046                 // closing the parent end of the pipe and there by getting into a blocking situation
2047                 // as parent will not be draining the pipe at the other end anymore. 
2048                 if (!NativeMethods.DuplicateHandle(new HandleRef(this, NativeMethods.GetCurrentProcess()), 
2049                                                                    hTmp,
2050                                                                    new HandleRef(this, NativeMethods.GetCurrentProcess()), 
2051                                                                    out parentHandle,
2052                                                                    0, 
2053                                                                    false, 
2054                                                                    NativeMethods.DUPLICATE_SAME_ACCESS)) {                                                                       
2055                     throw new Win32Exception();
2056                 }
2057             }
2058             finally {
2059                 if( hTmp != null && !hTmp.IsInvalid) {
2060                     hTmp.Close();
2061                 }
2062             }
2063         }            
2064
2065         private static StringBuilder BuildCommandLine(string executableFileName, string arguments) {
2066             // Construct a StringBuilder with the appropriate command line
2067             // to pass to CreateProcess.  If the filename isn't already 
2068             // in quotes, we quote it here.  This prevents some security
2069             // problems (it specifies exactly which part of the string
2070             // is the file to execute).
2071             StringBuilder commandLine = new StringBuilder();
2072             string fileName = executableFileName.Trim();
2073             bool fileNameIsQuoted = (fileName.StartsWith("\"", StringComparison.Ordinal) && fileName.EndsWith("\"", StringComparison.Ordinal));
2074             if (!fileNameIsQuoted) { 
2075                 commandLine.Append("\"");
2076             }
2077             
2078             commandLine.Append(fileName);
2079             
2080             if (!fileNameIsQuoted) {
2081                 commandLine.Append("\"");
2082             }
2083             
2084             if (!String.IsNullOrEmpty(arguments)) {
2085                 commandLine.Append(" ");
2086                 commandLine.Append(arguments);                
2087             }                        
2088
2089             return commandLine;
2090         }
2091         
2092         [ResourceExposure(ResourceScope.Machine)]
2093         [ResourceConsumption(ResourceScope.Machine)]
2094         private bool StartWithCreateProcess(ProcessStartInfo startInfo) {
2095             if( startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) {
2096                 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2097             }
2098
2099             if( startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) {
2100                 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2101             }            
2102             
2103             // See knowledge base article Q190351 for an explanation of the following code.  Noteworthy tricky points:
2104             //    * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
2105             //      that the child process can not close them
2106             //    * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
2107             //      GetStdHandle for the handles that are not being redirected
2108
2109             //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.            
2110             if (this.disposed) {
2111                 throw new ObjectDisposedException(GetType().Name);
2112             }
2113
2114             StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
2115
2116             NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO();
2117             SafeNativeMethods.PROCESS_INFORMATION processInfo = new SafeNativeMethods.PROCESS_INFORMATION();
2118             SafeProcessHandle procSH = new SafeProcessHandle();
2119             SafeThreadHandle threadSH = new SafeThreadHandle();
2120             bool retVal;
2121             int errorCode = 0;
2122             // handles used in parent process
2123             SafeFileHandle standardInputWritePipeHandle = null;
2124             SafeFileHandle standardOutputReadPipeHandle = null;
2125             SafeFileHandle standardErrorReadPipeHandle = null;
2126             GCHandle environmentHandle = new GCHandle();            
2127             lock (s_CreateProcessLock) {
2128             try {
2129                 // set up the streams
2130                 if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {                        
2131                     if (startInfo.RedirectStandardInput) {
2132                         CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
2133                         } else {
2134                         startupInfo.hStdInput  =  new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);
2135                     }
2136     
2137                     if (startInfo.RedirectStandardOutput) {                        
2138                         CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false);
2139                         } else {
2140                         startupInfo.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_OUTPUT_HANDLE), false);
2141                     }
2142     
2143                     if (startInfo.RedirectStandardError) {
2144                         CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false);
2145                         } else {
2146                         startupInfo.hStdError = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_ERROR_HANDLE), false);
2147                     }
2148     
2149                     startupInfo.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
2150                 }
2151     
2152                 // set up the creation flags paramater
2153                 int creationFlags = 0;
2154 #if !FEATURE_PAL                
2155                 if (startInfo.CreateNoWindow)  creationFlags |= NativeMethods.CREATE_NO_WINDOW;               
2156 #endif // !FEATURE_PAL                
2157
2158                 // set up the environment block parameter
2159                 IntPtr environmentPtr = (IntPtr)0;
2160                 if (startInfo.environmentVariables != null) {
2161                     bool unicode = false;
2162 #if !FEATURE_PAL                    
2163                     if (ProcessManager.IsNt) {
2164                         creationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;                
2165                         unicode = true;
2166                     }
2167 #endif // !FEATURE_PAL
2168                     
2169                     byte[] environmentBytes = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode);
2170                     environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
2171                     environmentPtr = environmentHandle.AddrOfPinnedObject();
2172                 }
2173
2174                 string workingDirectory = startInfo.WorkingDirectory;
2175                 if (workingDirectory == string.Empty)
2176                     workingDirectory = Environment.CurrentDirectory;
2177
2178 #if !FEATURE_PAL                    
2179                 if (startInfo.UserName.Length != 0) {                              
2180                     if (startInfo.Password != null && startInfo.PasswordInClearText != null)
2181                             throw new ArgumentException(SR.GetString(SR.CantSetDuplicatePassword));
2182
2183                     NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0;                    
2184                     if( startInfo.LoadUserProfile) {
2185                         logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
2186                     }
2187
2188                     IntPtr password = IntPtr.Zero;
2189                     try {
2190                         if( startInfo.Password != null) {
2191                             password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
2192                         } else if( startInfo.PasswordInClearText != null) {
2193                             password = Marshal.StringToCoTaskMemUni(startInfo.PasswordInClearText);
2194                         } else {
2195                             password = Marshal.StringToCoTaskMemUni(String.Empty);
2196                         }
2197
2198                         RuntimeHelpers.PrepareConstrainedRegions();
2199                         try {} finally {
2200                            retVal = NativeMethods.CreateProcessWithLogonW(
2201                                    startInfo.UserName,
2202                                    startInfo.Domain,
2203                                    password,
2204                                    logonFlags,
2205                                    null,            // we don't need this since all the info is in commandLine
2206                                    commandLine,
2207                                    creationFlags,
2208                                    environmentPtr,
2209                                    workingDirectory,
2210                                    startupInfo,        // pointer to STARTUPINFO
2211                                    processInfo         // pointer to PROCESS_INFORMATION
2212                                ); 
2213                            if (!retVal)                            
2214                               errorCode = Marshal.GetLastWin32Error();
2215                            if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2216                               procSH.InitialSetHandle(processInfo.hProcess);  
2217                            if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2218                               threadSH.InitialSetHandle(processInfo.hThread);            
2219                         }
2220                         if (!retVal){                            
2221                                 if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2222                                 throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2223                             }
2224
2225                             throw new Win32Exception(errorCode);
2226                         }
2227                         } finally {
2228                         if( password != IntPtr.Zero) {
2229                             Marshal.ZeroFreeCoTaskMemUnicode(password);
2230                         }
2231                     }
2232                     } else {
2233 #endif // !FEATURE_PAL
2234                     RuntimeHelpers.PrepareConstrainedRegions();
2235                     try {} finally {
2236                        retVal = NativeMethods.CreateProcess (
2237                                null,               // we don't need this since all the info is in commandLine
2238                                commandLine,        // pointer to the command line string
2239                                null,               // pointer to process security attributes, we don't need to inheriat the handle
2240                                null,               // pointer to thread security attributes
2241                                true,               // handle inheritance flag
2242                                creationFlags,      // creation flags
2243                                environmentPtr,     // pointer to new environment block
2244                                workingDirectory,   // pointer to current directory name
2245                                startupInfo,        // pointer to STARTUPINFO
2246                                processInfo         // pointer to PROCESS_INFORMATION
2247                            );
2248                        if (!retVal)                            
2249                               errorCode = Marshal.GetLastWin32Error();
2250                        if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2251                            procSH.InitialSetHandle(processInfo.hProcess);  
2252                        if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
2253                           threadSH.InitialSetHandle(processInfo.hThread);                    
2254                     }
2255                     if (!retVal) {
2256                             if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2257                           throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication));
2258                        }
2259                         throw new Win32Exception(errorCode);
2260                     }
2261 #if !FEATURE_PAL                    
2262                 }
2263 #endif
2264                 } finally {
2265                 // free environment block
2266                 if (environmentHandle.IsAllocated) {
2267                     environmentHandle.Free();   
2268                 }
2269
2270                 startupInfo.Dispose();
2271             }
2272             }
2273
2274             if (startInfo.RedirectStandardInput) {
2275                 standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096);
2276                 standardInput.AutoFlush = true;
2277             }
2278             if (startInfo.RedirectStandardOutput) {
2279                 Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
2280                 standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2281             }
2282             if (startInfo.RedirectStandardError) {
2283                 Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
2284                 standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
2285             }
2286             
2287             bool ret = false;
2288             if (!procSH.IsInvalid) {
2289                 SetProcessHandle(procSH);
2290                 SetProcessId(processInfo.dwProcessId);
2291                 threadSH.Close();
2292                 ret = true;
2293             }
2294
2295             return ret;
2296
2297         }
2298 #endif // !MONO
2299
2300 #if !FEATURE_PAL
2301
2302 #if !MONO
2303         [ResourceExposure(ResourceScope.Machine)]
2304         [ResourceConsumption(ResourceScope.Machine)]
2305         private bool StartWithShellExecuteEx(ProcessStartInfo startInfo) {                        
2306             //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.            
2307             if (this.disposed)
2308                 throw new ObjectDisposedException(GetType().Name);
2309
2310             if( !String.IsNullOrEmpty(startInfo.UserName) || (startInfo.Password != null) ) {
2311                 throw new InvalidOperationException(SR.GetString(SR.CantStartAsUser));                
2312             }
2313             
2314             if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
2315                 throw new InvalidOperationException(SR.GetString(SR.CantRedirectStreams));
2316             }
2317
2318             if (startInfo.StandardErrorEncoding != null) {
2319                 throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
2320             }
2321
2322             if (startInfo.StandardOutputEncoding != null) {
2323                 throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
2324             }
2325
2326             // can't set env vars with ShellExecuteEx...
2327             if (startInfo.environmentVariables != null) {
2328                 throw new InvalidOperationException(SR.GetString(SR.CantUseEnvVars));
2329             }
2330
2331             NativeMethods.ShellExecuteInfo shellExecuteInfo = new NativeMethods.ShellExecuteInfo();
2332             shellExecuteInfo.fMask = NativeMethods.SEE_MASK_NOCLOSEPROCESS;
2333             if (startInfo.ErrorDialog) {
2334                 shellExecuteInfo.hwnd = startInfo.ErrorDialogParentHandle;
2335             }
2336             else {
2337                 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_NO_UI;
2338             }
2339
2340             switch (startInfo.WindowStyle) {
2341                 case ProcessWindowStyle.Hidden:
2342                     shellExecuteInfo.nShow = NativeMethods.SW_HIDE;
2343                     break;
2344                 case ProcessWindowStyle.Minimized:
2345                     shellExecuteInfo.nShow = NativeMethods.SW_SHOWMINIMIZED;
2346                     break;
2347                 case ProcessWindowStyle.Maximized:
2348                     shellExecuteInfo.nShow = NativeMethods.SW_SHOWMAXIMIZED;
2349                     break;
2350                 default:
2351                     shellExecuteInfo.nShow = NativeMethods.SW_SHOWNORMAL;
2352                     break;
2353             }
2354
2355             
2356             try {
2357                 if (startInfo.FileName.Length != 0)
2358                     shellExecuteInfo.lpFile = Marshal.StringToHGlobalAuto(startInfo.FileName);
2359                 if (startInfo.Verb.Length != 0)
2360                     shellExecuteInfo.lpVerb = Marshal.StringToHGlobalAuto(startInfo.Verb);
2361                 if (startInfo.Arguments.Length != 0)
2362                     shellExecuteInfo.lpParameters = Marshal.StringToHGlobalAuto(startInfo.Arguments);
2363                 if (startInfo.WorkingDirectory.Length != 0)
2364                     shellExecuteInfo.lpDirectory = Marshal.StringToHGlobalAuto(startInfo.WorkingDirectory);
2365
2366                 shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_DDEWAIT;
2367
2368                 ShellExecuteHelper executeHelper = new ShellExecuteHelper(shellExecuteInfo);
2369                 if (!executeHelper.ShellExecuteOnSTAThread()) {
2370                     int error = executeHelper.ErrorCode;
2371                     if (error == 0) {
2372                         switch ((long)shellExecuteInfo.hInstApp) {
2373                             case NativeMethods.SE_ERR_FNF: error = NativeMethods.ERROR_FILE_NOT_FOUND; break;
2374                             case NativeMethods.SE_ERR_PNF: error = NativeMethods.ERROR_PATH_NOT_FOUND; break;
2375                             case NativeMethods.SE_ERR_ACCESSDENIED: error = NativeMethods.ERROR_ACCESS_DENIED; break;
2376                             case NativeMethods.SE_ERR_OOM: error = NativeMethods.ERROR_NOT_ENOUGH_MEMORY; break;
2377                             case NativeMethods.SE_ERR_DDEFAIL:
2378                             case NativeMethods.SE_ERR_DDEBUSY:
2379                             case NativeMethods.SE_ERR_DDETIMEOUT: error = NativeMethods.ERROR_DDE_FAIL; break;
2380                             case NativeMethods.SE_ERR_SHARE: error = NativeMethods.ERROR_SHARING_VIOLATION; break;
2381                             case NativeMethods.SE_ERR_NOASSOC: error = NativeMethods.ERROR_NO_ASSOCIATION; break;
2382                             case NativeMethods.SE_ERR_DLLNOTFOUND: error = NativeMethods.ERROR_DLL_NOT_FOUND; break;
2383                             default: error = (int)shellExecuteInfo.hInstApp; break;
2384                         }
2385                     }
2386                     if( error == NativeMethods.ERROR_BAD_EXE_FORMAT || error == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
2387                         throw new Win32Exception(error, SR.GetString(SR.InvalidApplication));
2388                     }
2389                     throw new Win32Exception(error);
2390                 }
2391             
2392             }
2393             finally {                
2394                 if (shellExecuteInfo.lpFile != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpFile);
2395                 if (shellExecuteInfo.lpVerb != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpVerb);
2396                 if (shellExecuteInfo.lpParameters != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpParameters);
2397                 if (shellExecuteInfo.lpDirectory != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpDirectory);
2398             }
2399
2400             if (shellExecuteInfo.hProcess != (IntPtr)0) {                
2401                 SafeProcessHandle handle = new SafeProcessHandle(shellExecuteInfo.hProcess);
2402                 SetProcessHandle(handle);
2403                 return true;
2404             }
2405             
2406             return false;            
2407         }
2408 #endif
2409
2410         [ResourceExposure(ResourceScope.Machine)]
2411         [ResourceConsumption(ResourceScope.Machine)]
2412         public static Process Start( string fileName, string userName, SecureString password, string domain ) {
2413             ProcessStartInfo startInfo = new ProcessStartInfo(fileName);            
2414             startInfo.UserName = userName;
2415             startInfo.Password = password;
2416             startInfo.Domain = domain;
2417             startInfo.UseShellExecute = false;
2418             return Start(startInfo);
2419         }
2420         
2421         [ResourceExposure(ResourceScope.Machine)]
2422         [ResourceConsumption(ResourceScope.Machine)]
2423         public static Process Start( string fileName, string arguments, string userName, SecureString password, string domain ) {
2424             ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);                        
2425             startInfo.UserName = userName;
2426             startInfo.Password = password;
2427             startInfo.Domain = domain;
2428             startInfo.UseShellExecute = false;            
2429             return Start(startInfo);            
2430         }
2431
2432
2433 #endif // !FEATURE_PAL
2434
2435         /// <devdoc>
2436         ///    <para>
2437         ///       Starts a process resource by specifying the name of a
2438         ///       document or application file. Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2439         ///       component.
2440         ///    </para>
2441         /// </devdoc>
2442         [ResourceExposure(ResourceScope.Machine)]
2443         [ResourceConsumption(ResourceScope.Machine)]
2444         public static Process Start(string fileName) {
2445             return Start(new ProcessStartInfo(fileName));
2446         }
2447
2448         /// <devdoc>
2449         ///    <para>
2450         ///       Starts a process resource by specifying the name of an
2451         ///       application and a set of command line arguments. Associates the process resource
2452         ///       with a new <see cref='System.Diagnostics.Process'/>
2453         ///       component.
2454         ///    </para>
2455         /// </devdoc>
2456         [ResourceExposure(ResourceScope.Machine)]
2457         [ResourceConsumption(ResourceScope.Machine)]
2458         public static Process Start(string fileName, string arguments) {
2459             return Start(new ProcessStartInfo(fileName, arguments));
2460         }
2461
2462         /// <devdoc>
2463         ///    <para>
2464         ///       Starts a process resource specified by the process start
2465         ///       information passed in, for example the file name of the process to start.
2466         ///       Associates the process resource with a new <see cref='System.Diagnostics.Process'/>
2467         ///       component.
2468         ///    </para>
2469         /// </devdoc>
2470         [ResourceExposure(ResourceScope.Machine)]
2471         [ResourceConsumption(ResourceScope.Machine)]
2472         public static Process Start(ProcessStartInfo startInfo) {
2473             Process process = new Process();
2474             if (startInfo == null) throw new ArgumentNullException("startInfo");
2475             process.StartInfo = startInfo;
2476             if (process.Start()) {
2477                 return process;
2478             }
2479             return null;
2480         }
2481
2482 #endif // MONO_FEATURE_PROCESS_START
2483
2484         /// <devdoc>
2485         ///    <para>
2486         ///       Stops the
2487         ///       associated process immediately.
2488         ///    </para>
2489         /// </devdoc>
2490         [ResourceExposure(ResourceScope.Machine)]
2491         [ResourceConsumption(ResourceScope.Machine)]
2492         public void Kill() {
2493             SafeProcessHandle handle = null;
2494             try {
2495                 handle = GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
2496                 if (!NativeMethods.TerminateProcess(handle, -1))
2497                     throw new Win32Exception();
2498             }
2499             finally {
2500                 ReleaseProcessHandle(handle);
2501             }
2502         }
2503
2504         /// <devdoc>
2505         ///     Make sure we are not watching for process exit.
2506         /// </devdoc>
2507         /// <internalonly/>
2508         void StopWatchingForExit() {
2509             if (watchingForExit) {
2510                 lock (this) {
2511                     if (watchingForExit) {
2512                         watchingForExit = false;
2513                         registeredWaitHandle.Unregister(null);
2514                         waitHandle.Close();
2515                         waitHandle = null;
2516                         registeredWaitHandle = null;
2517                     }
2518                 }
2519             }
2520         }
2521
2522         public override string ToString() {
2523 #if !FEATURE_PAL        
2524             if (Associated) {
2525                 string processName  =  String.Empty;  
2526                 //
2527                 // On windows 9x, we can't map a handle to an id.
2528                 // So ProcessName will throw. We shouldn't throw in Process.ToString though.
2529                 // Process.GetProcesses should be used to get all the processes on the machine.
2530                 // The processes returned from it will have a nice name.
2531                 //
2532                 try {
2533                     processName = this.ProcessName;
2534                 }    
2535                 catch(PlatformNotSupportedException) {
2536                 }
2537                 if( processName.Length != 0) { 
2538                     return String.Format(CultureInfo.CurrentCulture, "{0} ({1})", base.ToString(), processName);
2539                 }
2540                 return base.ToString();
2541             }    
2542             else
2543 #endif // !FEATURE_PAL                
2544                 return base.ToString();
2545         }
2546
2547         /// <devdoc>
2548         ///    <para>
2549         ///       Instructs the <see cref='System.Diagnostics.Process'/> component to wait the specified number of milliseconds for the associated process to exit.
2550         ///    </para>
2551         /// </devdoc>
2552         public bool WaitForExit(int milliseconds) {
2553             SafeProcessHandle handle = null;
2554              bool exited;
2555             ProcessWaitHandle processWaitHandle = null;
2556             try {
2557                 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE, false);                
2558                 if (handle.IsInvalid) {
2559                     exited = true;
2560                 }
2561                 else {
2562                     processWaitHandle = new ProcessWaitHandle(handle);
2563                     if( processWaitHandle.WaitOne(milliseconds, false)) {
2564                         exited = true;
2565                         signaled = true;
2566                     }
2567                     else {
2568                         exited = false;
2569                         signaled = false;
2570                     }
2571                 }
2572             }
2573             finally {
2574                 if( processWaitHandle != null) {
2575                     processWaitHandle.Close();
2576                 }
2577
2578                 // If we have a hard timeout, we cannot wait for the streams
2579                 if( output != null && milliseconds == -1) {
2580                     output.WaitUtilEOF();
2581                 }
2582
2583                 if( error != null && milliseconds == -1) {
2584                     error.WaitUtilEOF();
2585                 }
2586
2587                 ReleaseProcessHandle(handle);
2588
2589             }
2590             
2591             if (exited && watchForExit) {
2592                 RaiseOnExited();
2593             }
2594                         
2595             return exited;
2596         }
2597
2598         /// <devdoc>
2599         ///    <para>
2600         ///       Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2601         ///       indefinitely for the associated process to exit.
2602         ///    </para>
2603         /// </devdoc>
2604         public void WaitForExit() {
2605             WaitForExit(-1);
2606         }
2607
2608 #if !FEATURE_PAL        
2609
2610         /// <devdoc>
2611         ///    <para>
2612         ///       Causes the <see cref='System.Diagnostics.Process'/> component to wait the
2613         ///       specified number of milliseconds for the associated process to enter an
2614         ///       idle state.
2615         ///       This is only applicable for processes with a user interface,
2616         ///       therefore a message loop.
2617         ///    </para>
2618         /// </devdoc>
2619         public bool WaitForInputIdle(int milliseconds) {
2620             SafeProcessHandle handle = null;
2621             bool idle;
2622             try {
2623                 handle = GetProcessHandle(NativeMethods.SYNCHRONIZE | NativeMethods.PROCESS_QUERY_INFORMATION);
2624                 int ret = NativeMethods.WaitForInputIdle(handle, milliseconds);
2625                 switch (ret) {
2626                     case NativeMethods.WAIT_OBJECT_0:
2627                         idle = true;
2628                         break;
2629                     case NativeMethods.WAIT_TIMEOUT:
2630                         idle = false;
2631                         break;
2632                     case NativeMethods.WAIT_FAILED:
2633                     default:
2634                         throw new InvalidOperationException(SR.GetString(SR.InputIdleUnkownError));
2635                 }
2636             }
2637             finally {
2638                 ReleaseProcessHandle(handle);
2639             }
2640             return idle;
2641         }
2642
2643         /// <devdoc>
2644         ///    <para>
2645         ///       Instructs the <see cref='System.Diagnostics.Process'/> component to wait
2646         ///       indefinitely for the associated process to enter an idle state. This
2647         ///       is only applicable for processes with a user interface, therefore a message loop.
2648         ///    </para>
2649         /// </devdoc>
2650         public bool WaitForInputIdle() {
2651             return WaitForInputIdle(Int32.MaxValue);
2652         }
2653
2654 #endif // !FEATURE_PAL        
2655
2656 #if MONO_FEATURE_PROCESS_START
2657         // Support for working asynchronously with streams
2658         /// <devdoc>
2659         /// <para>
2660         /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2661         /// reading the StandardOutput stream asynchronously. The user can register a callback
2662         /// that will be called when a line of data terminated by \n,\r or \r\n is reached, or the end of stream is reached
2663         /// then the remaining information is returned. The user can add an event handler to OutputDataReceived.
2664         /// </para>
2665         /// </devdoc>
2666         [System.Runtime.InteropServices.ComVisible(false)]        
2667         public void BeginOutputReadLine() {
2668
2669             if(outputStreamReadMode == StreamReadMode.undefined) {
2670                 outputStreamReadMode = StreamReadMode.asyncMode;
2671             }
2672             else if (outputStreamReadMode != StreamReadMode.asyncMode) {
2673                 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));                    
2674             }
2675             
2676             if (pendingOutputRead)
2677                 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2678
2679             pendingOutputRead = true;
2680             // We can't detect if there's a pending sychronous read, tream also doesn't.
2681             if (output == null) {
2682                 if (standardOutput == null) {
2683                     throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
2684                 }
2685
2686                 Stream s = standardOutput.BaseStream;
2687                 output = new AsyncStreamReader(this, s, new UserCallBack(this.OutputReadNotifyUser), standardOutput.CurrentEncoding);
2688             }
2689             output.BeginReadLine();
2690         }
2691
2692
2693         /// <devdoc>
2694         /// <para>
2695         /// Instructs the <see cref='System.Diagnostics.Process'/> component to start
2696         /// reading the StandardError stream asynchronously. The user can register a callback
2697         /// that will be called when a line of data terminated by \n,\r or \r\n is reached, or the end of stream is reached
2698         /// then the remaining information is returned. The user can add an event handler to ErrorDataReceived.
2699         /// </para>
2700         /// </devdoc>
2701         [System.Runtime.InteropServices.ComVisible(false)]        
2702         public void BeginErrorReadLine() {
2703
2704             if(errorStreamReadMode == StreamReadMode.undefined) {
2705                 errorStreamReadMode = StreamReadMode.asyncMode;
2706             }
2707             else if (errorStreamReadMode != StreamReadMode.asyncMode) {
2708                 throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));                    
2709             }
2710             
2711             if (pendingErrorRead) {
2712                 throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
2713             }
2714
2715             pendingErrorRead = true;
2716             // We can't detect if there's a pending sychronous read, stream also doesn't.
2717             if (error == null) {
2718                 if (standardError == null) {
2719                     throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
2720                 }
2721
2722                 Stream s = standardError.BaseStream;
2723                 error = new AsyncStreamReader(this, s, new UserCallBack(this.ErrorReadNotifyUser), standardError.CurrentEncoding);
2724             }
2725             error.BeginReadLine();
2726         }
2727
2728         /// <devdoc>
2729         /// <para>
2730         /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2731         /// specified by BeginOutputReadLine().
2732         /// </para>
2733         /// </devdoc>
2734         [System.Runtime.InteropServices.ComVisible(false)]
2735         public void CancelOutputRead() {        
2736             if (output != null) {
2737                 output.CancelOperation();
2738             }
2739             else {
2740                 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2741             }
2742
2743             pendingOutputRead = false;
2744         }
2745
2746         /// <devdoc>
2747         /// <para>
2748         /// Instructs the <see cref='System.Diagnostics.Process'/> component to cancel the asynchronous operation
2749         /// specified by BeginErrorReadLine().
2750         /// </para>
2751         /// </devdoc>
2752         [System.Runtime.InteropServices.ComVisible(false)]        
2753         public void CancelErrorRead() {
2754             if (error != null) {
2755                 error.CancelOperation();
2756             }
2757             else {
2758                 throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation));
2759             }
2760
2761             pendingErrorRead = false;
2762         }
2763
2764         internal void OutputReadNotifyUser(String data) {
2765             // To avoid ---- between remove handler and raising the event
2766             DataReceivedEventHandler outputDataReceived = OutputDataReceived;
2767             if (outputDataReceived != null) {
2768                 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2769                 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2770                     SynchronizingObject.Invoke(outputDataReceived, new object[] {this, e});
2771                 }
2772                 else {
2773                     outputDataReceived(this,e);  // Call back to user informing data is available.
2774                 }
2775             }
2776         }
2777
2778         internal void ErrorReadNotifyUser(String data) {
2779             // To avoid ---- between remove handler and raising the event
2780             DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
2781             if (errorDataReceived != null) {
2782                 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
2783                 if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
2784                     SynchronizingObject.Invoke(errorDataReceived, new object[] {this, e});
2785                 }
2786                 else {
2787                     errorDataReceived(this,e); // Call back to user informing data is available.
2788                 }
2789             }
2790         }
2791 #endif // MONO_FEATURE_PROCESS_START
2792
2793         /// <summary>
2794         ///     A desired internal state.
2795         /// </summary>
2796         /// <internalonly/>
2797         enum State {
2798             HaveId = 0x1,
2799             IsLocal = 0x2,
2800             IsNt = 0x4,
2801             HaveProcessInfo = 0x8,
2802             Exited = 0x10,
2803             Associated = 0x20,
2804             IsWin2k = 0x40,
2805             HaveNtProcessInfo = HaveProcessInfo | IsNt
2806         }
2807     }
2808
2809     /// <devdoc>
2810     ///     This data structure contains information about a process that is collected
2811     ///     in bulk by querying the operating system.  The reason to make this a separate
2812     ///     structure from the process component is so that we can throw it away all at once
2813     ///     when Refresh is called on the component.
2814     /// </devdoc>
2815     /// <internalonly/>
2816     internal class ProcessInfo {
2817 #if !MONO
2818         public ArrayList threadInfoList = new ArrayList();
2819         public int basePriority;
2820         public string processName;
2821         public int processId;
2822         public int handleCount;
2823         public long poolPagedBytes;
2824         public long poolNonpagedBytes;
2825         public long virtualBytes;
2826         public long virtualBytesPeak;
2827         public long workingSetPeak;
2828         public long workingSet;
2829         public long pageFileBytesPeak;
2830         public long pageFileBytes;
2831         public long privateBytes;
2832         public int mainModuleId; // used only for win9x - id is only for use with CreateToolHelp32
2833         public int sessionId; 
2834 #endif
2835     }
2836
2837 #if !MONO
2838     /// <devdoc>
2839     ///     This data structure contains information about a thread in a process that
2840     ///     is collected in bulk by querying the operating system.  The reason to
2841     ///     make this a separate structure from the ProcessThread component is so that we
2842     ///     can throw it away all at once when Refresh is called on the component.
2843     /// </devdoc>
2844     /// <internalonly/>
2845     internal class ThreadInfo {
2846         public int threadId;
2847         public int processId;
2848         public int basePriority;
2849         public int currentPriority;
2850         public IntPtr startAddress;
2851         public ThreadState threadState;
2852 #if !FEATURE_PAL        
2853         public ThreadWaitReason threadWaitReason;
2854 #endif // !FEATURE_PAL
2855     }
2856
2857     /// <devdoc>
2858     ///     This data structure contains information about a module in a process that
2859     ///     is collected in bulk by querying the operating system.  The reason to
2860     ///     make this a separate structure from the ProcessModule component is so that we
2861     ///     can throw it away all at once when Refresh is called on the component.
2862     /// </devdoc>
2863     /// <internalonly/>
2864     internal class ModuleInfo {
2865         public string baseName;
2866         public string fileName;
2867         public IntPtr baseOfDll;
2868         public IntPtr entryPoint;
2869         public int sizeOfImage;
2870         public int Id; // used only on win9x - for matching up with ProcessInfo.mainModuleId
2871     }
2872 #endif
2873
2874     internal static class EnvironmentBlock {
2875         public static byte[] ToByteArray(StringDictionary sd, bool unicode) {
2876             // get the keys
2877             string[] keys = new string[sd.Count];
2878             byte[] envBlock = null;
2879             sd.Keys.CopyTo(keys, 0);
2880             
2881             // get the values
2882             string[] values = new string[sd.Count];
2883             sd.Values.CopyTo(values, 0);
2884             
2885             // sort both by the keys
2886             // Windows 2000 requires the environment block to be sorted by the key
2887             // It will first converting the case the strings and do ordinal comparison.
2888             Array.Sort(keys, values, OrdinalCaseInsensitiveComparer.Default);
2889
2890             // create a list of null terminated "key=val" strings
2891             StringBuilder stringBuff = new StringBuilder();
2892             for (int i = 0; i < sd.Count; ++ i) {
2893                 stringBuff.Append(keys[i]);
2894                 stringBuff.Append('=');
2895                 stringBuff.Append(values[i]);
2896                 stringBuff.Append('\0');
2897             }
2898             // an extra null at the end indicates end of list.
2899             stringBuff.Append('\0');
2900                         
2901             if( unicode) {
2902                 envBlock = Encoding.Unicode.GetBytes(stringBuff.ToString());                        
2903             }
2904             else {
2905                 envBlock = Encoding.Default.GetBytes(stringBuff.ToString());
2906
2907                 if (envBlock.Length > UInt16.MaxValue)
2908                     throw new InvalidOperationException(SR.GetString(SR.EnvironmentBlockTooLong, envBlock.Length));
2909             }
2910
2911             return envBlock;
2912         }        
2913     }
2914
2915     internal class OrdinalCaseInsensitiveComparer : IComparer {
2916         internal static readonly OrdinalCaseInsensitiveComparer Default = new OrdinalCaseInsensitiveComparer();
2917         
2918         public int Compare(Object a, Object b) {
2919             String sa = a as String;
2920             String sb = b as String;
2921             if (sa != null && sb != null) {
2922                 return String.Compare(sa, sb, StringComparison.OrdinalIgnoreCase); 
2923             }
2924             return Comparer.Default.Compare(a,b);
2925         }
2926     }
2927
2928     internal class ProcessThreadTimes {
2929         internal long create;
2930         internal long exit; 
2931         internal long kernel; 
2932         internal long user;
2933
2934         public DateTime StartTime {   
2935             get {             
2936                 return DateTime.FromFileTime(create);
2937             }
2938         }
2939
2940         public DateTime ExitTime {
2941             get {
2942                 return DateTime.FromFileTime(exit);
2943             }
2944         }
2945
2946         public TimeSpan PrivilegedProcessorTime {
2947             get {
2948                 return new TimeSpan(kernel);
2949             }
2950         }
2951
2952         public TimeSpan UserProcessorTime {
2953             get {
2954                 return new TimeSpan(user);
2955             }
2956         }
2957         
2958         public TimeSpan TotalProcessorTime {
2959             get {
2960                 return new TimeSpan(user + kernel);
2961             }
2962         }
2963     }
2964
2965 #if !MONO
2966     internal class ShellExecuteHelper {
2967         private NativeMethods.ShellExecuteInfo _executeInfo;
2968         private int _errorCode;
2969         private bool _succeeded;
2970         
2971         public ShellExecuteHelper(NativeMethods.ShellExecuteInfo executeInfo) {
2972             _executeInfo = executeInfo;            
2973         }
2974
2975         [ResourceExposure(ResourceScope.None)]
2976         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
2977         public void ShellExecuteFunction()    {
2978             if (!(_succeeded = NativeMethods.ShellExecuteEx(_executeInfo))) {
2979                 _errorCode = Marshal.GetLastWin32Error();
2980             }
2981         }
2982
2983         public bool ShellExecuteOnSTAThread() {
2984             //
2985             // SHELL API ShellExecute() requires STA in order to work correctly.
2986             // If current thread is not a STA thread, we need to call ShellExecute on a new thread.
2987             //
2988             if( Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) {
2989                 ThreadStart threadStart = new ThreadStart(this.ShellExecuteFunction);
2990                 Thread executionThread = new Thread(threadStart);
2991                 executionThread.SetApartmentState(ApartmentState.STA);    
2992                 executionThread.Start();
2993                 executionThread.Join();
2994             }    
2995             else {
2996                 ShellExecuteFunction();
2997             }
2998             return _succeeded;
2999         }        
3000
3001         public int ErrorCode {
3002             get { 
3003                 return _errorCode; 
3004             }
3005         }
3006     }
3007 #endif
3008 }