Process.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Services / Monitoring / system / Diagnosticts / Process.cs / 1305376 / Process.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Diagnostics { 
    using System.Text; 
    using System.Threading;
    using System.Runtime.InteropServices; 
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Runtime.CompilerServices;
    using System.Runtime.ConstrainedExecution; 
    using System.Diagnostics;
    using System; 
    using System.Collections; 
    using System.IO;
    using Microsoft.Win32; 
    using Microsoft.Win32.SafeHandles;
    using System.Collections.Specialized;
    using System.Globalization;
    using System.Security; 
    using System.Security.Permissions;
    using System.Security.Principal; 
    using System.Runtime.Versioning; 

    ///  
    ///    
    ///       Provides access to local and remote
    ///       processes. Enables you to start and stop system processes.
    ///     
    /// 
    [ 
    MonitoringDescription(SR.ProcessDesc), 
    DefaultEvent("Exited"),
    DefaultProperty("StartInfo"), 
    Designer("System.Diagnostics.Design.ProcessDesigner, " + AssemblyRef.SystemDesign),
    // Disabling partial trust scenarios
    PermissionSet(SecurityAction.LinkDemand, Name="FullTrust"),
    PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust"), 
    HostProtection(SharedState=true, Synchronization=true, ExternalProcessMgmt=true, SelfAffectingProcessMgmt=true)
    ] 
    public class Process : Component { 
        //
        // FIELDS 
        //

        bool haveProcessId;
        int processId; 
        bool haveProcessHandle;
        SafeProcessHandle m_processHandle; 
        bool isRemoteMachine; 
        string machineName;
        ProcessInfo processInfo; 
        Int32 m_processAccess;

#if !FEATURE_PAL
        ProcessThreadCollection threads; 
        ProcessModuleCollection modules;
#endif // !FEATURE_PAL 
 
        bool haveMainWindow;
        IntPtr mainWindowHandle;  // no need to use SafeHandle for window 
        string mainWindowTitle;

        bool haveWorkingSetLimits;
        IntPtr minWorkingSet; 
        IntPtr maxWorkingSet;
 
        bool haveProcessorAffinity; 
        IntPtr processorAffinity;
 
        bool havePriorityClass;
        ProcessPriorityClass priorityClass;

        ProcessStartInfo startInfo; 

        bool watchForExit; 
        bool watchingForExit; 
        EventHandler onExited;
        bool exited; 
        int exitCode;
        bool signaled;
 		
        DateTime exitTime; 
        bool haveExitTime;
 
        bool responding; 
        bool haveResponding;
 
        bool priorityBoostEnabled;
        bool havePriorityBoostEnabled;

        bool raisedOnExited; 
        RegisteredWaitHandle registeredWaitHandle;
        WaitHandle waitHandle; 
        ISynchronizeInvoke synchronizingObject; 
        StreamReader standardOutput;
        StreamWriter standardInput; 
        StreamReader standardError;
        OperatingSystem operatingSystem;
        bool disposed;
 
        static object s_CreateProcessLock = new object();
 
        // This enum defines the operation mode for redirected process stream. 
        // We don't support switching between synchronous mode and asynchronous mode.
        private enum StreamReadMode 
        {
            undefined,
            syncMode,
            asyncMode 
        }
 
        StreamReadMode outputStreamReadMode; 
        StreamReadMode errorStreamReadMode;
 

        // Support for asynchrously reading streams
        [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
        //[System.Runtime.InteropServices.ComVisible(false)] 
        public event DataReceivedEventHandler OutputDataReceived;
        [Browsable(true), MonitoringDescription(SR.ProcessAssociated)] 
        //[System.Runtime.InteropServices.ComVisible(false)] 
        public event DataReceivedEventHandler ErrorDataReceived;
        // Abstract the stream details 
        internal AsyncStreamReader output;
        internal AsyncStreamReader error;
        internal bool pendingOutputRead;
        internal bool pendingErrorRead; 

 
        private static SafeFileHandle InvalidPipeHandle = new SafeFileHandle(IntPtr.Zero, false); 
#if DEBUG
        internal static TraceSwitch processTracing = new TraceSwitch("processTracing", "Controls debug output from Process component"); 
#else
        internal static TraceSwitch processTracing = null;
#endif
 
        //
        // CONSTRUCTORS 
        // 

        ///  
        ///    
        ///       Initializes a new instance of the  class.
        ///    
        ///  
        public Process() {
            this.machineName = "."; 
            this.outputStreamReadMode = StreamReadMode.undefined; 
            this.errorStreamReadMode = StreamReadMode.undefined;
            this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS; 
        }

        [ResourceExposure(ResourceScope.Machine)]
        Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo) : base() { 
            Debug.Assert(SyntaxCheck.CheckMachineName(machineName), "The machine name should be valid!");
            this.processInfo = processInfo; 
            this.machineName = machineName; 
            this.isRemoteMachine = isRemoteMachine;
            this.processId = processId; 
            this.haveProcessId = true;
            this.outputStreamReadMode = StreamReadMode.undefined;
            this.errorStreamReadMode = StreamReadMode.undefined;
            this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS; 
        }
 
        // 
        // PROPERTIES
        // 

        /// 
        ///     Returns whether this process component is associated with a real process.
        ///  
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessAssociated)] 
        bool Associated { 
            get {
                return haveProcessId || haveProcessHandle; 
            }
        }

 #if !FEATURE_PAL 
        /// 
        ///     
        ///       Gets the base priority of 
        ///       the associated process.
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessBasePriority)]
        public int BasePriority {
            get { 
                EnsureState(State.HaveProcessInfo);
                return processInfo.basePriority; 
            } 
        }
#endif // FEATURE_PAL 

        /// 
        ///    
        ///       Gets 
        ///       the
        ///       value that was specified by the associated process when it was terminated. 
        ///     
        /// 
        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitCode)] 
        public int ExitCode {
            get {
                EnsureState(State.Exited);
                return exitCode; 
            }
          } 
 
        /// 
        ///     
        ///       Gets a
        ///       value indicating whether the associated process has been terminated.
        ///    
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTerminated)]
        public bool HasExited { 
            get { 
                if (!exited) {
                    EnsureState(State.Associated); 
                    SafeProcessHandle handle = null;
                    try {
                        handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.SYNCHRONIZE, false);
                        if (handle.IsInvalid) { 
                            exited = true;
                        } 
                        else { 
                            int exitCode;
 
                            // Although this is the wrong way to check whether the process has exited,
                            // it was historically the way we checked for it, and a lot of code then took a dependency on
                            // the fact that this would always be set before the pipes were closed, so they would read
                            // the exit code out after calling ReadToEnd() or standard output or standard error. In order 
                            // to allow 259 to function as a valid exit code and to break as few people as possible that
                            // took the ReadToEnd dependency, we check for an exit code before doing the more correct 
                            // check to see if we have been signalled. 
                            if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
                                this.exited = true; 
                                this.exitCode = exitCode;
                            }
                            else {
 
                                // The best check for exit is that the kernel process object handle is invalid,
                                // or that it is valid and signaled.  Checking if the exit code != STILL_ACTIVE 
                                // does not guarantee the process is closed, 
                                // since some process could return an actual STILL_ACTIVE exit code (259).
                                if (!signaled) // if we just came from WaitForExit, don't repeat 
                                {
                                    ProcessWaitHandle wh = null;
                                    try
                                    { 
                                        wh = new ProcessWaitHandle(handle);
                                        this.signaled = wh.WaitOne(0, false);					 
                                    } 
                                    finally
                                    { 

                                        if (wh != null)
                                        wh.Close();
                                    } 
                                }
                                if (signaled) 
                                { 
                                    if (!NativeMethods.GetExitCodeProcess(handle, out exitCode))
                                        throw new Win32Exception(); 

                                    this.exited = true;
                                    this.exitCode = exitCode;
                                } 
                            }
                        }	 
                    } 
                    finally
                    { 
                        ReleaseProcessHandle(handle);
                    }

                    if (exited) { 
                        RaiseOnExited();
                    } 
                } 
                return exited;
            } 
        }

        private ProcessThreadTimes GetProcessTimes() {
            ProcessThreadTimes processTimes = new ProcessThreadTimes(); 
            SafeProcessHandle handle = null;
            try { 
                handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION, false); 
                if( handle.IsInvalid) {
                    // On OS older than XP, we will not be able to get the handle for a process 
                    // after it terminates.
                    // On Windows XP and newer OS, the information about a process will stay longer.
                    throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
                } 

                if (!NativeMethods.GetProcessTimes(handle, 
                                                   out processTimes.create, 
                                                   out processTimes.exit,
                                                   out processTimes.kernel, 
                                                   out processTimes.user)) {
                    throw new Win32Exception();
                }
 
            }
            finally { 
                ReleaseProcessHandle(handle); 
            }
            return processTimes; 
        }

 #if !FEATURE_PAL
        ///  
        ///    
        ///       Gets the time that the associated process exited. 
        ///     
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitTime)] 
        public DateTime ExitTime {
            get {
                if (!haveExitTime) {
                    EnsureState(State.IsNt | State.Exited); 
                    exitTime = GetProcessTimes().ExitTime;
                    haveExitTime = true; 
                } 
                return exitTime;
            } 
        }
#endif // !FEATURE_PAL

        ///  
        ///    
        ///       Returns the native handle for the associated process. The handle is only available 
        ///       if this component started the process. 
        ///    
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandle)]
        public IntPtr Handle {
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)] 
            get {
                EnsureState(State.Associated); 
                return OpenProcessHandle(this.m_processAccess).DangerousGetHandle(); 
            }
        } 

#if !FEATURE_PAL
        /// 
        ///     
        ///       Gets the number of handles that are associated
        ///       with the process. 
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandleCount)] 
        public int HandleCount {
            get {
                EnsureState(State.HaveProcessInfo);
                return processInfo.handleCount; 
            }
        } 
#endif // !FEATURE_PAL 

        ///  
        ///    
        ///       Gets
        ///       the unique identifier for the associated process.
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessId)] 
        public int Id { 
            get {
                EnsureState(State.HaveId); 
                return processId;
            }
        }
 
        /// 
        ///     
        ///       Gets 
        ///       the name of the computer on which the associated process is running.
        ///     
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMachineName)]
        public string MachineName {
            get { 
                EnsureState(State.Associated);
                return machineName; 
            } 
        }
 
 #if !FEATURE_PAL

        /// 
        ///     
        ///       Returns the window handle of the main window of the associated process.
        ///     
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowHandle)]
        public IntPtr MainWindowHandle { 
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)]
            get {
                if (!haveMainWindow) { 
                    EnsureState(State.IsLocal | State.HaveId);
                    mainWindowHandle = ProcessManager.GetMainWindowHandle(processId); 
 
                    if (mainWindowHandle != (IntPtr)0) {
                        haveMainWindow = true; 
                    } else {
                        // 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
                        // we always did this check but have now changed it to just require a ProcessId. In the case where someone has called Refresh()
                        // and the process has exited this call will throw an exception where as the above code would return 0 as the handle. 
                        EnsureState(State.HaveProcessInfo);
                    } 
                } 
                return mainWindowHandle;
            } 
        }

        /// 
        ///     
        ///       Returns the caption of the  of
        ///       the process. If the handle is zero (0), then an empty string is returned. 
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowTitle)] 
        public string MainWindowTitle {
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                if (mainWindowTitle == null) {
                    IntPtr handle = MainWindowHandle; 
                    if (handle == (IntPtr)0) { 
                        mainWindowTitle = String.Empty;
                    } 
                    else {
                        int length = NativeMethods.GetWindowTextLength(new HandleRef(this, handle)) * 2;
                        StringBuilder builder = new StringBuilder(length);
                        NativeMethods.GetWindowText(new HandleRef(this, handle), builder, builder.Capacity); 
                        mainWindowTitle = builder.ToString();
                    } 
                } 
                return mainWindowTitle;
            } 
        }


 
        /// 
        ///     
        ///       Gets 
        ///       the main module for the associated process.
        ///     
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainModule)]
        public ProcessModule MainModule {
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                // We only return null if we couldn't find a main module. 
                // This could be because
                //      1. The process hasn't finished loading the main module (most likely) 
                //      2. There are no modules loaded (possible for certain OS processes)
                //      3. Possibly other?

                if (OperatingSystem.Platform == PlatformID.Win32NT) { 
                    EnsureState(State.HaveId | State.IsLocal);
                    // on NT the first module is the main module 
                    ModuleInfo module = NtProcessManager.GetFirstModuleInfo(processId); 
                    return new ProcessModule(module);
                } 
                else {
                    ProcessModuleCollection moduleCollection = Modules;
                    // on 9x we have to do a little more work
                    EnsureState(State.HaveProcessInfo); 
                    foreach (ProcessModule pm in moduleCollection) {
                        if (pm.moduleInfo.Id == processInfo.mainModuleId) { 
                            return pm; 
                        }
                    } 
                    return null;
                }
            }
        } 

        ///  
        ///     
        ///       Gets or sets the maximum allowable working set for the associated
        ///       process. 
        ///    
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMaxWorkingSet)]
        public IntPtr MaxWorkingSet { 
            get {
                EnsureWorkingSetLimits(); 
                return maxWorkingSet; 
            }
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetWorkingSetLimits(null, value);
            } 
        }
 
        ///  
        ///    
        ///       Gets or sets the minimum allowable working set for the associated 
        ///       process.
        ///    
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMinWorkingSet)] 
        public IntPtr MinWorkingSet {
            get { 
                EnsureWorkingSetLimits(); 
                return minWorkingSet;
            } 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetWorkingSetLimits(value, null); 
            }
        } 
 
        /// 
        ///     
        ///       Gets
        ///       the modules that have been loaded by the associated process.
        ///    
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessModules)]
        public ProcessModuleCollection Modules { 
            [ResourceExposure(ResourceScope.None)] 
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                if (modules == null) {
                    EnsureState(State.HaveId | State.IsLocal);
                    ModuleInfo[] moduleInfos = ProcessManager.GetModuleInfos(processId);
                    ProcessModule[] newModulesArray = new ProcessModule[moduleInfos.Length]; 
                    for (int i = 0; i < moduleInfos.Length; i++) {
                        newModulesArray[i] = new ProcessModule(moduleInfos[i]); 
                    } 
                    ProcessModuleCollection newModules = new ProcessModuleCollection(newModulesArray);
                    modules = newModules; 
                }
                return modules;
            }
        } 

        ///  
        ///     Returns the amount of memory that the system has allocated on behalf of the 
        ///     associated process that can not be written to the virtual memory paging file.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
        public int NonpagedSystemMemorySize {
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.poolNonpagedBytes); 
            } 
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)]
        public long NonpagedSystemMemorySize64 {
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.poolNonpagedBytes; 
            } 
        }
 
        /// 
        ///     Returns the amount of memory that the associated process has allocated
        ///     that can be written to the virtual memory paging file.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PagedMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)] 
        public int PagedMemorySize { 
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return unchecked((int)processInfo.pageFileBytes);
            }
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long PagedMemorySize64 { 
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return processInfo.pageFileBytes;
            }
        }
 

        ///  
        ///     Returns the amount of memory that the system has allocated on behalf of the 
        ///     associated process that can be written to the virtual memory paging file.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PagedSystemMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
        public int PagedSystemMemorySize {
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.poolPagedBytes); 
            } 
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)]
        public long PagedSystemMemorySize64 {
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.poolPagedBytes; 
            } 
        }
 

        /// 
        ///    
        ///       Returns the maximum amount of memory that the associated process has 
        ///       allocated that could be written to the virtual memory paging file.
        ///     
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakPagedMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)] 
        public int PeakPagedMemorySize {
            get {
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.pageFileBytesPeak); 
            }
        } 
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long PeakPagedMemorySize64 {
            get {
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.pageFileBytesPeak; 
            }
        } 
 
        /// 
        ///     
        ///       Returns the maximum amount of physical memory that the associated
        ///       process required at once.
        ///    
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakWorkingSet64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)] 
        public int PeakWorkingSet { 
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return unchecked((int)processInfo.workingSetPeak);
            }
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long PeakWorkingSet64 { 
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return processInfo.workingSetPeak;
            }
        }
 
        /// 
        ///     Returns the maximum amount of virtual memory that the associated 
        ///     process has requested. 
        /// 
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakVirtualMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
        public int PeakVirtualMemorySize {
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return unchecked((int)processInfo.virtualBytesPeak);
            } 
        } 

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)] 
        [System.Runtime.InteropServices.ComVisible(false)]
        public long PeakVirtualMemorySize64 {
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return processInfo.virtualBytesPeak;
            } 
        } 

        private OperatingSystem OperatingSystem { 
            get {
                if (operatingSystem == null) {
                    operatingSystem = Environment.OSVersion;
                } 
                return operatingSystem;
            } 
        } 

        ///  
        ///    
        ///       Gets or sets a value indicating whether the associated process priority
        ///       should be temporarily boosted by the operating system when the main window
        ///       has focus. 
        ///    
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityBoostEnabled)] 
        public bool PriorityBoostEnabled {
            get { 
                EnsureState(State.IsNt);
                if (!havePriorityBoostEnabled) {
                    SafeProcessHandle handle = null;
                    try { 
                        handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
                        bool disabled = false; 
                        if (!NativeMethods.GetProcessPriorityBoost(handle, out disabled)) { 
                            throw new Win32Exception();
                        } 
                        priorityBoostEnabled = !disabled;
                        havePriorityBoostEnabled = true;
                    }
                    finally { 
                        ReleaseProcessHandle(handle);
                    } 
                } 
                return priorityBoostEnabled;
            } 
            set {
                EnsureState(State.IsNt);
                SafeProcessHandle handle = null;
                try { 
                    handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
                    if (!NativeMethods.SetProcessPriorityBoost(handle, !value)) 
                        throw new Win32Exception(); 
                    priorityBoostEnabled = value;
                    havePriorityBoostEnabled = true; 
                }
                finally {
                    ReleaseProcessHandle(handle);
                } 
            }
        } 
 
        /// 
        ///     
        ///       Gets or sets the overall priority category for the
        ///       associated process.
        ///    
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityClass)]
        public ProcessPriorityClass PriorityClass { 
            get { 
                if (!havePriorityClass) {
                    SafeProcessHandle handle = null; 
                    try {
                        handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
                        int value = NativeMethods.GetPriorityClass(handle);
                        if (value == 0) { 
                            throw new Win32Exception();
                        } 
                        priorityClass = (ProcessPriorityClass)value; 
                        havePriorityClass = true;
                    } 
                    finally {
                        ReleaseProcessHandle(handle);
                    }
                } 
                return priorityClass;
            } 
            [ResourceExposure(ResourceScope.Machine)] 
            [ResourceConsumption(ResourceScope.Machine)]
            set { 
                if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
                }
 
                // BelowNormal and AboveNormal are only available on Win2k and greater.
                if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0)   && 
                    (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) { 
                    throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
                } 

                SafeProcessHandle handle = null;

                try { 
                    handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
                    if (!NativeMethods.SetPriorityClass(handle, (int)value)) { 
                        throw new Win32Exception(); 
                    }
                    priorityClass = value; 
                    havePriorityClass = true;
                }
                finally {
                    ReleaseProcessHandle(handle); 
                }
            } 
        } 

        ///  
        ///     Returns the number of bytes that the associated process has allocated that cannot
        ///     be shared with other processes.
        /// 
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PrivateMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
        public int PrivateMemorySize { 
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.privateBytes); 
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)] 
        [System.Runtime.InteropServices.ComVisible(false)]
        public long PrivateMemorySize64 { 
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.privateBytes; 
            }
        }

        ///  
        ///     Returns the amount of time the process has spent running code inside the operating
        ///     system core. 
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivilegedProcessorTime)]
        public TimeSpan PrivilegedProcessorTime { 
            get {
                EnsureState(State.IsNt);
                return GetProcessTimes().PrivilegedProcessorTime;
            } 
        }
 
        ///  
        ///    
        ///       Gets 
        ///       the friendly name of the process.
        ///    
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessName)] 
        public string ProcessName {
            [ResourceExposure(ResourceScope.None)] 
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
            get {
                EnsureState(State.HaveProcessInfo); 
                String processName =  processInfo.processName;
                //
                // On some old NT-based OS like win2000, the process name from NTQuerySystemInformation is up to 15 characters.
                // Processes executing notepad_1234567.exe and notepad_12345678.exe will have the same process name. 
                // GetProcessByNames will not be able find the process for notepad_12345678.exe.
                // So we will try to replace the name of the process by its main module name if the name is 15 characters. 
                // However we can't always get the module name: 
                //     (1) Normal user will not be able to get module information about processes.
                //     (2) We can't get module information about remoting process. 
                // We can't get module name for a remote process
                //
                if (processName.Length == 15 && ProcessManager.IsNt && ProcessManager.IsOSOlderThanXP && !isRemoteMachine) {
                    try { 
                        String mainModuleName = MainModule.ModuleName;
                        if (mainModuleName != null) { 
                            processInfo.processName = Path.ChangeExtension(Path.GetFileName(mainModuleName), null); 
                        }
                    } 
                    catch(Exception) {
                        // If we can't access the module information, we can still use the might-be-truncated name.
                        // We could fail for a few reasons:
                        // (1) We don't enough privilege to get module information. 
                        // (2) The process could have terminated.
                    } 
                } 

                return processInfo.processName; 
            }
        }

        ///  
        ///    
        ///       Gets 
        ///       or sets which processors the threads in this process can be scheduled to run on. 
        ///    
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessorAffinity)]
        public IntPtr ProcessorAffinity {
            get {
                if (!haveProcessorAffinity) { 
                    SafeProcessHandle handle = null;
                    try { 
                        handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION); 
                        IntPtr processAffinity;
                        IntPtr systemAffinity; 
                        if (!NativeMethods.GetProcessAffinityMask(handle, out processAffinity, out systemAffinity))
                            throw new Win32Exception();
                        processorAffinity = processAffinity;
                    } 
                    finally {
                        ReleaseProcessHandle(handle); 
                    } 
                    haveProcessorAffinity = true;
                } 
                return processorAffinity;
            }
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)] 
            set {
                SafeProcessHandle handle = null; 
                try { 
                    handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
                    if (!NativeMethods.SetProcessAffinityMask(handle, value)) 
                        throw new Win32Exception();

                    processorAffinity = value;
                    haveProcessorAffinity = true; 
                }
                finally { 
                    ReleaseProcessHandle(handle); 
                }
            } 
        }

        /// 
        ///     
        ///       Gets a value indicating whether or not the user
        ///       interface of the process is responding. 
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessResponding)] 
        public bool Responding {
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                if (!haveResponding) {
                    IntPtr mainWindow = MainWindowHandle; 
                    if (mainWindow == (IntPtr)0) { 
                        responding = true;
                    } 
                    else {
                        IntPtr result;
                        responding = NativeMethods.SendMessageTimeout(new HandleRef(this, mainWindow), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero, NativeMethods.SMTO_ABORTIFHUNG, 5000, out result) != (IntPtr)0;
                    } 
                }
                return responding; 
            } 
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessSessionId)]
        public int SessionId {
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return processInfo.sessionId;
            } 
        } 

