[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)]
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);
ThreadPool.RegisterWaitForSingleObject (h, cb, this, -1, true);
already_waiting = true;
}
-#endif
}
[DefaultValue (false), Browsable (false)]
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 {
}
[MonoTODO]
-#if NET_2_0
[Obsolete ("Use PagedMemorySize64")]
-#endif
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The number of bytes that are paged.")]
public int PagedMemorySize {
}
[MonoTODO]
-#if NET_2_0
[Obsolete ("Use PagedSystemMemorySize64")]
-#endif
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The amount of paged system memory in bytes.")]
public int PagedSystemMemorySize {
}
[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 {
}
}
-#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 {
}
}
-#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 {
}
}
-#if NET_2_0
[MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The number of bytes that are not pageable.")]
return GetProcessData (pid, 5, out error);
}
}
-#endif
[MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
throw new InvalidOperationException ("Process has not been started.");
int error;
- if (!SetPriorityClass (process_handle, (int) value, out error))
+ if (!SetPriorityClass (process_handle, (int) value, out error)) {
+ CheckExited ();
throw new Win32Exception (error);
+ }
}
}
+ void CheckExited () {
+ if (HasExited)
+ throw new InvalidOperationException (String.Format ("Cannot process request because the process ({0}) has exited.", Id));
+ }
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
static extern int GetPriorityClass (IntPtr handle, out int error);
[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;
}
}
-#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)]
public string ProcessName {
get {
if(process_name==null) {
+
+ if (process_handle == IntPtr.Zero)
+ throw new InvalidOperationException ("No process is associated with this object.");
+
process_name=ProcessName_internal(process_handle);
/* If process_name is _still_
* null, assume the process
* has exited
*/
if (process_name == null)
- throw new SystemException("The process has exited");
+ throw new InvalidOperationException ("Process has exited, so the requested information is not available.");
/* Strip the suffix (if it
* exists) simplistically
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);
}
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);
}
}
[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)]);
}
}
}
}
-#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 {
}
}
-#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 {
}
}
-#if NET_2_0
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The amount of memory exclusively used by this process.")]
[ComVisible (false)]
return GetProcessData (pid, 4, out error);
}
}
-#endif
public void Close()
{
public static Process[] GetProcesses()
{
int [] pids = GetProcesses_internal ();
- ArrayList proclist = new ArrayList ();
-
+ if (pids == null)
+ return new Process [0];
+
+ ArrayList proclist = new ArrayList (pids.Length);
for (int i = 0; i < pids.Length; i++) {
try {
proclist.Add (GetProcessById (pids [i]));
public static Process[] GetProcessesByName(string processName)
{
- Process [] procs = GetProcesses();
- ArrayList proclist = new ArrayList();
+ int [] pids = GetProcesses_internal ();
+ if (pids == null)
+ return new Process [0];
- for (int i = 0; i < procs.Length; i++) {
- /* Ignore case */
- if (String.Compare (processName,
- procs [i].ProcessName,
- true) == 0) {
- proclist.Add (procs [i]);
+ ArrayList proclist = new ArrayList (pids.Length);
+ for (int i = 0; i < pids.Length; i++) {
+ try {
+ Process p = GetProcessById (pids [i]);
+ if (String.Compare (processName, p.ProcessName, true) == 0)
+ proclist.Add (p);
+ } catch (SystemException) {
+ /* The process might exit
+ * between
+ * GetProcesses_internal and
+ * GetProcessById
+ */
}
}
- return ((Process[]) proclist.ToArray (typeof(Process)));
+ return ((Process []) proclist.ToArray (typeof (Process)));
}
[MonoTODO]
throw new Win32Exception (-proc_info.pid,
"ApplicationName='" + startInfo.FileName +
"', CommandLine='" + startInfo.Arguments +
- "', CurrentDirectory='" + startInfo.WorkingDirectory + "'");
+ "', CurrentDirectory='" + startInfo.WorkingDirectory +
+ "', Native error= " + Win32Exception.W32ErrorMessage (-proc_info.pid));
}
process.process_handle = proc_info.process_handle;
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);
// 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;
proc_info.Password = IntPtr.Zero;
proc_info.LoadUserProfile = startInfo.LoadUserProfile;
}
-#endif
}
private static bool Start_common (ProcessStartInfo startInfo,
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));
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);
}
psi.UseShellExecute = false;
return Start(psi);
}
-#endif
public override string ToString()
{
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))
return false;
}
}
-#endif
return WaitForExit_internal (process_handle, ms);
}
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;
internal int error;
public int operation = 8; // MAGIC NUMBER: see Socket.cs:AsyncOperation
public object ares;
-
+ public int EndCalled;
// These fields are not in SocketAsyncResult
Process process;
completed = true;
if (wait_handle != null)
wait_handle.Set ();
- Flush (true);
+ FlushLast ();
return;
}
}
}
+ void FlushLast ()
+ {
+ Flush (true);
+ if (err_out) {
+ process.OnOutputDataReceived (null);
+ } else {
+ process.OnErrorDataReceived (null);
+ }
+ }
+
void Flush (bool last)
{
if (sb.Length == 0 ||
}
}
}
+
+ public void Close () {
+ stream.Close ();
+ }
}
AsyncModes async_mode;
error_canceled = true;
}
-#endif
[Category ("Behavior")]
[MonitoringDescription ("Raised when this process exits.")]
// dispose all managed resources.
if(disposing) {
// Do stuff here
+ lock (this) {
+ /* These have open FileStreams on the pipes we are about to close */
+ if (async_output != null)
+ async_output.Close ();
+ if (async_error != null)
+ async_error.Close ();
+ }
}
// Release unmanaged resources
static void CBOnExit (object state, bool unused)
{
Process p = (Process) state;
+ p.already_waiting = false;
p.OnExited ();
}
// Need to keep a reference to this handle,
// in case the Process object is collected
Handle = ProcessHandle_duplicate (handle);
- }
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static void ProcessHandle_close (IntPtr handle);
-
- private bool disposed = false;
-
- protected override void Dispose (bool explicitDisposing)
- {
- if (this.disposed == false) {
- this.disposed = true;
-
- ProcessHandle_close (Handle);
- Handle = IntPtr.Zero;
- }
- base.Dispose (explicitDisposing);
- }
- ~ProcessWaitHandle ()
- {
- Dispose (false);
+ // When the wait handle is disposed, the duplicated handle will be
+ // closed, so no need to override dispose (bug #464628).
}
}
}