mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
363 lines
13 KiB
C#
363 lines
13 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
|
|
namespace System.Management.Automation
|
|
{
|
|
/// <summary>
|
|
/// Provides information about a mapping between a command name and a real command.
|
|
/// </summary>
|
|
public class AliasInfo : CommandInfo
|
|
{
|
|
#region ctor
|
|
|
|
/// <summary>
|
|
/// Creates an instance of the AliasInfo class with the specified name and referenced command.
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// The name of the command.
|
|
/// </param>
|
|
/// <param name="definition">
|
|
/// The token that the alias refers to.
|
|
/// </param>
|
|
/// <param name="context">
|
|
/// The execution context for this engine, used to lookup the current session state.
|
|
/// </param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If <paramref name="definition"/> is null or empty.
|
|
/// </exception>
|
|
/// <exception cref="ArgumentNullException">
|
|
/// If <paramref name="context"/> is null.
|
|
/// </exception>
|
|
internal AliasInfo(string name, string definition, ExecutionContext context) : base(name, CommandTypes.Alias)
|
|
{
|
|
_definition = definition;
|
|
this.Context = context;
|
|
|
|
if (context != null)
|
|
{
|
|
this.Module = context.SessionState.Internal.Module;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an instance of the AliasInfo class with the specified name and referenced command.
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// The name of the command.
|
|
/// </param>
|
|
/// <param name="definition">
|
|
/// The token that the alias refers to.
|
|
/// </param>
|
|
/// <param name="context">
|
|
/// The execution context for this engine instance, used to look up session state.
|
|
/// </param>
|
|
/// <param name="options">
|
|
/// The options to set on the alias. Note, Constant can only be set at creation time.
|
|
/// </param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If <paramref name="definition"/> is null or empty.
|
|
/// </exception>
|
|
/// <exception cref="ArgumentNullException">
|
|
/// If <paramref name="context"/> is null.
|
|
/// </exception>
|
|
internal AliasInfo(
|
|
string name,
|
|
string definition,
|
|
ExecutionContext context,
|
|
ScopedItemOptions options) : base(name, CommandTypes.Alias)
|
|
{
|
|
_definition = definition;
|
|
this.Context = context;
|
|
_options = options;
|
|
|
|
if (context != null)
|
|
{
|
|
this.Module = context.SessionState.Internal.Module;
|
|
}
|
|
}
|
|
|
|
#endregion ctor
|
|
|
|
internal override HelpCategory HelpCategory
|
|
{
|
|
get { return HelpCategory.Alias; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the command information for the command that is immediately referenced by this alias.
|
|
/// </summary>
|
|
public CommandInfo ReferencedCommand
|
|
{
|
|
get
|
|
{
|
|
// Need to lookup the referenced command every time
|
|
// to ensure we get the latest session state information
|
|
|
|
CommandInfo referencedCommand = null;
|
|
|
|
if ((_definition != null) && (Context != null))
|
|
{
|
|
CommandSearcher commandSearcher =
|
|
new CommandSearcher(
|
|
_definition,
|
|
SearchResolutionOptions.None,
|
|
CommandTypes.All,
|
|
Context);
|
|
|
|
if (commandSearcher.MoveNext())
|
|
{
|
|
System.Collections.Generic.IEnumerator<CommandInfo> ie = commandSearcher;
|
|
referencedCommand = ie.Current;
|
|
// referencedCommand = commandSearcher.Current;
|
|
}
|
|
}
|
|
|
|
return referencedCommand;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the command information for the command that
|
|
/// the alias eventually resolves to.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// An alias may reference another alias. This property follows the reference
|
|
/// chain of aliases to its end.
|
|
/// </remarks>
|
|
/// <!--
|
|
/// If the command didn't resolve to anything but aliases, the UnresolvedCommandName
|
|
/// property contains the last name the resolution succeeded in finding.
|
|
/// -->
|
|
public CommandInfo ResolvedCommand
|
|
{
|
|
get
|
|
{
|
|
// Need to lookup the resolved command every time to ensure
|
|
// we use the latest session state information
|
|
|
|
CommandInfo result = null;
|
|
|
|
if (_definition != null)
|
|
{
|
|
List<string> cyclePrevention = new List<string>();
|
|
cyclePrevention.Add(Name);
|
|
|
|
string commandNameToResolve = _definition;
|
|
result = ReferencedCommand;
|
|
while (result != null && result.CommandType == CommandTypes.Alias)
|
|
{
|
|
result = ((AliasInfo)result).ReferencedCommand;
|
|
|
|
if (result is AliasInfo)
|
|
{
|
|
// Check for the cycle by checking for the alias name
|
|
// in the cyclePrevention dictionary
|
|
|
|
if (SessionStateUtilities.CollectionContainsValue(cyclePrevention, result.Name, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
result = null;
|
|
break;
|
|
}
|
|
|
|
cyclePrevention.Add(result.Name);
|
|
|
|
commandNameToResolve = result.Definition;
|
|
}
|
|
}
|
|
|
|
if (result == null)
|
|
{
|
|
// Since we couldn't resolve the command that the alias
|
|
// points to, remember the definition so that we can
|
|
// provide better error reporting.
|
|
|
|
UnresolvedCommandName = commandNameToResolve;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the name of the command to which the alias refers.
|
|
/// </summary>
|
|
public override string Definition
|
|
{
|
|
get
|
|
{
|
|
return _definition;
|
|
}
|
|
}
|
|
|
|
private string _definition = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Sets the new definition for the alias.
|
|
/// </summary>
|
|
/// <param name="definition">
|
|
/// The new definition for the alias.
|
|
/// </param>
|
|
/// <param name="force">
|
|
/// If true, the value will be set even if the alias is ReadOnly.
|
|
/// </param>
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
/// If the alias is readonly or constant.
|
|
/// </exception>
|
|
internal void SetDefinition(string definition, bool force)
|
|
{
|
|
// Check to see if the variable is writable
|
|
|
|
if ((_options & ScopedItemOptions.Constant) != 0 ||
|
|
(!force && (_options & ScopedItemOptions.ReadOnly) != 0))
|
|
{
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Alias,
|
|
"AliasNotWritable",
|
|
SessionStateStrings.AliasNotWritable);
|
|
|
|
throw e;
|
|
}
|
|
|
|
_definition = definition;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the scope options for the alias.
|
|
/// </summary>
|
|
/// <exception cref="System.Management.Automation.SessionStateUnauthorizedAccessException">
|
|
/// If the trying to set an alias that is constant or
|
|
/// if the value trying to be set is ScopedItemOptions.Constant
|
|
/// </exception>
|
|
public ScopedItemOptions Options
|
|
{
|
|
get
|
|
{
|
|
return _options;
|
|
}
|
|
|
|
set
|
|
{
|
|
SetOptions(value, false);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the options for the alias and allows changes ReadOnly options only if force is specified.
|
|
/// </summary>
|
|
/// <param name="newOptions">
|
|
/// The new options value.
|
|
/// </param>
|
|
/// <param name="force">
|
|
/// If true the change to the options will happen even if the existing options are read-only.
|
|
/// </param>
|
|
internal void SetOptions(ScopedItemOptions newOptions, bool force)
|
|
{
|
|
// Check to see if the variable is constant, if so
|
|
// throw an exception because the options cannot be changed.
|
|
|
|
if ((_options & ScopedItemOptions.Constant) != 0)
|
|
{
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Alias,
|
|
"AliasIsConstant",
|
|
SessionStateStrings.AliasIsConstant);
|
|
|
|
throw e;
|
|
}
|
|
|
|
// Check to see if the variable is readonly, if so
|
|
// throw an exception because the options cannot be changed.
|
|
|
|
if (!force && (_options & ScopedItemOptions.ReadOnly) != 0)
|
|
{
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Alias,
|
|
"AliasIsReadOnly",
|
|
SessionStateStrings.AliasIsReadOnly);
|
|
|
|
throw e;
|
|
}
|
|
|
|
// Now check to see if the caller is trying to set
|
|
// the options to constant. This is only allowed at
|
|
// variable creation
|
|
|
|
if ((newOptions & ScopedItemOptions.Constant) != 0)
|
|
{
|
|
// user is trying to set the variable to constant after
|
|
// creating the variable. Do not allow this (as per spec).
|
|
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Alias,
|
|
"AliasCannotBeMadeConstant",
|
|
SessionStateStrings.AliasCannotBeMadeConstant);
|
|
|
|
throw e;
|
|
}
|
|
|
|
if ((newOptions & ScopedItemOptions.AllScope) == 0 &&
|
|
(_options & ScopedItemOptions.AllScope) != 0)
|
|
{
|
|
// user is trying to remove the AllScope option from the alias.
|
|
// Do not allow this (as per spec).
|
|
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
this.Name,
|
|
SessionStateCategory.Alias,
|
|
"AliasAllScopeOptionCannotBeRemoved",
|
|
SessionStateStrings.AliasAllScopeOptionCannotBeRemoved);
|
|
|
|
throw e;
|
|
}
|
|
|
|
_options = newOptions;
|
|
}
|
|
|
|
private ScopedItemOptions _options = ScopedItemOptions.None;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the description for the alias.
|
|
/// </summary>
|
|
public string Description { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// If ResolvedCommand returns null, this property will
|
|
/// return the name of the command that could not be resolved.
|
|
/// If ResolvedCommand has not yet been called or was able
|
|
/// to resolve the command, this property will return null.
|
|
/// </summary>
|
|
internal string UnresolvedCommandName { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The objects output from an alias are the objects output from the resolved
|
|
/// command. If we can't resolve the command, assume nothing is output - so use void.
|
|
/// </summary>
|
|
public override ReadOnlyCollection<PSTypeName> OutputType
|
|
{
|
|
get
|
|
{
|
|
CommandInfo resolvedCommand = this.ResolvedCommand;
|
|
if (resolvedCommand != null)
|
|
{
|
|
return resolvedCommand.OutputType;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|