#endif // !FEATURE_PAL 

        /// 
        ///    
        ///       Gets or sets the properties to pass into the  method for the  
        ///       .
        ///     
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MonitoringDescription(SR.ProcessStartInfo)]
        public ProcessStartInfo StartInfo { 
            get {
                if (startInfo == null) {
                    startInfo = new ProcessStartInfo(this);
                } 
                return startInfo;
            } 
            [ResourceExposure(ResourceScope.Machine)] 
            set {
                if (value == null) { 
                    throw new ArgumentNullException("value");
                }
                startInfo = value;
            } 
        }
 
#if !FEATURE_PAL 
        /// 
        ///     Returns the time the associated process was started. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStartTime)]
        public DateTime StartTime {
            get { 
                EnsureState(State.IsNt);
                return GetProcessTimes().StartTime; 
            } 
        }
#endif // !FEATURE_PAL 

        /// 
        ///   Represents the object used to marshal the event handler
        ///   calls issued as a result of a Process exit. Normally 
        ///   this property will  be set when the component is placed
        ///   inside a control or  a from, since those components are 
        ///   bound to a specific thread. 
        /// 
        [ 
        Browsable(false),
        DefaultValue(null),
        MonitoringDescription(SR.ProcessSynchronizingObject)
        ] 
        public ISynchronizeInvoke SynchronizingObject {
            get { 
               if (this.synchronizingObject == null && DesignMode) { 
                    IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
                    if (host != null) { 
                        object baseComponent = host.RootComponent;
                        if (baseComponent != null && baseComponent is ISynchronizeInvoke)
                            this.synchronizingObject = (ISynchronizeInvoke)baseComponent;
                    } 
                }
 
                return this.synchronizingObject; 
            }
 
            set {
                this.synchronizingObject = value;
            }
        } 

#if !FEATURE_PAL 
 
        /// 
        ///     
        ///       Gets the set of threads that are running in the associated
        ///       process.
        ///    
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessThreads)]
        public ProcessThreadCollection Threads { 
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)]
            get { 
                if (threads == null) {
                    EnsureState(State.HaveProcessInfo);
                    int count = processInfo.threadInfoList.Count;
                    ProcessThread[] newThreadsArray = new ProcessThread[count]; 
                    for (int i = 0; i < count; i++) {
                        newThreadsArray[i] = new ProcessThread(isRemoteMachine, (ThreadInfo)processInfo.threadInfoList[i]); 
                    } 
                    ProcessThreadCollection newThreads = new ProcessThreadCollection(newThreadsArray);
                    threads = newThreads; 
                }
                return threads;
            }
        } 

        ///  
        ///     Returns the amount of time the associated process has spent utilizing the CPU. 
        ///     It is the sum of the  and
        ///     . 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTotalProcessorTime)]
        public TimeSpan TotalProcessorTime {
            get { 
                EnsureState(State.IsNt);
                return GetProcessTimes().TotalProcessorTime; 
            } 
        }
 
        /// 
        ///     Returns the amount of time the associated process has spent running code
        ///     inside the application portion of the process (not the operating system core).
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessUserProcessorTime)]
        public TimeSpan UserProcessorTime { 
            get { 
                EnsureState(State.IsNt);
                return GetProcessTimes().UserProcessorTime; 
            }
        }

        ///  
        ///     Returns the amount of virtual memory that the associated process has requested.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.VirtualMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
        public int VirtualMemorySize { 
            get {
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.virtualBytes);
            } 
        }
#endif // !FEATURE_PAL 
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long VirtualMemorySize64 {
            get {
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.virtualBytes; 
            }
        } 
 
        /// 
        ///     
        ///       Gets or sets whether the 
        ///       event is fired
        ///       when the process terminates.
        ///     
        /// 
        [Browsable(false), DefaultValue(false), MonitoringDescription(SR.ProcessEnableRaisingEvents)] 
        public bool EnableRaisingEvents { 
            get {
                return watchForExit; 
            }
            set {
                if (value != watchForExit) {
                    if (Associated) { 
                        if (value) {
                            OpenProcessHandle(); 
                            EnsureWatchingForExit(); 
                        }
                        else { 
                            StopWatchingForExit();
                        }
                    }
                    watchForExit = value; 
                }
            } 
        } 

 
        /// 
        ///    [To be supplied.]
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardInput)] 
        public StreamWriter StandardInput {
            get { 
                if (standardInput == null) { 
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardIn));
                } 

                return standardInput;
            }
        } 

        ///  
        ///    [To be supplied.] 
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardOutput)] 
        public StreamReader StandardOutput {
            get {
                if (standardOutput == null) {
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut)); 
                }
 
                if(outputStreamReadMode == StreamReadMode.undefined) { 
                    outputStreamReadMode = StreamReadMode.syncMode;
                } 
                else if (outputStreamReadMode != StreamReadMode.syncMode) {
                    throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
                }
 
                return standardOutput;
            } 
        } 

        ///  
        ///    [To be supplied.]
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardError)]
        public StreamReader StandardError { 
            get {
                if (standardError == null) { 
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError)); 
                }
 
                if(errorStreamReadMode == StreamReadMode.undefined) {
                    errorStreamReadMode = StreamReadMode.syncMode;
                }
                else if (errorStreamReadMode != StreamReadMode.syncMode) { 
                    throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
                } 
 
                return standardError;
            } 
        }

#if !FEATURE_PAL
        ///  
        ///     Returns the total amount of physical memory the associated process.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.WorkingSet64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
        public int WorkingSet { 
            get {
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.workingSet);
            } 
        }
#endif // !FEATURE_PAL 
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long WorkingSet64 {
            get {
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.workingSet; 
            }
        } 
 
        [Category("Behavior"), MonitoringDescription(SR.ProcessExited)]
        public event EventHandler Exited { 
            add {
                onExited += value;
            }
            remove { 
                onExited -= value;
            } 
        } 

#if !FEATURE_PAL 

        /// 
        ///    
        ///       Closes a process that has a user interface by sending a close message 
        ///       to its main window.
        ///     
        ///  
        [ResourceExposure(ResourceScope.Machine)]  // Review usages of this.
        [ResourceConsumption(ResourceScope.Machine)] 
        public bool CloseMainWindow() {
            IntPtr mainWindowHandle = MainWindowHandle;
            if (mainWindowHandle == (IntPtr)0) return false;
            int style = NativeMethods.GetWindowLong(new HandleRef(this, mainWindowHandle), NativeMethods.GWL_STYLE); 
            if ((style & NativeMethods.WS_DISABLED) != 0) return false;
            NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); 
            return true; 
        }
 
#endif // !FEATURE_PAL

        /// 
        ///     Release the temporary handle we used to get process information. 
        ///     If we used the process handle stored in the process object (we have all access to the handle,) don't release it.
        ///  
        ///  
        void ReleaseProcessHandle(SafeProcessHandle handle) {
            if (handle == null) { 
                return;
            }

            if (haveProcessHandle && handle == m_processHandle) { 
                return;
            } 
            Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process)"); 
            handle.Close();
        } 

        /// 
        ///     This is called from the threadpool when a proces exits.
        ///  
        /// 
        private void CompletionCallback(object context, bool wasSignaled) { 
            StopWatchingForExit(); 
            RaiseOnExited();
        } 

        /// 
        /// 
        ///     
        ///       Free any resources associated with this component.
        ///     
        ///  
        protected override void Dispose(bool disposing) {
            if( !disposed) { 
                if (disposing) {
                    //Dispose managed and unmanaged resources
                    Close();
                } 
                this.disposed = true;
                base.Dispose(disposing); 
            } 
        }
 
        /// 
        ///    
        ///       Frees any resources associated with this component.
        ///     
        /// 
        public void Close() { 
            if (Associated) { 
                if (haveProcessHandle) {
                    StopWatchingForExit(); 
                    Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process) in Close()");
                    m_processHandle.Close();
                    m_processHandle = null;
                    haveProcessHandle = false; 
                }
                haveProcessId = false; 
                isRemoteMachine = false; 
                machineName = ".";
                raisedOnExited = false; 

                //Don't call close on the Readers and writers
                //since they might be referenced by somebody else while the
                //process is still alive but this method called. 
                standardOutput = null;
                standardInput = null; 
                standardError = null; 

                output = null; 
                error = null;
	

                Refresh(); 
            }
        } 
 
        /// 
        ///     Helper method for checking preconditions when accessing properties. 
        /// 
        /// 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        void EnsureState(State state) {
 
            if ((state & State.IsWin2k) != (State)0) { 
#if !FEATURE_PAL
                if (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5) 
#endif // !FEATURE_PAL
                    throw new PlatformNotSupportedException(SR.GetString(SR.Win2kRequired));
            }
 
            if ((state & State.IsNt) != (State)0) {
#if !FEATURE_PAL 
                if (OperatingSystem.Platform != PlatformID.Win32NT) 
#endif // !FEATURE_PAL
                    throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired)); 
            }

            if ((state & State.Associated) != (State)0)
                if (!Associated) 
                    throw new InvalidOperationException(SR.GetString(SR.NoAssociatedProcess));
 
            if ((state & State.HaveId) != (State)0) { 
                if (!haveProcessId) {
#if !FEATURE_PAL 
                    if (haveProcessHandle) {
                        SetProcessId(ProcessManager.GetProcessIdFromHandle(m_processHandle));
                     }
                    else { 
                        EnsureState(State.Associated);
                        throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired)); 
                    } 
#else
                    EnsureState(State.Associated); 
                    throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
#endif // !FEATURE_PAL
                }
            } 

            if ((state & State.IsLocal) != (State)0 && isRemoteMachine) { 
                    throw new NotSupportedException(SR.GetString(SR.NotSupportedRemote)); 
            }
 
            if ((state & State.HaveProcessInfo) != (State)0) {
#if !FEATURE_PAL
                if (processInfo == null) {
                    if ((state & State.HaveId) == (State)0) EnsureState(State.HaveId); 
                    ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
                    for (int i = 0; i < processInfos.Length; i++) { 
                        if (processInfos[i].processId == processId) { 
                            this.processInfo = processInfos[i];
                            break; 
                        }
                    }
                    if (processInfo == null) {
                        throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo)); 
                    }
                } 
#else 
                throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
#endif // !FEATURE_PAL 
            }

            if ((state & State.Exited) != (State)0) {
                if (!HasExited) { 
                    throw new InvalidOperationException(SR.GetString(SR.WaitTillExit));
                } 
 
                if (!haveProcessHandle) {
                    throw new InvalidOperationException(SR.GetString(SR.NoProcessHandle)); 
                }
            }
        }
 
        /// 
        ///     Make sure we are watching for a process exit. 
        ///  
        /// 
        void EnsureWatchingForExit() { 
            if (!watchingForExit) {
                lock (this) {
                    if (!watchingForExit) {
                        Debug.Assert(haveProcessHandle, "Process.EnsureWatchingForExit called with no process handle"); 
                        Debug.Assert(Associated, "Process.EnsureWatchingForExit called with no associated process");
                        watchingForExit = true; 
                        try { 
                            this.waitHandle = new ProcessWaitHandle(m_processHandle);
                            this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(this.waitHandle, 
                                new WaitOrTimerCallback(this.CompletionCallback), null, -1, true);
                        }
                        catch {
                            watchingForExit = false; 
                            throw;
                        } 
                    } 
                }
            } 
        }

#if !FEATURE_PAL
 
        /// 
        ///     Make sure we have obtained the min and max working set limits. 
        ///  
        /// 
        void EnsureWorkingSetLimits() { 
            EnsureState(State.IsNt);
            if (!haveWorkingSetLimits) {
                SafeProcessHandle handle = null;
                try { 
                    handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
                    IntPtr min; 
                    IntPtr max; 
                    if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
                        throw new Win32Exception(); 
                    }
                    minWorkingSet = min;
                    maxWorkingSet = max;
                    haveWorkingSetLimits = true; 
                }
                finally { 
                    ReleaseProcessHandle(handle); 
                }
            } 
        }

        public static void EnterDebugMode() {
            if (ProcessManager.IsNt) { 
                SetPrivilege("SeDebugPrivilege", NativeMethods.SE_PRIVILEGE_ENABLED);
            } 
        } 

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        private static void SetPrivilege(string privilegeName, int attrib) {
            IntPtr hToken = (IntPtr)0;
            NativeMethods.LUID debugValue = new NativeMethods.LUID(); 

            // this is only a "pseudo handle" to the current process - no need to close it later 
            IntPtr processHandle = NativeMethods.GetCurrentProcess(); 

            // get the process token so we can adjust the privilege on it.  We DO need to 
            // close the token when we're done with it.
            if (!NativeMethods.OpenProcessToken(new HandleRef(null, processHandle), NativeMethods.TOKEN_ADJUST_PRIVILEGES, out hToken)) {
                throw new Win32Exception();
            } 

            try { 
                if (!NativeMethods.LookupPrivilegeValue(null, privilegeName, out debugValue)) { 
                    throw new Win32Exception();
                } 

                NativeMethods.TokenPrivileges tkp = new NativeMethods.TokenPrivileges();
                tkp.Luid = debugValue;
                tkp.Attributes = attrib; 

                NativeMethods.AdjustTokenPrivileges(new HandleRef(null, hToken), false, tkp, 0, IntPtr.Zero, IntPtr.Zero); 
 
                // AdjustTokenPrivileges can return true even if it failed to
                // set the privilege, so we need to use GetLastError 
                if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_SUCCESS) {
                    throw new Win32Exception();
                }
            } 
            finally {
                Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(processToken)"); 
                SafeNativeMethods.CloseHandle(new HandleRef(null, hToken)); 
            }
        } 

        /// 
        ///    [To be supplied.]
        ///  
        public static void LeaveDebugMode() {
            if (ProcessManager.IsNt) { 
                SetPrivilege("SeDebugPrivilege", 0); 
            }
        } 

        /// 
        ///    
        ///       Returns a new  component given a process identifier and 
        ///       the name of a computer in the network.
        ///     
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process GetProcessById(int processId, string machineName) {
            if (!ProcessManager.IsProcessRunning(processId, machineName)) {
                throw new ArgumentException(SR.GetString(SR.MissingProccess, processId.ToString(CultureInfo.CurrentCulture)));
            } 

            return new Process(machineName, ProcessManager.IsRemoteMachine(machineName), processId, null); 
        } 

        ///  
        ///    
        ///       Returns a new  component given the
        ///       identifier of a process on the local computer.
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process GetProcessById(int processId) {
            return GetProcessById(processId, "."); 
        }

        /// 
        ///     
        ///       Creates an array of  components that are
        ///       associated 
        ///       with process resources on the 
        ///       local computer. These process resources share the specified process name.
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public static Process[] GetProcessesByName(string processName) { 
            return GetProcessesByName(processName, ".");
        } 
 
        /// 
        ///     
        ///       Creates an array of  components that are associated with process resources on a
        ///       remote computer. These process resources share the specified process name.
        ///    
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process[] GetProcessesByName(string processName, string machineName) { 
            if (processName == null) processName = String.Empty;
            Process[] procs = GetProcesses(machineName); 
            ArrayList list = new ArrayList();

            for(int i = 0; i < procs.Length; i++) {
                if( String.Equals(processName, procs[i].ProcessName, StringComparison.OrdinalIgnoreCase)) { 
                    list.Add( procs[i]);
                } 
            } 

            Process[] temp = new Process[list.Count]; 
            list.CopyTo(temp, 0);
            return temp;
        }
 
        /// 
        ///     
        ///       Creates a new  
        ///       component for each process resource on the local computer.
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public static Process[] GetProcesses() { 
            return GetProcesses(".");
        } 
 
        /// 
        ///     
        ///       Creates a new 
        ///       component for each
        ///       process resource on the specified computer.
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process[] GetProcesses(string machineName) {
            bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName); 
            ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
            Process[] processes = new Process[processInfos.Length];
            for (int i = 0; i < processInfos.Length; i++) {
                ProcessInfo processInfo = processInfos[i]; 
                processes[i] = new Process(machineName, isRemoteMachine, processInfo.processId, processInfo);
            } 
            Debug.WriteLineIf(processTracing.TraceVerbose, "Process.GetProcesses(" + machineName + ")"); 
