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