mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 20:56:02 +00:00
I (Jason Shirk) ran https://github.com/dotnet/codeformatter with the default rules, basically: codeformatter /nocopyright "/c:DEBUG,UNIX,CORECLR" @files.rsp This caused a few problems building, which were fixed up manually. Notable changes: `this.` is removed unless needed to disambiguate. private instance fields are renamed to have a `_` prefix. private static fields are renamed to have a `s_` prefix. I left some projects alone (like PackageManagement) and also left some generated code alone.
1003 lines
38 KiB
C#
1003 lines
38 KiB
C#
/********************************************************************++
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
--********************************************************************/
|
|
|
|
using System.IO;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Management.Automation.Internal;
|
|
using System.Management.Automation.Language;
|
|
using System.Reflection;
|
|
using PipelineResultTypes = System.Management.Automation.Runspaces.PipelineResultTypes;
|
|
|
|
namespace System.Management.Automation
|
|
{
|
|
#region Auxiliary
|
|
/// <summary>
|
|
/// An interface that a
|
|
/// <see cref="Cmdlet"/> or <see cref="Provider.CmdletProvider"/>
|
|
/// must implement to indicate that it has dynamic parameters.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Dynamic parameters allow a
|
|
/// <see cref="Cmdlet"/> or <see cref="Provider.CmdletProvider"/>
|
|
/// to define additional parameters based on the value of
|
|
/// the formal arguments. For example, the parameters of
|
|
/// "set-itemproperty" for the file system provider vary
|
|
/// depending on whether the target object is a file or directory.
|
|
/// </remarks>
|
|
/// <seealso cref="Cmdlet"/>
|
|
/// <seealso cref="PSCmdlet"/>
|
|
/// <seealso cref="RuntimeDefinedParameter"/>
|
|
/// <seealso cref="RuntimeDefinedParameterDictionary"/>
|
|
public interface IDynamicParameters
|
|
{
|
|
/// <summary>
|
|
/// Returns an instance of an object that defines the
|
|
/// dynamic parameters for this
|
|
/// <see cref="Cmdlet"/> or <see cref="Provider.CmdletProvider"/>.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// This method should return an object that has properties and fields
|
|
/// decorated with parameter attributes similar to a
|
|
/// <see cref="Cmdlet"/> or <see cref="Provider.CmdletProvider"/>.
|
|
/// These attributes include <see cref="ParameterAttribute"/>,
|
|
/// <see cref="AliasAttribute"/>, argument transformation and
|
|
/// validation attributes, etc.
|
|
///
|
|
/// Alternately, it can return a
|
|
/// <see cref="System.Management.Automation.RuntimeDefinedParameterDictionary"/>
|
|
/// instead.
|
|
///
|
|
/// The <see cref="Cmdlet"/> or <see cref="Provider.CmdletProvider"/>
|
|
/// should hold on to a reference to the object which it returns from
|
|
/// this method, since the argument values for the dynamic parameters
|
|
/// specified by that object will be set in that object.
|
|
///
|
|
/// This method will be called after all formal (command-line)
|
|
/// parameters are set, but before <see cref="Cmdlet.BeginProcessing"/>
|
|
/// is called and before any incoming pipeline objects are read.
|
|
/// Therefore, parameters which allow input from the pipeline
|
|
/// may not be set at the time this method is called,
|
|
/// even if the parameters are mandatory.
|
|
/// </returns>
|
|
object GetDynamicParameters();
|
|
}
|
|
/// <summary>
|
|
/// Type used to define a parameter on a cmdlet script of function that
|
|
/// can only be used as a switch.
|
|
/// </summary>
|
|
public struct SwitchParameter
|
|
{
|
|
private bool _isPresent;
|
|
/// <summary>
|
|
/// Returns true if the parameter was specified on the command line, false otherwise.
|
|
/// </summary>
|
|
/// <value>True if the parameter was specified, false otherwise</value>
|
|
public bool IsPresent
|
|
{
|
|
get { return _isPresent; }
|
|
}
|
|
/// <summary>
|
|
/// Implicit cast operator for casting SwitchParameter to bool.
|
|
/// </summary>
|
|
/// <param name="switchParameter">The SwitchParameter object to convert to bool</param>
|
|
/// <returns>The corresponding boolean value.</returns>
|
|
public static implicit operator bool (SwitchParameter switchParameter)
|
|
{
|
|
return switchParameter.IsPresent;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implicit cast operator for casting bool to SwitchParameter.
|
|
/// </summary>
|
|
/// <param name="value">The bool to convert to SwitchParameter</param>
|
|
/// <returns>The corresponding boolean value.</returns>
|
|
public static implicit operator SwitchParameter(bool value)
|
|
{
|
|
return new SwitchParameter(value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Explicit method to convert a SwitchParameter to a boolean value.
|
|
/// </summary>
|
|
/// <returns>The boolean equivalent of the SwitchParameter</returns>
|
|
public bool ToBool()
|
|
{
|
|
return _isPresent;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a SwitchParameter instance with a particular value.
|
|
/// </summary>
|
|
/// <param name="isPresent">
|
|
/// If true, it indicates that the switch is present, flase otherwise.
|
|
/// </param>
|
|
public SwitchParameter(bool isPresent)
|
|
{
|
|
_isPresent = isPresent;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Static method that returns a instance of SwitchParameter that indicates that it is present.
|
|
/// </summary>
|
|
/// <value>An instance of a switch parameter that will convert to true in a boolean context</value>
|
|
public static SwitchParameter Present
|
|
{
|
|
get { return new SwitchParameter(true); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compare this switch parameter to another object.
|
|
/// </summary>
|
|
/// <param name="obj">An object to compare against</param>
|
|
/// <returns>True if the objects are the same value.</returns>
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (obj is bool)
|
|
{
|
|
return _isPresent == (bool)obj;
|
|
}
|
|
else if (obj is SwitchParameter)
|
|
{
|
|
return _isPresent == ((SwitchParameter)obj).IsPresent;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Returns the hash code for this switch parameter.
|
|
/// </summary>
|
|
/// <returns>The hash code for this cobject.</returns>
|
|
public override int GetHashCode()
|
|
{
|
|
return _isPresent.GetHashCode();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implement the == operator for switch parameters objects.
|
|
/// </summary>
|
|
/// <param name="first">first object to compare</param>
|
|
/// <param name="second">second object to compare</param>
|
|
/// <returns>True if they are the same</returns>
|
|
public static bool operator ==(SwitchParameter first, SwitchParameter second)
|
|
{
|
|
return first.Equals(second);
|
|
}
|
|
/// <summary>
|
|
/// Implement the != operator for switch parameters
|
|
/// </summary>
|
|
/// <param name="first">first object to compare</param>
|
|
/// <param name="second">second object to compare</param>
|
|
/// <returns>True if they are different</returns>
|
|
public static bool operator !=(SwitchParameter first, SwitchParameter second)
|
|
{
|
|
return !first.Equals(second);
|
|
}
|
|
/// <summary>
|
|
/// Implement the == operator for switch parameters and booleans.
|
|
/// </summary>
|
|
/// <param name="first">first object to compare</param>
|
|
/// <param name="second">second object to compare</param>
|
|
/// <returns>True if they are the same</returns>
|
|
public static bool operator ==(SwitchParameter first, bool second)
|
|
{
|
|
return first.Equals(second);
|
|
}
|
|
/// <summary>
|
|
/// Implement the != operator for switch parameters and booleans.
|
|
/// </summary>
|
|
/// <param name="first">first object to compare</param>
|
|
/// <param name="second">second object to compare</param>
|
|
/// <returns>True if they are different</returns>
|
|
public static bool operator !=(SwitchParameter first, bool second)
|
|
{
|
|
return !first.Equals(second);
|
|
}
|
|
/// <summary>
|
|
/// Implement the == operator for bool and switch parameters
|
|
/// </summary>
|
|
/// <param name="first">first object to compare</param>
|
|
/// <param name="second">second object to compare</param>
|
|
/// <returns>True if they are the same</returns>
|
|
public static bool operator ==(bool first, SwitchParameter second)
|
|
{
|
|
return first.Equals(second);
|
|
}
|
|
/// <summary>
|
|
/// Implement the != operator for bool and switch parameters
|
|
/// </summary>
|
|
/// <param name="first">first object to compare</param>
|
|
/// <param name="second">second object to compare</param>
|
|
/// <returns>True if they are different</returns>
|
|
public static bool operator !=(bool first, SwitchParameter second)
|
|
{
|
|
return !first.Equals(second);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the string representation for this object
|
|
/// </summary>
|
|
/// <returns>The string for this object.</returns>
|
|
public override string ToString()
|
|
{
|
|
return _isPresent.ToString();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Interfaces that cmdlets can use to build script blocks and execute scripts.
|
|
/// </summary>
|
|
public class CommandInvocationIntrinsics
|
|
{
|
|
private ExecutionContext _context;
|
|
private PSCmdlet _cmdlet;
|
|
private MshCommandRuntime _commandRuntime;
|
|
|
|
internal CommandInvocationIntrinsics(ExecutionContext context, PSCmdlet cmdlet)
|
|
{
|
|
_context = context;
|
|
if (cmdlet != null)
|
|
{
|
|
_cmdlet = cmdlet;
|
|
_commandRuntime = cmdlet.CommandRuntime as MshCommandRuntime;
|
|
}
|
|
}
|
|
|
|
internal CommandInvocationIntrinsics(ExecutionContext context)
|
|
: this(context, null)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// If an error occurred while executing the cmdlet, this will be set to true.
|
|
/// </summary>
|
|
public bool HasErrors
|
|
{
|
|
get
|
|
{
|
|
return _commandRuntime.PipelineProcessor.ExecutionFailed;
|
|
}
|
|
set
|
|
{
|
|
_commandRuntime.PipelineProcessor.ExecutionFailed = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a string with all of the variable and expression substitutions done.
|
|
/// </summary>
|
|
/// <param name="source">The string to expand.
|
|
/// </param>
|
|
/// <returns>The expanded string.</returns>
|
|
/// <exception cref="ParseException">
|
|
/// Thrown if a parse exception occurred during subexpression substitution.
|
|
/// </exception>
|
|
public string ExpandString(string source)
|
|
{
|
|
if (null != _cmdlet)
|
|
_cmdlet.ThrowIfStopping();
|
|
return _context.Engine.Expand(source);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="commandName"></param>
|
|
/// <param name="type"></param>
|
|
/// <returns></returns>
|
|
public CommandInfo GetCommand(string commandName, CommandTypes type)
|
|
{
|
|
return GetCommand(commandName, type, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a command info for a given command name and type, using the specified arguments
|
|
/// to resolve dynamic parameters.
|
|
/// </summary>
|
|
/// <param name="commandName">The command name to search for</param>
|
|
/// <param name="type">The command type to search for</param>
|
|
/// <param name="arguments">The command arguments used to resolve dynamic parameters</param>
|
|
/// <returns>A CommandInfo result that represents the resolved command</returns>
|
|
public CommandInfo GetCommand(string commandName, CommandTypes type, object[] arguments)
|
|
{
|
|
CommandInfo result = null;
|
|
|
|
try
|
|
{
|
|
CommandOrigin commandOrigin = CommandOrigin.Runspace;
|
|
if (_cmdlet != null)
|
|
{
|
|
commandOrigin = _cmdlet.CommandOrigin;
|
|
}
|
|
else if (_context != null)
|
|
{
|
|
commandOrigin = _context.EngineSessionState.CurrentScope.ScopeOrigin;
|
|
}
|
|
|
|
result = CommandDiscovery.LookupCommandInfo(commandName, type, SearchResolutionOptions.None, commandOrigin, _context);
|
|
|
|
if ((result != null) && (arguments != null) && (arguments.Length > 0))
|
|
{
|
|
// We've been asked to retrieve dynamic parameters
|
|
if (result.ImplementsDynamicParameters)
|
|
{
|
|
result = result.CreateGetCommandCopy(arguments);
|
|
}
|
|
}
|
|
}
|
|
catch (CommandNotFoundException) { }
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This event handler is called when a command is not found.
|
|
/// If should have a single string parameter that is the name
|
|
/// of the command and should return a CommandInfo object or null. By default
|
|
/// it will search the module path looking for a module that exports the
|
|
/// desired command.
|
|
/// </summary>
|
|
public System.EventHandler<CommandLookupEventArgs> CommandNotFoundAction { get; set; }
|
|
|
|
/// <summary>
|
|
/// This event handler is called before the command lookup is done.
|
|
/// If should have a single string parameter that is the name
|
|
/// of the command and should return a CommandInfo object or null.
|
|
/// </summary>
|
|
public System.EventHandler<CommandLookupEventArgs> PreCommandLookupAction { get; set; }
|
|
|
|
/// <summary>
|
|
/// This event handler is after the command lookup is done but before the event object is
|
|
/// returned to the caller. This allows things like interning scripts to work.
|
|
/// If should have a single string parameter that is the name
|
|
/// of the command and should return a CommandInfo object or null.
|
|
/// </summary>
|
|
public System.EventHandler<CommandLookupEventArgs> PostCommandLookupAction { get; set; }
|
|
|
|
/// <summary>
|
|
/// Returns the CmdletInfo object that corresponds to the name argument
|
|
/// </summary>
|
|
/// <param name="commandName">The name of the cmdlet to look for</param>
|
|
/// <returns>The cmdletInfo object if found, null otherwise</returns>
|
|
public CmdletInfo GetCmdlet(string commandName)
|
|
{
|
|
return GetCmdlet(commandName, _context);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the CmdletInfo object that corresponds to the name argument
|
|
/// </summary>
|
|
/// <param name="commandName">The name of the cmdlet to look for</param>
|
|
/// <param name="context">The execution context instance to use for lookup</param>
|
|
/// <returns>The cmdletInfo object if found, null otherwise</returns>
|
|
internal static CmdletInfo GetCmdlet(string commandName, ExecutionContext context)
|
|
{
|
|
CmdletInfo current = null;
|
|
|
|
CommandSearcher searcher = new CommandSearcher(
|
|
commandName,
|
|
SearchResolutionOptions.None,
|
|
CommandTypes.Cmdlet,
|
|
context);
|
|
do
|
|
{
|
|
try
|
|
{
|
|
if (!searcher.MoveNext())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
catch (ArgumentException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (PathTooLongException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (FileLoadException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (MetadataException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
current = ((IEnumerator)searcher).Current as CmdletInfo;
|
|
} while (true);
|
|
|
|
return current;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the cmdlet info using the name of the cmdlet's implementing type. This bypasses
|
|
/// session state and retrieves the command directly. Note that the help file and snapin/module
|
|
/// info will both be null on returned object.
|
|
/// </summary>
|
|
/// <param name="cmdletTypeName">the type name of the class implementing this cmdlet</param>
|
|
/// <returns>CmdletInfo for the cmdlet if found, null otherwise</returns>
|
|
public CmdletInfo GetCmdletByTypeName(string cmdletTypeName)
|
|
{
|
|
if (string.IsNullOrEmpty(cmdletTypeName))
|
|
{
|
|
throw PSTraceSource.NewArgumentNullException("cmdletTypeName");
|
|
}
|
|
|
|
Exception e = null;
|
|
Type cmdletType = TypeResolver.ResolveType(cmdletTypeName, out e);
|
|
if (e != null)
|
|
{
|
|
throw e;
|
|
}
|
|
if (cmdletType == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
CmdletAttribute ca = null;
|
|
foreach (var attr in cmdletType.GetTypeInfo().GetCustomAttributes(true))
|
|
{
|
|
ca = attr as CmdletAttribute;
|
|
if (ca != null)
|
|
break;
|
|
}
|
|
if (ca == null)
|
|
{
|
|
throw PSTraceSource.NewNotSupportedException();
|
|
}
|
|
|
|
string noun = ca.NounName;
|
|
string verb = ca.VerbName;
|
|
string cmdletName = verb + "-" + noun;
|
|
|
|
return new CmdletInfo(cmdletName, cmdletType, null, null, _context);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a list of all cmdlets...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public List<CmdletInfo> GetCmdlets()
|
|
{
|
|
return GetCmdlets("*");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns all cmdlets whose names match the pattern...
|
|
/// </summary>
|
|
/// <returns>A list of CmdletInfo objects...</returns>
|
|
public List<CmdletInfo> GetCmdlets(string pattern)
|
|
{
|
|
if (pattern == null)
|
|
throw PSTraceSource.NewArgumentNullException("pattern");
|
|
|
|
List<CmdletInfo> cmdlets = new List<CmdletInfo>();
|
|
|
|
CmdletInfo current = null;
|
|
|
|
CommandSearcher searcher = new CommandSearcher(
|
|
pattern,
|
|
SearchResolutionOptions.CommandNameIsPattern,
|
|
CommandTypes.Cmdlet,
|
|
_context);
|
|
do
|
|
{
|
|
try
|
|
{
|
|
if (!searcher.MoveNext())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
catch (ArgumentException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (PathTooLongException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (FileLoadException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (MetadataException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
current = ((IEnumerator)searcher).Current as CmdletInfo;
|
|
if (current != null)
|
|
cmdlets.Add(current);
|
|
} while (true);
|
|
|
|
return cmdlets;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Searches for PowerShell commands, optionally using wildcard patterns
|
|
/// and optionally return the full path to applications and scripts rather than
|
|
/// the simple command name.
|
|
/// </summary>
|
|
/// <param name="name">The name of the command to use</param>
|
|
/// <param name="nameIsPattern">If true treat the name as a pattern to search for</param>
|
|
/// <param name="returnFullName">If true, return the full path to scripts and applications</param>
|
|
/// <returns>A list of command names...</returns>
|
|
public List<string> GetCommandName(string name, bool nameIsPattern, bool returnFullName)
|
|
{
|
|
if (name == null)
|
|
{
|
|
throw PSTraceSource.NewArgumentNullException("name");
|
|
}
|
|
|
|
List<string> commands = new List<string>();
|
|
|
|
foreach (CommandInfo current in this.GetCommands(name, CommandTypes.All, nameIsPattern))
|
|
{
|
|
if (current.CommandType == CommandTypes.Application)
|
|
{
|
|
string cmdExtension = System.IO.Path.GetExtension(current.Name);
|
|
if (!String.IsNullOrEmpty(cmdExtension))
|
|
{
|
|
// Only add the application in PATHEXT...
|
|
foreach (string extension in CommandDiscovery.PathExtensions)
|
|
{
|
|
if (extension.Equals(cmdExtension, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
if (returnFullName)
|
|
{
|
|
commands.Add(current.Definition);
|
|
}
|
|
else
|
|
{
|
|
commands.Add(current.Name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (current.CommandType == CommandTypes.ExternalScript)
|
|
{
|
|
if (returnFullName)
|
|
{
|
|
commands.Add(current.Definition);
|
|
}
|
|
else
|
|
{
|
|
commands.Add(current.Name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
commands.Add(current.Name);
|
|
}
|
|
}
|
|
|
|
return commands;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Searches for PowerShell commands, optionally using wildcard patterns
|
|
/// </summary>
|
|
/// <param name="name">The name of the command to use</param>
|
|
/// <param name="commandTypes">Type of commands to support</param>
|
|
/// <param name="nameIsPattern">If true treat the name as a pattern to search for</param>
|
|
/// <returns>Collection of command names...</returns>
|
|
public IEnumerable<CommandInfo> GetCommands(string name, CommandTypes commandTypes, bool nameIsPattern)
|
|
{
|
|
if (name == null)
|
|
{
|
|
throw PSTraceSource.NewArgumentNullException("name");
|
|
}
|
|
|
|
SearchResolutionOptions options = nameIsPattern ?
|
|
(SearchResolutionOptions.CommandNameIsPattern | SearchResolutionOptions.ResolveFunctionPatterns | SearchResolutionOptions.ResolveAliasPatterns)
|
|
: SearchResolutionOptions.None;
|
|
|
|
return GetCommands(name, commandTypes, options);
|
|
}
|
|
|
|
internal IEnumerable<CommandInfo> GetCommands(string name, CommandTypes commandTypes, SearchResolutionOptions options, CommandOrigin? commandOrigin = null)
|
|
{
|
|
CommandSearcher searcher = new CommandSearcher(
|
|
name,
|
|
options,
|
|
commandTypes,
|
|
_context);
|
|
|
|
if (commandOrigin != null)
|
|
{
|
|
searcher.CommandOrigin = commandOrigin.Value;
|
|
}
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
if (!searcher.MoveNext())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
catch (ArgumentException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (PathTooLongException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (FileLoadException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (MetadataException)
|
|
{
|
|
continue;
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
CommandInfo commandInfo = ((IEnumerator)searcher).Current as CommandInfo;
|
|
if (commandInfo != null)
|
|
{
|
|
yield return commandInfo;
|
|
}
|
|
} while (true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes a piece of text as a script synchronously.
|
|
/// </summary>
|
|
/// <param name="script">The script text to evaluate</param>
|
|
/// <returns>A collection of MshCobjects generated by the script.</returns>
|
|
/// <exception cref="ParseException">Thrown if there was a parsing error in the script.</exception>
|
|
/// <exception cref="RuntimeException">Represents a script-level exception</exception>
|
|
/// <exception cref="FlowControlException"></exception>
|
|
public Collection<PSObject> InvokeScript(string script)
|
|
{
|
|
return InvokeScript(script, true, PipelineResultTypes.None, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes a piece of text as a script synchronously.
|
|
/// </summary>
|
|
/// <param name="script">The script text to evaluate</param>
|
|
/// <param name="args">The arguments to the script</param>
|
|
/// <returns>A collection of MshCobjects generated by the script.</returns>
|
|
/// <exception cref="ParseException">Thrown if there was a parsing error in the script.</exception>
|
|
/// <exception cref="RuntimeException">Represents a script-level exception</exception>
|
|
/// <exception cref="FlowControlException"></exception>
|
|
public Collection<PSObject> InvokeScript(string script, params object[] args)
|
|
{
|
|
return InvokeScript(script, true, PipelineResultTypes.None, args);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="sessionState"></param>
|
|
/// <param name="scriptBlock"></param>
|
|
/// <param name="args"></param>
|
|
/// <returns></returns>
|
|
public Collection<PSObject> InvokeScript(
|
|
SessionState sessionState, ScriptBlock scriptBlock, params object[] args)
|
|
{
|
|
if (scriptBlock == null)
|
|
{
|
|
throw PSTraceSource.NewArgumentNullException("scriptBlock");
|
|
}
|
|
if (sessionState == null)
|
|
{
|
|
throw PSTraceSource.NewArgumentNullException("sessionState");
|
|
}
|
|
|
|
SessionStateInternal _oldSessionState = _context.EngineSessionState;
|
|
try
|
|
{
|
|
_context.EngineSessionState = sessionState.Internal;
|
|
return InvokeScript(scriptBlock, false, PipelineResultTypes.None, null, args);
|
|
}
|
|
finally
|
|
{
|
|
_context.EngineSessionState = _oldSessionState;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invoke a scriptblock in the current runspace, controlling if it gets a new scope.
|
|
/// </summary>
|
|
/// <param name="useLocalScope">If true, a new scope will be created</param>
|
|
/// <param name="scriptBlock">The scriptblock to execute</param>
|
|
/// <param name="input">Optionall input to the command</param>
|
|
/// <param name="args">Arguments to pass to the scriptblock</param>
|
|
/// <returns>The result of the evaluation</returns>
|
|
public Collection<PSObject> InvokeScript(
|
|
bool useLocalScope, ScriptBlock scriptBlock, IList input, params object[] args)
|
|
{
|
|
if (scriptBlock == null)
|
|
{
|
|
throw PSTraceSource.NewArgumentNullException("scriptBlock");
|
|
}
|
|
|
|
// Force the current runspace onto the callers thread - this is needed
|
|
// if this API is going to be callable through the SessionStateProxy on the runspace.
|
|
var old = System.Management.Automation.Runspaces.Runspace.DefaultRunspace;
|
|
System.Management.Automation.Runspaces.Runspace.DefaultRunspace = _context.CurrentRunspace;
|
|
try
|
|
{
|
|
return InvokeScript(scriptBlock, useLocalScope, PipelineResultTypes.None, input, args);
|
|
}
|
|
finally
|
|
{
|
|
System.Management.Automation.Runspaces.Runspace.DefaultRunspace = old;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes a piece of text as a script synchronously using the options provided.
|
|
/// </summary>
|
|
/// <param name="script">The script to evaluate.</param>
|
|
/// <param name="useNewScope">If true, evaluate the script in its own scope.
|
|
/// If false, the script will be evaluated in the current scope i.e. it will be "dotted"</param>
|
|
/// <param name="writeToPipeline">If set to Output, all output will be streamed
|
|
/// to the output pipe of the calling cmdlet. If set to None, the result will be returned
|
|
/// to the caller as a collection of PSObjects. No other flags are supported at this time and
|
|
/// will result in an exception if used.</param>
|
|
/// <param name="input">The list of objects to use as input to the script.</param>
|
|
/// <param name="args">The array of arguments to the command.</param>
|
|
/// <returns>A collection of MshCobjects generated by the script. This will be
|
|
/// empty if output was redirected.</returns>
|
|
/// <exception cref="ParseException">Thrown if there was a parsing error in the script.</exception>
|
|
/// <exception cref="RuntimeException">Represents a script-level exception</exception>
|
|
/// <exception cref="NotImplementedException">Thrown if any redirect other than output is attempted</exception>
|
|
/// <exception cref="FlowControlException"></exception>
|
|
public Collection<PSObject> InvokeScript(string script, bool useNewScope,
|
|
PipelineResultTypes writeToPipeline, IList input, params object[] args)
|
|
{
|
|
if (script == null)
|
|
throw new ArgumentNullException("script");
|
|
|
|
// Compile the script text into an executable script block.
|
|
ScriptBlock sb = ScriptBlock.Create(_context, script);
|
|
|
|
return InvokeScript(sb, useNewScope, writeToPipeline, input, args);
|
|
}
|
|
|
|
private Collection<PSObject> InvokeScript(ScriptBlock sb, bool useNewScope,
|
|
PipelineResultTypes writeToPipeline, IList input, params object[] args)
|
|
{
|
|
if (null != _cmdlet)
|
|
_cmdlet.ThrowIfStopping();
|
|
|
|
Cmdlet cmdletToUse = null;
|
|
ScriptBlock.ErrorHandlingBehavior errorHandlingBehavior = ScriptBlock.ErrorHandlingBehavior.WriteToExternalErrorPipe;
|
|
|
|
// Check if they want output
|
|
if ((writeToPipeline & PipelineResultTypes.Output) == PipelineResultTypes.Output)
|
|
{
|
|
cmdletToUse = _cmdlet;
|
|
writeToPipeline &= (~PipelineResultTypes.Output);
|
|
}
|
|
|
|
// Check if they want error
|
|
if ((writeToPipeline & PipelineResultTypes.Error) == PipelineResultTypes.Error)
|
|
{
|
|
errorHandlingBehavior = ScriptBlock.ErrorHandlingBehavior.WriteToCurrentErrorPipe;
|
|
writeToPipeline &= (~PipelineResultTypes.Error);
|
|
}
|
|
|
|
if (writeToPipeline != PipelineResultTypes.None)
|
|
{
|
|
// The only output types are Output and Error.
|
|
throw PSTraceSource.NewNotImplementedException();
|
|
}
|
|
|
|
// If the cmdletToUse is not null, then the result of the evaluation will be
|
|
// streamed out the output pipe of the cmdlet.
|
|
object rawResult;
|
|
if (cmdletToUse != null)
|
|
{
|
|
sb.InvokeUsingCmdlet(
|
|
contextCmdlet: cmdletToUse,
|
|
useLocalScope: useNewScope,
|
|
errorHandlingBehavior: errorHandlingBehavior,
|
|
dollarUnder: AutomationNull.Value,
|
|
input: input,
|
|
scriptThis: AutomationNull.Value,
|
|
args: args);
|
|
rawResult = AutomationNull.Value;
|
|
}
|
|
else
|
|
{
|
|
rawResult = sb.DoInvokeReturnAsIs(
|
|
useLocalScope: useNewScope,
|
|
errorHandlingBehavior: errorHandlingBehavior,
|
|
dollarUnder: AutomationNull.Value,
|
|
input: input,
|
|
scriptThis: AutomationNull.Value,
|
|
args: args);
|
|
}
|
|
|
|
if (rawResult == AutomationNull.Value)
|
|
{
|
|
return new Collection<PSObject>();
|
|
}
|
|
|
|
// If the result is already a collection of PSObjects, just return it...
|
|
Collection<PSObject> result = rawResult as Collection<PSObject>;
|
|
if (result != null)
|
|
return result;
|
|
|
|
result = new Collection<PSObject>();
|
|
|
|
IEnumerator list = null;
|
|
list = LanguagePrimitives.GetEnumerator(rawResult);
|
|
|
|
if (list != null)
|
|
{
|
|
while (list.MoveNext())
|
|
{
|
|
object val = list.Current;
|
|
|
|
result.Add(LanguagePrimitives.AsPSObjectOrNull(val));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result.Add(LanguagePrimitives.AsPSObjectOrNull(rawResult));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compile a string into a script block.
|
|
/// </summary>
|
|
/// <param name="scriptText">The source text to compile</param>
|
|
/// <returns>The compiled script block</returns>
|
|
/// <exception cref="ParseException"></exception>
|
|
public ScriptBlock NewScriptBlock(string scriptText)
|
|
{
|
|
if (null != _commandRuntime)
|
|
_commandRuntime.ThrowIfStopping();
|
|
|
|
ScriptBlock result = ScriptBlock.Create(_context, scriptText);
|
|
return result;
|
|
}
|
|
} //CommandInvocationIntrinsics
|
|
#endregion Auxiliary
|
|
|
|
/// <summary>
|
|
/// Defines members used by Cmdlets.
|
|
/// All Cmdlets must derive from
|
|
/// <see cref="System.Management.Automation.Cmdlet"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Do not attempt to create instances of
|
|
/// <see cref="System.Management.Automation.Cmdlet"/>
|
|
/// or its subclasses.
|
|
/// Instead, derive your own subclasses and mark them with
|
|
/// <see cref="System.Management.Automation.CmdletAttribute"/>,
|
|
/// and when your assembly is included in a shell, the Engine will
|
|
/// take care of instantiating your subclass.
|
|
/// </remarks>
|
|
public abstract partial class PSCmdlet : Cmdlet
|
|
{
|
|
#region private_members
|
|
|
|
internal bool HasDynamicParameters
|
|
{
|
|
get { return this is IDynamicParameters; }
|
|
}
|
|
|
|
#endregion private_members
|
|
|
|
#region public members
|
|
/// <summary>
|
|
/// The name of the parameter set in effect.
|
|
/// </summary>
|
|
/// <value>the parameter set name</value>
|
|
public string ParameterSetName
|
|
{
|
|
get
|
|
{
|
|
using (PSTransactionManager.GetEngineProtectionScope())
|
|
{
|
|
return _ParameterSetName;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Contains information about the identity of this cmdlet
|
|
/// and how it was invoked.
|
|
/// </summary>
|
|
/// <value></value>
|
|
public new InvocationInfo MyInvocation
|
|
{
|
|
get
|
|
{
|
|
using (PSTransactionManager.GetEngineProtectionScope())
|
|
{
|
|
return base.MyInvocation;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If the cmdlet declares paging support (via <see cref="CmdletCommonMetadataAttribute.SupportsPaging"/>),
|
|
/// then <see cref="PagingParameters"/> property contains arguments of the paging parameters.
|
|
/// Otherwise <see cref="PagingParameters"/> property is <c>null</c>.
|
|
/// </summary>
|
|
public PagingParameters PagingParameters
|
|
{
|
|
get
|
|
{
|
|
using (PSTransactionManager.GetEngineProtectionScope())
|
|
{
|
|
if (!this.CommandInfo.CommandMetadata.SupportsPaging)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (_pagingParameters == null)
|
|
{
|
|
MshCommandRuntime mshCommandRuntime = this.CommandRuntime as MshCommandRuntime;
|
|
if (mshCommandRuntime != null)
|
|
{
|
|
_pagingParameters = mshCommandRuntime.PagingParameters ?? new PagingParameters(mshCommandRuntime);
|
|
}
|
|
}
|
|
return _pagingParameters;
|
|
}
|
|
}
|
|
}
|
|
private PagingParameters _pagingParameters;
|
|
|
|
#region InvokeCommand
|
|
private CommandInvocationIntrinsics _invokeCommand;
|
|
|
|
/// <summary>
|
|
/// Provides access to utility routines for executing scripts
|
|
/// and creating script blocks.
|
|
/// </summary>
|
|
/// <value>Returns an object exposing the utility routines.</value>
|
|
public CommandInvocationIntrinsics InvokeCommand
|
|
{
|
|
get
|
|
{
|
|
using (PSTransactionManager.GetEngineProtectionScope())
|
|
{
|
|
if (_invokeCommand == null)
|
|
{
|
|
_invokeCommand = new CommandInvocationIntrinsics(Context, this);
|
|
}
|
|
return _invokeCommand;
|
|
}
|
|
}
|
|
} //InvokeCommand
|
|
#endregion InvokeCommand
|
|
|
|
#endregion public members
|
|
|
|
}
|
|
}
|
|
|