#if DEBUG
            if (processTracing.TraceVerbose) { 
                Debug.Indent();
                for (int i = 0; i < processInfos.Length; i++) {
                    Debug.WriteLine(processes[i].Id + ": " + processes[i].ProcessName);
                } 
                Debug.Unindent();
            } 
#endif 
            return processes;
        } 

#endif // !FEATURE_PAL

        ///  
        ///    
        ///       Returns a new  
        ///       component and associates it with the current active process. 
        ///    
        ///  
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Process)]
        public static Process GetCurrentProcess() {
            return new Process(".", false, NativeMethods.GetCurrentProcessId(), null); 
        }
 
        ///  
        ///    
        ///       Raises the  event. 
        ///    
        /// 
        protected void OnExited() {
            EventHandler exited = onExited; 
            if (exited != null) {
                if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired) 
                    this.SynchronizingObject.BeginInvoke(exited, new object[]{this, EventArgs.Empty}); 
                else
                   exited(this, EventArgs.Empty); 
            }
        }

        ///  
        ///     Gets a short-term handle to the process, with the given access.
        ///     If a handle is stored in current process object, then use it. 
        ///     Note that the handle we stored in current process object will have all access we need. 
        /// 
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        SafeProcessHandle GetProcessHandle(int access, bool throwIfExited) {
            Debug.WriteLineIf(processTracing.TraceVerbose, "GetProcessHandle(access = 0x" + access.ToString("X8", CultureInfo.InvariantCulture) + ", throwIfExited = " + throwIfExited + ")"); 
#if DEBUG
            if (processTracing.TraceVerbose) { 
                StackFrame calledFrom = new StackTrace(true).GetFrame(0); 
                Debug.WriteLine("   called from " + calledFrom.GetFileName() + ", line " + calledFrom.GetFileLineNumber());
            } 
#endif
            if (haveProcessHandle) {
                if (throwIfExited) {
                    // Since haveProcessHandle is true, we know we have the process handle 
                    // open with at least SYNCHRONIZE access, so we can wait on it with
                    // zero timeout to see if the process has exited. 
                    ProcessWaitHandle waitHandle = null; 
                    try {
                        waitHandle = new ProcessWaitHandle(m_processHandle); 
                        if (waitHandle.WaitOne(0, false)) {
                            if (haveProcessId)
                                throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
                            else 
                                throw new InvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
                        } 
                    } 
                    finally {
                        if( waitHandle != null) { 
                            waitHandle.Close();
                        }
                    }
                } 
                return m_processHandle;
            } 
            else { 
                EnsureState(State.HaveId | State.IsLocal);
                SafeProcessHandle handle = SafeProcessHandle.InvalidHandle; 
#if !FEATURE_PAL
                handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
#else
                IntPtr pseudohandle = NativeMethods.GetCurrentProcess(); 
                // Get a real handle
                if (!NativeMethods.DuplicateHandle (new HandleRef(this, pseudohandle), 
                                                    new HandleRef(this, pseudohandle), 
                                                    new HandleRef(this, pseudohandle),
                                                    out handle, 
                                                    0,
                                                    false,
                                                    NativeMethods.DUPLICATE_SAME_ACCESS |
                                                    NativeMethods.DUPLICATE_CLOSE_SOURCE)) { 
                    throw new Win32Exception();
                } 
#endif // !FEATURE_PAL 
                if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) {
                    if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) { 
                        throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
                    }
                }
                return handle; 
            }
 
        } 

        ///  
        ///     Gets a short-term handle to the process, with the given access.  If a handle exists,
        ///     then it is reused.  If the process has exited, it throws an exception.
        /// 
        ///  
        SafeProcessHandle GetProcessHandle(int access) {
            return GetProcessHandle(access, true); 
        } 

        ///  
        ///     Opens a long-term handle to the process, with all access.  If a handle exists,
        ///     then it is reused.  If the process has exited, it throws an exception.
        /// 
        ///  
        SafeProcessHandle OpenProcessHandle() {
            return OpenProcessHandle(NativeMethods.PROCESS_ALL_ACCESS); 
        } 

        SafeProcessHandle OpenProcessHandle(Int32 access) { 
            if (!haveProcessHandle) {
                //Cannot open a new process handle if the object has been disposed, since finalization has been suppressed.
                if (this.disposed) {
                    throw new ObjectDisposedException(GetType().Name); 
                }
 
                SetProcessHandle(GetProcessHandle(access)); 
            }
            return m_processHandle; 
        }

        /// 
        ///     Raise the Exited event, but make sure we don't do it more than once. 
        /// 
        ///  
        void RaiseOnExited() { 
            if (!raisedOnExited) {
                lock (this) { 
                    if (!raisedOnExited) {
                        raisedOnExited = true;
                        OnExited();
                    } 
                }
            } 
        } 

        ///  
        ///    
        ///       Discards any information about the associated process
        ///       that has been cached inside the process component. After  is called, the
        ///       first request for information for each property causes the process component 
        ///       to obtain a new value from the associated process.
        ///     
        ///  
        public void Refresh() {
            processInfo = null; 
#if !FEATURE_PAL
            threads = null;
            modules = null;
#endif // !FEATURE_PAL 
            mainWindowTitle = null;
            exited = false; 
            signaled = false; 
            haveMainWindow = false;
            haveWorkingSetLimits = false; 
            haveProcessorAffinity = false;
            havePriorityClass = false;
            haveExitTime = false;
            haveResponding = false; 
            havePriorityBoostEnabled = false;
        } 
 
        /// 
        ///     Helper to associate a process handle with this component. 
        /// 
        /// 
        void SetProcessHandle(SafeProcessHandle processHandle) {
            this.m_processHandle = processHandle; 
            this.haveProcessHandle = true;
            if (watchForExit) { 
                EnsureWatchingForExit(); 
            }
        } 

        /// 
        ///     Helper to associate a process id with this component.
        ///  
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        void SetProcessId(int processId) { 
            this.processId = processId;
            this.haveProcessId = true; 
        }

#if !FEATURE_PAL
 
        /// 
        ///     Helper to set minimum or maximum working set limits. 
        ///  
        /// 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        void SetWorkingSetLimits(object newMin, object newMax) {
            EnsureState(State.IsNt);
 
            SafeProcessHandle handle = null;
            try { 
                handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_SET_QUOTA); 
                IntPtr min;
                IntPtr max; 
                if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
                    throw new Win32Exception();
                }
 
                if (newMin != null) {
                    min = (IntPtr)newMin; 
                } 

                if (newMax != null) { 
                    max = (IntPtr)newMax;
                }

                if ((long)min > (long)max) { 
                    if (newMin != null) {
                        throw new ArgumentException(SR.GetString(SR.BadMinWorkset)); 
                    } 
                    else {
                        throw new ArgumentException(SR.GetString(SR.BadMaxWorkset)); 
                    }
                }

                if (!NativeMethods.SetProcessWorkingSetSize(handle, min, max)) { 
                    throw new Win32Exception();
                } 
 
                // The value may be rounded/changed by the OS, so go get it
                if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) { 
                    throw new Win32Exception();
                }
                minWorkingSet = min;
                maxWorkingSet = max; 
                haveWorkingSetLimits = true;
            } 
            finally { 
                ReleaseProcessHandle(handle);
            } 
        }

#endif // !FEATURE_PAL
 
        /// 
        ///     
        ///       Starts a process specified by the  property of this  
        ///       component and associates it with the
        ///     . If a process resource is reused 
        ///       rather than started, the reused process is associated with this 
        ///       component.
        ///    
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        public bool Start() { 
            Close();
            ProcessStartInfo startInfo = StartInfo; 
            if (startInfo.FileName.Length == 0)
                throw new InvalidOperationException(SR.GetString(SR.FileNameMissing));

            if (startInfo.UseShellExecute) { 
#if !FEATURE_PAL
                return StartWithShellExecuteEx(startInfo); 
#else 
                throw new InvalidOperationException(SR.GetString(SR.net_perm_invalid_val, "StartInfo.UseShellExecute", true));
#endif // !FEATURE_PAL 
            } else {
                return StartWithCreateProcess(startInfo);
            }
        } 

 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) { 
            bool ret = NativeMethods.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize);
            if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid) {
                throw new Win32Exception();
            } 
        }
 
        // Using synchronous Anonymous pipes for process input/output redirection means we would end up 
        // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
        // it will take advantage of the NT IO completion port infrastructure. But we can't really use 
        // Overlapped I/O for process input/output as it would break Console apps (managed Console class
        // methods such as WriteLine as well as native CRT functions like printf) which are making an
        // assumption that the console standard handles (obtained via GetStdHandle()) are opened
        // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously! 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) { 
            NativeMethods.SECURITY_ATTRIBUTES securityAttributesParent = new NativeMethods.SECURITY_ATTRIBUTES();
            securityAttributesParent.bInheritHandle = true; 

            SafeFileHandle hTmp = null;
            try {
                if (parentInputs) { 
                    CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);
                } 
                else { 
                    CreatePipeWithSecurityAttributes(out hTmp,
                                                          out childHandle, 
                                                          securityAttributesParent,
                                                          0);
                }
                // Duplicate the parent handle to be non-inheritable so that the child process 
                // doesn't have access. This is done for correctness sake, exact reason is unclear.
                // One potential theory is that child process can do something brain dead like 
                // closing the parent end of the pipe and there by getting into a blocking situation 
                // as parent will not be draining the pipe at the other end anymore.
                if (!NativeMethods.DuplicateHandle(new HandleRef(this, NativeMethods.GetCurrentProcess()), 
                                                                   hTmp,
                                                                   new HandleRef(this, NativeMethods.GetCurrentProcess()),
                                                                   out parentHandle,
                                                                   0, 
                                                                   false,
                                                                   NativeMethods.DUPLICATE_SAME_ACCESS)) { 
                    throw new Win32Exception(); 
                }
            } 
            finally {
                if( hTmp != null && !hTmp.IsInvalid) {
                    hTmp.Close();
                } 
            }
        } 
 
        private static StringBuilder BuildCommandLine(string executableFileName, string arguments) {
            // Construct a StringBuilder with the appropriate command line 
            // to pass to CreateProcess.  If the filename isn't already
            // in quotes, we quote it here.  This prevents some security
            // problems (it specifies exactly which part of the string
            // is the file to execute). 
            StringBuilder commandLine = new StringBuilder();
            string fileName = executableFileName.Trim(); 
            bool fileNameIsQuoted = (fileName.StartsWith("\"", StringComparison.Ordinal) && fileName.EndsWith("\"", StringComparison.Ordinal)); 
            if (!fileNameIsQuoted) {
                commandLine.Append("\""); 
            }

            commandLine.Append(fileName);
 
            if (!fileNameIsQuoted) {
                commandLine.Append("\""); 
            } 

            if (!String.IsNullOrEmpty(arguments)) { 
                commandLine.Append(" ");
                commandLine.Append(arguments);
            }
 
            return commandLine;
        } 
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        private bool StartWithCreateProcess(ProcessStartInfo startInfo) {
            if( startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) {
                throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
            } 

            if( startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) { 
                throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed)); 
            }
 
            // See knowledge base article Q190351 for an explanation of the following code.  Noteworthy tricky points:
            //    * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
            //      that the child process can not close them
            //    * CreateProcess allows you to redirect all or none of the standard IO handles, so we use 
            //      GetStdHandle for the handles that are not being redirected
 
            //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed. 
            if (this.disposed) {
                throw new ObjectDisposedException(GetType().Name); 
            }

            StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
 
            NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO();
            SafeNativeMethods.PROCESS_INFORMATION processInfo = new SafeNativeMethods.PROCESS_INFORMATION(); 
            SafeProcessHandle procSH = new SafeProcessHandle(); 
            SafeThreadHandle threadSH = new SafeThreadHandle();
            bool retVal; 
            int errorCode = 0;
            // handles used in parent process
            SafeFileHandle standardInputWritePipeHandle = null;
            SafeFileHandle standardOutputReadPipeHandle = null; 
            SafeFileHandle standardErrorReadPipeHandle = null;
            GCHandle environmentHandle = new GCHandle(); 
            lock (s_CreateProcessLock) { 
            try {
                // set up the streams 
                if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
                    if (startInfo.RedirectStandardInput) {
                        CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
                        } else { 
                        startupInfo.hStdInput  =  new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);
                    } 
 
                    if (startInfo.RedirectStandardOutput) {
                        CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false); 
                        } else {
                        startupInfo.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_OUTPUT_HANDLE), false);
                    }
 
                    if (startInfo.RedirectStandardError) {
                        CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false); 
                        } else { 
                        startupInfo.hStdError = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_ERROR_HANDLE), false);
                    } 

                    startupInfo.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
                }
 
                // set up the creation flags paramater
                int creationFlags = 0; 
#if !FEATURE_PAL 
                if (startInfo.CreateNoWindow)  creationFlags |= NativeMethods.CREATE_NO_WINDOW;
#endif // !FEATURE_PAL 

                // set up the environment block parameter
                IntPtr environmentPtr = (IntPtr)0;
                if (startInfo.environmentVariables != null) { 
                    bool unicode = false;
#if !FEATURE_PAL 
                    if (ProcessManager.IsNt) { 
                        creationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
                        unicode = true; 
                    }
#endif // !FEATURE_PAL

                    byte[] environmentBytes = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode); 
                    environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
                    environmentPtr = environmentHandle.AddrOfPinnedObject(); 
                } 

                string workingDirectory = startInfo.WorkingDirectory; 
                if (workingDirectory == string.Empty)
                    workingDirectory = Environment.CurrentDirectory;

#if !FEATURE_PAL 
                if (startInfo.UserName.Length != 0) {
                    NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0; 
                    if( startInfo.LoadUserProfile) { 
                        logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
                    } 

                    IntPtr password = IntPtr.Zero;
                    try {
                        if( startInfo.Password == null) { 
                            password = Marshal.StringToCoTaskMemUni(String.Empty);
                            } else { 
                            password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password); 
                        }
 
                        RuntimeHelpers.PrepareConstrainedRegions();
                        try {} finally {
                           retVal = NativeMethods.CreateProcessWithLogonW(
                                   startInfo.UserName, 
                                   startInfo.Domain,
                                   password, 
                                   logonFlags, 
                                   null,            // we don't need this since all the info is in commandLine
                                   commandLine, 
                                   creationFlags,
                                   environmentPtr,
                                   workingDirectory,
                                   startupInfo,        // pointer to STARTUPINFO 
                                   processInfo         // pointer to PROCESS_INFORMATION
                               ); 
                           if (!retVal) 
                              errorCode = Marshal.GetLastWin32Error();
                           if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) 
                              procSH.InitialSetHandle(processInfo.hProcess);
                           if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                              threadSH.InitialSetHandle(processInfo.hThread);
                        } 
                        if (!retVal){
                                if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) { 
                                throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication)); 
                            }
 
                            throw new Win32Exception(errorCode);
                        }
                        } finally {
                        if( password != IntPtr.Zero) { 
                            Marshal.ZeroFreeCoTaskMemUnicode(password);
                        } 
                    } 
                    } else {
#endif // !FEATURE_PAL 
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try {} finally {
                       retVal = NativeMethods.CreateProcess (
                               null,               // we don't need this since all the info is in commandLine 
                               commandLine,        // pointer to the command line string
                               null,               // pointer to process security attributes, we don't need to inheriat the handle 
                               null,               // pointer to thread security attributes 
                               true,               // handle inheritance flag
                               creationFlags,      // creation flags 
                               environmentPtr,     // pointer to new environment block
                               workingDirectory,   // pointer to current directory name
                               startupInfo,        // pointer to STARTUPINFO
                               processInfo         // pointer to PROCESS_INFORMATION 
                           );
                       if (!retVal) 
                              errorCode = Marshal.GetLastWin32Error(); 
                       if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                           procSH.InitialSetHandle(processInfo.hProcess); 
                       if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                          threadSH.InitialSetHandle(processInfo.hThread);
                    }
                    if (!retVal) { 
                            if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
                          throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication)); 
                       } 
                        throw new Win32Exception(errorCode);
                    } 
#if !FEATURE_PAL
                }
#endif
                } finally { 
                // free environment block
                if (environmentHandle.IsAllocated) { 
                    environmentHandle.Free(); 
                }
 
                startupInfo.Dispose();
            }
            }
 
            if (startInfo.RedirectStandardInput) {
                standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096); 
                standardInput.AutoFlush = true; 
            }
            if (startInfo.RedirectStandardOutput) { 
                Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
                standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError) { 
                Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
                standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096); 
            } 

            bool ret = false; 
            if (!procSH.IsInvalid) {
                SetProcessHandle(procSH);
                SetProcessId(processInfo.dwProcessId);
                threadSH.Close(); 
                ret = true;
            } 
 
            return ret;
 
        }

