Files
PowerShell/src/System.Management.Automation/utils/PowerShellExecutionHelper.cs
T
xtqqczze 9212aac0fa Use nameof operator (#12716)
# PR Summary

Using *Roslynator Command Line Tool version 0.1.0.4*

* Fix RCS1015:
  * `"argument"` → `nameof(argument)`
  * `enum.ToString()` → `nameof(enum)`

[RCS1015.log](https://github.com/PowerShell/PowerShell/files/4646102/RCS1015.log)


## PR Context

<!-- Provide a little reasoning as to why this Pull Request helps and why you have opened it. -->

## PR Checklist

- [x] [PR has a meaningful title](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission)
    - Use the present tense and imperative mood when describing your changes
- [x] [Summarized changes](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission)
- [x] [Make sure all `.h`, `.cpp`, `.cs`, `.ps1` and `.psm1` files have the correct copyright header](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission)
- [x] This PR is ready to merge and is not [Work in Progress](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---work-in-progress).
    - If the PR is work in progress, please add the prefix `WIP:` or `[ WIP ]` to the beginning of the title (the `WIP` bot will keep its status check at `Pending` while the prefix is present) and remove the prefix when the PR is ready.
- **[Breaking changes](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#making-breaking-changes)**
    - [x] None
    - **OR**
    - [ ] [Experimental feature(s) needed](https://github.com/MicrosoftDocs/PowerShell-Docs/blob/staging/reference/6/Microsoft.PowerShell.Core/About/about_Experimental_Features.md)
        - [ ] Experimental feature name(s): <!-- Experimental feature name(s) here -->
- **User-facing changes**
    - [x] Not Applicable
    - **OR**
    - [ ] [Documentation needed](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission)
        - [ ] Issue filed: <!-- Number/link of that issue here -->
- **Testing - New and feature**
    - [x] N/A or can only be tested interactively
    - **OR**
    - [ ] [Make sure you've added a new test if existing tests do not effectively test the code changed](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#before-submitting)
- **Tooling**
    - [x] I have considered the user experience from a tooling perspective and don't believe tooling will be impacted.
    - **OR**
    - [ ] I have considered the user experience from a tooling perspective and enumerated concerns in the summary. This may include:
        - Impact on [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices) which is used in the [PowerShell extension](https://github.com/PowerShell/vscode-powershell) for VSCode (which runs in a different PS Host).
        - Impact on Completions (both in the console and in editors) - one of PowerShell's most powerful features.
        - Impact on [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) (which provides linting & formatting in the editor extensions).
        - Impact on [EditorSyntax](https://github.com/PowerShell/EditorSyntax) (which provides syntax highlighting with in VSCode, GitHub, and many other editors).
2020-05-19 18:57:52 +00:00

264 lines
8.8 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;
namespace System.Management.Automation
{
internal class PowerShellExecutionHelper
{
#region Constructors
// Creates a new PowerShellExecutionHelper with the PowerShell instance that will be used to execute the tab expansion commands
// Used by the ISE
internal PowerShellExecutionHelper(PowerShell powershell)
{
if (powershell == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(powershell));
}
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 => CurrentPowerShell.InvocationStateInfo.State == PSInvocationState.Running;
// Returns true if the command executed by this instance was stopped
internal bool IsStopped => CurrentPowerShell.InvocationStateInfo.State == PSInvocationState.Stopped;
#endregion Fields and Properties
#region Command Execution
internal Collection<PSObject> ExecuteCommand(string command)
{
Exception unused;
return ExecuteCommand(command, true, out unused, null);
}
internal bool ExecuteCommandAndGetResultAsBool()
{
Exception exceptionThrown;
Collection<PSObject> 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<PSObject> 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<PSObject> 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 (CancelTabCompletion)
{
return new Collection<PSObject>();
}
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<PSObject> 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 (IsStopped)
{
results = new Collection<PSObject>();
CancelTabCompletion = true;
}
}
catch (Exception e)
{
exceptionThrown = e;
}
return results;
}
internal Collection<PSObject> ExecuteCurrentPowerShell(out Exception exceptionThrown, IEnumerable input = null)
{
exceptionThrown = null;
// This flag indicates a previous call to this method had its pipeline cancelled
if (CancelTabCompletion)
{
return new Collection<PSObject>();
}
Collection<PSObject> 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 (IsStopped)
{
results = new Collection<PSObject>();
CancelTabCompletion = true;
}
}
catch (Exception e)
{
exceptionThrown = e;
}
finally
{
CurrentPowerShell.Commands.Clear();
}
return results;
}
#endregion Command Execution
#region Helpers
/// <summary>
/// Converts an object to a string safely...
/// </summary>
/// <param name="obj">The object to convert.</param>
/// <returns>The result of the conversion...</returns>
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)
{
// We swallow all exceptions from command completion because we don't want the shell to crash
return string.Empty;
}
}
/// <summary>
/// Converts an object to a string adn, if the string is not empty, adds it to the list.
/// </summary>
/// <param name="list">The list to update.</param>
/// <param name="obj">The object to convert to a string...</param>
internal static void SafeAddToStringList(List<string> list, object obj)
{
if (list == null)
return;
string result = SafeToString(obj);
if (!string.IsNullOrEmpty(result))
list.Add(result);
}
#endregion Helpers
}
internal static class PowerShellExtensionHelpers
{
internal static PowerShell AddCommandWithPreferenceSetting(this PowerShellExecutionHelper helper,
string command, Type type = null)
{
return helper.CurrentPowerShell.AddCommandWithPreferenceSetting(command, type);
}
internal static PowerShell AddCommandWithPreferenceSetting(this PowerShell powershell, string command, Type type = null)
{
Diagnostics.Assert(powershell != null, "the passed-in powershell cannot be null");
Diagnostics.Assert(!string.IsNullOrWhiteSpace(command),
"the passed-in command name should not be null or whitespaces");
if (type != null)
{
var cmdletInfo = new CmdletInfo(command, type);
powershell.AddCommand(cmdletInfo);
}
else
{
powershell.AddCommand(command);
}
powershell
.AddParameter("ErrorAction", ActionPreference.Ignore)
.AddParameter("WarningAction", ActionPreference.Ignore)
.AddParameter("InformationAction", ActionPreference.Ignore)
.AddParameter("Verbose", false)
.AddParameter("Debug", false);
return powershell;
}
}
}