Xamarin Public Jenkins (auto-signing) 8e12397d70 Imported Upstream version 5.18.0.205
Former-commit-id: 7f59f7e792705db773f1caecdaa823092f4e2927
2018-11-16 08:20:38 +00:00

910 lines
29 KiB
C#

//
// System.Diagnostics.Process.cs
//
// Authors:
// Dick Porter (dick@ximian.com)
// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
// (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.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");
}
}
/* 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 = Encoding.Default;
#else
var stdinEncoding = 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();
}
}
}
}
}
}