#if !FEATURE_PAL
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        private bool StartWithShellExecuteEx(ProcessStartInfo startInfo) { 
            //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
            if (this.disposed) 
                throw new ObjectDisposedException(GetType().Name);

            if( !String.IsNullOrEmpty(startInfo.UserName) || (startInfo.Password != null) ) {
                throw new InvalidOperationException(SR.GetString(SR.CantStartAsUser)); 
            }
 
            if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) { 
                throw new InvalidOperationException(SR.GetString(SR.CantRedirectStreams));
            } 

            if (startInfo.StandardErrorEncoding != null) {
                throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
            } 

            if (startInfo.StandardOutputEncoding != null) { 
                throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed)); 
            }
 
            // can't set env vars with ShellExecuteEx...
            if (startInfo.environmentVariables != null) {
                throw new InvalidOperationException(SR.GetString(SR.CantUseEnvVars));
            } 

            NativeMethods.ShellExecuteInfo shellExecuteInfo = new NativeMethods.ShellExecuteInfo(); 
            shellExecuteInfo.fMask = NativeMethods.SEE_MASK_NOCLOSEPROCESS; 
            if (startInfo.ErrorDialog) {
                shellExecuteInfo.hwnd = startInfo.ErrorDialogParentHandle; 
            }
            else {
                shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_NO_UI;
            } 

            switch (startInfo.WindowStyle) { 
                case ProcessWindowStyle.Hidden: 
                    shellExecuteInfo.nShow = NativeMethods.SW_HIDE;
                    break; 
                case ProcessWindowStyle.Minimized:
                    shellExecuteInfo.nShow = NativeMethods.SW_SHOWMINIMIZED;
                    break;
                case ProcessWindowStyle.Maximized: 
                    shellExecuteInfo.nShow = NativeMethods.SW_SHOWMAXIMIZED;
                    break; 
                default: 
                    shellExecuteInfo.nShow = NativeMethods.SW_SHOWNORMAL;
                    break; 
            }


            try { 
                if (startInfo.FileName.Length != 0)
                    shellExecuteInfo.lpFile = Marshal.StringToHGlobalAuto(startInfo.FileName); 
                if (startInfo.Verb.Length != 0) 
                    shellExecuteInfo.lpVerb = Marshal.StringToHGlobalAuto(startInfo.Verb);
                if (startInfo.Arguments.Length != 0) 
                    shellExecuteInfo.lpParameters = Marshal.StringToHGlobalAuto(startInfo.Arguments);
                if (startInfo.WorkingDirectory.Length != 0)
                    shellExecuteInfo.lpDirectory = Marshal.StringToHGlobalAuto(startInfo.WorkingDirectory);
 
                shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_DDEWAIT;
 
                ShellExecuteHelper executeHelper = new ShellExecuteHelper(shellExecuteInfo); 
                if (!executeHelper.ShellExecuteOnSTAThread()) {
                    int error = executeHelper.ErrorCode; 
                    if (error == 0) {
                        switch ((long)shellExecuteInfo.hInstApp) {
                            case NativeMethods.SE_ERR_FNF: error = NativeMethods.ERROR_FILE_NOT_FOUND; break;
                            case NativeMethods.SE_ERR_PNF: error = NativeMethods.ERROR_PATH_NOT_FOUND; break; 
                            case NativeMethods.SE_ERR_ACCESSDENIED: error = NativeMethods.ERROR_ACCESS_DENIED; break;
                            case NativeMethods.SE_ERR_OOM: error = NativeMethods.ERROR_NOT_ENOUGH_MEMORY; break; 
                            case NativeMethods.SE_ERR_DDEFAIL: 
                            case NativeMethods.SE_ERR_DDEBUSY:
                            case NativeMethods.SE_ERR_DDETIMEOUT: error = NativeMethods.ERROR_DDE_FAIL; break; 
                            case NativeMethods.SE_ERR_SHARE: error = NativeMethods.ERROR_SHARING_VIOLATION; break;
                            case NativeMethods.SE_ERR_NOASSOC: error = NativeMethods.ERROR_NO_ASSOCIATION; break;
                            case NativeMethods.SE_ERR_DLLNOTFOUND: error = NativeMethods.ERROR_DLL_NOT_FOUND; break;
                            default: error = (int)shellExecuteInfo.hInstApp; break; 
                        }
                    } 
                    if( error == NativeMethods.ERROR_BAD_EXE_FORMAT || error == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) { 
                        throw new Win32Exception(error, SR.GetString(SR.InvalidApplication));
                    } 
                    throw new Win32Exception(error);
                }

            } 
            finally {
                if (shellExecuteInfo.lpFile != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpFile); 
                if (shellExecuteInfo.lpVerb != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpVerb); 
                if (shellExecuteInfo.lpParameters != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpParameters);
                if (shellExecuteInfo.lpDirectory != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpDirectory); 
            }

            if (shellExecuteInfo.hProcess != (IntPtr)0) {
                SafeProcessHandle handle = new SafeProcessHandle(shellExecuteInfo.hProcess); 
                SetProcessHandle(handle);
                return true; 
            } 

            return false; 
        }

        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process Start( string fileName, string userName, SecureString password, string domain ) {
            ProcessStartInfo startInfo = new ProcessStartInfo(fileName); 
            startInfo.UserName = userName; 
            startInfo.Password = password;
            startInfo.Domain = domain; 
            startInfo.UseShellExecute = false;
            return Start(startInfo);
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process Start( string fileName, string arguments, string userName, SecureString password, string domain ) { 
            ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
            startInfo.UserName = userName; 
            startInfo.Password = password;
            startInfo.Domain = domain;
            startInfo.UseShellExecute = false;
            return Start(startInfo); 
        }
 
 
#endif // !FEATURE_PAL
 
        /// 
        ///    
        ///       Starts a process resource by specifying the name of a
        ///       document or application file. Associates the process resource with a new  
        ///       component.
        ///     
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process Start(string fileName) {
            return Start(new ProcessStartInfo(fileName));
        }
 
        /// 
        ///     
        ///       Starts a process resource by specifying the name of an 
        ///       application and a set of command line arguments. Associates the process resource
        ///       with a new  
        ///       component.
        ///    
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static Process Start(string fileName, string arguments) { 
            return Start(new ProcessStartInfo(fileName, arguments)); 
        }
 
        /// 
        ///    
        ///       Starts a process resource specified by the process start
        ///       information passed in, for example the file name of the process to start. 
        ///       Associates the process resource with a new 
        ///       component. 
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static Process Start(ProcessStartInfo startInfo) {
            Process process = new Process();
            if (startInfo == null) throw new ArgumentNullException("startInfo"); 
            process.StartInfo = startInfo;
            if (process.Start()) { 
                return process; 
            }
            return null; 
        }

        /// 
        ///     
        ///       Stops the
        ///       associated process immediately. 
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public void Kill() {
            SafeProcessHandle handle = null;
            try { 
                handle = GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
                if (!NativeMethods.TerminateProcess(handle, -1)) 
                    throw new Win32Exception(); 
            }
            finally { 
                ReleaseProcessHandle(handle);
            }
        }
 
        /// 
        ///     Make sure we are not watching for process exit. 
        ///  
        /// 
        void StopWatchingForExit() { 
            if (watchingForExit) {
                lock (this) {
                    if (watchingForExit) {
                        watchingForExit = false; 
                        registeredWaitHandle.Unregister(null);
                        waitHandle.Close(); 
                        waitHandle = null; 
                        registeredWaitHandle = null;
                    } 
                }
            }
        }
 
        public override string ToString() {
#if !FEATURE_PAL 
            if (Associated) { 
                string processName  =  String.Empty;
                // 
                // On windows 9x, we can't map a handle to an id.
                // So ProcessName will throw. We shouldn't throw in Process.ToString though.
                // Process.GetProcesses should be used to get all the processes on the machine.
                // The processes returned from it will have a nice name. 
                //
                try { 
                    processName = this.ProcessName; 
                }
                catch(PlatformNotSupportedException) { 
                }
                if( processName.Length != 0) {
                    return String.Format(CultureInfo.CurrentCulture, "{0} ({1})", base.ToString(), processName);
                } 
                return base.ToString();
            } 
            else 
#endif // !FEATURE_PAL
                return base.ToString(); 
        }

        /// 
        ///     
        ///       Instructs the  component to wait the specified number of milliseconds for the associated process to exit.
        ///     
        ///  
        public bool WaitForExit(int milliseconds) {
            SafeProcessHandle handle = null; 
	     bool exited;
            ProcessWaitHandle processWaitHandle = null;
            try {
                handle = GetProcessHandle(NativeMethods.SYNCHRONIZE, false); 
                if (handle.IsInvalid) {
                    exited = true; 
                } 
                else {
                    processWaitHandle = new ProcessWaitHandle(handle); 
                    if( processWaitHandle.WaitOne(milliseconds, false)) {
                        exited = true;
                        signaled = true;
                    } 
                    else {
                        exited = false; 
                        signaled = false; 
                    }
                } 
            }
            finally {
                if( processWaitHandle != null) {
                    processWaitHandle.Close(); 
                }
 
                // If we have a hard timeout, we cannot wait for the streams 
                if( output != null && milliseconds == -1) {
                    output.WaitUtilEOF(); 
                }

                if( error != null && milliseconds == -1) {
                    error.WaitUtilEOF(); 
                }
 
                ReleaseProcessHandle(handle); 

            } 

            if (exited && watchForExit) {
                RaiseOnExited();
            } 
			
            return exited; 
        } 

        ///  
        ///    
        ///       Instructs the  component to wait
        ///       indefinitely for the associated process to exit.
        ///     
        /// 
        public void WaitForExit() { 
            WaitForExit(-1); 
        }
 
#if !FEATURE_PAL

        /// 
        ///     
        ///       Causes the  component to wait the
        ///       specified number of milliseconds for the associated process to enter an 
        ///       idle state. 
        ///       This is only applicable for processes with a user interface,
        ///       therefore a message loop. 
        ///    
        /// 
        public bool WaitForInputIdle(int milliseconds) {
            SafeProcessHandle handle = null; 
            bool idle;
            try { 
                handle = GetProcessHandle(NativeMethods.SYNCHRONIZE | NativeMethods.PROCESS_QUERY_INFORMATION); 
                int ret = NativeMethods.WaitForInputIdle(handle, milliseconds);
                switch (ret) { 
                    case NativeMethods.WAIT_OBJECT_0:
                        idle = true;
                        break;
                    case NativeMethods.WAIT_TIMEOUT: 
                        idle = false;
                        break; 
                    case NativeMethods.WAIT_FAILED: 
                    default:
                        throw new InvalidOperationException(SR.GetString(SR.InputIdleUnkownError)); 
                }
            }
            finally {
                ReleaseProcessHandle(handle); 
            }
            return idle; 
        } 

        ///  
        ///    
        ///       Instructs the  component to wait
        ///       indefinitely for the associated process to enter an idle state. This
        ///       is only applicable for processes with a user interface, therefore a message loop. 
        ///    
        ///  
        public bool WaitForInputIdle() { 
            return WaitForInputIdle(Int32.MaxValue);
        } 

#endif // !FEATURE_PAL

        // Support for working asynchronously with streams 
        /// 
        ///  
        /// Instructs the  component to start 
        /// reading the StandardOutput stream asynchronously. The user can register a callback
        /// 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 
        /// then the remaining information is returned. The user can add an event handler to OutputDataReceived.
        /// 
        /// 
        [System.Runtime.InteropServices.ComVisible(false)] 
        public void BeginOutputReadLine() {
 
            if(outputStreamReadMode == StreamReadMode.undefined) { 
                outputStreamReadMode = StreamReadMode.asyncMode;
            } 
            else if (outputStreamReadMode != StreamReadMode.asyncMode) {
                throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
            }
 
            if (pendingOutputRead)
                throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation)); 
 
            pendingOutputRead = true;
            // We can't detect if there's a pending sychronous read, tream also doesn't. 
            if (output == null) {
                if (standardOutput == null) {
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
                } 

                Stream s = standardOutput.BaseStream; 
                output = new AsyncStreamReader(this, s, new UserCallBack(this.OutputReadNotifyUser), standardOutput.CurrentEncoding); 
            }
            output.BeginReadLine(); 
        }


        ///  
        /// 
        /// Instructs the  component to start 
        /// reading the StandardError stream asynchronously. The user can register a callback 
        /// 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
        /// then the remaining information is returned. The user can add an event handler to ErrorDataReceived. 
        /// 
        /// 
        [System.Runtime.InteropServices.ComVisible(false)]
        public void BeginErrorReadLine() { 

            if(errorStreamReadMode == StreamReadMode.undefined) { 
                errorStreamReadMode = StreamReadMode.asyncMode; 
            }
            else if (errorStreamReadMode != StreamReadMode.asyncMode) { 
                throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
            }

            if (pendingErrorRead) { 
                throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
            } 
 
            pendingErrorRead = true;
            // We can't detect if there's a pending sychronous read, stream also doesn't. 
            if (error == null) {
                if (standardError == null) {
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
                } 

                Stream s = standardError.BaseStream; 
                error = new AsyncStreamReader(this, s, new UserCallBack(this.ErrorReadNotifyUser), standardError.CurrentEncoding); 
            }
            error.BeginReadLine(); 
        }

        /// 
        ///  
        /// Instructs the  component to cancel the asynchronous operation
        /// specified by BeginOutputReadLine(). 
        ///  
        /// 
        [System.Runtime.InteropServices.ComVisible(false)] 
        public void CancelOutputRead() {
            if (output != null) {
                output.CancelOperation();
            } 
            else {
                throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation)); 
            } 

            pendingOutputRead = false; 
        }

        /// 
        ///  
        /// Instructs the  component to cancel the asynchronous operation
        /// specified by BeginErrorReadLine(). 
        ///  
        /// 
        [System.Runtime.InteropServices.ComVisible(false)] 
        public void CancelErrorRead() {
            if (error != null) {
                error.CancelOperation();
            } 
            else {
                throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation)); 
            } 

            pendingErrorRead = false; 
        }

        internal void OutputReadNotifyUser(String data) {
            // To avoid ---- between remove handler and raising the event 
            DataReceivedEventHandler outputDataReceived = OutputDataReceived;
            if (outputDataReceived != null) { 
                DataReceivedEventArgs e = new DataReceivedEventArgs(data); 
                if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
                    SynchronizingObject.Invoke(outputDataReceived, new object[] {this, e}); 
                }
                else {
                    outputDataReceived(this,e);  // Call back to user informing data is available.
                } 
            }
        } 
 
        internal void ErrorReadNotifyUser(String data) {
            // To avoid ---- between remove handler and raising the event 
            DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
            if (errorDataReceived != null) {
                DataReceivedEventArgs e = new DataReceivedEventArgs(data);
                if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) { 
                    SynchronizingObject.Invoke(errorDataReceived, new object[] {this, e});
                } 
                else { 
                    errorDataReceived(this,e); // Call back to user informing data is available.
                } 
            }
        }

        ///  
        ///     A desired internal state.
        ///  
        ///  
        enum State {
            HaveId = 0x1, 
            IsLocal = 0x2,
            IsNt = 0x4,
            HaveProcessInfo = 0x8,
            Exited = 0x10, 
            Associated = 0x20,
            IsWin2k = 0x40, 
            HaveNtProcessInfo = HaveProcessInfo | IsNt 
        }
    } 

    /// 
    ///     This data structure contains information about a process that is collected
    ///     in bulk by querying the operating system.  The reason to make this a separate 
    ///     structure from the process component is so that we can throw it away all at once
    ///     when Refresh is called on the component. 
    ///  
    /// 
    internal class ProcessInfo { 
        public ArrayList threadInfoList = new ArrayList();
        public int basePriority;
        public string processName;
        public int processId; 
        public int handleCount;
        public long poolPagedBytes; 
        public long poolNonpagedBytes; 
        public long virtualBytes;
        public long virtualBytesPeak; 
        public long workingSetPeak;
        public long workingSet;
        public long pageFileBytesPeak;
        public long pageFileBytes; 
        public long privateBytes;
        public int mainModuleId; // used only for win9x - id is only for use with CreateToolHelp32 
        public int sessionId; 
    }
 
    /// 
    ///     This data structure contains information about a thread in a process that
    ///     is collected in bulk by querying the operating system.  The reason to
    ///     make this a separate structure from the ProcessThread component is so that we 
    ///     can throw it away all at once when Refresh is called on the component.
    ///  
    ///  
    internal class ThreadInfo {
        public int threadId; 
        public int processId;
        public int basePriority;
        public int currentPriority;
        public IntPtr startAddress; 
        public ThreadState threadState;
#if !FEATURE_PAL 
        public ThreadWaitReason threadWaitReason; 
#endif // !FEATURE_PAL
    } 

    /// 
    ///     This data structure contains information about a module in a process that
    ///     is collected in bulk by querying the operating system.  The reason to 
    ///     make this a separate structure from the ProcessModule component is so that we
    ///     can throw it away all at once when Refresh is called on the component. 
    ///  
    /// 
    internal class ModuleInfo { 
        public string baseName;
        public string fileName;
        public IntPtr baseOfDll;
        public IntPtr entryPoint; 
        public int sizeOfImage;
        public int Id; // used only on win9x - for matching up with ProcessInfo.mainModuleId 
    } 

    internal static class EnvironmentBlock { 
        public static byte[] ToByteArray(StringDictionary sd, bool unicode) {
            // get the keys
            string[] keys = new string[sd.Count];
            byte[] envBlock = null; 
            sd.Keys.CopyTo(keys, 0);
 
            // get the values 
            string[] values = new string[sd.Count];
            sd.Values.CopyTo(values, 0); 

            // sort both by the keys
            // Windows 2000 requires the environment block to be sorted by the key
            // It will first converting the case the strings and do ordinal comparison. 
            Array.Sort(keys, values, OrdinalCaseInsensitiveComparer.Default);
 
            // create a list of null terminated "key=val" strings 
            StringBuilder stringBuff = new StringBuilder();
            for (int i = 0; i < sd.Count; ++ i) { 
                stringBuff.Append(keys[i]);
                stringBuff.Append('=');
                stringBuff.Append(values[i]);
                stringBuff.Append('\0'); 
            }
            // an extra null at the end indicates end of list. 
            stringBuff.Append('\0'); 

            if( unicode) { 
                envBlock = Encoding.Unicode.GetBytes(stringBuff.ToString());
            }
            else
                envBlock = Encoding.Default.GetBytes(stringBuff.ToString()); 

            if (envBlock.Length > UInt16.MaxValue) 
                throw new InvalidOperationException(SR.GetString(SR.EnvironmentBlockTooLong, envBlock.Length)); 

            return envBlock; 
        }
    }

    internal class OrdinalCaseInsensitiveComparer : IComparer { 
        internal static readonly OrdinalCaseInsensitiveComparer Default = new OrdinalCaseInsensitiveComparer();
 
        public int Compare(Object a, Object b) { 
            String sa = a as String;
            String sb = b as String; 
            if (sa != null && sb != null) {
                return String.Compare(sa, sb, StringComparison.OrdinalIgnoreCase);
            }
            return Comparer.Default.Compare(a,b); 
        }
    } 
 
    internal class ProcessThreadTimes {
        internal long create; 
        internal long exit;
        internal long kernel;
        internal long user;
 
        public DateTime StartTime {
            get { 
                return DateTime.FromFileTime(create); 
            }
        } 

        public DateTime ExitTime {
            get {
                return DateTime.FromFileTime(exit); 
            }
        } 
 
        public TimeSpan PrivilegedProcessorTime {
            get { 
                return new TimeSpan(kernel);
            }
        }
 
        public TimeSpan UserProcessorTime {
            get { 
                return new TimeSpan(user); 
            }
        } 

        public TimeSpan TotalProcessorTime {
            get {
                return new TimeSpan(user + kernel); 
            }
        } 
    } 

    internal class ShellExecuteHelper { 
        private NativeMethods.ShellExecuteInfo _executeInfo;
        private int _errorCode;
        private bool _succeeded;
 
        public ShellExecuteHelper(NativeMethods.ShellExecuteInfo executeInfo) {
            _executeInfo = executeInfo; 
        } 

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        public void ShellExecuteFunction()    {
            if (!(_succeeded = NativeMethods.ShellExecuteEx(_executeInfo))) {
                _errorCode = Marshal.GetLastWin32Error(); 
            }
        } 
 
        public bool ShellExecuteOnSTAThread() {
            // 
            // SHELL API ShellExecute() requires STA in order to work correctly.
            // If current thread is not a STA thread, we need to call ShellExecute on a new thread.
            //
            if( Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) { 
                ThreadStart threadStart = new ThreadStart(this.ShellExecuteFunction);
                Thread executionThread = new Thread(threadStart); 
                executionThread.SetApartmentState(ApartmentState.STA); 
                executionThread.Start();
                executionThread.Join(); 
            }
            else {
                ShellExecuteFunction();
            } 
            return _succeeded;
        } 
 
        public int ErrorCode {
            get { 
                return _errorCode;
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Diagnostics { 
    using System.Text; 
    using System.Threading;
    using System.Runtime.InteropServices; 
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Runtime.CompilerServices;
    using System.Runtime.ConstrainedExecution; 
    using System.Diagnostics;
    using System; 
    using System.Collections; 
    using System.IO;
    using Microsoft.Win32; 
    using Microsoft.Win32.SafeHandles;
    using System.Collections.Specialized;
    using System.Globalization;
    using System.Security; 
    using System.Security.Permissions;
    using System.Security.Principal; 
    using System.Runtime.Versioning; 

    ///  
    ///    
    ///       Provides access to local and remote
    ///       processes. Enables you to start and stop system processes.
    ///     
    /// 
    [ 
    MonitoringDescription(SR.ProcessDesc), 
    DefaultEvent("Exited"),
    DefaultProperty("StartInfo"), 
    Designer("System.Diagnostics.Design.ProcessDesigner, " + AssemblyRef.SystemDesign),
    // Disabling partial trust scenarios
    PermissionSet(SecurityAction.LinkDemand, Name="FullTrust"),
    PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust"), 
    HostProtection(SharedState=true, Synchronization=true, ExternalProcessMgmt=true, SelfAffectingProcessMgmt=true)
    ] 
    public class Process : Component { 
        //
        // FIELDS 
        //

        bool haveProcessId;
        int processId; 
        bool haveProcessHandle;
        SafeProcessHandle m_processHandle; 
        bool isRemoteMachine; 
        string machineName;
        ProcessInfo processInfo; 
        Int32 m_processAccess;

#if !FEATURE_PAL
        ProcessThreadCollection threads; 
        ProcessModuleCollection modules;
#endif // !FEATURE_PAL 
 
        bool haveMainWindow;
        IntPtr mainWindowHandle;  // no need to use SafeHandle for window 
        string mainWindowTitle;

        bool haveWorkingSetLimits;
        IntPtr minWorkingSet; 
        IntPtr maxWorkingSet;
 
        bool haveProcessorAffinity; 
        IntPtr processorAffinity;
 
        bool havePriorityClass;
        ProcessPriorityClass priorityClass;

        ProcessStartInfo startInfo; 

        bool watchForExit; 
        bool watchingForExit; 
        EventHandler onExited;
        bool exited; 
        int exitCode;
        bool signaled;
 		
        DateTime exitTime; 
        bool haveExitTime;
 
        bool responding; 
        bool haveResponding;
 
        bool priorityBoostEnabled;
        bool havePriorityBoostEnabled;

        bool raisedOnExited; 
        RegisteredWaitHandle registeredWaitHandle;
        WaitHandle waitHandle; 
        ISynchronizeInvoke synchronizingObject; 
        StreamReader standardOutput;
        StreamWriter standardInput; 
        StreamReader standardError;
        OperatingSystem operatingSystem;
        bool disposed;
 
        static object s_CreateProcessLock = new object();
 
        // This enum defines the operation mode for redirected process stream. 
        // We don't support switching between synchronous mode and asynchronous mode.
        private enum StreamReadMode 
        {
            undefined,
            syncMode,
            asyncMode 
        }
 
        StreamReadMode outputStreamReadMode; 
        StreamReadMode errorStreamReadMode;
 

        // Support for asynchrously reading streams
        [Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
        //[System.Runtime.InteropServices.ComVisible(false)] 
        public event DataReceivedEventHandler OutputDataReceived;
        [Browsable(true), MonitoringDescription(SR.ProcessAssociated)] 
        //[System.Runtime.InteropServices.ComVisible(false)] 
        public event DataReceivedEventHandler ErrorDataReceived;
        // Abstract the stream details 
        internal AsyncStreamReader output;
        internal AsyncStreamReader error;
        internal bool pendingOutputRead;
        internal bool pendingErrorRead; 

 
        private static SafeFileHandle InvalidPipeHandle = new SafeFileHandle(IntPtr.Zero, false); 
#if DEBUG
        internal static TraceSwitch processTracing = new TraceSwitch("processTracing", "Controls debug output from Process component"); 
#else
        internal static TraceSwitch processTracing = null;
#endif
 
        //
        // CONSTRUCTORS 
        // 

        ///  
        ///    
        ///       Initializes a new instance of the  class.
        ///    
        ///  
        public Process() {
            this.machineName = "."; 
            this.outputStreamReadMode = StreamReadMode.undefined; 
            this.errorStreamReadMode = StreamReadMode.undefined;
            this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS; 
        }

        [ResourceExposure(ResourceScope.Machine)]
        Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo) : base() { 
            Debug.Assert(SyntaxCheck.CheckMachineName(machineName), "The machine name should be valid!");
            this.processInfo = processInfo; 
            this.machineName = machineName; 
            this.isRemoteMachine = isRemoteMachine;
            this.processId = processId; 
            this.haveProcessId = true;
            this.outputStreamReadMode = StreamReadMode.undefined;
            this.errorStreamReadMode = StreamReadMode.undefined;
            this.m_processAccess = NativeMethods.PROCESS_ALL_ACCESS; 
        }
 
        // 
        // PROPERTIES
        // 

        /// 
        ///     Returns whether this process component is associated with a real process.
        ///  
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessAssociated)] 
        bool Associated { 
            get {
                return haveProcessId || haveProcessHandle; 
            }
        }

 #if !FEATURE_PAL 
        /// 
        ///     
        ///       Gets the base priority of 
        ///       the associated process.
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessBasePriority)]
        public int BasePriority {
            get { 
                EnsureState(State.HaveProcessInfo);
                return processInfo.basePriority; 
            } 
        }
#endif // FEATURE_PAL 

        /// 
        ///    
        ///       Gets 
        ///       the
        ///       value that was specified by the associated process when it was terminated. 
        ///     
        /// 
        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitCode)] 
        public int ExitCode {
            get {
                EnsureState(State.Exited);
                return exitCode; 
            }
          } 
 
        /// 
        ///     
        ///       Gets a
        ///       value indicating whether the associated process has been terminated.
        ///    
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTerminated)]
        public bool HasExited { 
            get { 
                if (!exited) {
                    EnsureState(State.Associated); 
                    SafeProcessHandle handle = null;
                    try {
                        handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.SYNCHRONIZE, false);
                        if (handle.IsInvalid) { 
                            exited = true;
                        } 
                        else { 
                            int exitCode;
 
                            // Although this is the wrong way to check whether the process has exited,
                            // it was historically the way we checked for it, and a lot of code then took a dependency on
                            // the fact that this would always be set before the pipes were closed, so they would read
                            // the exit code out after calling ReadToEnd() or standard output or standard error. In order 
                            // to allow 259 to function as a valid exit code and to break as few people as possible that
                            // took the ReadToEnd dependency, we check for an exit code before doing the more correct 
                            // check to see if we have been signalled. 
                            if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
                                this.exited = true; 
                                this.exitCode = exitCode;
                            }
                            else {
 
                                // The best check for exit is that the kernel process object handle is invalid,
                                // or that it is valid and signaled.  Checking if the exit code != STILL_ACTIVE 
                                // does not guarantee the process is closed, 
                                // since some process could return an actual STILL_ACTIVE exit code (259).
                                if (!signaled) // if we just came from WaitForExit, don't repeat 
                                {
                                    ProcessWaitHandle wh = null;
                                    try
                                    { 
                                        wh = new ProcessWaitHandle(handle);
                                        this.signaled = wh.WaitOne(0, false);					 
                                    } 
                                    finally
                                    { 

                                        if (wh != null)
                                        wh.Close();
                                    } 
                                }
                                if (signaled) 
                                { 
                                    if (!NativeMethods.GetExitCodeProcess(handle, out exitCode))
                                        throw new Win32Exception(); 

                                    this.exited = true;
                                    this.exitCode = exitCode;
                                } 
                            }
                        }	 
                    } 
                    finally
                    { 
                        ReleaseProcessHandle(handle);
                    }

                    if (exited) { 
                        RaiseOnExited();
                    } 
                } 
                return exited;
            } 
        }

        private ProcessThreadTimes GetProcessTimes() {
            ProcessThreadTimes processTimes = new ProcessThreadTimes(); 
            SafeProcessHandle handle = null;
            try { 
                handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION, false); 
                if( handle.IsInvalid) {
                    // On OS older than XP, we will not be able to get the handle for a process 
                    // after it terminates.
                    // On Windows XP and newer OS, the information about a process will stay longer.
                    throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
                } 

                if (!NativeMethods.GetProcessTimes(handle, 
                                                   out processTimes.create, 
                                                   out processTimes.exit,
                                                   out processTimes.kernel, 
                                                   out processTimes.user)) {
                    throw new Win32Exception();
                }
 
            }
            finally { 
                ReleaseProcessHandle(handle); 
            }
            return processTimes; 
        }

 #if !FEATURE_PAL
        ///  
        ///    
        ///       Gets the time that the associated process exited. 
        ///     
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessExitTime)] 
        public DateTime ExitTime {
            get {
                if (!haveExitTime) {
                    EnsureState(State.IsNt | State.Exited); 
                    exitTime = GetProcessTimes().ExitTime;
                    haveExitTime = true; 
                } 
                return exitTime;
            } 
        }
