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