public new void BeginOutputReadLine() { Stream baseStream = StandardOutput.BaseStream; this.output = new AsyncStreamReader(this, baseStream, new UserCallBack(this.FixedOutputReadNotifyUser), StandardOutput.CurrentEncoding); this.output.BeginReadLine(); }
public void BeginErrorReadLine() { Stream baseStream = StandardError.BaseStream; this.error = new AsyncStreamReader(this, baseStream, new UserCallBack(this.FixedErrorReadNotifyUser), StandardError.CurrentEncoding); this.error.BeginReadLine(); }
/// <devdoc> /// <para> /// Instructs the <see cref='System.Diagnostics.Process'/> component to start /// reading the StandardError stream asynchronously. The user can register a callback /// that will be called when a line of data terminated by \n,\r or \r\n is reached, or the end of stream is reached /// then the remaining information is returned. The user can add an event handler to ErrorDataReceived. /// </para> /// </devdoc> public void BeginErrorReadLine() { if (_errorStreamReadMode == StreamReadMode.Undefined) { _errorStreamReadMode = StreamReadMode.AsyncMode; } else if (_errorStreamReadMode != StreamReadMode.AsyncMode) { throw new InvalidOperationException(SR.CantMixSyncAsyncOperation); } if (_pendingErrorRead) { throw new InvalidOperationException(SR.PendingAsyncOperation); } _pendingErrorRead = true; // We can't detect if there's a pending synchronous read, stream also doesn't. if (_error == null) { if (_standardError == null) { throw new InvalidOperationException(SR.CantGetStandardError); } Stream s = _standardError.BaseStream; _error = new AsyncStreamReader(s, ErrorReadNotifyUser, _standardError.CurrentEncoding); } _error.BeginReadLine(); }
public void BeginErrorReadLine () { if (process_handle == IntPtr.Zero || error_stream == null || StartInfo.RedirectStandardError == false) throw new InvalidOperationException ("Standard error has not been redirected or process has not been started."); if ((async_mode & AsyncModes.SyncError) != 0) throw new InvalidOperationException ("Cannot mix asynchronous and synchonous reads."); async_mode |= AsyncModes.AsyncError; if (async_error == null) async_error = new AsyncStreamReader (this, error_stream.BaseStream, new UserCallBack(this.ErrorReadNotifyUser), error_stream.CurrentEncoding); async_error.BeginReadLine (); }
private void OpenConnection(IConnection connection, string data, Action initializeCallback, Action<Exception> errorCallback) { // If we're reconnecting add /connect to the url bool reconnecting = initializeCallback == null; var url = (reconnecting ? connection.Url : connection.Url + "connect") + GetReceiveQueryString(connection, data); Action<IRequest> prepareRequest = PrepareRequest(connection); Debug.WriteLine("SSE: GET {0}", (object)url); _httpClient.GetAsync(url, request => { prepareRequest(request); request.Accept = "text/event-stream"; }).ContinueWith(task => { if (task.IsFaulted) { var exception = task.Exception.GetBaseException(); if (!IsRequestAborted(exception)) { if (errorCallback != null && Interlocked.Exchange(ref _initializedCalled, 1) == 0) { errorCallback(exception); } else if (reconnecting) { // Only raise the error event if we failed to reconnect connection.OnError(exception); } } if (reconnecting) { // Retry Reconnect(connection, data); return; } } else { // Get the reseponse stream and read it for messages var response = task.Result; var stream = response.GetResponseStream(); var reader = new AsyncStreamReader(stream, connection, () => { if (Interlocked.CompareExchange(ref _initializedCalled, 1, 0) == 0) { initializeCallback(); } }, () => { response.Close(); Reconnect(connection, data); }); if (reconnecting) { // Raise the reconnect event if the connection comes back up connection.OnReconnected(); } reader.StartReading(); // Set the reader for this connection connection.Items[ReaderKey] = reader; } }); if (initializeCallback != null) { TaskAsyncHelper.Delay(ConnectionTimeout).Then(() => { if (Interlocked.CompareExchange(ref _initializedCalled, 1, 0) == 0) { // Stop the connection Stop(connection); // Connection timeout occured errorCallback(new TimeoutException()); } }); } }
protected override void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (disposed != 0 || Interlocked.CompareExchange (ref disposed, 1, 0) != 0) return; // If this is a call to Dispose, // dispose all managed resources. if (disposing) { #if MONO_FEATURE_PROCESS_START async_output = null; async_error = null; if (input_stream != null) { if (!input_stream_exposed) input_stream.Close (); input_stream = null; } if (output_stream != null) { if (!output_stream_exposed) output_stream.Close (); output_stream = null; } if (error_stream != null) { if (!error_stream_exposed) error_stream.Close (); error_stream = null; } #endif // MONO_FEATURE_PROCESS_START } // Release unmanaged resources if (process_handle!=IntPtr.Zero) { Process_free_internal (process_handle); process_handle = IntPtr.Zero; } base.Dispose (disposing); }
public void BeginOutputReadLine () { if (process_handle == IntPtr.Zero || output_stream == null || StartInfo.RedirectStandardOutput == false) throw new InvalidOperationException ("Standard output has not been redirected or process has not been started."); if ((async_mode & AsyncModes.SyncOutput) != 0) throw new InvalidOperationException ("Cannot mix asynchronous and synchonous reads."); if ((async_mode & AsyncModes.AsyncOutput) != 0) throw new InvalidOperationException ("An async read operation has already been started on the stream."); async_mode |= AsyncModes.AsyncOutput; if (async_output == null) async_output = new AsyncStreamReader (this, output_stream.BaseStream, new UserCallBack(this.OutputReadNotifyUser), output_stream.CurrentEncoding); async_output.BeginReadLine (); }
/// <summary> /// Create the multiplexer and attach it to the specified handler. /// </summary> /// <param name="readers">Readers to read.</param> /// <param name="handler">Called for queued data item.</param> /// <param name="complete">Called when all readers complete.</param> public AsyncStreamReaderMultiplexer(AsyncStreamReader[] readers, AsyncStreamReader.Handler handler, CompletionHandler complete = null) { queuedItem = new AutoResetEvent(false); queue = System.Collections.Queue.Synchronized(new System.Collections.Queue()); activeStreams = new HashSet<int>(); foreach (AsyncStreamReader reader in readers) { reader.DataReceived += HandleRead; activeStreams.Add(reader.Handle); } DataReceived += handler; if (complete != null) Complete += complete; (new Thread(new ThreadStart(PollQueue))).Start(); }
public void BeginOutputReadLine() { if (outputStreamReadMode == Process2.StreamReadMode.undefined) { outputStreamReadMode = Process2.StreamReadMode.asyncMode; } else { if (outputStreamReadMode != Process2.StreamReadMode.asyncMode) { throw new InvalidOperationException("CantMixSyncAsyncOperation"); } } if (pendingOutputRead) { throw new InvalidOperationException("PendingAsyncOperation"); } pendingOutputRead = true; if (output == null) { if (standardOutput == null) { throw new InvalidOperationException("CantGetStandardOut"); } Stream baseStream = standardOutput.BaseStream; output = new AsyncStreamReader(this, baseStream, new UserCallBack(OutputReadNotifyUser), standardOutput.CurrentEncoding); } output.BeginReadLine(); }
private bool StartWithCreateProcess(ProcessStartInfo startInfo) { if ((startInfo.StandardOutputEncoding != null) && !startInfo.RedirectStandardOutput) { throw new InvalidOperationException(SR.GetString("StandardOutputEncodingNotAllowed")); } if ((startInfo.StandardErrorEncoding != null) && !startInfo.RedirectStandardError) { throw new InvalidOperationException(SR.GetString("StandardErrorEncodingNotAllowed")); } if (this.disposed) { throw new ObjectDisposedException(base.GetType().Name); } StringBuilder cmdLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments); Microsoft.Win32.NativeMethods.STARTUPINFO lpStartupInfo = new Microsoft.Win32.NativeMethods.STARTUPINFO(); Microsoft.Win32.SafeNativeMethods.PROCESS_INFORMATION lpProcessInformation = new Microsoft.Win32.SafeNativeMethods.PROCESS_INFORMATION(); Microsoft.Win32.SafeHandles.SafeProcessHandle processHandle = new Microsoft.Win32.SafeHandles.SafeProcessHandle(); Microsoft.Win32.SafeHandles.SafeThreadHandle handle2 = new Microsoft.Win32.SafeHandles.SafeThreadHandle(); int error = 0; SafeFileHandle parentHandle = null; SafeFileHandle handle4 = null; SafeFileHandle handle5 = null; GCHandle handle6 = new GCHandle(); lock (s_CreateProcessLock) { try { bool flag; if ((startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput) || startInfo.RedirectStandardError) { if (startInfo.RedirectStandardInput) { this.CreatePipe(out parentHandle, out lpStartupInfo.hStdInput, true); } else { lpStartupInfo.hStdInput = new SafeFileHandle(Microsoft.Win32.NativeMethods.GetStdHandle(-10), false); } if (startInfo.RedirectStandardOutput) { this.CreatePipe(out handle4, out lpStartupInfo.hStdOutput, false); } else { lpStartupInfo.hStdOutput = new SafeFileHandle(Microsoft.Win32.NativeMethods.GetStdHandle(-11), false); } if (startInfo.RedirectStandardError) { this.CreatePipe(out handle5, out lpStartupInfo.hStdError, false); } else { lpStartupInfo.hStdError = new SafeFileHandle(Microsoft.Win32.NativeMethods.GetStdHandle(-12), false); } lpStartupInfo.dwFlags = 0x100; } int creationFlags = 0; if (startInfo.CreateNoWindow) { creationFlags |= 0x8000000; } IntPtr zero = IntPtr.Zero; if (startInfo.environmentVariables != null) { bool unicode = false; if (ProcessManager.IsNt) { creationFlags |= 0x400; unicode = true; } handle6 = GCHandle.Alloc(EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode), GCHandleType.Pinned); zero = handle6.AddrOfPinnedObject(); } string workingDirectory = startInfo.WorkingDirectory; if (workingDirectory == string.Empty) { workingDirectory = Environment.CurrentDirectory; } if (startInfo.UserName.Length != 0) { Microsoft.Win32.NativeMethods.LogonFlags logonFlags = 0; if (startInfo.LoadUserProfile) { logonFlags = Microsoft.Win32.NativeMethods.LogonFlags.LOGON_WITH_PROFILE; } IntPtr password = IntPtr.Zero; try { if (startInfo.Password == null) { password = Marshal.StringToCoTaskMemUni(string.Empty); } else { password = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password); } RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { flag = Microsoft.Win32.NativeMethods.CreateProcessWithLogonW(startInfo.UserName, startInfo.Domain, password, logonFlags, null, cmdLine, creationFlags, zero, workingDirectory, lpStartupInfo, lpProcessInformation); if (!flag) { error = Marshal.GetLastWin32Error(); } if ((lpProcessInformation.hProcess != IntPtr.Zero) && (lpProcessInformation.hProcess != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE)) { processHandle.InitialSetHandle(lpProcessInformation.hProcess); } if ((lpProcessInformation.hThread != IntPtr.Zero) && (lpProcessInformation.hThread != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE)) { handle2.InitialSetHandle(lpProcessInformation.hThread); } } if (!flag) { if ((error != 0xc1) && (error != 0xd8)) { throw new Win32Exception(error); } throw new Win32Exception(error, SR.GetString("InvalidApplication")); } goto Label_03E0; } finally { if (password != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(password); } } } RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { flag = Microsoft.Win32.NativeMethods.CreateProcess(null, cmdLine, null, null, true, creationFlags, zero, workingDirectory, lpStartupInfo, lpProcessInformation); if (!flag) { error = Marshal.GetLastWin32Error(); } if ((lpProcessInformation.hProcess != IntPtr.Zero) && (lpProcessInformation.hProcess != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE)) { processHandle.InitialSetHandle(lpProcessInformation.hProcess); } if ((lpProcessInformation.hThread != IntPtr.Zero) && (lpProcessInformation.hThread != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE)) { handle2.InitialSetHandle(lpProcessInformation.hThread); } } if (!flag) { if ((error != 0xc1) && (error != 0xd8)) { throw new Win32Exception(error); } throw new Win32Exception(error, SR.GetString("InvalidApplication")); } } finally { if (handle6.IsAllocated) { handle6.Free(); } lpStartupInfo.Dispose(); } } Label_03E0: if (startInfo.RedirectStandardInput) { this.standardInput = new StreamWriter(new FileStream(parentHandle, FileAccess.Write, 0x1000, false), Console.InputEncoding, 0x1000); this.standardInput.AutoFlush = true; } if (startInfo.RedirectStandardOutput) { Encoding encoding = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding; this.standardOutput = new StreamReader(new FileStream(handle4, FileAccess.Read, 0x1000, false), encoding, true, 0x1000); } if (startInfo.RedirectStandardError) { Encoding encoding2 = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding; this.standardError = new StreamReader(new FileStream(handle5, FileAccess.Read, 0x1000, false), encoding2, true, 0x1000); } bool flag3 = false; if (!processHandle.IsInvalid) { this.SetProcessHandle(processHandle); this.SetProcessId(lpProcessInformation.dwProcessId); handle2.Close(); flag3 = true; } return flag3; }
public void Close() { if (this.Associated) { if (this.haveProcessHandle) { this.StopWatchingForExit(); this.m_processHandle.Close(); this.m_processHandle = null; this.haveProcessHandle = false; } this.haveProcessId = false; this.isRemoteMachine = false; this.machineName = "."; this.raisedOnExited = false; this.standardOutput = null; this.standardInput = null; this.standardError = null; this.output = null; this.error = null; this.Refresh(); } }
public void BeginOutputReadLine() { if (this.outputStreamReadMode == StreamReadMode.undefined) { this.outputStreamReadMode = StreamReadMode.asyncMode; } else if (this.outputStreamReadMode != StreamReadMode.asyncMode) { throw new InvalidOperationException(SR.GetString("CantMixSyncAsyncOperation")); } if (this.pendingOutputRead) { throw new InvalidOperationException(SR.GetString("PendingAsyncOperation")); } this.pendingOutputRead = true; if (this.output == null) { if (this.standardOutput == null) { throw new InvalidOperationException(SR.GetString("CantGetStandardOut")); } Stream baseStream = this.standardOutput.BaseStream; this.output = new AsyncStreamReader(this, baseStream, new UserCallBack(this.OutputReadNotifyUser), this.standardOutput.CurrentEncoding); } this.output.BeginReadLine(); }
/// <summary> /// Run Pscp synchronously /// </summary> /// <param name="result">Result object where results </param> /// <param name="args">The args to send to pscp</param> /// <param name="argsToLog">The args that are logged or can be returned in status messages</param> /// <param name="inlineOutHandler">Inline handler for output</param> /// <param name="inlineErrHandler">Inline handler for error</param> /// <param name="successOutHandler">Handler for output of successful operation</param> void RunPscp( PscpResult result, string args, string argsToLog, Func<string, bool> inlineOutHandler, Func<string, bool> inlineErrHandler, Action<string[]> successOutHandler) { if (!File.Exists(this.Options.PscpLocation)) { result.SetError(string.Format("Pscp missing, path={0}.", this.Options.PscpLocation), null); } else if (this.Session.Username == null) { result.SetError("UserName is null", null); } else if (this.Session.Host == null) { result.SetError("Host is null", null); } else if (this.Session.Port < 0) { result.SetError("Invalid port: " + this.Session.Port, null); } else { Process proc = NewProcess(this.Options.PscpLocation, args); Timer timeoutTimer = null; AsyncStreamReader outReader = null; AsyncStreamReader errReader = null; try { // Start pscp Log.InfoFormat("Starting process: file={0}, args={1}", this.Options.PscpLocation, argsToLog); proc.Start(); // Timeout when no output is received timeoutTimer = new Timer( (x) => { // timeout SafeKill(proc); result.SetErrorFormat("Process timed out, args={0}", argsToLog); }, null, this.Options.TimeoutMs, Timeout.Infinite); // Async read output/err. Inline actions to quick kill the process when pscp prompts user. // NOTE: Using BeginReadOutput/ErrorReadLine doesn't work here. Calls to read an empty stream // will block (e.g. "user's password:"******"OUT", proc.StandardOutput, strOut => { bool keepReading = true; bool completed = false; if (strOut == PUTTY_INTERACTIVE_AUTH || strOut.Contains("assword:")) { result.StatusCode = ResultStatusCode.RetryAuthentication; Log.Debug("Username/Password invalid or not sent"); SafeKill(proc); keepReading = false; } else if (inlineOutHandler != null) { completed = inlineOutHandler(strOut); } timeoutTimer.Change(completed ? Timeout.Infinite : this.Options.TimeoutMs, Timeout.Infinite); return keepReading; }); errReader = new AsyncStreamReader( "ERR", proc.StandardError, strErr => { bool keepReading = true; bool completed = false; if (strErr != null && strErr.Contains(PUTTY_NO_KEY)) { result.SetError("Host key not cached. Connect via putty to cache key then try again", null); SafeKill(proc); keepReading = false; } else if (inlineErrHandler != null) { completed = inlineErrHandler(strErr); } timeoutTimer.Change(completed ? Timeout.Infinite : this.Options.TimeoutMs, Timeout.Infinite); return keepReading; }); // start process and wait for results Log.DebugFormat("WaitingForExit"); proc.WaitForExit(); Log.InfoFormat("Process exited, pid={0}, exitCode={1}", proc.Id, proc.ExitCode); timeoutTimer.Change(Timeout.Infinite, Timeout.Infinite); string[] output = outReader.StopAndGetData(); string[] err = errReader.StopAndGetData(); string outputStr = String.Join("\r\n", output); if (proc.ExitCode == 0 && outputStr.Contains(PUTTY_UNABLE_TO_OPEN)) { // bad path int idx = outputStr.IndexOf(PUTTY_UNABLE_TO_OPEN); result.SetErrorFormat(outputStr.Substring(idx)); } else if (proc.ExitCode == 0) { // successful operation if (successOutHandler != null) { successOutHandler(output); } } else { // some kind of error if (result.StatusCode != ResultStatusCode.Success) { Log.Debug("Skipping output check since proactively killed process."); } else if (output.Contains(PUTTY_ARGUMENTS_HELP_HEADER)) { result.SetErrorFormat("Invalid arguments sent to pscp, args={0}, output={1}", args, output); } else if (err.Contains(PUTTY_HOST_DOES_NOT_EXIST)) { result.SetErrorFormat("Host does not exist. {0}:{1}", this.Session.Host, this.Session.Port); } else { result.SetErrorFormat("Unknown error. exitCode={0}, out='{1}', err='{2}'", proc.ExitCode, String.Join("|", output), String.Join("|", err)); } } } finally { SafeKill(proc); SafeDispose(timeoutTimer, proc, outReader, errReader); } } }
/// <devdoc> /// <para> /// Frees any resources associated with this component. /// </para> /// </devdoc> public void Close() { if (Associated) { if (_haveProcessHandle) { // We need to lock to ensure we don't run concurrently with CompletionCallback. // Without this lock we could reset _raisedOnExited which causes CompletionCallback to // raise the Exited event a second time for the same process. lock (this) { // This sets _waitHandle to null which causes CompletionCallback to not emit events. StopWatchingForExit(); } _processHandle.Dispose(); _processHandle = null; _haveProcessHandle = false; } _haveProcessId = false; _isRemoteMachine = false; _machineName = "."; _raisedOnExited = false; // Only call close on the streams if the user cannot have a reference on them. // If they are referenced it is the user's responsibility to dispose of them. try { if (_standardOutput != null && (_outputStreamReadMode == StreamReadMode.AsyncMode || _outputStreamReadMode == StreamReadMode.Undefined)) { if (_outputStreamReadMode == StreamReadMode.AsyncMode) { _output.CancelOperation(); } _standardOutput.Close(); } if (_standardError != null && (_errorStreamReadMode == StreamReadMode.AsyncMode || _errorStreamReadMode == StreamReadMode.Undefined)) { if (_errorStreamReadMode == StreamReadMode.AsyncMode) { _error.CancelOperation(); } _standardError.Close(); } if (_standardInput != null && !_standardInputAccessed) { _standardInput.Close(); } } finally { _standardOutput = null; _standardInput = null; _standardError = null; _output = null; _error = null; CloseCore(); Refresh(); } } }
/// <summary> /// Create a set of readers to read the specified streams, handles are assigned /// based upon the index of each stream in the provided array. /// </summary> /// <param name="streams">Streams to read.</param> /// <param name="bufferSize">Size of the buffer to use to read each stream.</param> public static AsyncStreamReader[] CreateFromStreams(Stream[] streams, int bufferSize) { AsyncStreamReader[] readers = new AsyncStreamReader[streams.Length]; for (int i = 0; i < streams.Length; i++) { readers[i] = new AsyncStreamReader(i, streams[i], bufferSize); } return readers; }