#endif // !FEATURE_PAL

        ///  
        ///    
        ///       Returns the native handle for the associated process. The handle is only available 
        ///       if this component started the process. 
        ///    
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandle)]
        public IntPtr Handle {
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)] 
            get {
                EnsureState(State.Associated); 
                return OpenProcessHandle(this.m_processAccess).DangerousGetHandle(); 
            }
        } 

#if !FEATURE_PAL
        /// 
        ///     
        ///       Gets the number of handles that are associated
        ///       with the process. 
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessHandleCount)] 
        public int HandleCount {
            get {
                EnsureState(State.HaveProcessInfo);
                return processInfo.handleCount; 
            }
        } 
#endif // !FEATURE_PAL 

        ///  
        ///    
        ///       Gets
        ///       the unique identifier for the associated process.
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessId)] 
        public int Id { 
            get {
                EnsureState(State.HaveId); 
                return processId;
            }
        }
 
        /// 
        ///     
        ///       Gets 
        ///       the name of the computer on which the associated process is running.
        ///     
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMachineName)]
        public string MachineName {
            get { 
                EnsureState(State.Associated);
                return machineName; 
            } 
        }
 
 #if !FEATURE_PAL

        /// 
        ///     
        ///       Returns the window handle of the main window of the associated process.
        ///     
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowHandle)]
        public IntPtr MainWindowHandle { 
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)]
            get {
                if (!haveMainWindow) { 
                    EnsureState(State.IsLocal | State.HaveId);
                    mainWindowHandle = ProcessManager.GetMainWindowHandle(processId); 
 
                    if (mainWindowHandle != (IntPtr)0) {
                        haveMainWindow = true; 
                    } else {
                        // 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
                        // we always did this check but have now changed it to just require a ProcessId. In the case where someone has called Refresh()
                        // and the process has exited this call will throw an exception where as the above code would return 0 as the handle. 
                        EnsureState(State.HaveProcessInfo);
                    } 
                } 
                return mainWindowHandle;
            } 
        }

        /// 
        ///     
        ///       Returns the caption of the  of
        ///       the process. If the handle is zero (0), then an empty string is returned. 
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainWindowTitle)] 
        public string MainWindowTitle {
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                if (mainWindowTitle == null) {
                    IntPtr handle = MainWindowHandle; 
                    if (handle == (IntPtr)0) { 
                        mainWindowTitle = String.Empty;
                    } 
                    else {
                        int length = NativeMethods.GetWindowTextLength(new HandleRef(this, handle)) * 2;
                        StringBuilder builder = new StringBuilder(length);
                        NativeMethods.GetWindowText(new HandleRef(this, handle), builder, builder.Capacity); 
                        mainWindowTitle = builder.ToString();
                    } 
                } 
                return mainWindowTitle;
            } 
        }


 
        /// 
        ///     
        ///       Gets 
        ///       the main module for the associated process.
        ///     
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMainModule)]
        public ProcessModule MainModule {
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                // We only return null if we couldn't find a main module. 
                // This could be because
                //      1. The process hasn't finished loading the main module (most likely) 
                //      2. There are no modules loaded (possible for certain OS processes)
                //      3. Possibly other?

                if (OperatingSystem.Platform == PlatformID.Win32NT) { 
                    EnsureState(State.HaveId | State.IsLocal);
                    // on NT the first module is the main module 
                    ModuleInfo module = NtProcessManager.GetFirstModuleInfo(processId); 
                    return new ProcessModule(module);
                } 
                else {
                    ProcessModuleCollection moduleCollection = Modules;
                    // on 9x we have to do a little more work
                    EnsureState(State.HaveProcessInfo); 
                    foreach (ProcessModule pm in moduleCollection) {
                        if (pm.moduleInfo.Id == processInfo.mainModuleId) { 
                            return pm; 
                        }
                    } 
                    return null;
                }
            }
        } 

        ///  
        ///     
        ///       Gets or sets the maximum allowable working set for the associated
        ///       process. 
        ///    
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMaxWorkingSet)]
        public IntPtr MaxWorkingSet { 
            get {
                EnsureWorkingSetLimits(); 
                return maxWorkingSet; 
            }
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetWorkingSetLimits(null, value);
            } 
        }
 
        ///  
        ///    
        ///       Gets or sets the minimum allowable working set for the associated 
        ///       process.
        ///    
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessMinWorkingSet)] 
        public IntPtr MinWorkingSet {
            get { 
                EnsureWorkingSetLimits(); 
                return minWorkingSet;
            } 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetWorkingSetLimits(value, null); 
            }
        } 
 
        /// 
        ///     
        ///       Gets
        ///       the modules that have been loaded by the associated process.
        ///    
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessModules)]
        public ProcessModuleCollection Modules { 
            [ResourceExposure(ResourceScope.None)] 
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                if (modules == null) {
                    EnsureState(State.HaveId | State.IsLocal);
                    ModuleInfo[] moduleInfos = ProcessManager.GetModuleInfos(processId);
                    ProcessModule[] newModulesArray = new ProcessModule[moduleInfos.Length]; 
                    for (int i = 0; i < moduleInfos.Length; i++) {
                        newModulesArray[i] = new ProcessModule(moduleInfos[i]); 
                    } 
                    ProcessModuleCollection newModules = new ProcessModuleCollection(newModulesArray);
                    modules = newModules; 
                }
                return modules;
            }
        } 

        ///  
        ///     Returns the amount of memory that the system has allocated on behalf of the 
        ///     associated process that can not be written to the virtual memory paging file.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
        public int NonpagedSystemMemorySize {
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.poolNonpagedBytes); 
            } 
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessNonpagedSystemMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)]
        public long NonpagedSystemMemorySize64 {
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.poolNonpagedBytes; 
            } 
        }
 
        /// 
        ///     Returns the amount of memory that the associated process has allocated
        ///     that can be written to the virtual memory paging file.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PagedMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)] 
        public int PagedMemorySize { 
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return unchecked((int)processInfo.pageFileBytes);
            }
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long PagedMemorySize64 { 
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return processInfo.pageFileBytes;
            }
        }
 

        ///  
        ///     Returns the amount of memory that the system has allocated on behalf of the 
        ///     associated process that can be written to the virtual memory paging file.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PagedSystemMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
        public int PagedSystemMemorySize {
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.poolPagedBytes); 
            } 
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPagedSystemMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)]
        public long PagedSystemMemorySize64 {
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.poolPagedBytes; 
            } 
        }
 

        /// 
        ///    
        ///       Returns the maximum amount of memory that the associated process has 
        ///       allocated that could be written to the virtual memory paging file.
        ///     
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakPagedMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)] 
        public int PeakPagedMemorySize {
            get {
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.pageFileBytesPeak); 
            }
        } 
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakPagedMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long PeakPagedMemorySize64 {
            get {
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.pageFileBytesPeak; 
            }
        } 
 
        /// 
        ///     
        ///       Returns the maximum amount of physical memory that the associated
        ///       process required at once.
        ///    
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakWorkingSet64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)] 
        public int PeakWorkingSet { 
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return unchecked((int)processInfo.workingSetPeak);
            }
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakWorkingSet)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long PeakWorkingSet64 { 
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return processInfo.workingSetPeak;
            }
        }
 
        /// 
        ///     Returns the maximum amount of virtual memory that the associated 
        ///     process has requested. 
        /// 
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PeakVirtualMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)]
        public int PeakVirtualMemorySize {
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return unchecked((int)processInfo.virtualBytesPeak);
            } 
        } 

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPeakVirtualMemorySize)] 
        [System.Runtime.InteropServices.ComVisible(false)]
        public long PeakVirtualMemorySize64 {
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return processInfo.virtualBytesPeak;
            } 
        } 

        private OperatingSystem OperatingSystem { 
            get {
                if (operatingSystem == null) {
                    operatingSystem = Environment.OSVersion;
                } 
                return operatingSystem;
            } 
        } 

        ///  
        ///    
        ///       Gets or sets a value indicating whether the associated process priority
        ///       should be temporarily boosted by the operating system when the main window
        ///       has focus. 
        ///    
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityBoostEnabled)] 
        public bool PriorityBoostEnabled {
            get { 
                EnsureState(State.IsNt);
                if (!havePriorityBoostEnabled) {
                    SafeProcessHandle handle = null;
                    try { 
                        handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
                        bool disabled = false; 
                        if (!NativeMethods.GetProcessPriorityBoost(handle, out disabled)) { 
                            throw new Win32Exception();
                        } 
                        priorityBoostEnabled = !disabled;
                        havePriorityBoostEnabled = true;
                    }
                    finally { 
                        ReleaseProcessHandle(handle);
                    } 
                } 
                return priorityBoostEnabled;
            } 
            set {
                EnsureState(State.IsNt);
                SafeProcessHandle handle = null;
                try { 
                    handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
                    if (!NativeMethods.SetProcessPriorityBoost(handle, !value)) 
                        throw new Win32Exception(); 
                    priorityBoostEnabled = value;
                    havePriorityBoostEnabled = true; 
                }
                finally {
                    ReleaseProcessHandle(handle);
                } 
            }
        } 
 
        /// 
        ///     
        ///       Gets or sets the overall priority category for the
        ///       associated process.
        ///    
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPriorityClass)]
        public ProcessPriorityClass PriorityClass { 
            get { 
                if (!havePriorityClass) {
                    SafeProcessHandle handle = null; 
                    try {
                        handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
                        int value = NativeMethods.GetPriorityClass(handle);
                        if (value == 0) { 
                            throw new Win32Exception();
                        } 
                        priorityClass = (ProcessPriorityClass)value; 
                        havePriorityClass = true;
                    } 
                    finally {
                        ReleaseProcessHandle(handle);
                    }
                } 
                return priorityClass;
            } 
            [ResourceExposure(ResourceScope.Machine)] 
            [ResourceConsumption(ResourceScope.Machine)]
            set { 
                if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
                }
 
                // BelowNormal and AboveNormal are only available on Win2k and greater.
                if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0)   && 
                    (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) { 
                    throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
                } 

                SafeProcessHandle handle = null;

                try { 
                    handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
                    if (!NativeMethods.SetPriorityClass(handle, (int)value)) { 
                        throw new Win32Exception(); 
                    }
                    priorityClass = value; 
                    havePriorityClass = true;
                }
                finally {
                    ReleaseProcessHandle(handle); 
                }
            } 
        } 

        ///  
        ///     Returns the number of bytes that the associated process has allocated that cannot
        ///     be shared with other processes.
        /// 
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.PrivateMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)]
        public int PrivateMemorySize { 
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.privateBytes); 
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivateMemorySize)] 
        [System.Runtime.InteropServices.ComVisible(false)]
        public long PrivateMemorySize64 { 
            get { 
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.privateBytes; 
            }
        }

        ///  
        ///     Returns the amount of time the process has spent running code inside the operating
        ///     system core. 
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessPrivilegedProcessorTime)]
        public TimeSpan PrivilegedProcessorTime { 
            get {
                EnsureState(State.IsNt);
                return GetProcessTimes().PrivilegedProcessorTime;
            } 
        }
 
        ///  
        ///    
        ///       Gets 
        ///       the friendly name of the process.
        ///    
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessName)] 
        public string ProcessName {
            [ResourceExposure(ResourceScope.None)] 
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
            get {
                EnsureState(State.HaveProcessInfo); 
                String processName =  processInfo.processName;
                //
                // On some old NT-based OS like win2000, the process name from NTQuerySystemInformation is up to 15 characters.
                // Processes executing notepad_1234567.exe and notepad_12345678.exe will have the same process name. 
                // GetProcessByNames will not be able find the process for notepad_12345678.exe.
                // So we will try to replace the name of the process by its main module name if the name is 15 characters. 
                // However we can't always get the module name: 
                //     (1) Normal user will not be able to get module information about processes.
                //     (2) We can't get module information about remoting process. 
                // We can't get module name for a remote process
                //
                if (processName.Length == 15 && ProcessManager.IsNt && ProcessManager.IsOSOlderThanXP && !isRemoteMachine) {
                    try { 
                        String mainModuleName = MainModule.ModuleName;
                        if (mainModuleName != null) { 
                            processInfo.processName = Path.ChangeExtension(Path.GetFileName(mainModuleName), null); 
                        }
                    } 
                    catch(Exception) {
                        // If we can't access the module information, we can still use the might-be-truncated name.
                        // We could fail for a few reasons:
                        // (1) We don't enough privilege to get module information. 
                        // (2) The process could have terminated.
                    } 
                } 

                return processInfo.processName; 
            }
        }

        ///  
        ///    
        ///       Gets 
        ///       or sets which processors the threads in this process can be scheduled to run on. 
        ///    
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessProcessorAffinity)]
        public IntPtr ProcessorAffinity {
            get {
                if (!haveProcessorAffinity) { 
                    SafeProcessHandle handle = null;
                    try { 
                        handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION); 
                        IntPtr processAffinity;
                        IntPtr systemAffinity; 
                        if (!NativeMethods.GetProcessAffinityMask(handle, out processAffinity, out systemAffinity))
                            throw new Win32Exception();
                        processorAffinity = processAffinity;
                    } 
                    finally {
                        ReleaseProcessHandle(handle); 
                    } 
                    haveProcessorAffinity = true;
                } 
                return processorAffinity;
            }
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)] 
            set {
                SafeProcessHandle handle = null; 
                try { 
                    handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
                    if (!NativeMethods.SetProcessAffinityMask(handle, value)) 
                        throw new Win32Exception();

                    processorAffinity = value;
                    haveProcessorAffinity = true; 
                }
                finally { 
                    ReleaseProcessHandle(handle); 
                }
            } 
        }

        /// 
        ///     
        ///       Gets a value indicating whether or not the user
        ///       interface of the process is responding. 
        ///     
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessResponding)] 
        public bool Responding {
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                if (!haveResponding) {
                    IntPtr mainWindow = MainWindowHandle; 
                    if (mainWindow == (IntPtr)0) { 
                        responding = true;
                    } 
                    else {
                        IntPtr result;
                        responding = NativeMethods.SendMessageTimeout(new HandleRef(this, mainWindow), NativeMethods.WM_NULL, IntPtr.Zero, IntPtr.Zero, NativeMethods.SMTO_ABORTIFHUNG, 5000, out result) != (IntPtr)0;
                    } 
                }
                return responding; 
            } 
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessSessionId)]
        public int SessionId {
            get {
                EnsureState(State.HaveNtProcessInfo); 
                return processInfo.sessionId;
            } 
        } 

