| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919 |
- //
- // System.Diagnostics.Process.cs
- //
- // Authors:
- // Dick Porter ([email protected])
- // Andreas Nahr ([email protected])
- // Gonzalo Paniagua Javier ([email protected])
- //
- // (C) 2002 Ximian, Inc.
- // (C) 2003 Andreas Nahr
- // (c) 2004,2005,2006 Novell, Inc. (http://www.novell.com)
- //
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- using System.IO;
- using System.Text;
- using System.Collections;
- using System.ComponentModel;
- using System.ComponentModel.Design;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using System.Runtime.Remoting.Messaging;
- using System.Security.Permissions;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Security;
- using System.Threading;
- using Microsoft.Win32;
- using Microsoft.Win32.SafeHandles;
- namespace System.Diagnostics
- {
- public partial class Process : Component
- {
- [StructLayout(LayoutKind.Sequential)]
- private struct ProcInfo
- {
- public IntPtr process_handle;
- /* If thread_handle is ever needed for
- * something, take out the CloseHandle() in
- * the Start_internal icall in
- * mono/metadata/process.c
- */
- public int pid; // Contains -GetLastError () on failure.
- public string[] envVariables;
- public string UserName;
- public string Domain;
- public IntPtr Password;
- public bool LoadUserProfile;
- };
- string process_name;
- static ProcessModule current_main_module;
- /* Private constructor called from other methods */
- private Process (SafeProcessHandle handle, int id) {
- SetProcessHandle (handle);
- SetProcessId (id);
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("Base process priority.")]
- public int BasePriority {
- get { return 0; }
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("Handles for this process.")]
- public int HandleCount {
- get {
- return(0);
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
- [MonitoringDescription ("The main module of the process.")]
- public ProcessModule MainModule {
- get {
- /* Optimize Process.GetCurrentProcess ().MainModule */
- if (processId == NativeMethods.GetCurrentProcessId ()) {
- if (current_main_module == null)
- current_main_module = this.Modules [0];
- return current_main_module;
- } else {
- return this.Modules [0];
- }
- }
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The handle of the main window of the process.")]
- public IntPtr MainWindowHandle {
- get {
- return((IntPtr)0);
- }
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The title of the main window of the process.")]
- public string MainWindowTitle {
- get {
- return("null");
- }
- }
- private static void AppendArguments (StringBuilder stringBuilder, Collection<string> argumentList)
- {
- if (argumentList.Count > 0) {
- foreach (string argument in argumentList) {
- PasteArguments.AppendArgument (stringBuilder, argument);
- }
- }
- }
- /* Returns the list of process modules. The main module is
- * element 0.
- */
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern ProcessModule[] GetModules_internal(IntPtr handle);
- ProcessModule[] GetModules_internal (SafeProcessHandle handle)
- {
- bool release = false;
- try {
- handle.DangerousAddRef (ref release);
- return GetModules_internal (handle.DangerousGetHandle ());
- } finally {
- if (release)
- handle.DangerousRelease ();
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
- [MonitoringDescription ("The modules that are loaded as part of this process.")]
- public ProcessModuleCollection Modules {
- get {
- if (modules == null) {
- SafeProcessHandle handle = null;
- try {
- handle = GetProcessHandle (NativeMethods.PROCESS_QUERY_INFORMATION);
- modules = new ProcessModuleCollection (GetModules_internal (handle));
- } finally {
- ReleaseProcessHandle (handle);
- }
- }
- return modules;
- }
- }
- /* 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]
- [Obsolete ("Use NonpagedSystemMemorySize64")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The number of bytes that are not pageable.")]
- public int NonpagedSystemMemorySize {
- get {
- return(0);
- }
- }
- [Obsolete ("Use PagedMemorySize64")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The number of bytes that are paged.")]
- public int PagedMemorySize {
- get {
- return(int)PagedMemorySize64;
- }
- }
- [Obsolete ("Use PagedSystemMemorySize64")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The amount of paged system memory in bytes.")]
- public int PagedSystemMemorySize {
- get {
- return(int)PagedMemorySize64;
- }
- }
- [MonoTODO]
- [Obsolete ("Use PeakPagedMemorySize64")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The maximum amount of paged memory used by this process.")]
- public int PeakPagedMemorySize {
- get {
- return(0);
- }
- }
- [Obsolete ("Use PeakVirtualMemorySize64")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
- public int PeakVirtualMemorySize {
- get {
- int error;
- return (int)GetProcessData (processId, 8, out error);
- }
- }
- [Obsolete ("Use PeakWorkingSet64")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The maximum amount of system memory used by this process.")]
- public int PeakWorkingSet {
- get {
- int error;
- return (int)GetProcessData (processId, 5, out error);
- }
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The number of bytes that are not pageable.")]
- [ComVisible (false)]
- public long NonpagedSystemMemorySize64 {
- get {
- return(0);
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The number of bytes that are paged.")]
- [ComVisible (false)]
- public long PagedMemorySize64 {
- get {
- int error;
- return GetProcessData (processId, 12, out error);
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The amount of paged system memory in bytes.")]
- [ComVisible (false)]
- public long PagedSystemMemorySize64 {
- get {
- return PagedMemorySize64;
- }
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The maximum amount of paged memory used by this process.")]
- [ComVisible (false)]
- public long PeakPagedMemorySize64 {
- get {
- return(0);
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
- [ComVisible (false)]
- public long PeakVirtualMemorySize64 {
- get {
- int error;
- return GetProcessData (processId, 8, out error);
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The maximum amount of system memory used by this process.")]
- [ComVisible (false)]
- public long PeakWorkingSet64 {
- get {
- int error;
- return GetProcessData (processId, 5, out error);
- }
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("Process will be of higher priority while it is actively used.")]
- public bool PriorityBoostEnabled {
- get {
- return(false);
- }
- set {
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The amount of memory exclusively used by this process.")]
- [Obsolete ("Use PrivateMemorySize64")]
- public int PrivateMemorySize {
- get {
- int error;
- return (int)GetProcessData (processId, 6, out error);
- }
- }
- [MonoNotSupported ("")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The session ID for this process.")]
- public int SessionId {
- get { return 0; }
- }
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static string ProcessName_internal(IntPtr handle);
- static string ProcessName_internal(SafeProcessHandle handle)
- {
- bool release = false;
- try {
- handle.DangerousAddRef (ref release);
- return ProcessName_internal (handle.DangerousGetHandle ());
- } finally {
- if (release)
- handle.DangerousRelease ();
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The name of this process.")]
- public string ProcessName {
- get {
- if (process_name == null) {
- SafeProcessHandle handle = null;
- try {
- handle = GetProcessHandle (NativeMethods.PROCESS_QUERY_INFORMATION);
- process_name = ProcessName_internal (handle);
- /* If process_name is _still_ null, assume the process has exited or is inaccessible */
- if (process_name == null)
- 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 */
- if(process_name.EndsWith(".exe") || process_name.EndsWith(".bat") || process_name.EndsWith(".com"))
- process_name = process_name.Substring (0, process_name.Length - 4);
- } finally {
- ReleaseProcessHandle (handle);
- }
- }
- return process_name;
- }
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("Allowed processor that can be used by this process.")]
- public IntPtr ProcessorAffinity {
- get {
- return((IntPtr)0);
- }
- set {
- }
- }
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("Is this process responsive.")]
- public bool Responding {
- get {
- return(false);
- }
- }
- #if !MONO_FEATURE_PROCESS_START
- [Obsolete ("Process.StartInfo is not supported on the current platform.", true)]
- public ProcessStartInfo StartInfo {
- get { throw new PlatformNotSupportedException ("Process.StartInfo is not supported on the current platform."); }
- set { throw new PlatformNotSupportedException ("Process.StartInfo is not supported on the current platform."); }
- }
- [Obsolete ("Process.StandardError is not supported on the current platform.", true)]
- public StreamReader StandardError {
- get { throw new PlatformNotSupportedException ("Process.StandardError is not supported on the current platform."); }
- }
- [Obsolete ("Process.StandardInput is not supported on the current platform.", true)]
- public StreamWriter StandardInput {
- get { throw new PlatformNotSupportedException ("Process.StandardInput is not supported on the current platform."); }
- }
- [Obsolete ("Process.StandardOutput is not supported on the current platform.", true)]
- public StreamReader StandardOutput {
- get { throw new PlatformNotSupportedException ("Process.StandardOutput is not supported on the current platform."); }
- }
- #endif // !MONO_FEATURE_PROCESS_START
- [MonoTODO]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The number of threads of this process.")]
- public ProcessThreadCollection Threads {
- get {
- if (threads == null) {
- int error;
- // This'll return a correctly-sized array of empty ProcessThreads for now.
- threads = new ProcessThreadCollection(new ProcessThread [GetProcessData (processId, 0, out error)]);
- }
- return threads;
- }
- }
- [Obsolete ("Use VirtualMemorySize64")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The amount of virtual memory currently used for this process.")]
- public int VirtualMemorySize {
- get {
- int error;
- return (int)GetProcessData (processId, 7, out error);
- }
- }
- [Obsolete ("Use WorkingSet64")]
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The amount of physical memory currently used for this process.")]
- public int WorkingSet {
- get {
- int error;
- return (int)GetProcessData (processId, 4, out error);
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The amount of memory exclusively used by this process.")]
- [ComVisible (false)]
- public long PrivateMemorySize64 {
- get {
- int error;
- return GetProcessData (processId, 6, out error);
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The amount of virtual memory currently used for this process.")]
- [ComVisible (false)]
- public long VirtualMemorySize64 {
- get {
- int error;
- return GetProcessData (processId, 7, out error);
- }
- }
- [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- [MonitoringDescription ("The amount of physical memory currently used for this process.")]
- [ComVisible (false)]
- public long WorkingSet64 {
- get {
- int error;
- return GetProcessData (processId, 4, out error);
- }
- }
- public bool CloseMainWindow ()
- {
- SafeProcessHandle handle = null;
- try {
- handle = GetProcessHandle (NativeMethods.PROCESS_TERMINATE);
- return NativeMethods.TerminateProcess(handle, -2);
- } finally {
- ReleaseProcessHandle(handle);
- }
- }
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static IntPtr GetProcess_internal(int pid);
- [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 ());
- /* 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));
- }
- public static Process[] GetProcessesByName(string processName, string machineName)
- {
- if (machineName == null)
- throw new ArgumentNullException ("machineName");
- if (!IsLocalMachine (machineName))
- throw new NotImplementedException ();
- Process[] processes = GetProcesses ();
- if (processes.Length == 0)
- return processes;
- int size = 0;
- for (int i = 0; i < processes.Length; i++) {
- var process = processes[i];
- try {
- if (String.Compare (processName, process.ProcessName, true) == 0)
- processes [size++] = process;
- else
- process.Dispose();
- } catch (SystemException) {
- /* The process might exit between GetProcesses_internal and GetProcessById */
- }
- }
- 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)
- throw new ArgumentNullException ("machineName");
- if (!IsLocalMachine (machineName))
- throw new NotImplementedException ();
- 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 {
- proclist.Add (GetProcessById (pids [i]));
- } catch (SystemException) {
- /* The process might exit
- * between
- * GetProcesses_internal and
- * GetProcessById
- */
- }
- }
- return proclist.ToArray ();
- }
- private static bool IsLocalMachine (string machineName)
- {
- if (machineName == "." || machineName.Length == 0)
- return true;
- return (string.Compare (machineName, Environment.MachineName, true) == 0);
- }
- #if MONO_FEATURE_PROCESS_START
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- 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 procInfo);
- bool StartWithShellExecuteEx (ProcessStartInfo startInfo)
- {
- 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));
- ProcInfo procInfo = new ProcInfo();
- bool ret;
- FillUserInfo (startInfo, ref procInfo);
- try {
- ret = ShellExecuteEx_internal (startInfo, ref procInfo);
- } finally {
- if (procInfo.Password != IntPtr.Zero)
- Marshal.ZeroFreeBSTR (procInfo.Password);
- procInfo.Password = IntPtr.Zero;
- }
- if (!ret) {
- throw new Win32Exception (-procInfo.pid);
- }
- SetProcessHandle (new SafeProcessHandle (procInfo.process_handle, true));
- SetProcessId (procInfo.pid);
- return ret;
- }
- //
- // Creates a pipe with read and write descriptors
- //
- static void CreatePipe (out IntPtr read, out IntPtr write, bool writeDirection)
- {
- MonoIOError error;
- //
- // Creates read/write pipe from parent -> child perspective
- // a child process uses same descriptors after fork. That's
- // 4 descriptors in total where only 2. One in child, one in parent
- // should be active and the other 2 closed. Which ones depends on
- // comunication direction
- //
- // parent --------> child (parent can write, child can read)
- //
- // read: closed read: used
- // write: used write: closed
- //
- //
- // parent <-------- child (parent can read, child can write)
- //
- // read: used read: closed
- // write: closed write: used
- //
- // It can still be tricky for predefined descriptiors http://unixwiz.net/techtips/remap-pipe-fds.html
- //
- if (!MonoIO.CreatePipe (out read, out write, out error))
- throw MonoIO.GetException (error);
- if (IsWindows) {
- const int DUPLICATE_SAME_ACCESS = 0x00000002;
- var tmp = writeDirection ? write : read;
- if (!MonoIO.DuplicateHandle (Process.GetCurrentProcess ().Handle, tmp, Process.GetCurrentProcess ().Handle, out tmp, 0, 0, DUPLICATE_SAME_ACCESS, out error))
- throw MonoIO.GetException (error);
- if (writeDirection) {
- if (!MonoIO.Close (write, out error))
- throw MonoIO.GetException (error);
- write = tmp;
- } else {
- if (!MonoIO.Close (read, out error))
- throw MonoIO.GetException (error);
- read = tmp;
- }
- }
- }
- 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 false;
- }
- }
- 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));
- if (this.disposed)
- throw new ObjectDisposedException (GetType ().Name);
- var procInfo = new ProcInfo ();
- if (startInfo.HaveEnvVars) {
- List<string> envVariables = new List<string> ();
- foreach (DictionaryEntry de in startInfo.EnvironmentVariables) {
- if (de.Value == null)
- continue;
- envVariables.Add (string.Concat (
- (string) de.Key,
- "=",
- (string) de.Value));
- }
- procInfo.envVariables = envVariables.ToArray ();
- }
- MonoIOError error;
- IntPtr stdin_read = IntPtr.Zero, stdin_write = IntPtr.Zero;
- IntPtr stdout_read = IntPtr.Zero, stdout_write = IntPtr.Zero;
- IntPtr stderr_read = IntPtr.Zero, stderr_write = IntPtr.Zero;
- try {
- if (startInfo.RedirectStandardInput) {
- CreatePipe (out stdin_read, out stdin_write, true);
- } else {
- stdin_read = MonoIO.ConsoleInput;
- stdin_write = IntPtr.Zero;
- }
- if (startInfo.RedirectStandardOutput) {
- CreatePipe (out stdout_read, out stdout_write, false);
- } else {
- stdout_read = IntPtr.Zero;
- stdout_write = MonoIO.ConsoleOutput;
- }
- if (startInfo.RedirectStandardError) {
- CreatePipe (out stderr_read, out stderr_write, false);
- } else {
- stderr_read = IntPtr.Zero;
- stderr_write = MonoIO.ConsoleError;
- }
- 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 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) {
- if (stdin_read != IntPtr.Zero)
- MonoIO.Close (stdin_read, out error);
- if (stdin_write != IntPtr.Zero)
- MonoIO.Close (stdin_write, out error);
- }
- if (startInfo.RedirectStandardOutput) {
- if (stdout_read != IntPtr.Zero)
- MonoIO.Close (stdout_read, out error);
- if (stdout_write != IntPtr.Zero)
- MonoIO.Close (stdout_write, out error);
- }
- if (startInfo.RedirectStandardError) {
- if (stderr_read != IntPtr.Zero)
- MonoIO.Close (stderr_read, out error);
- if (stderr_write != IntPtr.Zero)
- MonoIO.Close (stderr_write, out error);
- }
- throw;
- } finally {
- if (procInfo.Password != IntPtr.Zero) {
- Marshal.ZeroFreeBSTR (procInfo.Password);
- procInfo.Password = IntPtr.Zero;
- }
- }
- SetProcessHandle (new SafeProcessHandle (procInfo.process_handle, true));
- SetProcessId (procInfo.pid);
-
- #pragma warning disable 618
- if (startInfo.RedirectStandardInput) {
- MonoIO.Close (stdin_read, out error);
- #if MOBILE
- var stdinEncoding = startInfo.StandardInputEncoding ?? Encoding.Default;
- #else
- var stdinEncoding = startInfo.StandardInputEncoding ?? Console.InputEncoding;
- #endif
- standardInput = new StreamWriter (new FileStream (stdin_write, FileAccess.Write, true, 8192), stdinEncoding) {
- AutoFlush = true
- };
- }
- if (startInfo.RedirectStandardOutput) {
- MonoIO.Close (stdout_write, out error);
- Encoding stdoutEncoding = startInfo.StandardOutputEncoding ?? Console.OutputEncoding;
- standardOutput = new StreamReader (new FileStream (stdout_read, FileAccess.Read, true, 8192), stdoutEncoding, true);
- }
- if (startInfo.RedirectStandardError) {
- MonoIO.Close (stderr_write, out error);
- Encoding stderrEncoding = startInfo.StandardErrorEncoding ?? Console.OutputEncoding;
- standardError = new StreamReader (new FileStream (stderr_read, FileAccess.Read, true, 8192), stderrEncoding, true);
- }
- #pragma warning restore
- return true;
- }
- // Note that ProcInfo.Password must be freed.
- private static void FillUserInfo (ProcessStartInfo startInfo, ref ProcInfo procInfo)
- {
- if (startInfo.UserName.Length != 0) {
- procInfo.UserName = startInfo.UserName;
- procInfo.Domain = startInfo.Domain;
- if (startInfo.Password != null)
- procInfo.Password = Marshal.SecureStringToBSTR (startInfo.Password);
- else
- procInfo.Password = IntPtr.Zero;
- procInfo.LoadUserProfile = startInfo.LoadUserProfile;
- }
- }
- #else
- [Obsolete ("Process.Start is not supported on the current platform.", true)]
- public bool Start ()
- {
- 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 (ProcessStartInfo startInfo)
- {
- 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)
- {
- 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)
- {
- 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 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)
- {
- throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
- }
- #endif // MONO_FEATURE_PROCESS_START
- #if !MONO_FEATURE_PROCESS_START
- [Obsolete ("Process.BeginOutputReadLine is not supported on the current platform.", true)]
- public void BeginOutputReadLine ()
- {
- throw new PlatformNotSupportedException ("Process.BeginOutputReadLine is not supported on the current platform.");
- }
- [Obsolete ("Process.BeginOutputReadLine is not supported on the current platform.", true)]
- public void CancelOutputRead ()
- {
- throw new PlatformNotSupportedException ("Process.BeginOutputReadLine is not supported on the current platform.");
- }
- [Obsolete ("Process.BeginOutputReadLine is not supported on the current platform.", true)]
- public void BeginErrorReadLine ()
- {
- throw new PlatformNotSupportedException ("Process.BeginOutputReadLine is not supported on the current platform.");
- }
- [Obsolete ("Process.BeginOutputReadLine is not supported on the current platform.", true)]
- public void CancelErrorRead ()
- {
- throw new PlatformNotSupportedException ("Process.BeginOutputReadLine is not supported on the current platform.");
- }
- #endif // !MONO_FEATURE_PROCESS_START
- /// <devdoc>
- /// Raise the Exited event, but make sure we don't do it more than once.
- /// </devdoc>
- /// <internalonly/>
- void RaiseOnExited() {
- if (!watchForExit)
- return;
- if (!raisedOnExited) {
- lock (this) {
- if (!raisedOnExited) {
- raisedOnExited = true;
- OnExited();
- }
- }
- }
- }
- }
- }
|