MegaBites-AI/Windows-powershell
0308
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Management.Automation.Runspaces;8 9namespace System.Management.Automation10{11 internal class PowerShellExecutionHelper12 {13 #region Constructors14 15 // Creates a new PowerShellExecutionHelper with the PowerShell instance that will be used to execute the tab expansion commands16 // Used by the ISE17 internal PowerShellExecutionHelper(PowerShell powershell)18 {19 if (powershell == null)20 {21 throw PSTraceSource.NewArgumentNullException(nameof(powershell));22 }23 24 CurrentPowerShell = powershell;25 }26 27 #endregion Constructors28 29 #region Fields and Properties30 31 // Gets and sets a flag set to false at the beginning of each tab completion and32 // set to true if a pipeline is stopped to indicate all commands should return empty matches33 internal bool CancelTabCompletion { get; set; }34 35 // Gets and sets the PowerShell instance used to run command completion commands36 // Used by the ISE37 internal PowerShell CurrentPowerShell { get; set; }38 39 // Returns true if this instance is currently executing a command40 internal bool IsRunning => CurrentPowerShell.InvocationStateInfo.State == PSInvocationState.Running;41 42 // Returns true if the command executed by this instance was stopped43 internal bool IsStopped => CurrentPowerShell.InvocationStateInfo.State == PSInvocationState.Stopped;44 45 #endregion Fields and Properties46 47 #region Command Execution48 49 internal bool ExecuteCommandAndGetResultAsBool()50 {51 Exception exceptionThrown;52 Collection<PSObject> streamResults = ExecuteCurrentPowerShell(out exceptionThrown);53 54 if (exceptionThrown != null || streamResults == null || streamResults.Count == 0)55 {56 return false;57 }58 59 // we got back one or more objects.60 return (streamResults.Count > 1) || (LanguagePrimitives.IsTrue(streamResults[0]));61 }62 63 internal Collection<PSObject> ExecuteCurrentPowerShell(out Exception exceptionThrown, IEnumerable input = null)64 {65 return ExecuteCurrentPowerShell(out exceptionThrown, out _, input);66 }67 68 internal Collection<PSObject> ExecuteCurrentPowerShell(out Exception exceptionThrown, out bool hadErrors, IEnumerable input = null)69 {70 exceptionThrown = null;71 72 // This flag indicates a previous call to this method had its pipeline cancelled73 if (CancelTabCompletion)74 {75 hadErrors = false;76 return new Collection<PSObject>();77 }78 79 Collection<PSObject> results = null;80 try81 {82 results = CurrentPowerShell.Invoke(input);83 84 // If this pipeline has been stopped lets set a flag to cancel all future tab completion calls85 // until the next completion86 if (IsStopped)87 {88 results = new Collection<PSObject>();89 CancelTabCompletion = true;90 }91 }92 catch (Exception e)93 {94 exceptionThrown = e;95 }96 finally97 {98 hadErrors = CurrentPowerShell.HadErrors;99 CurrentPowerShell.Commands.Clear();100 }101 102 return results;103 }104 105 #endregion Command Execution106 107 #region Helpers108 109 /// <summary>110 /// Converts an object to a string safely...111 /// </summary>112 /// <param name="obj">The object to convert.</param>113 /// <returns>The result of the conversion...</returns>114 internal static string SafeToString(object obj)115 {116 if (obj == null)117 {118 return string.Empty;119 }120 121 try122 {123 string result;124 if (obj is PSObject pso)125 {126 object baseObject = pso.BaseObject;127 if (baseObject != null && baseObject is not PSCustomObject)128 result = baseObject.ToString();129 else130 result = pso.ToString();131 }132 else133 {134 result = obj.ToString();135 }136 137 return result;138 }139 catch (Exception)140 {141 // We swallow all exceptions from command completion because we don't want the shell to crash142 return string.Empty;143 }144 }145 146 /// <summary>147 /// Converts an object to a string adn, if the string is not empty, adds it to the list.148 /// </summary>149 /// <param name="list">The list to update.</param>150 /// <param name="obj">The object to convert to a string...</param>151 internal static void SafeAddToStringList(List<string> list, object obj)152 {153 if (list == null)154 return;155 string result = SafeToString(obj);156 if (!string.IsNullOrEmpty(result))157 list.Add(result);158 }159 160 #endregion Helpers161 }162 163 internal static class PowerShellExtensionHelpers164 {165 internal static PowerShell AddCommandWithPreferenceSetting(this PowerShellExecutionHelper helper,166 string command, Type type = null)167 {168 return helper.CurrentPowerShell.AddCommandWithPreferenceSetting(command, type);169 }170 171 internal static PowerShell AddCommandWithPreferenceSetting(this PowerShell powershell, string command, Type type = null)172 {173 Diagnostics.Assert(powershell != null, "the passed-in powershell cannot be null");174 Diagnostics.Assert(!string.IsNullOrWhiteSpace(command),175 "the passed-in command name should not be null or whitespaces");176 177 if (type != null)178 {179 var cmdletInfo = new CmdletInfo(command, type);180 181 powershell.AddCommand(cmdletInfo);182 }183 else184 {185 powershell.AddCommand(command);186 }187 188 powershell189 .AddParameter("ErrorAction", ActionPreference.Ignore)190 .AddParameter("WarningAction", ActionPreference.Ignore)191 .AddParameter("InformationAction", ActionPreference.Ignore)192 .AddParameter("Verbose", false)193 .AddParameter("Debug", false);194 195 return powershell;196 }197 }198}199 