#endif // !FEATURE_PAL 

        /// 
        ///    
        ///       Gets or sets the properties to pass into the  method for the  
        ///       .
        ///     
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MonitoringDescription(SR.ProcessStartInfo)]
        public ProcessStartInfo StartInfo { 
            get {
                if (startInfo == null) {
                    startInfo = new ProcessStartInfo(this);
                } 
                return startInfo;
            } 
            [ResourceExposure(ResourceScope.Machine)] 
            set {
                if (value == null) { 
                    throw new ArgumentNullException("value");
                }
                startInfo = value;
            } 
        }
 
#if !FEATURE_PAL 
        /// 
        ///     Returns the time the associated process was started. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStartTime)]
        public DateTime StartTime {
            get { 
                EnsureState(State.IsNt);
                return GetProcessTimes().StartTime; 
            } 
        }
#endif // !FEATURE_PAL 

        /// 
        ///   Represents the object used to marshal the event handler
        ///   calls issued as a result of a Process exit. Normally 
        ///   this property will  be set when the component is placed
        ///   inside a control or  a from, since those components are 
        ///   bound to a specific thread. 
        /// 
        [ 
        Browsable(false),
        DefaultValue(null),
        MonitoringDescription(SR.ProcessSynchronizingObject)
        ] 
        public ISynchronizeInvoke SynchronizingObject {
            get { 
               if (this.synchronizingObject == null && DesignMode) { 
                    IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
                    if (host != null) { 
                        object baseComponent = host.RootComponent;
                        if (baseComponent != null && baseComponent is ISynchronizeInvoke)
                            this.synchronizingObject = (ISynchronizeInvoke)baseComponent;
                    } 
                }
 
                return this.synchronizingObject; 
            }
 
            set {
                this.synchronizingObject = value;
            }
        } 

#if !FEATURE_PAL 
 
        /// 
        ///     
        ///       Gets the set of threads that are running in the associated
        ///       process.
        ///    
        ///  
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessThreads)]
        public ProcessThreadCollection Threads { 
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)]
            get { 
                if (threads == null) {
                    EnsureState(State.HaveProcessInfo);
                    int count = processInfo.threadInfoList.Count;
                    ProcessThread[] newThreadsArray = new ProcessThread[count]; 
                    for (int i = 0; i < count; i++) {
                        newThreadsArray[i] = new ProcessThread(isRemoteMachine, (ThreadInfo)processInfo.threadInfoList[i]); 
                    } 
                    ProcessThreadCollection newThreads = new ProcessThreadCollection(newThreadsArray);
                    threads = newThreads; 
                }
                return threads;
            }
        } 

        ///  
        ///     Returns the amount of time the associated process has spent utilizing the CPU. 
        ///     It is the sum of the  and
        ///     . 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessTotalProcessorTime)]
        public TimeSpan TotalProcessorTime {
            get { 
                EnsureState(State.IsNt);
                return GetProcessTimes().TotalProcessorTime; 
            } 
        }
 
        /// 
        ///     Returns the amount of time the associated process has spent running code
        ///     inside the application portion of the process (not the operating system core).
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessUserProcessorTime)]
        public TimeSpan UserProcessorTime { 
            get { 
                EnsureState(State.IsNt);
                return GetProcessTimes().UserProcessorTime; 
            }
        }

        ///  
        ///     Returns the amount of virtual memory that the associated process has requested.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.VirtualMemorySize64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
        public int VirtualMemorySize { 
            get {
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.virtualBytes);
            } 
        }
#endif // !FEATURE_PAL 
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long VirtualMemorySize64 {
            get {
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.virtualBytes; 
            }
        } 
 
        /// 
        ///     
        ///       Gets or sets whether the 
        ///       event is fired
        ///       when the process terminates.
        ///     
        /// 
        [Browsable(false), DefaultValue(false), MonitoringDescription(SR.ProcessEnableRaisingEvents)] 
        public bool EnableRaisingEvents { 
            get {
                return watchForExit; 
            }
            set {
                if (value != watchForExit) {
                    if (Associated) { 
                        if (value) {
                            OpenProcessHandle(); 
                            EnsureWatchingForExit(); 
                        }
                        else { 
                            StopWatchingForExit();
                        }
                    }
                    watchForExit = value; 
                }
            } 
        } 

 
        /// 
        ///    [To be supplied.]
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardInput)] 
        public StreamWriter StandardInput {
            get { 
                if (standardInput == null) { 
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardIn));
                } 

                return standardInput;
            }
        } 

        ///  
        ///    [To be supplied.] 
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardOutput)] 
        public StreamReader StandardOutput {
            get {
                if (standardOutput == null) {
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut)); 
                }
 
                if(outputStreamReadMode == StreamReadMode.undefined) { 
                    outputStreamReadMode = StreamReadMode.syncMode;
                } 
                else if (outputStreamReadMode != StreamReadMode.syncMode) {
                    throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
                }
 
                return standardOutput;
            } 
        } 

        ///  
        ///    [To be supplied.]
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessStandardError)]
        public StreamReader StandardError { 
            get {
                if (standardError == null) { 
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError)); 
                }
 
                if(errorStreamReadMode == StreamReadMode.undefined) {
                    errorStreamReadMode = StreamReadMode.syncMode;
                }
                else if (errorStreamReadMode != StreamReadMode.syncMode) { 
                    throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
                } 
 
                return standardError;
            } 
        }

#if !FEATURE_PAL
        ///  
        ///     Returns the total amount of physical memory the associated process.
        ///  
        [Obsolete("This property has been deprecated.  Please use System.Diagnostics.Process.WorkingSet64 instead.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
        public int WorkingSet { 
            get {
                EnsureState(State.HaveNtProcessInfo);
                return unchecked((int)processInfo.workingSet);
            } 
        }
#endif // !FEATURE_PAL 
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
        [System.Runtime.InteropServices.ComVisible(false)] 
        public long WorkingSet64 {
            get {
                EnsureState(State.HaveNtProcessInfo);
                return processInfo.workingSet; 
            }
        } 
 
        [Category("Behavior"), MonitoringDescription(SR.ProcessExited)]
        public event EventHandler Exited { 
            add {
                onExited += value;
            }
            remove { 
                onExited -= value;
            } 
        } 

#if !FEATURE_PAL 

        /// 
        ///    
        ///       Closes a process that has a user interface by sending a close message 
        ///       to its main window.
        ///     
        ///  
        [ResourceExposure(ResourceScope.Machine)]  // Review usages of this.
        [ResourceConsumption(ResourceScope.Machine)] 
        public bool CloseMainWindow() {
            IntPtr mainWindowHandle = MainWindowHandle;
            if (mainWindowHandle == (IntPtr)0) return false;
            int style = NativeMethods.GetWindowLong(new HandleRef(this, mainWindowHandle), NativeMethods.GWL_STYLE); 
            if ((style & NativeMethods.WS_DISABLED) != 0) return false;
            NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); 
            return true; 
        }
 
#endif // !FEATURE_PAL

        /// 
        ///     Release the temporary handle we used to get process information. 
        ///     If we used the process handle stored in the process object (we have all access to the handle,) don't release it.
        ///  
        ///  
        void ReleaseProcessHandle(SafeProcessHandle handle) {
            if (handle == null) { 
                return;
            }

            if (haveProcessHandle && handle == m_processHandle) { 
                return;
            } 
            Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process)"); 
            handle.Close();
        } 

        /// 
        ///     This is called from the threadpool when a proces exits.
        ///  
        /// 
        private void CompletionCallback(object context, bool wasSignaled) { 
            StopWatchingForExit(); 
            RaiseOnExited();
        } 

        /// 
        /// 
        ///     
        ///       Free any resources associated with this component.
        ///     
        ///  
        protected override void Dispose(bool disposing) {
            if( !disposed) { 
                if (disposing) {
                    //Dispose managed and unmanaged resources
                    Close();
                } 
                this.disposed = true;
                base.Dispose(disposing); 
            } 
        }
 
        /// 
        ///    
        ///       Frees any resources associated with this component.
        ///     
        /// 
        public void Close() { 
            if (Associated) { 
                if (haveProcessHandle) {
                    StopWatchingForExit(); 
                    Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process) in Close()");
                    m_processHandle.Close();
                    m_processHandle = null;
                    haveProcessHandle = false; 
                }
                haveProcessId = false; 
                isRemoteMachine = false; 
                machineName = ".";
                raisedOnExited = false; 

                //Don't call close on the Readers and writers
                //since they might be referenced by somebody else while the
                //process is still alive but this method called. 
                standardOutput = null;
                standardInput = null; 
                standardError = null; 

                output = null; 
                error = null;
	

                Refresh(); 
            }
        } 
 
        /// 
        ///     Helper method for checking preconditions when accessing properties. 
        /// 
        /// 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        void EnsureState(State state) {
 
            if ((state & State.IsWin2k) != (State)0) { 
#if !FEATURE_PAL
                if (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5) 
#endif // !FEATURE_PAL
                    throw new PlatformNotSupportedException(SR.GetString(SR.Win2kRequired));
            }
 
            if ((state & State.IsNt) != (State)0) {
#if !FEATURE_PAL 
                if (OperatingSystem.Platform != PlatformID.Win32NT) 
#endif // !FEATURE_PAL
                    throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired)); 
            }

            if ((state & State.Associated) != (State)0)
                if (!Associated) 
                    throw new InvalidOperationException(SR.GetString(SR.NoAssociatedProcess));
 
            if ((state & State.HaveId) != (State)0) { 
                if (!haveProcessId) {
#if !FEATURE_PAL 
                    if (haveProcessHandle) {
                        SetProcessId(ProcessManager.GetProcessIdFromHandle(m_processHandle));
                     }
                    else { 
                        EnsureState(State.Associated);
                        throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired)); 
                    } 
#else
                    EnsureState(State.Associated); 
                    throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
#endif // !FEATURE_PAL
                }
            } 

            if ((state & State.IsLocal) != (State)0 && isRemoteMachine) { 
                    throw new NotSupportedException(SR.GetString(SR.NotSupportedRemote)); 
            }
 
            if ((state & State.HaveProcessInfo) != (State)0) {
#if !FEATURE_PAL
                if (processInfo == null) {
                    if ((state & State.HaveId) == (State)0) EnsureState(State.HaveId); 
                    ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
                    for (int i = 0; i < processInfos.Length; i++) { 
                        if (processInfos[i].processId == processId) { 
                            this.processInfo = processInfos[i];
                            break; 
                        }
                    }
                    if (processInfo == null) {
                        throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo)); 
                    }
                } 
#else 
                throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
#endif // !FEATURE_PAL 
            }

            if ((state & State.Exited) != (State)0) {
                if (!HasExited) { 
                    throw new InvalidOperationException(SR.GetString(SR.WaitTillExit));
                } 
 
                if (!haveProcessHandle) {
                    throw new InvalidOperationException(SR.GetString(SR.NoProcessHandle)); 
                }
            }
        }
 
        /// 
        ///     Make sure we are watching for a process exit. 
        ///  
        /// 
        void EnsureWatchingForExit() { 
            if (!watchingForExit) {
                lock (this) {
                    if (!watchingForExit) {
                        Debug.Assert(haveProcessHandle, "Process.EnsureWatchingForExit called with no process handle"); 
                        Debug.Assert(Associated, "Process.EnsureWatchingForExit called with no associated process");
                        watchingForExit = true; 
                        try { 
                            this.waitHandle = new ProcessWaitHandle(m_processHandle);
                            this.registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(this.waitHandle, 
                                new WaitOrTimerCallback(this.CompletionCallback), null, -1, true);
                        }
                        catch {
                            watchingForExit = false; 
                            throw;
                        } 
                    } 
                }
            } 
        }

#if !FEATURE_PAL
 
        /// 
        ///     Make sure we have obtained the min and max working set limits. 
        ///  
        /// 
        void EnsureWorkingSetLimits() { 
            EnsureState(State.IsNt);
            if (!haveWorkingSetLimits) {
                SafeProcessHandle handle = null;
                try { 
                    handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION);
                    IntPtr min; 
                    IntPtr max; 
                    if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
                        throw new Win32Exception(); 
                    }
                    minWorkingSet = min;
                    maxWorkingSet = max;
                    haveWorkingSetLimits = true; 
                }
                finally { 
                    ReleaseProcessHandle(handle); 
                }
            } 
        }

        public static void EnterDebugMode() {
            if (ProcessManager.IsNt) { 
                SetPrivilege("SeDebugPrivilege", NativeMethods.SE_PRIVILEGE_ENABLED);
            } 
        } 

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        private static void SetPrivilege(string privilegeName, int attrib) {
            IntPtr hToken = (IntPtr)0;
            NativeMethods.LUID debugValue = new NativeMethods.LUID(); 

            // this is only a "pseudo handle" to the current process - no need to close it later 
            IntPtr processHandle = NativeMethods.GetCurrentProcess(); 

            // get the process token so we can adjust the privilege on it.  We DO need to 
            // close the token when we're done with it.
            if (!NativeMethods.OpenProcessToken(new HandleRef(null, processHandle), NativeMethods.TOKEN_ADJUST_PRIVILEGES, out hToken)) {
                throw new Win32Exception();
            } 

            try { 
                if (!NativeMethods.LookupPrivilegeValue(null, privilegeName, out debugValue)) { 
                    throw new Win32Exception();
                } 

                NativeMethods.TokenPrivileges tkp = new NativeMethods.TokenPrivileges();
                tkp.Luid = debugValue;
                tkp.Attributes = attrib; 

                NativeMethods.AdjustTokenPrivileges(new HandleRef(null, hToken), false, tkp, 0, IntPtr.Zero, IntPtr.Zero); 
 
                // AdjustTokenPrivileges can return true even if it failed to
                // set the privilege, so we need to use GetLastError 
                if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_SUCCESS) {
                    throw new Win32Exception();
                }
            } 
            finally {
                Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(processToken)"); 
                SafeNativeMethods.CloseHandle(new HandleRef(null, hToken)); 
            }
        } 

        /// 
        ///    [To be supplied.]
        ///  
        public static void LeaveDebugMode() {
            if (ProcessManager.IsNt) { 
                SetPrivilege("SeDebugPrivilege", 0); 
            }
        } 

        /// 
        ///    
        ///       Returns a new  component given a process identifier and 
        ///       the name of a computer in the network.
        ///     
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process GetProcessById(int processId, string machineName) {
            if (!ProcessManager.IsProcessRunning(processId, machineName)) {
                throw new ArgumentException(SR.GetString(SR.MissingProccess, processId.ToString(CultureInfo.CurrentCulture)));
            } 

            return new Process(machineName, ProcessManager.IsRemoteMachine(machineName), processId, null); 
        } 

        ///  
        ///    
        ///       Returns a new  component given the
        ///       identifier of a process on the local computer.
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process GetProcessById(int processId) {
            return GetProcessById(processId, "."); 
        }

        /// 
        ///     
        ///       Creates an array of  components that are
        ///       associated 
        ///       with process resources on the 
        ///       local computer. These process resources share the specified process name.
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public static Process[] GetProcessesByName(string processName) { 
            return GetProcessesByName(processName, ".");
        } 
 
        /// 
        ///     
        ///       Creates an array of  components that are associated with process resources on a
        ///       remote computer. These process resources share the specified process name.
        ///    
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process[] GetProcessesByName(string processName, string machineName) { 
            if (processName == null) processName = String.Empty;
            Process[] procs = GetProcesses(machineName); 
            ArrayList list = new ArrayList();

            for(int i = 0; i < procs.Length; i++) {
                if( String.Equals(processName, procs[i].ProcessName, StringComparison.OrdinalIgnoreCase)) { 
                    list.Add( procs[i]);
                } 
            } 

            Process[] temp = new Process[list.Count]; 
            list.CopyTo(temp, 0);
            return temp;
        }
 
        /// 
        ///     
        ///       Creates a new  
        ///       component for each process resource on the local computer.
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public static Process[] GetProcesses() { 
            return GetProcesses(".");
        } 
 
        /// 
        ///     
        ///       Creates a new 
        ///       component for each
        ///       process resource on the specified computer.
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process[] GetProcesses(string machineName) {
            bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName); 
            ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
            Process[] processes = new Process[processInfos.Length];
            for (int i = 0; i < processInfos.Length; i++) {
                ProcessInfo processInfo = processInfos[i]; 
                processes[i] = new Process(machineName, isRemoteMachine, processInfo.processId, processInfo);
            } 
            Debug.WriteLineIf(processTracing.TraceVerbose, "Process.GetProcesses(" + machineName + ")"); 
