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