// </copyright>
//------------------------------------------------------------------------------
+#if MONO
+#undef FEATURE_PAL
+#endif
+
namespace System.Diagnostics {
using System.Text;
using System.Threading;
PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust"),
HostProtection(SharedState=true, Synchronization=true, ExternalProcessMgmt=true, SelfAffectingProcessMgmt=true)
]
- public class Process : Component {
+ public partial class Process : Component {
//
// FIELDS
//
SafeProcessHandle m_processHandle;
bool isRemoteMachine;
string machineName;
+#if !MONO
ProcessInfo processInfo;
+#endif
Int32 m_processAccess;
#if !FEATURE_PAL
DateTime exitTime;
bool haveExitTime;
-
+
+#if !MONO
bool responding;
bool haveResponding;
bool priorityBoostEnabled;
bool havePriorityBoostEnabled;
+#endif
bool raisedOnExited;
RegisteredWaitHandle registeredWaitHandle;
OperatingSystem operatingSystem;
bool disposed;
+#if !MONO
static object s_CreateProcessLock = new object();
+#endif
// This enum defines the operation mode for redirected process stream.
// We don't support switching between synchronous mode and asynchronous mode.
StreamReadMode outputStreamReadMode;
StreamReadMode errorStreamReadMode;
+#if MONO
+ StreamReadMode inputStreamReadMode;
+#endif
// Support for asynchrously reading streams
[Browsable(true), MonitoringDescription(SR.ProcessAssociated)]
internal bool pendingOutputRead;
internal bool pendingErrorRead;
-
+#if !MONO
private static SafeFileHandle InvalidPipeHandle = new SafeFileHandle(IntPtr.Zero, false);
+#endif
#if DEBUG
internal static TraceSwitch processTracing = new TraceSwitch("processTracing", "Controls debug output from Process component");
#else
[ResourceExposure(ResourceScope.Machine)]
Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo) : base() {
Debug.Assert(SyntaxCheck.CheckMachineName(machineName), "The machine name should be valid!");
+#if !MONO
this.processInfo = processInfo;
+#endif
this.machineName = machineName;
this.isRemoteMachine = isRemoteMachine;
this.processId = processId;
}
}
- #if !FEATURE_PAL
+ #if !FEATURE_PAL && !MONO
/// <devdoc>
/// <para>
/// Gets the base priority of
return processInfo.basePriority;
}
}
-#endif // FEATURE_PAL
+#endif // !FEATURE_PAL && !MONO
/// <devdoc>
/// <para>
public int ExitCode {
get {
EnsureState(State.Exited);
+#if MONO
+ if (exitCode == -1)
+ throw new InvalidOperationException ("Cannot get the exit code from a non-child process on Unix");
+#endif
return exitCode;
}
}
}
if (signaled)
{
+ /* If it's a non-child process, it's impossible to get its exit code on
+ * Unix. We don't throw here, but GetExitCodeProcess (in the io-layer)
+ * will set exitCode to -1, and we will throw if we try to call ExitCode */
if (!NativeMethods.GetExitCodeProcess(handle, out exitCode))
throw new Win32Exception();
}
}
-#if !FEATURE_PAL
+ [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public SafeProcessHandle SafeHandle {
+ get {
+ EnsureState(State.Associated);
+ return OpenProcessHandle(this.m_processAccess);
+ }
+ }
+
+#if !FEATURE_PAL && !MONO
/// <devdoc>
/// <para>
/// Gets the number of handles that are associated
return processInfo.handleCount;
}
}
-#endif // !FEATURE_PAL
+#endif // !FEATURE_PAL && !MONO
/// <devdoc>
/// <para>
#if !FEATURE_PAL
+#if !MONO
/// <devdoc>
/// <para>
/// Returns the window handle of the main window of the associated process.
}
}
}
+#endif
/// <devdoc>
/// <para>
}
}
+#if !MONO
/// <devdoc>
/// <para>
/// Gets
return processInfo.virtualBytesPeak;
}
}
+#endif
private OperatingSystem OperatingSystem {
get {
}
}
+#if !MONO
/// <devdoc>
/// <para>
/// Gets or sets a value indicating whether the associated process priority
}
}
}
+#endif
/// <devdoc>
/// <para>
throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
}
+#if !MONO
// BelowNormal and AboveNormal are only available on Win2k and greater.
if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0) &&
(OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) {
throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
}
+#endif // !MONO
SafeProcessHandle handle = null;
}
}
+#if !MONO
/// <devdoc>
/// Returns the number of bytes that the associated process has allocated that cannot
/// be shared with other processes.
return processInfo.privateBytes;
}
}
+#endif
/// <devdoc>
/// Returns the amount of time the process has spent running code inside the operating
}
}
+#if !MONO
/// <devdoc>
/// <para>
/// Gets
return processInfo.sessionId;
}
}
+#endif // !MONO
#endif // !FEATURE_PAL
+#if MONO_FEATURE_PROCESS_START
/// <devdoc>
/// <para>
/// Gets or sets the properties to pass into the <see cref='System.Diagnostics.Process.Start'/> method for the <see cref='System.Diagnostics.Process'/>
startInfo = value;
}
}
+#endif
#if !FEATURE_PAL
/// <devdoc>
#if !FEATURE_PAL
+#if !MONO
/// <devdoc>
/// <para>
/// Gets the set of threads that are running in the associated
return threads;
}
}
+#endif
/// <devdoc>
/// Returns the amount of time the associated process has spent utilizing the CPU.
}
}
+#if !MONO
/// <devdoc>
/// Returns the amount of virtual memory that the associated process has requested.
/// </devdoc>
return unchecked((int)processInfo.virtualBytes);
}
}
+#endif // !MONO
+
#endif // !FEATURE_PAL
+#if !MONO
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessVirtualMemorySize)]
[System.Runtime.InteropServices.ComVisible(false)]
public long VirtualMemorySize64 {
return processInfo.virtualBytes;
}
}
+#endif
/// <devdoc>
/// <para>
}
}
-
+#if MONO_FEATURE_PROCESS_START
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
throw new InvalidOperationException(SR.GetString(SR.CantGetStandardIn));
}
+#if MONO
+ inputStreamReadMode = StreamReadMode.syncMode;
+#endif
return standardInput;
}
}
return standardError;
}
}
+#endif
-#if !FEATURE_PAL
+#if !FEATURE_PAL && !MONO
/// <devdoc>
/// Returns the total amount of physical memory the associated process.
/// </devdoc>
return unchecked((int)processInfo.workingSet);
}
}
-#endif // !FEATURE_PAL
+#endif // !FEATURE_PAL && !MONO
+#if !MONO
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), MonitoringDescription(SR.ProcessWorkingSet)]
[System.Runtime.InteropServices.ComVisible(false)]
public long WorkingSet64 {
return processInfo.workingSet;
}
}
+#endif
[Category("Behavior"), MonitoringDescription(SR.ProcessExited)]
public event EventHandler Exited {
}
}
-#if !FEATURE_PAL
-
+#if !FEATURE_PAL && !MONO
/// <devdoc>
/// <para>
/// Closes a process that has a user interface by sending a close message
NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
return true;
}
-
-#endif // !FEATURE_PAL
+#endif // !FEATURE_PAL && !MONO
/// <devdoc>
/// Release the temporary handle we used to get process information.
machineName = ".";
raisedOnExited = false;
+#if MONO
+ //Call close on streams if the user never saw them.
+ //A stream in the undefined mode was never fetched by the user.
+ //A stream in the async mode is wrapped on a AsyncStreamReader and we should dispose that instead.
+ // no way for users to get a hand on a AsyncStreamReader.
+ var tmpIn = standardInput;
+ standardInput = null;
+ if (inputStreamReadMode == StreamReadMode.undefined && tmpIn != null)
+ tmpIn.Close ();
+
+ var tmpOut = standardOutput;
+ standardOutput = null;
+ if (outputStreamReadMode == StreamReadMode.undefined && tmpOut != null)
+ tmpOut.Close ();
+
+ tmpOut = standardError;
+ standardError = null;
+ if (errorStreamReadMode == StreamReadMode.undefined && tmpOut != null)
+ tmpOut.Close ();
+
+ var tmpAsync = output;
+ output = null;
+ if (outputStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
+ tmpAsync.CancelOperation ();
+ tmpAsync.Close ();
+ }
+
+ tmpAsync = error;
+ error = null;
+ if (errorStreamReadMode == StreamReadMode.asyncMode && tmpAsync != null) {
+ tmpAsync.CancelOperation ();
+ tmpAsync.Close ();
+ }
+#else
//Don't call close on the Readers and writers
//since they might be referenced by somebody else while the
//process is still alive but this method called.
output = null;
error = null;
+#endif
Refresh();
}
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
void EnsureState(State state) {
+#if !MONO
if ((state & State.IsWin2k) != (State)0) {
#if !FEATURE_PAL
if (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)
#endif // !FEATURE_PAL
throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
}
+#endif // !MONO
if ((state & State.Associated) != (State)0)
if (!Associated)
if ((state & State.HaveId) != (State)0) {
if (!haveProcessId) {
-#if !FEATURE_PAL
+#if !FEATURE_PAL && !MONO
if (haveProcessHandle) {
SetProcessId(ProcessManager.GetProcessIdFromHandle(m_processHandle));
}
#else
EnsureState(State.Associated);
throw new InvalidOperationException(SR.GetString(SR.ProcessIdRequired));
-#endif // !FEATURE_PAL
+#endif // !FEATURE_PAL && !MONO
}
}
}
if ((state & State.HaveProcessInfo) != (State)0) {
-#if !FEATURE_PAL
+#if !FEATURE_PAL && !MONO
if (processInfo == null) {
if ((state & State.HaveId) == (State)0) EnsureState(State.HaveId);
ProcessInfo[] processInfos = ProcessManager.GetProcessInfos(machineName);
}
#else
throw new InvalidOperationException(SR.GetString(SR.NoProcessInfo));
-#endif // !FEATURE_PAL
+#endif // !FEATURE_PAL && !MONO
}
if ((state & State.Exited) != (State)0) {
}
public static void EnterDebugMode() {
+#if !MONO
if (ProcessManager.IsNt) {
SetPrivilege("SeDebugPrivilege", NativeMethods.SE_PRIVILEGE_ENABLED);
}
+#endif
}
+#if !MONO
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
private static void SetPrivilege(string privilegeName, int attrib) {
SafeNativeMethods.CloseHandle(hToken);
}
}
+#endif
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static void LeaveDebugMode() {
+#if !MONO
if (ProcessManager.IsNt) {
SetPrivilege("SeDebugPrivilege", 0);
}
+#endif
}
+#if !MONO
/// <devdoc>
/// <para>
/// Returns a new <see cref='System.Diagnostics.Process'/> component given a process identifier and
}
Debug.Unindent();
}
-#endif
+#endif // DEBUG
return processes;
}
+#endif // !MONO
#endif // !FEATURE_PAL
else {
EnsureState(State.HaveId | State.IsLocal);
SafeProcessHandle handle = SafeProcessHandle.InvalidHandle;
-#if !FEATURE_PAL
+#if !FEATURE_PAL && !MONO
handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
#else
IntPtr pseudohandle = NativeMethods.GetCurrentProcess();
NativeMethods.DUPLICATE_CLOSE_SOURCE)) {
throw new Win32Exception();
}
-#endif // !FEATURE_PAL
+#endif // !FEATURE_PAL && !MONO
if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) {
if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
return m_processHandle;
}
+#if !MONO
/// <devdoc>
/// Raise the Exited event, but make sure we don't do it more than once.
/// </devdoc>
}
}
}
+#endif
/// <devdoc>
/// <para>
/// </para>
/// </devdoc>
public void Refresh() {
+#if !MONO
processInfo = null;
+#endif
#if !FEATURE_PAL
threads = null;
modules = null;
haveProcessorAffinity = false;
havePriorityClass = false;
haveExitTime = false;
+#if !MONO
haveResponding = false;
havePriorityBoostEnabled = false;
+#endif
}
/// <devdoc>
#endif // !FEATURE_PAL
+#if MONO_FEATURE_PROCESS_START
+
/// <devdoc>
/// <para>
/// Starts a process specified by the <see cref='System.Diagnostics.Process.StartInfo'/> property of this <see cref='System.Diagnostics.Process'/>
}
}
-
+#if !MONO
[ResourceExposure(ResourceScope.Process)]
[ResourceConsumption(ResourceScope.Process)]
private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) {
#if !FEATURE_PAL
if (startInfo.UserName.Length != 0) {
+ if (startInfo.Password != null && startInfo.PasswordInClearText != null)
+ throw new ArgumentException(SR.GetString(SR.CantSetDuplicatePassword));
+
NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0;
if( startInfo.LoadUserProfile) {
logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
IntPtr password = IntPtr.Zero;
try {
- if( startInfo.Password == null) {
+ if( startInfo.Password != null) {
+ password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
+ } else if( startInfo.PasswordInClearText != null) {
+ password = Marshal.StringToCoTaskMemUni(startInfo.PasswordInClearText);
+ } else {
password = Marshal.StringToCoTaskMemUni(String.Empty);
- } else {
- password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
}
RuntimeHelpers.PrepareConstrainedRegions();
return ret;
}
+#endif // !MONO
#if !FEATURE_PAL
+#if !MONO
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
private bool StartWithShellExecuteEx(ProcessStartInfo startInfo) {
return false;
}
+#endif
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
return null;
}
+#endif // MONO_FEATURE_PROCESS_START
+
/// <devdoc>
/// <para>
/// Stops the
#endif // !FEATURE_PAL
+#if MONO_FEATURE_PROCESS_START
// Support for working asynchronously with streams
/// <devdoc>
/// <para>
}
}
}
+#endif // MONO_FEATURE_PROCESS_START
/// <summary>
/// A desired internal state.
/// </devdoc>
/// <internalonly/>
internal class ProcessInfo {
+#if !MONO
public ArrayList threadInfoList = new ArrayList();
public int basePriority;
public string processName;
public long privateBytes;
public int mainModuleId; // used only for win9x - id is only for use with CreateToolHelp32
public int sessionId;
+#endif
}
+#if !MONO
/// <devdoc>
/// This data structure contains information about a thread in a process that
/// is collected in bulk by querying the operating system. The reason to
public int sizeOfImage;
public int Id; // used only on win9x - for matching up with ProcessInfo.mainModuleId
}
+#endif
internal static class EnvironmentBlock {
public static byte[] ToByteArray(StringDictionary sd, bool unicode) {
}
}
+#if !MONO
internal class ShellExecuteHelper {
private NativeMethods.ShellExecuteInfo _executeInfo;
private int _errorCode;
}
}
}
+#endif
}