#if DEBUG
            if (processTracing.TraceVerbose) { 
                Debug.Indent();
                for (int i = 0; i < processInfos.Length; i++) {
                    Debug.WriteLine(processes[i].Id + ": " + processes[i].ProcessName);
                } 
                Debug.Unindent();
            } 
#endif 
            return processes;
        } 

#endif // !FEATURE_PAL

        ///  
        ///    
        ///       Returns a new  
        ///       component and associates it with the current active process. 
        ///    
        ///  
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Process)]
        public static Process GetCurrentProcess() {
            return new Process(".", false, NativeMethods.GetCurrentProcessId(), null); 
        }
 
        ///  
        ///    
        ///       Raises the  event. 
        ///    
        /// 
        protected void OnExited() {
            EventHandler exited = onExited; 
            if (exited != null) {
                if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired) 
                    this.SynchronizingObject.BeginInvoke(exited, new object[]{this, EventArgs.Empty}); 
                else
                   exited(this, EventArgs.Empty); 
            }
        }

        ///  
        ///     Gets a short-term handle to the process, with the given access.
        ///     If a handle is stored in current process object, then use it. 
        ///     Note that the handle we stored in current process object will have all access we need. 
        /// 
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        SafeProcessHandle GetProcessHandle(int access, bool throwIfExited) {
            Debug.WriteLineIf(processTracing.TraceVerbose, "GetProcessHandle(access = 0x" + access.ToString("X8", CultureInfo.InvariantCulture) + ", throwIfExited = " + throwIfExited + ")"); 
#if DEBUG
            if (processTracing.TraceVerbose) { 
                StackFrame calledFrom = new StackTrace(true).GetFrame(0); 
                Debug.WriteLine("   called from " + calledFrom.GetFileName() + ", line " + calledFrom.GetFileLineNumber());
            } 
#endif
            if (haveProcessHandle) {
                if (throwIfExited) {
                    // Since haveProcessHandle is true, we know we have the process handle 
                    // open with at least SYNCHRONIZE access, so we can wait on it with
                    // zero timeout to see if the process has exited. 
                    ProcessWaitHandle waitHandle = null; 
                    try {
                        waitHandle = new ProcessWaitHandle(m_processHandle); 
                        if (waitHandle.WaitOne(0, false)) {
                            if (haveProcessId)
                                throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
                            else 
                                throw new InvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
                        } 
                    } 
                    finally {
                        if( waitHandle != null) { 
                            waitHandle.Close();
                        }
                    }
                } 
                return m_processHandle;
            } 
            else { 
                EnsureState(State.HaveId | State.IsLocal);
                SafeProcessHandle handle = SafeProcessHandle.InvalidHandle; 
#if !FEATURE_PAL
                handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
#else
                IntPtr pseudohandle = NativeMethods.GetCurrentProcess(); 
                // Get a real handle
                if (!NativeMethods.DuplicateHandle (new HandleRef(this, pseudohandle), 
                                                    new HandleRef(this, pseudohandle), 
                                                    new HandleRef(this, pseudohandle),
                                                    out handle, 
                                                    0,
                                                    false,
                                                    NativeMethods.DUPLICATE_SAME_ACCESS |
                                                    NativeMethods.DUPLICATE_CLOSE_SOURCE)) { 
                    throw new Win32Exception();
                } 
#endif // !FEATURE_PAL 
                if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) {
                    if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) { 
                        throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
                    }
                }
                return handle; 
            }
 
        } 

        ///  
        ///     Gets a short-term handle to the process, with the given access.  If a handle exists,
        ///     then it is reused.  If the process has exited, it throws an exception.
        /// 
        ///  
        SafeProcessHandle GetProcessHandle(int access) {
            return GetProcessHandle(access, true); 
        } 

        ///  
        ///     Opens a long-term handle to the process, with all access.  If a handle exists,
        ///     then it is reused.  If the process has exited, it throws an exception.
        /// 
        ///  
        SafeProcessHandle OpenProcessHandle() {
            return OpenProcessHandle(NativeMethods.PROCESS_ALL_ACCESS); 
        } 

        SafeProcessHandle OpenProcessHandle(Int32 access) { 
            if (!haveProcessHandle) {
                //Cannot open a new process handle if the object has been disposed, since finalization has been suppressed.
                if (this.disposed) {
                    throw new ObjectDisposedException(GetType().Name); 
                }
 
                SetProcessHandle(GetProcessHandle(access)); 
            }
            return m_processHandle; 
        }

        /// 
        ///     Raise the Exited event, but make sure we don't do it more than once. 
        /// 
        ///  
        void RaiseOnExited() { 
            if (!raisedOnExited) {
                lock (this) { 
                    if (!raisedOnExited) {
                        raisedOnExited = true;
                        OnExited();
                    } 
                }
            } 
        } 

        ///  
        ///    
        ///       Discards any information about the associated process
        ///       that has been cached inside the process component. After  is called, the
        ///       first request for information for each property causes the process component 
        ///       to obtain a new value from the associated process.
        ///     
        ///  
        public void Refresh() {
            processInfo = null; 
#if !FEATURE_PAL
            threads = null;
            modules = null;
#endif // !FEATURE_PAL 
            mainWindowTitle = null;
            exited = false; 
            signaled = false; 
            haveMainWindow = false;
            haveWorkingSetLimits = false; 
            haveProcessorAffinity = false;
            havePriorityClass = false;
            haveExitTime = false;
            haveResponding = false; 
            havePriorityBoostEnabled = false;
        } 
 
        /// 
        ///     Helper to associate a process handle with this component. 
        /// 
        /// 
        void SetProcessHandle(SafeProcessHandle processHandle) {
            this.m_processHandle = processHandle; 
            this.haveProcessHandle = true;
            if (watchForExit) { 
                EnsureWatchingForExit(); 
            }
        } 

        /// 
        ///     Helper to associate a process id with this component.
        ///  
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        void SetProcessId(int processId) { 
            this.processId = processId;
            this.haveProcessId = true; 
        }

#if !FEATURE_PAL
 
        /// 
        ///     Helper to set minimum or maximum working set limits. 
        ///  
        /// 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        void SetWorkingSetLimits(object newMin, object newMax) {
            EnsureState(State.IsNt);
 
            SafeProcessHandle handle = null;
            try { 
                handle = GetProcessHandle(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_SET_QUOTA); 
                IntPtr min;
                IntPtr max; 
                if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) {
                    throw new Win32Exception();
                }
 
                if (newMin != null) {
                    min = (IntPtr)newMin; 
                } 

                if (newMax != null) { 
                    max = (IntPtr)newMax;
                }

                if ((long)min > (long)max) { 
                    if (newMin != null) {
                        throw new ArgumentException(SR.GetString(SR.BadMinWorkset)); 
                    } 
                    else {
                        throw new ArgumentException(SR.GetString(SR.BadMaxWorkset)); 
                    }
                }

                if (!NativeMethods.SetProcessWorkingSetSize(handle, min, max)) { 
                    throw new Win32Exception();
                } 
 
                // The value may be rounded/changed by the OS, so go get it
                if (!NativeMethods.GetProcessWorkingSetSize(handle, out min, out max)) { 
                    throw new Win32Exception();
                }
                minWorkingSet = min;
                maxWorkingSet = max; 
                haveWorkingSetLimits = true;
            } 
            finally { 
                ReleaseProcessHandle(handle);
            } 
        }

#endif // !FEATURE_PAL
 
        /// 
        ///     
        ///       Starts a process specified by the  property of this  
        ///       component and associates it with the
        ///     . If a process resource is reused 
        ///       rather than started, the reused process is associated with this 
        ///       component.
        ///    
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        public bool Start() { 
            Close();
            ProcessStartInfo startInfo = StartInfo; 
            if (startInfo.FileName.Length == 0)
                throw new InvalidOperationException(SR.GetString(SR.FileNameMissing));

            if (startInfo.UseShellExecute) { 
#if !FEATURE_PAL
                return StartWithShellExecuteEx(startInfo); 
#else 
                throw new InvalidOperationException(SR.GetString(SR.net_perm_invalid_val, "StartInfo.UseShellExecute", true));
#endif // !FEATURE_PAL 
            } else {
                return StartWithCreateProcess(startInfo);
            }
        } 

 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) { 
            bool ret = NativeMethods.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize);
            if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid) {
                throw new Win32Exception();
            } 
        }
 
        // Using synchronous Anonymous pipes for process input/output redirection means we would end up 
        // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
        // it will take advantage of the NT IO completion port infrastructure. But we can't really use 
        // Overlapped I/O for process input/output as it would break Console apps (managed Console class
        // methods such as WriteLine as well as native CRT functions like printf) which are making an
        // assumption that the console standard handles (obtained via GetStdHandle()) are opened
        // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously! 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) { 
            NativeMethods.SECURITY_ATTRIBUTES securityAttributesParent = new NativeMethods.SECURITY_ATTRIBUTES();
            securityAttributesParent.bInheritHandle = true; 

            SafeFileHandle hTmp = null;
            try {
                if (parentInputs) { 
                    CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);
                } 
                else { 
                    CreatePipeWithSecurityAttributes(out hTmp,
                                                          out childHandle, 
                                                          securityAttributesParent,
                                                          0);
                }
                // Duplicate the parent handle to be non-inheritable so that the child process 
                // doesn't have access. This is done for correctness sake, exact reason is unclear.
                // One potential theory is that child process can do something brain dead like 
                // closing the parent end of the pipe and there by getting into a blocking situation 
                // as parent will not be draining the pipe at the other end anymore.
                if (!NativeMethods.DuplicateHandle(new HandleRef(this, NativeMethods.GetCurrentProcess()), 
                                                                   hTmp,
                                                                   new HandleRef(this, NativeMethods.GetCurrentProcess()),
                                                                   out parentHandle,
                                                                   0, 
                                                                   false,
                                                                   NativeMethods.DUPLICATE_SAME_ACCESS)) { 
                    throw new Win32Exception(); 
                }
            } 
            finally {
                if( hTmp != null && !hTmp.IsInvalid) {
                    hTmp.Close();
                } 
            }
        } 
 
        private static StringBuilder BuildCommandLine(string executableFileName, string arguments) {
            // Construct a StringBuilder with the appropriate command line 
            // to pass to CreateProcess.  If the filename isn't already
            // in quotes, we quote it here.  This prevents some security
            // problems (it specifies exactly which part of the string
            // is the file to execute). 
            StringBuilder commandLine = new StringBuilder();
            string fileName = executableFileName.Trim(); 
            bool fileNameIsQuoted = (fileName.StartsWith("\"", StringComparison.Ordinal) && fileName.EndsWith("\"", StringComparison.Ordinal)); 
            if (!fileNameIsQuoted) {
                commandLine.Append("\""); 
            }

            commandLine.Append(fileName);
 
            if (!fileNameIsQuoted) {
                commandLine.Append("\""); 
            } 

            if (!String.IsNullOrEmpty(arguments)) { 
                commandLine.Append(" ");
                commandLine.Append(arguments);
            }
 
            return commandLine;
        } 
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        private bool StartWithCreateProcess(ProcessStartInfo startInfo) {
            if( startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) {
                throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed));
            } 

            if( startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) { 
                throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed)); 
            }
 
            // See knowledge base article Q190351 for an explanation of the following code.  Noteworthy tricky points:
            //    * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
            //      that the child process can not close them
            //    * CreateProcess allows you to redirect all or none of the standard IO handles, so we use 
            //      GetStdHandle for the handles that are not being redirected
 
            //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed. 
            if (this.disposed) {
                throw new ObjectDisposedException(GetType().Name); 
            }

            StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
 
            NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO();
            SafeNativeMethods.PROCESS_INFORMATION processInfo = new SafeNativeMethods.PROCESS_INFORMATION(); 
            SafeProcessHandle procSH = new SafeProcessHandle(); 
            SafeThreadHandle threadSH = new SafeThreadHandle();
            bool retVal; 
            int errorCode = 0;
            // handles used in parent process
            SafeFileHandle standardInputWritePipeHandle = null;
            SafeFileHandle standardOutputReadPipeHandle = null; 
            SafeFileHandle standardErrorReadPipeHandle = null;
            GCHandle environmentHandle = new GCHandle(); 
            lock (s_CreateProcessLock) { 
            try {
                // set up the streams 
                if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) {
                    if (startInfo.RedirectStandardInput) {
                        CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
                        } else { 
                        startupInfo.hStdInput  =  new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);
                    } 
 
                    if (startInfo.RedirectStandardOutput) {
                        CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false); 
                        } else {
                        startupInfo.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_OUTPUT_HANDLE), false);
                    }
 
                    if (startInfo.RedirectStandardError) {
                        CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false); 
                        } else { 
                        startupInfo.hStdError = new SafeFileHandle(NativeMethods.GetStdHandle(NativeMethods.STD_ERROR_HANDLE), false);
                    } 

                    startupInfo.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
                }
 
                // set up the creation flags paramater
                int creationFlags = 0; 
#if !FEATURE_PAL 
                if (startInfo.CreateNoWindow)  creationFlags |= NativeMethods.CREATE_NO_WINDOW;
#endif // !FEATURE_PAL 

                // set up the environment block parameter
                IntPtr environmentPtr = (IntPtr)0;
                if (startInfo.environmentVariables != null) { 
                    bool unicode = false;
#if !FEATURE_PAL 
                    if (ProcessManager.IsNt) { 
                        creationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
                        unicode = true; 
                    }
#endif // !FEATURE_PAL

                    byte[] environmentBytes = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode); 
                    environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
                    environmentPtr = environmentHandle.AddrOfPinnedObject(); 
                } 

                string workingDirectory = startInfo.WorkingDirectory; 
                if (workingDirectory == string.Empty)
                    workingDirectory = Environment.CurrentDirectory;

#if !FEATURE_PAL 
                if (startInfo.UserName.Length != 0) {
                    NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0; 
                    if( startInfo.LoadUserProfile) { 
                        logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
                    } 

                    IntPtr password = IntPtr.Zero;
                    try {
                        if( startInfo.Password == null) { 
                            password = Marshal.StringToCoTaskMemUni(String.Empty);
                            } else { 
                            password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password); 
                        }
 
                        RuntimeHelpers.PrepareConstrainedRegions();
                        try {} finally {
                           retVal = NativeMethods.CreateProcessWithLogonW(
                                   startInfo.UserName, 
                                   startInfo.Domain,
                                   password, 
                                   logonFlags, 
                                   null,            // we don't need this since all the info is in commandLine
                                   commandLine, 
                                   creationFlags,
                                   environmentPtr,
                                   workingDirectory,
                                   startupInfo,        // pointer to STARTUPINFO 
                                   processInfo         // pointer to PROCESS_INFORMATION
                               ); 
                           if (!retVal) 
                              errorCode = Marshal.GetLastWin32Error();
                           if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) 
                              procSH.InitialSetHandle(processInfo.hProcess);
                           if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                              threadSH.InitialSetHandle(processInfo.hThread);
                        } 
                        if (!retVal){
                                if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) { 
                                throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication)); 
                            }
 
                            throw new Win32Exception(errorCode);
                        }
                        } finally {
                        if( password != IntPtr.Zero) { 
                            Marshal.ZeroFreeCoTaskMemUnicode(password);
                        } 
                    } 
                    } else {
#endif // !FEATURE_PAL 
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try {} finally {
                       retVal = NativeMethods.CreateProcess (
                               null,               // we don't need this since all the info is in commandLine 
                               commandLine,        // pointer to the command line string
                               null,               // pointer to process security attributes, we don't need to inheriat the handle 
                               null,               // pointer to thread security attributes 
                               true,               // handle inheritance flag
                               creationFlags,      // creation flags 
                               environmentPtr,     // pointer to new environment block
                               workingDirectory,   // pointer to current directory name
                               startupInfo,        // pointer to STARTUPINFO
                               processInfo         // pointer to PROCESS_INFORMATION 
                           );
                       if (!retVal) 
                              errorCode = Marshal.GetLastWin32Error(); 
                       if ( processInfo.hProcess!= (IntPtr)0 && processInfo.hProcess!= (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                           procSH.InitialSetHandle(processInfo.hProcess); 
                       if ( processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                          threadSH.InitialSetHandle(processInfo.hThread);
                    }
                    if (!retVal) { 
                            if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) {
                          throw new Win32Exception(errorCode, SR.GetString(SR.InvalidApplication)); 
                       } 
                        throw new Win32Exception(errorCode);
                    } 
#if !FEATURE_PAL
                }
#endif
                } finally { 
                // free environment block
                if (environmentHandle.IsAllocated) { 
                    environmentHandle.Free(); 
                }
 
                startupInfo.Dispose();
            }
            }
 
            if (startInfo.RedirectStandardInput) {
                standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096); 
                standardInput.AutoFlush = true; 
            }
            if (startInfo.RedirectStandardOutput) { 
                Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
                standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError) { 
                Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
                standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096); 
            } 

            bool ret = false; 
            if (!procSH.IsInvalid) {
                SetProcessHandle(procSH);
                SetProcessId(processInfo.dwProcessId);
                threadSH.Close(); 
                ret = true;
            } 
 
            return ret;
 
        }

