Merge pull request #963 from kebby/master
[mono.git] / mcs / class / System / System.Diagnostics / Process.cs
index 4b0911045d8a9089d3de5b8bad888a23ef486f53..af427037b285cfc9ae8e1b4e7aa7183d1fddc04b 100644 (file)
@@ -49,9 +49,7 @@ namespace System.Diagnostics {
        [Designer ("System.Diagnostics.Design.ProcessDesigner, " + Consts.AssemblySystem_Design)]
        [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
        [PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]
-#if NET_2_0
        [MonitoringDescription ("Represents a system process")]
-#endif
        public class Process : Component 
        {
                [StructLayout(LayoutKind.Sequential)]
@@ -104,7 +102,6 @@ namespace System.Diagnostics {
 
                void StartExitCallbackIfNeeded ()
                {
-#if !NET_2_1
                        bool start = (!already_waiting && enableRaisingEvents && exited_event != null);
                        if (start && process_handle != IntPtr.Zero) {
                                WaitOrTimerCallback cb = new WaitOrTimerCallback (CBOnExit);
@@ -112,7 +109,6 @@ namespace System.Diagnostics {
                                ThreadPool.RegisterWaitForSingleObject (h, cb, this, -1, true);
                                already_waiting = true;
                        }
-#endif
                }
 
                [DefaultValue (false), Browsable (false)]
@@ -339,9 +335,7 @@ namespace System.Diagnostics {
                private extern static long GetProcessData (int pid, int data_type, out int error);
 
                [MonoTODO]
-#if NET_2_0
                [Obsolete ("Use NonpagedSystemMemorySize64")]
-#endif
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The number of bytes that are not pageable.")]
                public int NonpagedSystemMemorySize {
@@ -351,9 +345,7 @@ namespace System.Diagnostics {
                }
 
                [MonoTODO]
-#if NET_2_0
                [Obsolete ("Use PagedMemorySize64")]
-#endif
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The number of bytes that are paged.")]
                public int PagedMemorySize {
@@ -363,9 +355,7 @@ namespace System.Diagnostics {
                }
 
                [MonoTODO]
-#if NET_2_0
                [Obsolete ("Use PagedSystemMemorySize64")]
-#endif
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The amount of paged system memory in bytes.")]
                public int PagedSystemMemorySize {
@@ -375,9 +365,7 @@ namespace System.Diagnostics {
                }
 
                [MonoTODO]
-#if NET_2_0
                [Obsolete ("Use PeakPagedMemorySize64")]
-#endif
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The maximum amount of paged memory used by this process.")]
                public int PeakPagedMemorySize {
@@ -386,9 +374,7 @@ namespace System.Diagnostics {
                        }
                }
 
-#if NET_2_0
                [Obsolete ("Use PeakVirtualMemorySize64")]
-#endif
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
                public int PeakVirtualMemorySize {
@@ -398,9 +384,7 @@ namespace System.Diagnostics {
                        }
                }
 
-#if NET_2_0
                [Obsolete ("Use PeakWorkingSet64")]
-#endif
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The maximum amount of system memory used by this process.")]
                public int PeakWorkingSet {
@@ -410,7 +394,6 @@ namespace System.Diagnostics {
                        }
                }
 
-#if NET_2_0
                [MonoTODO]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The number of bytes that are not pageable.")]
@@ -470,7 +453,6 @@ namespace System.Diagnostics {
                                return GetProcessData (pid, 5, out error);
                        }
                }
-#endif
 
                [MonoTODO]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
@@ -527,9 +509,7 @@ namespace System.Diagnostics {
 
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The amount of memory exclusively used by this process.")]
-#if NET_2_0
                [Obsolete ("Use PrivateMemorySize64")]
-#endif
                public int PrivateMemorySize {
                        get {
                                int error;
@@ -537,14 +517,12 @@ namespace System.Diagnostics {
                        }
                }
 
-#if NET_2_0
                [MonoNotSupported ("")]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The session ID for this process.")]
                public int SessionId {
                        get { throw new NotImplementedException (); }
                }
-#endif
 
                /* the meaning of type is as follows: 0: user, 1: system, 2: total */
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -626,12 +604,10 @@ namespace System.Diagnostics {
                                if (error_stream == null)
                                        throw new InvalidOperationException("Standard error has not been redirected");
 
-#if NET_2_0
                                if ((async_mode & AsyncModes.AsyncError) != 0)
                                        throw new InvalidOperationException ("Cannot mix asynchronous and synchonous reads.");
 
                                async_mode |= AsyncModes.SyncError;
-#endif
 
                                return(error_stream);
                        }
@@ -659,12 +635,10 @@ namespace System.Diagnostics {
                                if (output_stream == null)
                                        throw new InvalidOperationException("Standard output has not been redirected");
 
-#if NET_2_0
                                if ((async_mode & AsyncModes.AsyncOutput) != 0)
                                        throw new InvalidOperationException ("Cannot mix asynchronous and synchonous reads.");
 
                                async_mode |= AsyncModes.SyncOutput;
-#endif
 
                                return(output_stream);
                        }
@@ -709,11 +683,13 @@ namespace System.Diagnostics {
                }
 
                [MonoTODO]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The number of threads of this process.")]
                public ProcessThreadCollection Threads {
                        get {
-                               return ProcessThreadCollection.GetEmpty ();
+                               // This'll return a correctly-sized array of empty ProcessThreads for now.
+                               int error;
+                               return new ProcessThreadCollection(new ProcessThread[GetProcessData (pid, 0, out error)]);
                        }
                }
 
@@ -733,9 +709,7 @@ namespace System.Diagnostics {
                        }
                }
 
-#if NET_2_0
                [Obsolete ("Use VirtualMemorySize64")]
-#endif
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The amount of virtual memory currently used for this process.")]
                public int VirtualMemorySize {
@@ -745,9 +719,7 @@ namespace System.Diagnostics {
                        }
                }
 
-#if NET_2_0
                [Obsolete ("Use WorkingSet64")]
-#endif
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The amount of physical memory currently used for this process.")]
                public int WorkingSet {
@@ -757,7 +729,6 @@ namespace System.Diagnostics {
                        }
                }
 
-#if NET_2_0
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The amount of memory exclusively used by this process.")]
                [ComVisible (false)]
@@ -787,7 +758,6 @@ namespace System.Diagnostics {
                                return GetProcessData (pid, 4, out error);
                        }
                }
-#endif
 
                public void Close()
                {
@@ -948,8 +918,7 @@ namespace System.Diagnostics {
                                                                  IntPtr stderr,
                                                                  ref ProcInfo proc_info);
 
-               private static bool Start_shell (ProcessStartInfo startInfo,
-                                                Process process)
+               private static bool Start_shell (ProcessStartInfo startInfo, Process process)
                {
                        ProcInfo proc_info=new ProcInfo();
                        bool ret;
@@ -978,9 +947,7 @@ namespace System.Diagnostics {
 
                        process.process_handle = proc_info.process_handle;
                        process.pid = proc_info.pid;
-
                        process.StartExitCallbackIfNeeded ();
-
                        return(ret);
                }
 
@@ -1146,13 +1113,8 @@ namespace System.Diagnostics {
                                process.input_stream.AutoFlush = true;
                        }
 
-#if NET_2_0
                        Encoding stdoutEncoding = startInfo.StandardOutputEncoding ?? Console.Out.Encoding;
                        Encoding stderrEncoding = startInfo.StandardErrorEncoding ?? Console.Out.Encoding;
-#else
-                       Encoding stdoutEncoding = Console.Out.Encoding;
-                       Encoding stderrEncoding = stdoutEncoding;
-#endif
 
                        if (startInfo.RedirectStandardOutput == true) {
                                MonoIO.Close (stdout_wr, out error);
@@ -1172,7 +1134,6 @@ namespace System.Diagnostics {
                // Note that ProcInfo.Password must be freed.
                private static void FillUserInfo (ProcessStartInfo startInfo, ref ProcInfo proc_info)
                {
-#if NET_2_0
                        if (startInfo.UserName != null) {
                                proc_info.UserName = startInfo.UserName;
                                proc_info.Domain = startInfo.Domain;
@@ -1182,7 +1143,6 @@ namespace System.Diagnostics {
                                        proc_info.Password = IntPtr.Zero;
                                proc_info.LoadUserProfile = startInfo.LoadUserProfile;
                        }
-#endif
                }
 
                private static bool Start_common (ProcessStartInfo startInfo,
@@ -1191,18 +1151,14 @@ namespace System.Diagnostics {
                        if (startInfo.FileName == null || startInfo.FileName.Length == 0)
                                throw new InvalidOperationException("File name has not been set");
                        
-#if NET_2_0
                        if (startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError)
                                throw new InvalidOperationException ("StandardErrorEncoding is only supported when standard error is redirected");
                        if (startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput)
                                throw new InvalidOperationException ("StandardOutputEncoding is only supported when standard output is redirected");
-#endif
                        
                        if (startInfo.UseShellExecute) {
-#if NET_2_0
                                if (!String.IsNullOrEmpty (startInfo.UserName))
                                        throw new InvalidOperationException ("UserShellExecute must be false if an explicit UserName is specified when starting a process");
-#endif
                                return (Start_shell (startInfo, process));
                        } else {
                                return (Start_noshell (startInfo, process));
@@ -1223,9 +1179,9 @@ namespace System.Diagnostics {
                        if (startInfo == null)
                                throw new ArgumentNullException ("startInfo");
 
-                       Process process=new Process();
+                       Process process = new Process();
                        process.StartInfo = startInfo;
-                       if (Start_common(startInfo, process))
+                       if (Start_common(startInfo, process) && process.process_handle != IntPtr.Zero)
                                return process;
                        return null;
                }
@@ -1240,7 +1196,6 @@ namespace System.Diagnostics {
                        return Start (new ProcessStartInfo (fileName, arguments));
                }
 
-#if NET_2_0
                public static Process Start(string fileName, string username, SecureString password, string domain) {
                        return Start(fileName, null, username, password, domain);
                }
@@ -1253,7 +1208,6 @@ namespace System.Diagnostics {
                        psi.UseShellExecute = false;
                        return Start(psi);
                }
-#endif
 
                public override string ToString()
                {
@@ -1276,7 +1230,6 @@ namespace System.Diagnostics {
                        if (ms == int.MaxValue)
                                ms = -1;
 
-#if NET_2_0
                        DateTime start = DateTime.UtcNow;
                        if (async_output != null && !async_output.IsCompleted) {
                                if (false == async_output.WaitHandle.WaitOne (ms, false))
@@ -1301,7 +1254,6 @@ namespace System.Diagnostics {
                                                return false;
                                }
                        }
-#endif
                        return WaitForExit_internal (process_handle, ms);
                }
 
@@ -1331,7 +1283,6 @@ namespace System.Diagnostics {
                        return (string.Compare (machineName, Environment.MachineName, true) == 0);
                }
 
-#if NET_2_0
                [Browsable (true)]
                [MonitoringDescription ("Raised when it receives output data")]
                public event DataReceivedEventHandler OutputDataReceived;
@@ -1563,8 +1514,8 @@ namespace System.Diagnostics {
                [ComVisibleAttribute(false)] 
                public void CancelErrorRead ()
                {
-                       if (process_handle == IntPtr.Zero || output_stream == null || StartInfo.RedirectStandardOutput == false)
-                               throw new InvalidOperationException ("Standard output has not been redirected or process has not been started.");
+                       if (process_handle == IntPtr.Zero || error_stream == null || StartInfo.RedirectStandardError == false)
+                               throw new InvalidOperationException ("Standard error has not been redirected or process has not been started.");
 
                        if ((async_mode & AsyncModes.SyncOutput) != 0)
                                throw new InvalidOperationException ("OutputStream is not enabled for asynchronous read operations.");
@@ -1574,7 +1525,6 @@ namespace System.Diagnostics {
 
                        error_canceled = true;
                }
-#endif
 
                [Category ("Behavior")]
                [MonitoringDescription ("Raised when this process exits.")]
@@ -1613,6 +1563,21 @@ namespace System.Diagnostics {
                                                        async_output.Close ();
                                                if (async_error != null)
                                                        async_error.Close ();
+
+                                               if (input_stream != null) {
+                                                       input_stream.Close();
+                                                       input_stream = null;
+                                               }
+
+                                               if (output_stream != null) {
+                                                       output_stream.Close();
+                                                       output_stream = null;
+                                               }
+
+                                               if (error_stream != null) {
+                                                       error_stream.Close();
+                                                       error_stream = null;
+                                               }
                                        }
                                }
                                
@@ -1623,21 +1588,6 @@ namespace System.Diagnostics {
                                                Process_free_internal(process_handle);
                                                process_handle=IntPtr.Zero;
                                        }
-
-                                       if (input_stream != null) {
-                                               input_stream.Close();
-                                               input_stream = null;
-                                       }
-
-                                       if (output_stream != null) {
-                                               output_stream.Close();
-                                               output_stream = null;
-                                       }
-
-                                       if (error_stream != null) {
-                                               error_stream.Close();
-                                               error_stream = null;
-                                       }
                                }
                        }
                        base.Dispose (disposing);