2018-02-13 09:23:53 -08:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
|
// Licensed under the MIT License.
|
2016-07-29 13:02:49 -07:00
|
|
|
|
2016-03-30 14:20:52 -07:00
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Management.Automation.Language;
|
|
|
|
|
using System.Management.Automation.Runspaces;
|
2016-07-29 13:02:49 -07:00
|
|
|
using Dbg = System.Management.Automation.Diagnostics;
|
2016-03-30 14:20:52 -07:00
|
|
|
|
|
|
|
|
namespace System.Management.Automation
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
2017-01-16 13:31:14 -08:00
|
|
|
/// Holds the state of a Monad Shell session
|
2016-03-30 14:20:52 -07:00
|
|
|
/// </summary>
|
|
|
|
|
internal sealed partial class SessionStateInternal
|
|
|
|
|
{
|
|
|
|
|
#region Functions
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Add an new SessionState function entry to this session state object...
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="entry">The entry to add</param>
|
|
|
|
|
internal void AddSessionStateEntry(SessionStateFunctionEntry entry)
|
|
|
|
|
{
|
|
|
|
|
ScriptBlock sb = entry.ScriptBlock.Clone();
|
|
|
|
|
|
|
|
|
|
FunctionInfo fn = this.SetFunction(entry.Name, sb, null, entry.Options, false, CommandOrigin.Internal, this.ExecutionContext, entry.HelpFile, true);
|
|
|
|
|
fn.Visibility = entry.Visibility;
|
|
|
|
|
fn.Module = entry.Module;
|
2018-11-13 16:16:29 -08:00
|
|
|
fn.ScriptBlock.LanguageMode = entry.ScriptBlock.LanguageMode ?? PSLanguageMode.FullLanguage;
|
2016-03-30 14:20:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a flattened view of the functions that are visible using
|
|
|
|
|
/// the current scope as a reference and filtering the functions in
|
|
|
|
|
/// the other scopes based on the scoping rules.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// An IDictionary representing the visible functions.
|
|
|
|
|
/// </returns>
|
|
|
|
|
internal IDictionary GetFunctionTable()
|
2016-07-29 13:02:49 -07:00
|
|
|
{
|
2016-03-30 14:20:52 -07:00
|
|
|
SessionStateScopeEnumerator scopeEnumerator =
|
2016-07-29 13:02:49 -07:00
|
|
|
new SessionStateScopeEnumerator(_currentScope);
|
2016-03-30 14:20:52 -07:00
|
|
|
|
|
|
|
|
Dictionary<string, FunctionInfo> result =
|
|
|
|
|
new Dictionary<string, FunctionInfo>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
foreach (SessionStateScope scope in scopeEnumerator)
|
|
|
|
|
{
|
|
|
|
|
foreach (FunctionInfo entry in scope.FunctionTable.Values)
|
|
|
|
|
{
|
|
|
|
|
if (!result.ContainsKey(entry.Name))
|
|
|
|
|
{
|
|
|
|
|
result.Add(entry.Name, entry);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
} // GetFunctionTable
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets an IEnumerable for the function table for a given scope
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="scopeID">
|
|
|
|
|
/// A scope identifier that is either one of the "special" scopes like
|
|
|
|
|
/// "global", "script", "local", or "private, or a numeric ID of a relative scope
|
|
|
|
|
/// to the current scope.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="scopeID"/> is less than zero, or not
|
|
|
|
|
/// a number and not "script", "global", "local", or "private"
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="ArgumentOutOfRangeException">
|
|
|
|
|
/// If <paramref name="scopeID"/> is less than zero or greater than the number of currently
|
|
|
|
|
/// active scopes.
|
|
|
|
|
/// </exception>
|
|
|
|
|
internal IDictionary<string, FunctionInfo> GetFunctionTableAtScope(string scopeID)
|
|
|
|
|
{
|
|
|
|
|
Dictionary<string, FunctionInfo> result =
|
|
|
|
|
new Dictionary<string, FunctionInfo>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
SessionStateScope scope = GetScopeByID(scopeID);
|
|
|
|
|
|
|
|
|
|
foreach (FunctionInfo entry in scope.FunctionTable.Values)
|
|
|
|
|
{
|
|
|
|
|
// Make sure the function/filter isn't private or if it is that the current
|
|
|
|
|
// scope is the same scope the alias was retrieved from.
|
|
|
|
|
|
|
|
|
|
if ((entry.Options & ScopedItemOptions.Private) == 0 ||
|
2016-07-29 13:02:49 -07:00
|
|
|
scope == _currentScope)
|
2016-03-30 14:20:52 -07:00
|
|
|
{
|
|
|
|
|
result.Add(entry.Name, entry);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
} // GetFunctionTableAtScope
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// List of functions/filters to export from this session state object...
|
|
|
|
|
/// </summary>
|
2016-08-02 13:29:09 -07:00
|
|
|
internal List<FunctionInfo> ExportedFunctions { get; } = new List<FunctionInfo>();
|
2016-03-30 14:20:52 -07:00
|
|
|
|
2016-08-02 13:29:09 -07:00
|
|
|
internal bool UseExportList { get; set; } = false;
|
2016-03-30 14:20:52 -07:00
|
|
|
|
2018-11-13 16:16:29 -08:00
|
|
|
/// <summary>
|
|
|
|
|
/// Set to true when module functions are being explicitly exported using Export-ModuleMember
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal bool FunctionsExported { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set to true when any processed module functions are being explicitly exported using '*' wildcard
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal bool FunctionsExportedWithWildcard
|
|
|
|
|
{
|
|
|
|
|
get { return _functionsExportedWithWildcard; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
Dbg.Assert((value == true), "This property should never be set/reset to false");
|
|
|
|
|
if (value == true)
|
|
|
|
|
{
|
|
|
|
|
_functionsExportedWithWildcard = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private bool _functionsExportedWithWildcard;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set to true if module loading is performed under a manifest that explicitly exports functions (no wildcards)
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal bool ManifestWithExplicitFunctionExport { get; set; }
|
|
|
|
|
|
2016-03-30 14:20:52 -07:00
|
|
|
/// <summary>
|
|
|
|
|
/// Get a functions out of session state.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// name of function to look up
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="origin">
|
|
|
|
|
/// Origin of the command that called this API...
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// The value of the specified function.
|
|
|
|
|
/// </returns>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
internal FunctionInfo GetFunction(string name, CommandOrigin origin)
|
|
|
|
|
{
|
|
|
|
|
if (String.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
throw PSTraceSource.NewArgumentException("name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FunctionInfo result = null;
|
|
|
|
|
|
|
|
|
|
FunctionLookupPath lookupPath = new FunctionLookupPath(name);
|
|
|
|
|
|
|
|
|
|
FunctionScopeItemSearcher searcher =
|
|
|
|
|
new FunctionScopeItemSearcher(this, lookupPath, origin);
|
|
|
|
|
|
|
|
|
|
if (searcher.MoveNext())
|
|
|
|
|
{
|
|
|
|
|
result = ((IEnumerator<FunctionInfo>)searcher).Current;
|
|
|
|
|
}
|
2018-11-13 16:16:29 -08:00
|
|
|
|
|
|
|
|
return (IsFunctionVisibleInDebugger(result, origin)) ? result : null;
|
2016-03-30 14:20:52 -07:00
|
|
|
} // GetFunction
|
|
|
|
|
|
2018-11-13 16:16:29 -08:00
|
|
|
private bool IsFunctionVisibleInDebugger(FunctionInfo fnInfo, CommandOrigin origin)
|
|
|
|
|
{
|
|
|
|
|
// Ensure the returned function item is not exposed across language boundaries when in
|
|
|
|
|
// a debugger breakpoint or nested prompt.
|
|
|
|
|
// A debugger breakpoint/nested prompt has access to all current scoped functions.
|
|
|
|
|
// This includes both running commands from the prompt or via a debugger Action scriptblock.
|
|
|
|
|
|
|
|
|
|
// Early out.
|
|
|
|
|
// Always allow built-in functions needed for command line debugging.
|
|
|
|
|
if ((this.ExecutionContext.LanguageMode == PSLanguageMode.FullLanguage) ||
|
|
|
|
|
(fnInfo == null) ||
|
|
|
|
|
(fnInfo.Name.Equals("prompt", StringComparison.OrdinalIgnoreCase)) ||
|
|
|
|
|
(fnInfo.Name.Equals("TabExpansion2", StringComparison.OrdinalIgnoreCase)) ||
|
|
|
|
|
(fnInfo.Name.Equals("Clear-Host", StringComparison.Ordinal)))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check both InNestedPrompt and Debugger.InBreakpoint to ensure we don't miss a case.
|
|
|
|
|
// Function is not visible if function and context language modes are different.
|
|
|
|
|
var runspace = this.ExecutionContext.CurrentRunspace;
|
|
|
|
|
if ((runspace != null) &&
|
|
|
|
|
(runspace.InNestedPrompt || (runspace.Debugger?.InBreakpoint == true)) &&
|
|
|
|
|
(fnInfo.DefiningLanguageMode.HasValue && (fnInfo.DefiningLanguageMode != this.ExecutionContext.LanguageMode)))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-30 14:20:52 -07:00
|
|
|
/// <summary>
|
|
|
|
|
/// Get a functions out of session state.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// name of function to look up
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// The value of the specified function.
|
|
|
|
|
/// </returns>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
internal FunctionInfo GetFunction(string name)
|
|
|
|
|
{
|
|
|
|
|
return GetFunction(name, CommandOrigin.Internal);
|
2017-01-16 13:31:14 -08:00
|
|
|
} // GetFunction
|
2016-03-30 14:20:52 -07:00
|
|
|
|
2016-07-29 13:02:49 -07:00
|
|
|
private IEnumerable<string> GetFunctionAliases(IParameterMetadataProvider ipmp)
|
2016-03-30 14:20:52 -07:00
|
|
|
{
|
|
|
|
|
if (ipmp == null || ipmp.Body.ParamBlock == null)
|
|
|
|
|
yield break;
|
|
|
|
|
|
|
|
|
|
var attributes = ipmp.Body.ParamBlock.Attributes;
|
|
|
|
|
foreach (var attributeAst in attributes)
|
|
|
|
|
{
|
|
|
|
|
var attributeType = attributeAst.TypeName.GetReflectionAttributeType();
|
|
|
|
|
if (attributeType == typeof(AliasAttribute))
|
|
|
|
|
{
|
2016-07-29 13:02:49 -07:00
|
|
|
var cvv = new ConstantValueVisitor { AttributeArgument = true };
|
2016-03-30 14:20:52 -07:00
|
|
|
for (int i = 0; i < attributeAst.PositionalArguments.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
yield return Compiler._attrArgToStringConverter.Target(Compiler._attrArgToStringConverter,
|
|
|
|
|
attributeAst.PositionalArguments[i].Accept(cvv));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set a function in the current scope of session state.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="function">
|
|
|
|
|
/// The new value of the function being set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="origin">
|
|
|
|
|
/// Origin of the caller of this API
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="ArgumentNullException">
|
|
|
|
|
/// If <paramref name="function"/> is null.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is read-only or constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal FunctionInfo SetFunctionRaw(
|
|
|
|
|
string name,
|
|
|
|
|
ScriptBlock function,
|
|
|
|
|
CommandOrigin origin)
|
|
|
|
|
{
|
|
|
|
|
if (String.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
throw PSTraceSource.NewArgumentException("name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (function == null)
|
|
|
|
|
{
|
|
|
|
|
throw PSTraceSource.NewArgumentNullException("function");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string originalName = name;
|
|
|
|
|
|
|
|
|
|
FunctionLookupPath path = new FunctionLookupPath(name);
|
|
|
|
|
name = path.UnqualifiedPath;
|
|
|
|
|
|
|
|
|
|
if (String.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
SessionStateException exception =
|
|
|
|
|
new SessionStateException(
|
|
|
|
|
originalName,
|
|
|
|
|
SessionStateCategory.Function,
|
|
|
|
|
"ScopedFunctionMustHaveName",
|
|
|
|
|
SessionStateStrings.ScopedFunctionMustHaveName,
|
|
|
|
|
ErrorCategory.InvalidArgument);
|
|
|
|
|
|
|
|
|
|
throw exception;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScopedItemOptions options = ScopedItemOptions.None;
|
|
|
|
|
if (path.IsPrivate)
|
|
|
|
|
{
|
|
|
|
|
options |= ScopedItemOptions.Private;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FunctionScopeItemSearcher searcher =
|
|
|
|
|
new FunctionScopeItemSearcher(
|
|
|
|
|
this,
|
|
|
|
|
path,
|
|
|
|
|
origin);
|
|
|
|
|
|
|
|
|
|
var functionInfo = searcher.InitialScope.SetFunction(name, function, null, options, false, origin, ExecutionContext);
|
|
|
|
|
|
|
|
|
|
foreach (var aliasName in GetFunctionAliases(function.Ast as IParameterMetadataProvider))
|
|
|
|
|
{
|
|
|
|
|
searcher.InitialScope.SetAliasValue(aliasName, name, ExecutionContext, false, origin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return functionInfo;
|
|
|
|
|
} // SetFunctionRaw
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set a function in the current scope of session state.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="function">
|
|
|
|
|
/// The new value of the function being set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="originalFunction">
|
|
|
|
|
/// The original function (if any) from which the ScriptBlock is derived.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="options">
|
|
|
|
|
/// The options to set on the function.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="force">
|
|
|
|
|
/// If true, the function will be set even if its ReadOnly.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="origin">
|
|
|
|
|
/// Origin of the caller of this API
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="ArgumentNullException">
|
|
|
|
|
/// If <paramref name="function"/> is null.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is read-only or constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal FunctionInfo SetFunction(
|
2016-07-29 13:02:49 -07:00
|
|
|
string name,
|
2016-03-30 14:20:52 -07:00
|
|
|
ScriptBlock function,
|
|
|
|
|
FunctionInfo originalFunction,
|
|
|
|
|
ScopedItemOptions options,
|
|
|
|
|
bool force,
|
|
|
|
|
CommandOrigin origin)
|
|
|
|
|
{
|
|
|
|
|
return SetFunction(name, function, originalFunction, options, force, origin, ExecutionContext, null);
|
|
|
|
|
} // SetFunction
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set a function in the current scope of session state.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="function">
|
|
|
|
|
/// The new value of the function being set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="originalFunction">
|
|
|
|
|
/// The original function (if any) from which the ScriptBlock is derived.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="options">
|
|
|
|
|
/// The options to set on the function.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="force">
|
|
|
|
|
/// If true, the function will be set even if its ReadOnly.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="origin">
|
|
|
|
|
/// Origin of the caller of this API
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="helpFile">
|
|
|
|
|
/// The name of the help file associated with the function.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="ArgumentNullException">
|
|
|
|
|
/// If <paramref name="function"/> is null.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is read-only or constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal FunctionInfo SetFunction(
|
|
|
|
|
string name,
|
|
|
|
|
ScriptBlock function,
|
|
|
|
|
FunctionInfo originalFunction,
|
|
|
|
|
ScopedItemOptions options,
|
|
|
|
|
bool force,
|
|
|
|
|
CommandOrigin origin,
|
|
|
|
|
string helpFile)
|
|
|
|
|
{
|
|
|
|
|
return SetFunction(name, function, originalFunction, options, force, origin, ExecutionContext, helpFile, false);
|
|
|
|
|
} // SetFunction
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set a function in the current scope of session state.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="function">
|
|
|
|
|
/// The new value of the function being set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="originalFunction">
|
|
|
|
|
/// The original function (if any) from which the ScriptBlock is derived.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="options">
|
|
|
|
|
/// The options to set on the function.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="force">
|
|
|
|
|
/// If true, the function will be set even if its ReadOnly.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="origin">
|
|
|
|
|
/// Origin of the caller of this API
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="context">
|
|
|
|
|
/// The execution context for the function.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="helpFile">
|
|
|
|
|
/// The name of the help file associated with the function.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </param>
|
2016-03-30 14:20:52 -07:00
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="ArgumentNullException">
|
|
|
|
|
/// If <paramref name="function"/> is null.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is read-only or constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal FunctionInfo SetFunction(
|
|
|
|
|
string name,
|
|
|
|
|
ScriptBlock function,
|
|
|
|
|
FunctionInfo originalFunction,
|
|
|
|
|
ScopedItemOptions options,
|
|
|
|
|
bool force,
|
|
|
|
|
CommandOrigin origin,
|
|
|
|
|
ExecutionContext context,
|
|
|
|
|
string helpFile)
|
|
|
|
|
{
|
|
|
|
|
return SetFunction(name, function, originalFunction, options, force, origin, context, helpFile, false);
|
|
|
|
|
} // SetFunction
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set a function in the current scope of session state.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="function">
|
|
|
|
|
/// The new value of the function being set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="originalFunction">
|
|
|
|
|
/// The original function (if any) from which the ScriptBlock is derived.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="options">
|
|
|
|
|
/// The options to set on the function.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="force">
|
|
|
|
|
/// If true, the function will be set even if its ReadOnly.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="origin">
|
|
|
|
|
/// Origin of the caller of this API
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="context">
|
|
|
|
|
/// The execution context for the function.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="helpFile">
|
|
|
|
|
/// The name of the help file associated with the function.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="isPreValidated">
|
2017-09-11 08:55:13 -07:00
|
|
|
/// Set to true if it is a regular function (meaning, we do not need to check if the script contains JobDefinition Attribute and then process it)
|
2016-03-30 14:20:52 -07:00
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="ArgumentNullException">
|
|
|
|
|
/// If <paramref name="function"/> is null.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is read-only or constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal FunctionInfo SetFunction(
|
|
|
|
|
string name,
|
|
|
|
|
ScriptBlock function,
|
|
|
|
|
FunctionInfo originalFunction,
|
|
|
|
|
ScopedItemOptions options,
|
|
|
|
|
bool force,
|
|
|
|
|
CommandOrigin origin,
|
|
|
|
|
ExecutionContext context,
|
|
|
|
|
string helpFile,
|
|
|
|
|
bool isPreValidated)
|
|
|
|
|
{
|
|
|
|
|
if (String.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
throw PSTraceSource.NewArgumentException("name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (function == null)
|
|
|
|
|
{
|
|
|
|
|
throw PSTraceSource.NewArgumentNullException("function");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string originalName = name;
|
|
|
|
|
|
|
|
|
|
FunctionLookupPath path = new FunctionLookupPath(name);
|
|
|
|
|
name = path.UnqualifiedPath;
|
|
|
|
|
|
|
|
|
|
if (String.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
SessionStateException exception =
|
|
|
|
|
new SessionStateException(
|
|
|
|
|
originalName,
|
|
|
|
|
SessionStateCategory.Function,
|
|
|
|
|
"ScopedFunctionMustHaveName",
|
|
|
|
|
SessionStateStrings.ScopedFunctionMustHaveName,
|
|
|
|
|
ErrorCategory.InvalidArgument);
|
|
|
|
|
|
|
|
|
|
throw exception;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (path.IsPrivate)
|
|
|
|
|
{
|
|
|
|
|
options |= ScopedItemOptions.Private;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FunctionScopeItemSearcher searcher =
|
|
|
|
|
new FunctionScopeItemSearcher(
|
|
|
|
|
this,
|
|
|
|
|
path,
|
|
|
|
|
origin);
|
|
|
|
|
|
|
|
|
|
return searcher.InitialScope.SetFunction(name, function, originalFunction, options, force, origin, context, helpFile);
|
|
|
|
|
} // SetFunction
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set a function in the current scope of session state.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="function">
|
|
|
|
|
/// The new value of the function being set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="originalFunction">
|
|
|
|
|
/// The original function (if any) from which the ScriptBlock is derived.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="force">
|
|
|
|
|
/// If true, the function will be set even if its ReadOnly.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="origin">
|
|
|
|
|
/// The origin of the caller
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// or
|
|
|
|
|
/// If <paramref name="function"/> is not a <see cref="FilterInfo">FilterInfo</see>
|
|
|
|
|
/// or <see cref="FunctionInfo">FunctionInfo</see>
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="ArgumentNullException">
|
|
|
|
|
/// If <paramref name="function"/> is null.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is read-only or constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal FunctionInfo SetFunction(
|
|
|
|
|
string name,
|
|
|
|
|
ScriptBlock function,
|
|
|
|
|
FunctionInfo originalFunction,
|
|
|
|
|
bool force,
|
|
|
|
|
CommandOrigin origin)
|
|
|
|
|
{
|
|
|
|
|
if (String.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
throw PSTraceSource.NewArgumentException("name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (function == null)
|
|
|
|
|
{
|
|
|
|
|
throw PSTraceSource.NewArgumentNullException("function");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string originalName = name;
|
|
|
|
|
|
|
|
|
|
FunctionLookupPath path = new FunctionLookupPath(name);
|
|
|
|
|
name = path.UnqualifiedPath;
|
|
|
|
|
|
|
|
|
|
if (String.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
SessionStateException exception =
|
|
|
|
|
new SessionStateException(
|
|
|
|
|
originalName,
|
|
|
|
|
SessionStateCategory.Function,
|
|
|
|
|
"ScopedFunctionMustHaveName",
|
|
|
|
|
SessionStateStrings.ScopedFunctionMustHaveName,
|
|
|
|
|
ErrorCategory.InvalidArgument);
|
|
|
|
|
|
|
|
|
|
throw exception;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScopedItemOptions options = ScopedItemOptions.None;
|
|
|
|
|
if (path.IsPrivate)
|
|
|
|
|
{
|
|
|
|
|
options |= ScopedItemOptions.Private;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FunctionScopeItemSearcher searcher =
|
|
|
|
|
new FunctionScopeItemSearcher(
|
|
|
|
|
this,
|
|
|
|
|
path,
|
|
|
|
|
origin);
|
|
|
|
|
|
|
|
|
|
FunctionInfo result = null;
|
|
|
|
|
|
|
|
|
|
SessionStateScope scope = searcher.InitialScope;
|
2016-07-29 13:02:49 -07:00
|
|
|
|
2016-03-30 14:20:52 -07:00
|
|
|
if (searcher.MoveNext())
|
|
|
|
|
{
|
|
|
|
|
scope = searcher.CurrentLookupScope;
|
|
|
|
|
name = searcher.Name;
|
|
|
|
|
|
|
|
|
|
if (path.IsPrivate)
|
|
|
|
|
{
|
|
|
|
|
// Need to add the Private flag
|
|
|
|
|
FunctionInfo existingFunction = scope.GetFunction(name);
|
|
|
|
|
options |= existingFunction.Options;
|
|
|
|
|
result = scope.SetFunction(name, function, originalFunction, options, force, origin, ExecutionContext);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result = scope.SetFunction(name, function, force, origin, ExecutionContext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (path.IsPrivate)
|
|
|
|
|
{
|
|
|
|
|
result = scope.SetFunction(name, function, originalFunction, options, force, origin, ExecutionContext);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result = scope.SetFunction(name, function, force, origin, ExecutionContext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Set a function in the current scope of session state.
|
2017-01-16 13:31:14 -08:00
|
|
|
///
|
2016-03-30 14:20:52 -07:00
|
|
|
/// BUGBUG: this overload is preserved because a lot of tests use reflection to
|
|
|
|
|
/// call it. The tests should be fixed and this API eventually removed.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="function">
|
|
|
|
|
/// The new value of the function being set.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="force">
|
|
|
|
|
/// If true, the function will be set even if its ReadOnly.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// or
|
|
|
|
|
/// If <paramref name="function"/> is not a <see cref="FilterInfo">FilterInfo</see>
|
|
|
|
|
/// or <see cref="FunctionInfo">FunctionInfo</see>
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="ArgumentNullException">
|
|
|
|
|
/// If <paramref name="function"/> is null.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is read-only or constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal FunctionInfo SetFunction(string name, ScriptBlock function, bool force)
|
|
|
|
|
{
|
|
|
|
|
return SetFunction(name, function, null, force, CommandOrigin.Internal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Removes a function from the function table.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to remove.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="origin">
|
|
|
|
|
/// THe origin of the caller of this API
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="force">
|
|
|
|
|
/// If true, the function is removed even if it is ReadOnly.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-07-29 13:02:49 -07:00
|
|
|
internal void RemoveFunction(string name, bool force, CommandOrigin origin)
|
2016-03-30 14:20:52 -07:00
|
|
|
{
|
|
|
|
|
if (String.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
throw PSTraceSource.NewArgumentException("name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use the scope enumerator to find an existing function
|
|
|
|
|
|
2016-07-29 13:02:49 -07:00
|
|
|
SessionStateScope scope = _currentScope;
|
2016-03-30 14:20:52 -07:00
|
|
|
|
|
|
|
|
FunctionLookupPath path = new FunctionLookupPath(name);
|
|
|
|
|
|
|
|
|
|
FunctionScopeItemSearcher searcher =
|
|
|
|
|
new FunctionScopeItemSearcher(
|
|
|
|
|
this,
|
|
|
|
|
path,
|
|
|
|
|
origin);
|
|
|
|
|
|
|
|
|
|
if (searcher.MoveNext())
|
|
|
|
|
{
|
|
|
|
|
scope = searcher.CurrentLookupScope;
|
|
|
|
|
}
|
|
|
|
|
scope.RemoveFunction(name, force);
|
|
|
|
|
} // RemoveFunction
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Removes a function from the function table.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to remove.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="force">
|
|
|
|
|
/// If true, the function is removed even if it is ReadOnly.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentException">
|
|
|
|
|
/// If <paramref name="name"/> is null or empty.
|
|
|
|
|
/// </exception>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal void RemoveFunction(string name, bool force)
|
|
|
|
|
{
|
|
|
|
|
RemoveFunction(name, force, CommandOrigin.Internal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2017-01-16 13:31:14 -08:00
|
|
|
/// Removes a function from the function table
|
2016-03-30 14:20:52 -07:00
|
|
|
/// if the function was imported from the given module.
|
2017-01-16 13:31:14 -08:00
|
|
|
///
|
2016-08-28 05:44:55 +00:00
|
|
|
/// BUGBUG: This is only used by the implicit remoting functions...
|
2016-03-30 14:20:52 -07:00
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
/// The name of the function to remove.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="module">
|
|
|
|
|
/// Module the function might be imported from.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
|
|
|
/// If the function is constant.
|
2017-01-16 13:31:14 -08:00
|
|
|
/// </exception>
|
2016-03-30 14:20:52 -07:00
|
|
|
internal void RemoveFunction(string name, PSModuleInfo module)
|
|
|
|
|
{
|
|
|
|
|
Dbg.Assert(module != null, "Caller should verify that module parameter is not null");
|
|
|
|
|
|
|
|
|
|
FunctionInfo func = GetFunction(name) as FunctionInfo;
|
|
|
|
|
if (func != null && func.ScriptBlock != null
|
|
|
|
|
&& func.ScriptBlock.File != null
|
|
|
|
|
&& func.ScriptBlock.File.Equals(module.Path, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
RemoveFunction(name, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion Functions
|
|
|
|
|
} // SessionStateInternal class
|
2018-11-13 16:16:29 -08:00
|
|
|
}
|