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