/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ namespace System.Management.Automation { using System; using System.Collections.ObjectModel; using System.Collections.Generic; using System.Management.Automation.Runspaces; using System.Collections; /// /// Auxilliary class to the execution of commands as needed by /// CommandCompletion /// internal class CompletionExecutionHelper { #region Constructors // Creates a new CompletionExecutionHelper with the PowerShell instance that will be used to execute the tab expansion commands // Used by the ISE internal CompletionExecutionHelper(PowerShell powershell) { if (powershell == null) { throw PSTraceSource.NewArgumentNullException("powershell"); } this.CurrentPowerShell = powershell; } #endregion Constructors #region Fields and Properties // Gets and sets a flag set to false at the beginning of each tab completion and // set to true if a pipeline is stopped to indicate all commands should return empty matches internal bool CancelTabCompletion { get; set; } // Gets and sets the PowerShell instance used to run command completion commands // Used by the ISE internal PowerShell CurrentPowerShell { get; set; } // Returns true if this instance is currently executing a command internal bool IsRunning { get { return CurrentPowerShell.InvocationStateInfo.State == PSInvocationState.Running; } } // Returns true if the command executed by this instance was stopped internal bool IsStopped { get { return CurrentPowerShell.InvocationStateInfo.State == PSInvocationState.Stopped; } } #endregion Fields and Properties #region Command Execution internal Collection ExecuteCommand(string command) { Exception unused; return this.ExecuteCommand(command, true, out unused, null); } internal bool ExecuteCommandAndGetResultAsBool() { Exception exceptionThrown; Collection streamResults = ExecuteCurrentPowerShell(out exceptionThrown); if (exceptionThrown != null || streamResults == null || streamResults.Count == 0) { return false; } // we got back one or more objects. return (streamResults.Count > 1) || (LanguagePrimitives.IsTrue(streamResults[0])); } internal string ExecuteCommandAndGetResultAsString() { Exception exceptionThrown; Collection streamResults = ExecuteCurrentPowerShell(out exceptionThrown); if (exceptionThrown != null || streamResults == null || streamResults.Count == 0) { return null; } // we got back one or more objects. Pick off the first result. if (streamResults[0] == null) return String.Empty; // And convert the base object into a string. We can't use the proxied // ToString() on the PSObject because there is no default runspace // available. return SafeToString(streamResults[0]); } internal Collection ExecuteCommand(string command, bool isScript, out Exception exceptionThrown, Hashtable args) { Diagnostics.Assert(command != null, "caller to verify command is not null"); exceptionThrown = null; // This flag indicates a previous call to this method had its pipeline cancelled if (this.CancelTabCompletion) { return new Collection(); } CurrentPowerShell.AddCommand(command); Command cmd = new Command(command, isScript); if (args != null) { foreach (DictionaryEntry arg in args) { cmd.Parameters.Add((string)(arg.Key), arg.Value); } } Collection results = null; try { // blocks until all results are retrieved. //results = this.ExecuteCommand(cmd); // If this pipeline has been stopped lets set a flag to cancel all future tab completion calls // untill the next completion if (this.IsStopped) { results = new Collection(); this.CancelTabCompletion = true; } } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); exceptionThrown = e; } return results; } internal Collection ExecuteCurrentPowerShell(out Exception exceptionThrown, IEnumerable input = null) { exceptionThrown = null; // This flag indicates a previous call to this method had its pipeline cancelled if (this.CancelTabCompletion) { return new Collection(); } Collection results = null; try { results = CurrentPowerShell.Invoke(input); // If this pipeline has been stopped lets set a flag to cancel all future tab completion calls // untill the next completion if (this.IsStopped) { results = new Collection(); this.CancelTabCompletion = true; } } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); exceptionThrown = e; } finally { CurrentPowerShell.Commands.Clear(); } return results; } #endregion Command Execution #region Helpers /// /// Converts an object to a string safely... /// /// The object to convert /// The result of the conversion... internal static string SafeToString(object obj) { if (obj == null) { return string.Empty; } try { PSObject pso = obj as PSObject; string result; if (pso != null) { object baseObject = pso.BaseObject; if (baseObject != null && !(baseObject is PSCustomObject)) result = baseObject.ToString(); else result = pso.ToString(); } else { result = obj.ToString(); } return result; } catch (Exception e) { // We swallow all exceptions from command completion because we don't want the shell to crash CommandProcessorBase.CheckForSevereException(e); return string.Empty; } } /// /// Converts an object to a string adn, if the string is not empty, adds it to the list /// /// The list to update /// The object to convert to a string... internal static void SafeAddToStringList(List list, object obj) { if (list == null) return; string result = SafeToString(obj); if (!string.IsNullOrEmpty(result)) list.Add(result); } #endregion Helpers } }