/// <devdoc> /// <para> /// Frees any resources associated with this component. /// </para> /// </devdoc> public void Close() { if (Associated) { // 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(); } if (_haveProcessHandle) { _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(); _output?.Dispose(); } _standardOutput.Close(); } if (_standardError != null && (_errorStreamReadMode == StreamReadMode.AsyncMode || _errorStreamReadMode == StreamReadMode.Undefined)) { if (_errorStreamReadMode == StreamReadMode.AsyncMode) { _error?.CancelOperation(); _error?.Dispose(); } _standardError.Close(); } if (_standardInput != null && !_standardInputAccessed) { _standardInput.Close(); } } finally { _standardOutput = null; _standardInput = null; _standardError = null; _output = null; _error = null; CloseCore(); Refresh(); } } }