#if !FEATURE_PAL
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        private bool StartWithShellExecuteEx(ProcessStartInfo startInfo) { 
            //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
            if (this.disposed) 
                throw new ObjectDisposedException(GetType().Name);

            if( !String.IsNullOrEmpty(startInfo.UserName) || (startInfo.Password != null) ) {
                throw new InvalidOperationException(SR.GetString(SR.CantStartAsUser)); 
            }
 
            if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) { 
                throw new InvalidOperationException(SR.GetString(SR.CantRedirectStreams));
            } 

            if (startInfo.StandardErrorEncoding != null) {
                throw new InvalidOperationException(SR.GetString(SR.StandardErrorEncodingNotAllowed));
            } 

            if (startInfo.StandardOutputEncoding != null) { 
                throw new InvalidOperationException(SR.GetString(SR.StandardOutputEncodingNotAllowed)); 
            }
 
            // can't set env vars with ShellExecuteEx...
            if (startInfo.environmentVariables != null) {
                throw new InvalidOperationException(SR.GetString(SR.CantUseEnvVars));
            } 

            NativeMethods.ShellExecuteInfo shellExecuteInfo = new NativeMethods.ShellExecuteInfo(); 
            shellExecuteInfo.fMask = NativeMethods.SEE_MASK_NOCLOSEPROCESS; 
            if (startInfo.ErrorDialog) {
                shellExecuteInfo.hwnd = startInfo.ErrorDialogParentHandle; 
            }
            else {
                shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_NO_UI;
            } 

            switch (startInfo.WindowStyle) { 
                case ProcessWindowStyle.Hidden: 
                    shellExecuteInfo.nShow = NativeMethods.SW_HIDE;
                    break; 
                case ProcessWindowStyle.Minimized:
                    shellExecuteInfo.nShow = NativeMethods.SW_SHOWMINIMIZED;
                    break;
                case ProcessWindowStyle.Maximized: 
                    shellExecuteInfo.nShow = NativeMethods.SW_SHOWMAXIMIZED;
                    break; 
                default: 
                    shellExecuteInfo.nShow = NativeMethods.SW_SHOWNORMAL;
                    break; 
            }


            try { 
                if (startInfo.FileName.Length != 0)
                    shellExecuteInfo.lpFile = Marshal.StringToHGlobalAuto(startInfo.FileName); 
                if (startInfo.Verb.Length != 0) 
                    shellExecuteInfo.lpVerb = Marshal.StringToHGlobalAuto(startInfo.Verb);
                if (startInfo.Arguments.Length != 0) 
                    shellExecuteInfo.lpParameters = Marshal.StringToHGlobalAuto(startInfo.Arguments);
                if (startInfo.WorkingDirectory.Length != 0)
                    shellExecuteInfo.lpDirectory = Marshal.StringToHGlobalAuto(startInfo.WorkingDirectory);
 
                shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_DDEWAIT;
 
                ShellExecuteHelper executeHelper = new ShellExecuteHelper(shellExecuteInfo); 
                if (!executeHelper.ShellExecuteOnSTAThread()) {
                    int error = executeHelper.ErrorCode; 
                    if (error == 0) {
                        switch ((long)shellExecuteInfo.hInstApp) {
                            case NativeMethods.SE_ERR_FNF: error = NativeMethods.ERROR_FILE_NOT_FOUND; break;
                            case NativeMethods.SE_ERR_PNF: error = NativeMethods.ERROR_PATH_NOT_FOUND; break; 
                            case NativeMethods.SE_ERR_ACCESSDENIED: error = NativeMethods.ERROR_ACCESS_DENIED; break;
                            case NativeMethods.SE_ERR_OOM: error = NativeMethods.ERROR_NOT_ENOUGH_MEMORY; break; 
                            case NativeMethods.SE_ERR_DDEFAIL: 
                            case NativeMethods.SE_ERR_DDEBUSY:
                            case NativeMethods.SE_ERR_DDETIMEOUT: error = NativeMethods.ERROR_DDE_FAIL; break; 
                            case NativeMethods.SE_ERR_SHARE: error = NativeMethods.ERROR_SHARING_VIOLATION; break;
                            case NativeMethods.SE_ERR_NOASSOC: error = NativeMethods.ERROR_NO_ASSOCIATION; break;
                            case NativeMethods.SE_ERR_DLLNOTFOUND: error = NativeMethods.ERROR_DLL_NOT_FOUND; break;
                            default: error = (int)shellExecuteInfo.hInstApp; break; 
                        }
                    } 
                    if( error == NativeMethods.ERROR_BAD_EXE_FORMAT || error == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH) { 
                        throw new Win32Exception(error, SR.GetString(SR.InvalidApplication));
                    } 
                    throw new Win32Exception(error);
                }

            } 
            finally {
                if (shellExecuteInfo.lpFile != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpFile); 
                if (shellExecuteInfo.lpVerb != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpVerb); 
                if (shellExecuteInfo.lpParameters != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpParameters);
                if (shellExecuteInfo.lpDirectory != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpDirectory); 
            }

            if (shellExecuteInfo.hProcess != (IntPtr)0) {
                SafeProcessHandle handle = new SafeProcessHandle(shellExecuteInfo.hProcess); 
                SetProcessHandle(handle);
                return true; 
            } 

            return false; 
        }

        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process Start( string fileName, string userName, SecureString password, string domain ) {
            ProcessStartInfo startInfo = new ProcessStartInfo(fileName); 
            startInfo.UserName = userName; 
            startInfo.Password = password;
            startInfo.Domain = domain; 
            startInfo.UseShellExecute = false;
            return Start(startInfo);
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process Start( string fileName, string arguments, string userName, SecureString password, string domain ) { 
            ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
            startInfo.UserName = userName; 
            startInfo.Password = password;
            startInfo.Domain = domain;
            startInfo.UseShellExecute = false;
            return Start(startInfo); 
        }
 
 
#endif // !FEATURE_PAL
 
        /// 
        ///    
        ///       Starts a process resource by specifying the name of a
        ///       document or application file. Associates the process resource with a new  
        ///       component.
        ///     
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static Process Start(string fileName) {
            return Start(new ProcessStartInfo(fileName));
        }
 
        /// 
        ///     
        ///       Starts a process resource by specifying the name of an 
        ///       application and a set of command line arguments. Associates the process resource
        ///       with a new  
        ///       component.
        ///    
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static Process Start(string fileName, string arguments) { 
            return Start(new ProcessStartInfo(fileName, arguments)); 
        }
 
        /// 
        ///    
        ///       Starts a process resource specified by the process start
        ///       information passed in, for example the file name of the process to start. 
        ///       Associates the process resource with a new 
        ///       component. 
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static Process Start(ProcessStartInfo startInfo) {
            Process process = new Process();
            if (startInfo == null) throw new ArgumentNullException("startInfo"); 
            process.StartInfo = startInfo;
            if (process.Start()) { 
                return process; 
            }
            return null; 
        }

        /// 
        ///     
        ///       Stops the
        ///       associated process immediately. 
        ///     
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public void Kill() {
            SafeProcessHandle handle = null;
            try { 
                handle = GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
                if (!NativeMethods.TerminateProcess(handle, -1)) 
                    throw new Win32Exception(); 
            }
            finally { 
                ReleaseProcessHandle(handle);
            }
        }
 
        /// 
        ///     Make sure we are not watching for process exit. 
        ///  
        /// 
        void StopWatchingForExit() { 
            if (watchingForExit) {
                lock (this) {
                    if (watchingForExit) {
                        watchingForExit = false; 
                        registeredWaitHandle.Unregister(null);
                        waitHandle.Close(); 
                        waitHandle = null; 
                        registeredWaitHandle = null;
                    } 
                }
            }
        }
 
        public override string ToString() {
#if !FEATURE_PAL 
            if (Associated) { 
                string processName  =  String.Empty;
                // 
                // On windows 9x, we can't map a handle to an id.
                // So ProcessName will throw. We shouldn't throw in Process.ToString though.
                // Process.GetProcesses should be used to get all the processes on the machine.
                // The processes returned from it will have a nice name. 
                //
                try { 
                    processName = this.ProcessName; 
                }
                catch(PlatformNotSupportedException) { 
                }
                if( processName.Length != 0) {
                    return String.Format(CultureInfo.CurrentCulture, "{0} ({1})", base.ToString(), processName);
                } 
                return base.ToString();
            } 
            else 
#endif // !FEATURE_PAL
                return base.ToString(); 
        }

        /// 
        ///     
        ///       Instructs the  component to wait the specified number of milliseconds for the associated process to exit.
        ///     
        ///  
        public bool WaitForExit(int milliseconds) {
            SafeProcessHandle handle = null; 
	     bool exited;
            ProcessWaitHandle processWaitHandle = null;
            try {
                handle = GetProcessHandle(NativeMethods.SYNCHRONIZE, false); 
                if (handle.IsInvalid) {
                    exited = true; 
                } 
                else {
                    processWaitHandle = new ProcessWaitHandle(handle); 
                    if( processWaitHandle.WaitOne(milliseconds, false)) {
                        exited = true;
                        signaled = true;
                    } 
                    else {
                        exited = false; 
                        signaled = false; 
                    }
                } 
            }
            finally {
                if( processWaitHandle != null) {
                    processWaitHandle.Close(); 
                }
 
                // If we have a hard timeout, we cannot wait for the streams 
                if( output != null && milliseconds == -1) {
                    output.WaitUtilEOF(); 
                }

                if( error != null && milliseconds == -1) {
                    error.WaitUtilEOF(); 
                }
 
                ReleaseProcessHandle(handle); 

            } 

            if (exited && watchForExit) {
                RaiseOnExited();
            } 
			
            return exited; 
        } 

        ///  
        ///    
        ///       Instructs the  component to wait
        ///       indefinitely for the associated process to exit.
        ///     
        /// 
        public void WaitForExit() { 
            WaitForExit(-1); 
        }
 
#if !FEATURE_PAL

        /// 
        ///     
        ///       Causes the  component to wait the
        ///       specified number of milliseconds for the associated process to enter an 
        ///       idle state. 
        ///       This is only applicable for processes with a user interface,
        ///       therefore a message loop. 
        ///    
        /// 
        public bool WaitForInputIdle(int milliseconds) {
            SafeProcessHandle handle = null; 
            bool idle;
            try { 
                handle = GetProcessHandle(NativeMethods.SYNCHRONIZE | NativeMethods.PROCESS_QUERY_INFORMATION); 
                int ret = NativeMethods.WaitForInputIdle(handle, milliseconds);
                switch (ret) { 
                    case NativeMethods.WAIT_OBJECT_0:
                        idle = true;
                        break;
                    case NativeMethods.WAIT_TIMEOUT: 
                        idle = false;
                        break; 
                    case NativeMethods.WAIT_FAILED: 
                    default:
                        throw new InvalidOperationException(SR.GetString(SR.InputIdleUnkownError)); 
                }
            }
            finally {
                ReleaseProcessHandle(handle); 
            }
            return idle; 
        } 

        ///  
        ///    
        ///       Instructs the  component to wait
        ///       indefinitely for the associated process to enter an idle state. This
        ///       is only applicable for processes with a user interface, therefore a message loop. 
        ///    
        ///  
        public bool WaitForInputIdle() { 
            return WaitForInputIdle(Int32.MaxValue);
        } 

#endif // !FEATURE_PAL

        // Support for working asynchronously with streams 
        /// 
        ///  
        /// Instructs the  component to start 
        /// reading the StandardOutput stream asynchronously. The user can register a callback
        /// 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 
        /// then the remaining information is returned. The user can add an event handler to OutputDataReceived.
        /// 
        /// 
        [System.Runtime.InteropServices.ComVisible(false)] 
        public void BeginOutputReadLine() {
 
            if(outputStreamReadMode == StreamReadMode.undefined) { 
                outputStreamReadMode = StreamReadMode.asyncMode;
            } 
            else if (outputStreamReadMode != StreamReadMode.asyncMode) {
                throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
            }
 
            if (pendingOutputRead)
                throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation)); 
 
            pendingOutputRead = true;
            // We can't detect if there's a pending sychronous read, tream also doesn't. 
            if (output == null) {
                if (standardOutput == null) {
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardOut));
                } 

                Stream s = standardOutput.BaseStream; 
                output = new AsyncStreamReader(this, s, new UserCallBack(this.OutputReadNotifyUser), standardOutput.CurrentEncoding); 
            }
            output.BeginReadLine(); 
        }


        ///  
        /// 
        /// Instructs the  component to start 
        /// reading the StandardError stream asynchronously. The user can register a callback 
        /// 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
        /// then the remaining information is returned. The user can add an event handler to ErrorDataReceived. 
        /// 
        /// 
        [System.Runtime.InteropServices.ComVisible(false)]
        public void BeginErrorReadLine() { 

            if(errorStreamReadMode == StreamReadMode.undefined) { 
                errorStreamReadMode = StreamReadMode.asyncMode; 
            }
            else if (errorStreamReadMode != StreamReadMode.asyncMode) { 
                throw new InvalidOperationException(SR.GetString(SR.CantMixSyncAsyncOperation));
            }

            if (pendingErrorRead) { 
                throw new InvalidOperationException(SR.GetString(SR.PendingAsyncOperation));
            } 
 
            pendingErrorRead = true;
            // We can't detect if there's a pending sychronous read, stream also doesn't. 
            if (error == null) {
                if (standardError == null) {
                    throw new InvalidOperationException(SR.GetString(SR.CantGetStandardError));
                } 

                Stream s = standardError.BaseStream; 
                error = new AsyncStreamReader(this, s, new UserCallBack(this.ErrorReadNotifyUser), standardError.CurrentEncoding); 
            }
            error.BeginReadLine(); 
        }

        /// 
        ///  
        /// Instructs the  component to cancel the asynchronous operation
        /// specified by BeginOutputReadLine(). 
        ///  
        /// 
        [System.Runtime.InteropServices.ComVisible(false)] 
        public void CancelOutputRead() {
            if (output != null) {
                output.CancelOperation();
            } 
            else {
                throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation)); 
            } 

            pendingOutputRead = false; 
        }

        /// 
        ///  
        /// Instructs the  component to cancel the asynchronous operation
        /// specified by BeginErrorReadLine(). 
        ///  
        /// 
        [System.Runtime.InteropServices.ComVisible(false)] 
        public void CancelErrorRead() {
            if (error != null) {
                error.CancelOperation();
            } 
            else {
                throw new InvalidOperationException(SR.GetString(SR.NoAsyncOperation)); 
            } 

            pendingErrorRead = false; 
        }

        internal void OutputReadNotifyUser(String data) {
            // To avoid ---- between remove handler and raising the event 
            DataReceivedEventHandler outputDataReceived = OutputDataReceived;
            if (outputDataReceived != null) { 
                DataReceivedEventArgs e = new DataReceivedEventArgs(data); 
                if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) {
                    SynchronizingObject.Invoke(outputDataReceived, new object[] {this, e}); 
                }
                else {
                    outputDataReceived(this,e);  // Call back to user informing data is available.
                } 
            }
        } 
 
        internal void ErrorReadNotifyUser(String data) {
            // To avoid ---- between remove handler and raising the event 
            DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
            if (errorDataReceived != null) {
                DataReceivedEventArgs e = new DataReceivedEventArgs(data);
                if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) { 
                    SynchronizingObject.Invoke(errorDataReceived, new object[] {this, e});
                } 
                else { 
                    errorDataReceived(this,e); // Call back to user informing data is available.
                } 
            }
        }

        ///  
        ///     A desired internal state.
        ///  
        ///  
        enum State {
            HaveId = 0x1, 
            IsLocal = 0x2,
            IsNt = 0x4,
            HaveProcessInfo = 0x8,
            Exited = 0x10, 
            Associated = 0x20,
            IsWin2k = 0x40, 
            HaveNtProcessInfo = HaveProcessInfo | IsNt 
        }
    } 

    /// 
    ///     This data structure contains information about a process that is collected
    ///     in bulk by querying the operating system.  The reason to make this a separate 
    ///     structure from the process component is so that we can throw it away all at once
    ///     when Refresh is called on the component. 
    ///  
    /// 
    internal class ProcessInfo { 
        public ArrayList threadInfoList = new ArrayList();
        public int basePriority;
        public string processName;
        public int processId; 
        public int handleCount;
        public long poolPagedBytes; 
        public long poolNonpagedBytes; 
        public long virtualBytes;
        public long virtualBytesPeak; 
        public long workingSetPeak;
        public long workingSet;
        public long pageFileBytesPeak;
        public long pageFileBytes; 
        public long privateBytes;
        public int mainModuleId; // used only for win9x - id is only for use with CreateToolHelp32 
        public int sessionId; 
    }
 
    /// 
    ///     This data structure contains information about a thread in a process that
    ///     is collected in bulk by querying the operating system.  The reason to
    ///     make this a separate structure from the ProcessThread component is so that we 
    ///     can throw it away all at once when Refresh is called on the component.
    ///  
    ///  
    internal class ThreadInfo {
        public int threadId; 
        public int processId;
        public int basePriority;
        public int currentPriority;
        public IntPtr startAddress; 
        public ThreadState threadState;
#if !FEATURE_PAL 
        public ThreadWaitReason threadWaitReason; 
#endif // !FEATURE_PAL
    } 

    /// 
    ///     This data structure contains information about a module in a process that
    ///     is collected in bulk by querying the operating system.  The reason to 
    ///     make this a separate structure from the ProcessModule component is so that we
    ///     can throw it away all at once when Refresh is called on the component. 
    ///  
    /// 
    internal class ModuleInfo { 
        public string baseName;
        public string fileName;
        public IntPtr baseOfDll;
        public IntPtr entryPoint; 
        public int sizeOfImage;
        public int Id; // used only on win9x - for matching up with ProcessInfo.mainModuleId 
    } 

    internal static class EnvironmentBlock { 
        public static byte[] ToByteArray(StringDictionary sd, bool unicode) {
            // get the keys
            string[] keys = new string[sd.Count];
            byte[] envBlock = null; 
            sd.Keys.CopyTo(keys, 0);
 
            // get the values 
            string[] values = new string[sd.Count];
            sd.Values.CopyTo(values, 0); 

            // sort both by the keys
            // Windows 2000 requires the environment block to be sorted by the key
            // It will first converting the case the strings and do ordinal comparison. 
            Array.Sort(keys, values, OrdinalCaseInsensitiveComparer.Default);
 
            // create a list of null terminated "key=val" strings 
            StringBuilder stringBuff = new StringBuilder();
            for (int i = 0; i < sd.Count; ++ i) { 
                stringBuff.Append(keys[i]);
                stringBuff.Append('=');
                stringBuff.Append(values[i]);
                stringBuff.Append('\0'); 
            }
            // an extra null at the end indicates end of list. 
            stringBuff.Append('\0'); 

            if( unicode) { 
                envBlock = Encoding.Unicode.GetBytes(stringBuff.ToString());
            }
            else
                envBlock = Encoding.Default.GetBytes(stringBuff.ToString()); 

            if (envBlock.Length > UInt16.MaxValue) 
                throw new InvalidOperationException(SR.GetString(SR.EnvironmentBlockTooLong, envBlock.Length)); 

            return envBlock; 
        }
    }

    internal class OrdinalCaseInsensitiveComparer : IComparer { 
        internal static readonly OrdinalCaseInsensitiveComparer Default = new OrdinalCaseInsensitiveComparer();
 
        public int Compare(Object a, Object b) { 
            String sa = a as String;
            String sb = b as String; 
            if (sa != null && sb != null) {
                return String.Compare(sa, sb, StringComparison.OrdinalIgnoreCase);
            }
            return Comparer.Default.Compare(a,b); 
        }
    } 
 
    internal class ProcessThreadTimes {
        internal long create; 
        internal long exit;
        internal long kernel;
        internal long user;
 
        public DateTime StartTime {
            get { 
                return DateTime.FromFileTime(create); 
            }
        } 

        public DateTime ExitTime {
            get {
                return DateTime.FromFileTime(exit); 
            }
        } 
 
        public TimeSpan PrivilegedProcessorTime {
            get { 
                return new TimeSpan(kernel);
            }
        }
 
        public TimeSpan UserProcessorTime {
            get { 
                return new TimeSpan(user); 
            }
        } 

        public TimeSpan TotalProcessorTime {
            get {
                return new TimeSpan(user + kernel); 
            }
        } 
    } 

    internal class ShellExecuteHelper { 
        private NativeMethods.ShellExecuteInfo _executeInfo;
        private int _errorCode;
        private bool _succeeded;
 
        public ShellExecuteHelper(NativeMethods.ShellExecuteInfo executeInfo) {
            _executeInfo = executeInfo; 
        } 

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        public void ShellExecuteFunction()    {
            if (!(_succeeded = NativeMethods.ShellExecuteEx(_executeInfo))) {
                _errorCode = Marshal.GetLastWin32Error(); 
            }
        } 
 
        public bool ShellExecuteOnSTAThread() {
            // 
            // SHELL API ShellExecute() requires STA in order to work correctly.
            // If current thread is not a STA thread, we need to call ShellExecute on a new thread.
            //
            if( Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) { 
                ThreadStart threadStart = new ThreadStart(this.ShellExecuteFunction);
                Thread executionThread = new Thread(threadStart); 
                executionThread.SetApartmentState(ApartmentState.STA); 
                executionThread.Start();
                executionThread.Join(); 
            }
            else {
                ShellExecuteFunction();
            } 
            return _succeeded;
        } 
 
        public int ErrorCode {
            get { 
                return _errorCode;
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK