using System.IO;
using System.Text;
+using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Runtime.CompilerServices;
public IntPtr thread_handle;
public int pid; // Contains -GetLastError () on failure.
public int tid;
- public string [] envKeys;
- public string [] envValues;
+ public string[] envVariables;
public string UserName;
public string Domain;
public IntPtr Password;
/* Private constructor called from other methods */
private Process (SafeProcessHandle handle, int id) {
- m_processHandle = handle;
+ SetProcessHandle (handle);
SetProcessId (id);
}
process_name = ProcessName_internal (handle);
- /* If process_name is _still_ null, assume the process has exited */
+ /* If process_name is _still_ null, assume the process has exited or is inaccessible */
if (process_name == null)
- throw new InvalidOperationException ("Process has exited, so the requested information is not available.");
+ throw new InvalidOperationException ("Process has exited or is inaccessible, so the requested information is not available.");
/* Strip the suffix (if it exists) simplistically instead of removing
* any trailing \.???, so we dont get stupid results on sane systems */
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static IntPtr GetProcess_internal(int pid);
- public static Process GetProcessById(int processId)
- {
+ [MonoTODO ("There is no support for retrieving process information from a remote machine")]
+ public static Process GetProcessById(int processId, string machineName) {
+ if (machineName == null)
+ throw new ArgumentNullException ("machineName");
+
+ if (!IsLocalMachine (machineName))
+ throw new NotImplementedException ();
+
IntPtr proc = GetProcess_internal(processId);
-
+
if (proc == IntPtr.Zero)
throw new ArgumentException ("Can't find process with ID " + processId.ToString ());
- return (new Process (new SafeProcessHandle (proc, false), processId));
+ /* The handle returned by GetProcess_internal is owned by its caller, so we must pass true to SafeProcessHandle */
+ return (new Process (new SafeProcessHandle (proc, true), processId));
}
- [MonoTODO ("There is no support for retrieving process information from a remote machine")]
- public static Process GetProcessById(int processId, string machineName) {
+ public static Process[] GetProcessesByName(string processName, string machineName)
+ {
if (machineName == null)
throw new ArgumentNullException ("machineName");
if (!IsLocalMachine (machineName))
throw new NotImplementedException ();
- return GetProcessById (processId);
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static int[] GetProcesses_internal();
+ Process[] processes = GetProcesses ();
+ if (processes.Length == 0)
+ return processes;
- public static Process[] GetProcesses ()
- {
- int [] pids = GetProcesses_internal ();
- if (pids == null)
- return new Process [0];
+ int size = 0;
- var proclist = new List<Process> (pids.Length);
- for (int i = 0; i < pids.Length; i++) {
+ for (int i = 0; i < processes.Length; i++) {
try {
- proclist.Add (GetProcessById (pids [i]));
+ if (String.Compare (processName, processes[i].ProcessName, true) == 0)
+ processes [size++] = processes[i];
} catch (SystemException) {
- /* The process might exit
- * between
- * GetProcesses_internal and
- * GetProcessById
- */
+ /* The process might exit between GetProcesses_internal and GetProcessById */
}
}
- return proclist.ToArray ();
+ Array.Resize<Process> (ref processes, size);
+
+ return processes;
}
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static int[] GetProcesses_internal();
+
[MonoTODO ("There is no support for retrieving process information from a remote machine")]
public static Process[] GetProcesses(string machineName) {
if (machineName == null)
if (!IsLocalMachine (machineName))
throw new NotImplementedException ();
- return GetProcesses ();
- }
-
- public static Process[] GetProcessesByName(string processName)
- {
int [] pids = GetProcesses_internal ();
if (pids == null)
return new Process [0];
-
+
var proclist = new List<Process> (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);
+ proclist.Add (GetProcessById (pids [i]));
} catch (SystemException) {
/* The process might exit
* between
return proclist.ToArray ();
}
- [MonoTODO]
- public static Process[] GetProcessesByName(string processName, string machineName) {
- throw new NotImplementedException();
- }
-
private static bool IsLocalMachine (string machineName)
{
if (machineName == "." || machineName.Length == 0)
#if MONO_FEATURE_PROCESS_START
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static bool ShellExecuteEx_internal(ProcessStartInfo startInfo, ref ProcInfo proc_info);
+ private extern static bool ShellExecuteEx_internal(ProcessStartInfo startInfo, ref ProcInfo procInfo);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static bool CreateProcess_internal(ProcessStartInfo startInfo, IntPtr stdin, IntPtr stdout, IntPtr stderr, ref ProcInfo proc_info);
+ private extern static bool CreateProcess_internal(ProcessStartInfo startInfo, IntPtr stdin, IntPtr stdout, IntPtr stderr, ref ProcInfo procInfo);
bool StartWithShellExecuteEx (ProcessStartInfo startInfo)
{
if (startInfo.environmentVariables != null)
throw new InvalidOperationException(SR.GetString(SR.CantUseEnvVars));
- ProcInfo proc_info = new ProcInfo();
+ ProcInfo procInfo = new ProcInfo();
bool ret;
- FillUserInfo (startInfo, ref proc_info);
+ FillUserInfo (startInfo, ref procInfo);
try {
- ret = ShellExecuteEx_internal (startInfo, ref proc_info);
+ ret = ShellExecuteEx_internal (startInfo, ref procInfo);
} finally {
- if (proc_info.Password != IntPtr.Zero)
- Marshal.ZeroFreeBSTR (proc_info.Password);
- proc_info.Password = IntPtr.Zero;
+ if (procInfo.Password != IntPtr.Zero)
+ Marshal.ZeroFreeBSTR (procInfo.Password);
+ procInfo.Password = IntPtr.Zero;
}
if (!ret) {
- throw new Win32Exception (-proc_info.pid);
+ throw new Win32Exception (-procInfo.pid);
}
- m_processHandle = new SafeProcessHandle (proc_info.process_handle, true);
- haveProcessHandle = true;
- SetProcessId (proc_info.pid);
-
- if (watchForExit)
- EnsureWatchingForExit ();
+ SetProcessHandle (new SafeProcessHandle (procInfo.process_handle, true));
+ SetProcessId (procInfo.pid);
return ret;
}
if (this.disposed)
throw new ObjectDisposedException (GetType ().Name);
- var proc_info = new ProcInfo ();
+ var procInfo = new ProcInfo ();
if (startInfo.HaveEnvVars) {
- string [] strs = new string [startInfo.EnvironmentVariables.Count];
- startInfo.EnvironmentVariables.Keys.CopyTo (strs, 0);
- proc_info.envKeys = strs;
+ List<string> envVariables = null;
+ StringBuilder sb = null;
+
+ foreach (DictionaryEntry de in startInfo.EnvironmentVariables) {
+ if (de.Value == null)
+ continue;
+
+ if (envVariables == null)
+ envVariables = new List<string> ();
+
+ if (sb == null)
+ sb = new StringBuilder ();
+ else
+ sb.Clear ();
+
+ sb.Append ((string) de.Key);
+ sb.Append ('=');
+ sb.Append ((string) de.Value);
- strs = new string [startInfo.EnvironmentVariables.Count];
- startInfo.EnvironmentVariables.Values.CopyTo (strs, 0);
- proc_info.envValues = strs;
+ envVariables.Add (sb.ToString ());
+ }
+
+ procInfo.envVariables = envVariables?.ToArray ();
}
MonoIOError error;
stderr_write = MonoIO.ConsoleError;
}
- FillUserInfo (startInfo, ref proc_info);
+ FillUserInfo (startInfo, ref procInfo);
//
// FIXME: For redirected pipes we need to send descriptors of
// stdin_write, stdout_read, stderr_read to child process and
// close them there (fork makes exact copy of parent's descriptors)
//
- if (!CreateProcess_internal (startInfo, stdin_read, stdout_write, stderr_write, ref proc_info)) {
- throw new Win32Exception (-proc_info.pid, "ApplicationName='" + startInfo.FileName + "', CommandLine='" + startInfo.Arguments +
- "', CurrentDirectory='" + startInfo.WorkingDirectory + "', Native error= " + Win32Exception.W32ErrorMessage (-proc_info.pid));
+ if (!CreateProcess_internal (startInfo, stdin_read, stdout_write, stderr_write, ref procInfo)) {
+ throw new Win32Exception (-procInfo.pid, "ApplicationName='" + startInfo.FileName + "', CommandLine='" + startInfo.Arguments +
+ "', CurrentDirectory='" + startInfo.WorkingDirectory + "', Native error= " + Win32Exception.GetErrorMessage (-procInfo.pid));
}
} catch {
if (startInfo.RedirectStandardInput) {
throw;
} finally {
- if (proc_info.Password != IntPtr.Zero) {
- Marshal.ZeroFreeBSTR (proc_info.Password);
- proc_info.Password = IntPtr.Zero;
+ if (procInfo.Password != IntPtr.Zero) {
+ Marshal.ZeroFreeBSTR (procInfo.Password);
+ procInfo.Password = IntPtr.Zero;
}
}
- m_processHandle = new SafeProcessHandle (proc_info.process_handle, true);
- haveProcessHandle = true;
- SetProcessId (proc_info.pid);
+ SetProcessHandle (new SafeProcessHandle (procInfo.process_handle, true));
+ SetProcessId (procInfo.pid);
+#pragma warning disable 618
+
if (startInfo.RedirectStandardInput) {
- //
- // FIXME: The descriptor needs to be closed but due to wapi io-layer
- // not coping with duplicated descriptors any StandardInput write fails
- //
- // MonoIO.Close (stdin_read, out error);
+ MonoIO.Close (stdin_read, out error);
#if MOBILE
var stdinEncoding = Encoding.Default;
standardError = new StreamReader (new FileStream (stderr_read, FileAccess.Read, true, 8192), stderrEncoding, true);
}
-
- if (watchForExit)
- EnsureWatchingForExit ();
+#pragma warning restore
return true;
}
// Note that ProcInfo.Password must be freed.
- private static void FillUserInfo (ProcessStartInfo startInfo, ref ProcInfo proc_info)
+ private static void FillUserInfo (ProcessStartInfo startInfo, ref ProcInfo procInfo)
{
if (startInfo.UserName.Length != 0) {
- proc_info.UserName = startInfo.UserName;
- proc_info.Domain = startInfo.Domain;
+ procInfo.UserName = startInfo.UserName;
+ procInfo.Domain = startInfo.Domain;
if (startInfo.Password != null)
- proc_info.Password = Marshal.SecureStringToBSTR (startInfo.Password);
+ procInfo.Password = Marshal.SecureStringToBSTR (startInfo.Password);
else
- proc_info.Password = IntPtr.Zero;
- proc_info.LoadUserProfile = startInfo.LoadUserProfile;
+ procInfo.Password = IntPtr.Zero;
+ procInfo.LoadUserProfile = startInfo.LoadUserProfile;
}
}
#else
}
[Obsolete ("Process.Start is not supported on the current platform.", true)]
- public static Process Start(string fileName, string username, SecureString password, string domain)
+ public static Process Start(string fileName, string userName, SecureString password, string domain)
{
throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
}
[Obsolete ("Process.Start is not supported on the current platform.", true)]
- public static Process Start(string fileName, string arguments, string username, SecureString password, string domain)
+ public static Process Start(string fileName, string arguments, string userName, SecureString password, string domain)
{
throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
}