[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)]
EventHandler exited_event;
IntPtr stdout_rd;
IntPtr stderr_rd;
-#if NET_2_0
- Encoding stdout_encoding;
- Encoding stderr_encoding;
-#endif
/* Private constructor called from other methods */
private Process(IntPtr handle, int id) {
void StartExitCallbackIfNeeded ()
{
-#if !NET_2_1
bool start = (!already_waiting && enableRaisingEvents && exited_event != null);
- if (start && process_handle != IntPtr.Zero && !HasExited) {
+ if (start && process_handle != IntPtr.Zero) {
WaitOrTimerCallback cb = new WaitOrTimerCallback (CBOnExit);
ProcessWaitHandle h = new ProcessWaitHandle (process_handle);
ThreadPool.RegisterWaitForSingleObject (h, cb, this, -1, true);
already_waiting = true;
}
-#endif
}
[DefaultValue (false), Browsable (false)]
[MonitoringDescription ("Process identifier.")]
public int Id {
get {
- if (pid == 0) {
+ if (pid == 0)
throw new InvalidOperationException ("Process ID has not been set.");
- }
return(pid);
}
[MonitoringDescription ("The maximum working set for this process.")]
public IntPtr MaxWorkingSet {
get {
- if(HasExited) {
- throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
- }
+ if(HasExited)
+ throw new InvalidOperationException(
+ "The process " + ProcessName +
+ " (ID " + Id + ") has exited");
int min;
int max;
[MonitoringDescription ("The minimum working set for this process.")]
public IntPtr MinWorkingSet {
get {
- if(HasExited) {
- throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
- }
+ if(HasExited)
+ throw new InvalidOperationException(
+ "The process " + ProcessName +
+ " (ID " + Id + ") has exited");
int min;
int max;
- bool ok=GetWorkingSet_internal(process_handle, out min, out max);
- if(ok==false) {
+ bool ok= GetWorkingSet_internal (process_handle, out min, out max);
+ if(!ok)
throw new Win32Exception();
- }
-
- return((IntPtr)min);
+ return ((IntPtr) min);
}
set {
- if(HasExited) {
- throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
- }
+ if(HasExited)
+ throw new InvalidOperationException(
+ "The process " + ProcessName +
+ " (ID " + Id + ") has exited");
- bool ok=SetWorkingSet_internal(process_handle, value.ToInt32(), 0, true);
- if(ok==false) {
+ bool ok = SetWorkingSet_internal (process_handle, value.ToInt32(), 0, true);
+ if (!ok)
throw new Win32Exception();
- }
}
}
* element 0.
*/
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern ProcessModule[] GetModules_internal();
+ private extern ProcessModule[] GetModules_internal(IntPtr handle);
private ProcessModuleCollection module_collection;
[MonitoringDescription ("The modules that are loaded as part of this process.")]
public ProcessModuleCollection Modules {
get {
- if(module_collection==null) {
- module_collection=new ProcessModuleCollection(GetModules_internal());
- }
-
+ if (module_collection == null)
+ module_collection = new ProcessModuleCollection(
+ GetModules_internal (process_handle));
return(module_collection);
}
}
+ /* data type is from the MonoProcessData enum in mono-proclib.h in the runtime */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ 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 {
}
}
- [MonoTODO]
-#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 {
get {
- return(0);
+ int error;
+ return (int)GetProcessData (pid, 8, out error);
}
}
- [MonoTODO]
-#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 {
get {
- return(0);
+ int error;
+ return (int)GetProcessData (pid, 5, out error);
}
}
-#if NET_2_0
[MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The number of bytes that are not pageable.")]
}
}
- [MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
[ComVisible (false)]
public long PeakVirtualMemorySize64 {
get {
- return(0);
+ int error;
+ return GetProcessData (pid, 8, out error);
}
}
- [MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The maximum amount of system memory used by this process.")]
[ComVisible (false)]
public long PeakWorkingSet64 {
get {
- return(0);
+ int error;
+ return GetProcessData (pid, 5, out error);
}
}
-#endif
[MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The relative process priority.")]
public ProcessPriorityClass PriorityClass {
get {
+ if (process_handle == IntPtr.Zero)
+ throw new InvalidOperationException ("Process has not been started.");
+
int error;
int prio = GetPriorityClass (process_handle, out error);
if (prio == 0)
return (ProcessPriorityClass) prio;
}
set {
- // LAMESPEC: not documented on MSDN for NET_1_1
if (!Enum.IsDefined (typeof (ProcessPriorityClass), value))
- throw new InvalidEnumArgumentException ();
+ throw new InvalidEnumArgumentException (
+ "value", (int) value,
+ typeof (ProcessPriorityClass));
+ if (process_handle == IntPtr.Zero)
+ 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);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
static extern bool SetPriorityClass (IntPtr handle, int priority, out int error);
- [MonoTODO]
[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 {
- return(0);
+ int error;
+ return (int)GetProcessData (pid, 6, out error);
}
}
+ [MonoNotSupported ("")]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ [MonitoringDescription ("The session ID for this process.")]
+ public int SessionId {
+ get { throw new NotImplementedException (); }
+ }
+
/* the meaning of type is as follows: 0: user, 1: system, 2: total */
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static long Times (IntPtr handle, int type);
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");
- }
+ if (process_name == null)
+ throw new InvalidOperationException ("Process has exited, so the requested information is not available.");
/* Strip the suffix (if it
* exists) simplistically
[MonitoringDescription ("The standard error stream of this process.")]
public StreamReader StandardError {
get {
- if (error_stream == null) {
+ 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);
}
[MonitoringDescription ("The standard input stream of this process.")]
public StreamWriter StandardInput {
get {
- if (input_stream == null) {
+ if (input_stream == null)
throw new InvalidOperationException("Standard input has not been redirected");
- }
return(input_stream);
}
[MonitoringDescription ("The standard output stream of this process.")]
public StreamReader StandardOutput {
get {
- if (output_stream == null) {
+ 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);
}
[MonitoringDescription ("Information for the start of this process.")]
public ProcessStartInfo StartInfo {
get {
- if(start_info==null) {
- start_info=new ProcessStartInfo();
- }
-
- return(start_info);
+ if (start_info == null)
+ start_info = new ProcessStartInfo();
+ return start_info;
}
set {
- if(value==null) {
- throw new ArgumentException("value is null");
- }
-
- start_info=value;
+ if (value == null)
+ throw new ArgumentNullException("value");
+ start_info = value;
}
}
}
[MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The number of threads of this process.")]
public ProcessThreadCollection Threads {
get {
- return(null);
+ // This'll return a correctly-sized array of empty ProcessThreads for now.
+ int error;
+ return new ProcessThreadCollection(new ProcessThread[GetProcessData (pid, 0, out error)]);
}
}
}
}
- [MonoTODO]
-#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 {
get {
- return(0);
+ int error;
+ return (int)GetProcessData (pid, 7, out error);
}
}
- [MonoTODO]
-#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 {
get {
- return(0);
+ int error;
+ return (int)GetProcessData (pid, 4, out error);
}
}
-#if NET_2_0
- [MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The amount of memory exclusively used by this process.")]
[ComVisible (false)]
public long PrivateMemorySize64 {
get {
- return(0);
+ int error;
+ return GetProcessData (pid, 6, out error);
}
}
- [MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The amount of virtual memory currently used for this process.")]
[ComVisible (false)]
public long VirtualMemorySize64 {
get {
- return(0);
+ int error;
+ return GetProcessData (pid, 7, out error);
}
}
- [MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The amount of physical memory currently used for this process.")]
[ComVisible (false)]
public long WorkingSet64 {
get {
- return(0);
+ int error;
+ return GetProcessData (pid, 4, out error);
}
}
-#endif
public void Close()
{
int pid = GetPid_internal();
IntPtr proc = GetProcess_internal(pid);
- if (proc == IntPtr.Zero) {
+ if (proc == IntPtr.Zero)
throw new SystemException("Can't find current process");
- }
return (new Process (proc, pid));
}
{
IntPtr proc = GetProcess_internal(processId);
- if (proc == IntPtr.Zero) {
+ if (proc == IntPtr.Zero)
throw new ArgumentException ("Can't find process with ID " + processId.ToString ());
- }
return (new Process (proc, processId));
}
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]
}
public void Refresh ()
- {
+ {
// FIXME: should refresh any cached data we might have about
// the process (currently we have none).
}
throw new InvalidOperationException ("UseShellExecute must be false when redirecting I/O.");
}
- if (startInfo.HaveEnvVars) {
+ if (startInfo.HaveEnvVars)
throw new InvalidOperationException ("UseShellExecute must be false in order to use environment variables.");
- }
FillUserInfo (startInfo, ref proc_info);
try {
private static bool Start_noshell (ProcessStartInfo startInfo,
Process process)
{
- if (Path.IsPathRooted (startInfo.FileName) && !File.Exists (startInfo.FileName))
- throw new FileNotFoundException ("Executable not found: " + startInfo.FileName);
ProcInfo proc_info=new ProcInfo();
- IntPtr stdin_rd, stdin_wr;
+ IntPtr stdin_rd = IntPtr.Zero, stdin_wr = IntPtr.Zero;
IntPtr stdout_wr;
IntPtr stderr_wr;
bool ret;
}
if (startInfo.RedirectStandardInput == true) {
- ret = MonoIO.CreatePipe (out stdin_rd,
- out stdin_wr);
+ if (IsWindows) {
+ int DUPLICATE_SAME_ACCESS = 0x00000002;
+ IntPtr stdin_wr_tmp;
+
+ ret = MonoIO.CreatePipe (out stdin_rd,
+ out stdin_wr_tmp);
+ if (ret) {
+ ret = MonoIO.DuplicateHandle (Process.GetCurrentProcess ().Handle, stdin_wr_tmp,
+ Process.GetCurrentProcess ().Handle, out stdin_wr, 0, 0, DUPLICATE_SAME_ACCESS);
+ MonoIO.Close (stdin_wr_tmp, out error);
+ }
+ }
+ else
+ {
+ ret = MonoIO.CreatePipe (out stdin_rd,
+ out stdin_wr);
+ }
if (ret == false) {
throw new IOException ("Error creating standard input pipe");
}
}
if (startInfo.RedirectStandardOutput == true) {
- IntPtr out_rd;
- ret = MonoIO.CreatePipe (out out_rd,
- out stdout_wr);
+ IntPtr out_rd = IntPtr.Zero;
+ if (IsWindows) {
+ IntPtr out_rd_tmp;
+ int DUPLICATE_SAME_ACCESS = 0x00000002;
+
+ ret = MonoIO.CreatePipe (out out_rd_tmp,
+ out stdout_wr);
+ if (ret) {
+ MonoIO.DuplicateHandle (Process.GetCurrentProcess ().Handle, out_rd_tmp,
+ Process.GetCurrentProcess ().Handle, out out_rd, 0, 0, DUPLICATE_SAME_ACCESS);
+ MonoIO.Close (out_rd_tmp, out error);
+ }
+ }
+ else {
+ ret = MonoIO.CreatePipe (out out_rd,
+ out stdout_wr);
+ }
process.stdout_rd = out_rd;
if (ret == false) {
}
if (startInfo.RedirectStandardError == true) {
- IntPtr err_rd;
- ret = MonoIO.CreatePipe (out err_rd,
- out stderr_wr);
+ IntPtr err_rd = IntPtr.Zero;
+ if (IsWindows) {
+ IntPtr err_rd_tmp;
+ int DUPLICATE_SAME_ACCESS = 0x00000002;
+
+ ret = MonoIO.CreatePipe (out err_rd_tmp,
+ out stderr_wr);
+ if (ret) {
+ MonoIO.DuplicateHandle (Process.GetCurrentProcess ().Handle, err_rd_tmp,
+ Process.GetCurrentProcess ().Handle, out err_rd, 0, 0, DUPLICATE_SAME_ACCESS);
+ MonoIO.Close (err_rd_tmp, out error);
+ }
+ }
+ else {
+ ret = MonoIO.CreatePipe (out err_rd,
+ out stderr_wr);
+ }
process.stderr_rd = err_rd;
if (ret == false) {
MonoIO.Close (stderr_wr, out error);
}
- throw new Win32Exception (-proc_info.pid,
- "ApplicationName='"+startInfo.FileName+
- "', CommandLine='"+startInfo.Arguments+
- "', CurrentDirectory='"+startInfo.WorkingDirectory+
- "', PATH='"+startInfo.EnvironmentVariables["PATH"]+"'");
+ throw new Win32Exception (-proc_info.pid,
+ "ApplicationName='" + startInfo.FileName +
+ "', CommandLine='" + startInfo.Arguments +
+ "', CurrentDirectory='" + startInfo.WorkingDirectory +
+ "', Native error= " + Win32Exception.W32ErrorMessage (-proc_info.pid));
}
process.process_handle = proc_info.process_handle;
if (startInfo.RedirectStandardInput == true) {
MonoIO.Close (stdin_rd, out error);
- process.input_stream = new StreamWriter (new FileStream (stdin_wr, FileAccess.Write, true), ConsoleEncoding.InputEncoding);
+ process.input_stream = new StreamWriter (new MonoSyncFileStream (stdin_wr, FileAccess.Write, true, 8192), Console.Out.Encoding);
process.input_stream.AutoFlush = true;
}
-#if NET_2_0
- // TODO: which ones has precedence? The one from startInfo or the one set using
- // the Process instance properties?
- Encoding stdoutEncoding = startInfo.StandardOutputEncoding ?? process.StandardOutputEncoding;
- Encoding stderrEncoding = startInfo.StandardErrorEncoding ?? process.StandardErrorEncoding;
-#else
- Encoding stdoutEncoding = ConsoleEncoding.OutputEncoding;
- Encoding stderrEncoding = ConsoleEncoding.OutputEncoding;
-#endif
+ Encoding stdoutEncoding = startInfo.StandardOutputEncoding ?? Console.Out.Encoding;
+ Encoding stderrEncoding = startInfo.StandardErrorEncoding ?? Console.Out.Encoding;
if (startInfo.RedirectStandardOutput == true) {
MonoIO.Close (stdout_wr, out error);
- process.output_stream = new StreamReader (new FileStream (process.stdout_rd, FileAccess.Read, true), stdoutEncoding);
+ process.output_stream = new StreamReader (new MonoSyncFileStream (process.stdout_rd, FileAccess.Read, true, 8192), stdoutEncoding, true, 8192);
}
if (startInfo.RedirectStandardError == true) {
MonoIO.Close (stderr_wr, out error);
- process.error_stream = new StreamReader (new FileStream (process.stderr_rd, FileAccess.Read, true), stderrEncoding);
+ process.error_stream = new StreamReader (new MonoSyncFileStream (process.stderr_rd, FileAccess.Read, true, 8192), stderrEncoding, true, 8192);
}
process.StartExitCallbackIfNeeded ();
// 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,
Process process)
{
- if(startInfo.FileName == null ||
- startInfo.FileName == "") {
+ 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 (startInfo.UserName != null)
+ 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));
}
}
- public bool Start() {
- bool ret;
-
+ public bool Start ()
+ {
if (process_handle != IntPtr.Zero) {
Process_free_internal (process_handle);
process_handle = IntPtr.Zero;
}
- ret=Start_common(start_info, this);
-
- return(ret);
+ return Start_common(start_info, this);
}
- public static Process Start(ProcessStartInfo startInfo) {
+ public static Process Start (ProcessStartInfo startInfo)
+ {
+ if (startInfo == null)
+ throw new ArgumentNullException ("startInfo");
Process process=new Process();
- bool ret;
-
process.StartInfo = startInfo;
- ret=Start_common(startInfo, process);
-
- if(ret==true) {
- return(process);
- } else {
- return(null);
- }
+ if (Start_common(startInfo, process))
+ return process;
+ return null;
}
- public static Process Start(string fileName) {
- return Start(new ProcessStartInfo(fileName));
+ public static Process Start (string fileName)
+ {
+ return Start (new ProcessStartInfo (fileName));
}
- public static Process Start(string fileName,
- string arguments) {
- return Start(new ProcessStartInfo(fileName, arguments));
+ public static Process Start(string fileName, string arguments)
+ {
+ 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() {
- return(base.ToString() +
- " (" + this.ProcessName + ")");
+ public override string ToString()
+ {
+ return(base.ToString() + " (" + this.ProcessName + ")");
}
/* Waits up to ms milliseconds for process 'handle' to
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);
}
+ /* Waits up to ms milliseconds for process 'handle' to
+ * wait for input. ms can be <0 to mean wait forever.
+ */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool WaitForInputIdle_internal(IntPtr handle, int ms);
+
+ // The internal call is only implemented properly on Windows.
[MonoTODO]
public bool WaitForInputIdle() {
- return(false);
+ return WaitForInputIdle (-1);
}
+ // The internal call is only implemented properly on Windows.
[MonoTODO]
public bool WaitForInputIdle(int milliseconds) {
- return(false);
+ return WaitForInputIdle_internal (process_handle, milliseconds);
}
private static bool IsLocalMachine (string machineName)
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;
The following fields match those of SocketAsyncResult.
This is so that changes needed in the runtime to handle
asynchronous reads are trivial
+ Keep this in sync with SocketAsyncResult in
+ ./System.Net.Sockets/Socket.cs and MonoSocketAsyncResult
+ in metadata/socket-io.h.
*/
/* DON'T shuffle fields around. DON'T remove fields */
public object Sock;
public int Size;
public int SockFlags;
+ public object AcceptSocket;
+ public object[] Addresses;
+ public int port;
+ public object Buffers; // Reserve this slot in older profiles
+ public bool ReuseSocket; // Disconnect
public object acc_socket;
public int total;
public bool completed_sync;
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
lock(this) {
if(process_handle!=IntPtr.Zero) {
-
Process_free_internal(process_handle);
process_handle=IntPtr.Zero;
}
static void CBOnExit (object state, bool unused)
{
Process p = (Process) state;
+ p.already_waiting = false;
p.OnExited ();
}
synchronizingObject.BeginInvoke (exited_event, args);
}
-#if NET_2_0
- public Encoding StandardOutputEncoding {
- get {
- if (stdout_encoding != null) {
- return stdout_encoding;
- }
- return ConsoleEncoding.OutputEncoding;
- }
- set {
- stdout_encoding = value; // if null, we'll use the default
- }
- }
-
- public Encoding StandardErrorEncoding {
- get {
- if (stderr_encoding != null) {
- return stderr_encoding;
+ static bool IsWindows
+ {
+ get
+ {
+ PlatformID platform = Environment.OSVersion.Platform;
+ if (platform == PlatformID.Win32S ||
+ platform == PlatformID.Win32Windows ||
+ platform == PlatformID.Win32NT ||
+ platform == PlatformID.WinCE) {
+ return true;
}
- return ConsoleEncoding.OutputEncoding;
- }
- set {
- stderr_encoding = value; // if null, we'll use the default
+ return false;
}
}
-#endif
class ProcessWaitHandle : WaitHandle
{
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static IntPtr ProcessHandle_duplicate (IntPtr handle);
+
public ProcessWaitHandle (IntPtr handle)
{
- Handle = handle;
- }
+ // Need to keep a reference to this handle,
+ // in case the Process object is collected
+ Handle = ProcessHandle_duplicate (handle);
- protected override void Dispose (bool explicitDisposing)
- {
- // Do nothing, we don't own the handle and we won't close it.
- }
- }
-
- class ConsoleEncoding
- {
- [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
- private static extern int GetConsoleCP ();
- [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
- private static extern int GetConsoleOutputCP ();
-
- static bool RunningOnWindows {
- get {
- return ((int) Environment.OSVersion.Platform != 4 &&
-#if NET_2_0
- Environment.OSVersion.Platform != PlatformID.Unix);
-#else
- (int) Environment.OSVersion.Platform != 128);
-#endif
- }
- }
-
- public static Encoding InputEncoding {
- get {
- if(!RunningOnWindows) {
- return Encoding.Default;
- }
-
-#if !NET_2_0
- try {
- return Encoding.GetEncoding (GetConsoleCP ());
- } catch {
- return Encoding.GetEncoding (28591);
- }
-#else
- return Console.InputEncoding;
-#endif
- }
- }
-
- public static Encoding OutputEncoding {
- get {
- if(!RunningOnWindows) {
- return Encoding.Default;
- }
-
-#if !NET_2_0
- try {
- return Encoding.GetEncoding (GetConsoleOutputCP ());
- } catch {
- return Encoding.GetEncoding (28591);
- }
-#else
- return Console.OutputEncoding;
-#endif
- }
+ // When the wait handle is disposed, the duplicated handle will be
+ // closed, so no need to override dispose (bug #464628).
}
}
}