/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Management.Automation.Internal; using System.Management.Automation.Provider; using System.Management.Automation.Language; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; using Microsoft.PowerShell.Commands; using Debug = System.Management.Automation.Diagnostics; using System.Management.Automation.Host; using System.Text; using System.Threading.Tasks; namespace System.Management.Automation.Runspaces { internal class EarlyStartup { internal static void Init() { // Code added here should: // * run every time we start PowerSHell // * have high CPU cost // * be ordered from most expensive to least expensive, or at least needed earliest // * this method should return quickly, so all work should be run in one or more tasks. // * code called from here should correctly handle being called twice, in case initialization // is needed in the main code path before the task completes. // // Code added here should not: // * count on running - not all hosts will call this method // * have high disk cost // We shouldn't create too many tasks. // This task takes awhile, so it gets it's own task Task.Run(() => { // Building the catalog is expensive, so force that to happen early on a background thread, and do so // on a file we are very likely to read anyway. var pshome = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID); var unused = SecuritySupport.IsProductBinary(Path.Combine(pshome, "Modules", "Microsoft.PowerShell.Utility", "Microsoft.PowerShell.Utility.psm1")); }); // One other task for other stuff that's faster, but still a little slow. Task.Run(() => { // Loading the resources for System.Management.Automation can be expensive, so force that to // happen early on a background thread. var unused0 = RunspaceInit.OutputEncodingDescription; // Amsi initialize can also be a little slow if (Platform.IsWindows) { AmsiUtils.Init(); } // This will init some tables and could load some assemblies. var unused1 = TypeAccelerators.builtinTypeAccelerators; // This will init some tables and could load some assemblies. var unused2 = LanguagePrimitives.GetEnumerator(null); }); } } /// /// Baseclass for defining elements that can be added /// to an InitialSessionState object. /// public abstract class InitialSessionStateEntry { /// /// ctor so that each derived class has a name /// /// protected InitialSessionStateEntry(string name) { _name = name; } /// /// The name of this entry /// public string Name { get { return _name; } internal set { _name = value; } } private string _name; /// /// The SnapIn to load from initially /// public PSSnapInInfo PSSnapIn { get { return _psSnapIn; } } internal void SetPSSnapIn(PSSnapInInfo psSnapIn) { _psSnapIn = psSnapIn; } private PSSnapInInfo _psSnapIn; /// /// The SnapIn to load from initially /// public PSModuleInfo Module { get { return _module; } } internal void SetModule(PSModuleInfo module) { _module = module; } private PSModuleInfo _module; /// /// Shallow-clone this object /// /// The cloned object... public abstract InitialSessionStateEntry Clone(); } /// /// Class to constrain session state entries /// public abstract class ConstrainedSessionStateEntry : InitialSessionStateEntry { /// /// /// /// /// protected ConstrainedSessionStateEntry(string name, SessionStateEntryVisibility visibility) : base(name) { _visibility = visibility; } /// /// /// public SessionStateEntryVisibility Visibility { get { return _visibility; } set { _visibility = value; } } private SessionStateEntryVisibility _visibility; } /// /// Command class so that all the commands can derive off this one. /// Adds the flexibility of adding addditional derived class, /// such as ProxyCommand for Exchange. /// Derived classes - Alias, Application, Cmdlet, Function, Script. /// public abstract class SessionStateCommandEntry : ConstrainedSessionStateEntry { /// /// Base constructor for all SessionState commands. /// /// protected SessionStateCommandEntry(string name) : base(name, SessionStateEntryVisibility.Public) { } /// /// /// /// /// protected internal SessionStateCommandEntry(string name, SessionStateEntryVisibility visibility) : base(name, visibility) { } /// /// Returns the type of the command using an enum /// instead of requiring a full reflection type check. /// public CommandTypes CommandType { get { return _commandType; } } /// /// Is internal so it can be set by the engine code... /// internal CommandTypes _commandType; /// /// Is internal so it can be set by the engine code... /// This is used to specify whether this command was imported or not /// If noClobber is specified during Import-Module, it is set to false /// internal bool _isImported = true; } /// /// Type file configuration entry... /// public sealed class SessionStateTypeEntry : InitialSessionStateEntry { /// /// Loads all entries from the types file. /// /// public SessionStateTypeEntry(string fileName) : base(fileName) { if (String.IsNullOrEmpty(fileName) || fileName.Trim().Length == 0) { throw PSTraceSource.NewArgumentException("fileName"); } _fileName = fileName.Trim(); } /// /// Loads all the types specified in the typeTable /// /// public SessionStateTypeEntry(TypeTable typeTable) : base("*") { if (typeTable == null) { throw PSTraceSource.NewArgumentNullException("typeTable"); } _typeTable = typeTable; } /// /// Loads all entries from the typeData /// /// /// public SessionStateTypeEntry(TypeData typeData, bool isRemove) : base("*") { if (typeData == null) { throw PSTraceSource.NewArgumentNullException("typeData"); } _typeData = typeData; _isRemove = isRemove; } /// /// Shallow-clone this object /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateTypeEntry entry; if (_fileName != null) { entry = new SessionStateTypeEntry(_fileName); } else if (_typeTable != null) { entry = new SessionStateTypeEntry(_typeTable); } else { entry = new SessionStateTypeEntry(_typeData, _isRemove); } entry.SetPSSnapIn(this.PSSnapIn); entry.SetModule(this.Module); return entry; } /// /// The pathname of the types.ps1xml file. This can be null if /// TypeTable constructor or TypeData constructor is used. /// public string FileName { get { return _fileName; } } private string _fileName; /// /// The TypeTable specified with constructor. This can be null if /// FileName constructor or TypeData constructor is used. /// public TypeTable TypeTable { get { return _typeTable; } } private TypeTable _typeTable; /// /// The TypeData we want to update with. This can be null if /// FileName constructor or TypeTable constructor is used. /// public TypeData TypeData { get { return _typeData; } } private TypeData _typeData; /// /// The operation will be done on the typedata. This is only /// meaningful when the TypeData constructor is used. /// public bool IsRemove { get { return _isRemove; } } private bool _isRemove; //So that we can specify the type information on the fly, //without using Types.ps1xml file //public SessionStateTypeEntry(string name, xmlreader definition); //public string Definition { get; } } /// /// Format file configuration entry... /// public sealed class SessionStateFormatEntry : InitialSessionStateEntry { /// /// Loads the entire formats file /// /// public SessionStateFormatEntry(string fileName) : base("*") { if (String.IsNullOrEmpty(fileName) || fileName.Trim().Length == 0) { throw PSTraceSource.NewArgumentException("fileName"); } _fileName = fileName.Trim(); } /// /// Loads all the format data specified in the formatTable /// /// public SessionStateFormatEntry(FormatTable formattable) : base("*") { if (formattable == null) { throw PSTraceSource.NewArgumentNullException("formattable"); } _formattable = formattable; } /// /// Loads all the format data specified in the typeDefinition /// /// public SessionStateFormatEntry(ExtendedTypeDefinition typeDefinition) : base("*") { if (typeDefinition == null) { throw PSTraceSource.NewArgumentNullException("typeDefinition"); } _typeDefinition = typeDefinition; } /// /// Shallow-clone this object... /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateFormatEntry entry; if (_fileName != null) { entry = new SessionStateFormatEntry(_fileName); } else if (_formattable != null) { entry = new SessionStateFormatEntry(_formattable); } else { entry = new SessionStateFormatEntry(_typeDefinition); } entry.SetPSSnapIn(this.PSSnapIn); entry.SetModule(this.Module); return entry; } /// /// The name of the format file referenced by this entry... /// public string FileName { get { return _fileName; } } private string _fileName; /// /// The FormatTable specified with constructor. This can be null if /// FileName constructor is used. /// public FormatTable Formattable { get { return _formattable; } } private FormatTable _formattable; /// /// The FormatData specified with constructor. This can be null if /// FileName or FormatTable constructor is used /// public ExtendedTypeDefinition FormatData { get { return _typeDefinition; } } private ExtendedTypeDefinition _typeDefinition; //So that we can specify the format information on the fly, //without using Format.ps1xml file //public SessionStateFormatEntry(string name, xmlreader definition); //public string Definition { get; } } /// /// An assembly to load for this sessionstate... /// public sealed class SessionStateAssemblyEntry : InitialSessionStateEntry { /// /// Create a named entry for the assembly to load with both the /// name and the path to the assembly as a backup. /// /// The name of the assembly to load /// The path to the assembly to use as an alternative public SessionStateAssemblyEntry(string name, string fileName) : base(name) { _fileName = fileName; } /// /// Create a named entry for the assembly to load, specifying /// just the nanme /// /// The name of the assembly to load public SessionStateAssemblyEntry(string name) : base(name) { ; } /// /// Shallow-clone this object /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateAssemblyEntry entry = new SessionStateAssemblyEntry(Name, _fileName); entry.SetPSSnapIn(this.PSSnapIn); entry.SetModule(this.Module); return entry; } /// /// Return the assembly file name... /// public string FileName { get { return _fileName; } } private string _fileName; } /// /// List a cmdlet to add to this session state entry /// public sealed class SessionStateCmdletEntry : SessionStateCommandEntry { /// /// /// /// /// /// public SessionStateCmdletEntry(string name, Type implementingType, string helpFileName) : base(name, SessionStateEntryVisibility.Public) { _implementingType = implementingType; _helpFileName = helpFileName; _commandType = CommandTypes.Cmdlet; } /// /// /// /// /// /// /// internal SessionStateCmdletEntry(string name, Type implementingType, string helpFileName, SessionStateEntryVisibility visibility) : base(name, visibility) { _implementingType = implementingType; _helpFileName = helpFileName; _commandType = CommandTypes.Cmdlet; } /// /// Shallow-clone this object... /// /// public override InitialSessionStateEntry Clone() { SessionStateCmdletEntry entry = new SessionStateCmdletEntry(Name, _implementingType, _helpFileName, Visibility); entry.SetPSSnapIn(this.PSSnapIn); entry.SetModule(this.Module); return entry; } /// /// /// public Type ImplementingType { get { return _implementingType; } } private Type _implementingType; /// /// /// public string HelpFileName { get { return _helpFileName; } } private string _helpFileName; } /// /// /// public sealed class SessionStateProviderEntry : ConstrainedSessionStateEntry { /// /// /// /// /// /// public SessionStateProviderEntry(string name, Type implementingType, string helpFileName) : base(name, SessionStateEntryVisibility.Public) { _implementingType = implementingType; _helpFileName = helpFileName; } internal SessionStateProviderEntry(string name, Type implementingType, string helpFileName, SessionStateEntryVisibility visibility) : base(name, visibility) { _implementingType = implementingType; _helpFileName = helpFileName; } /// /// Shallow-clone this object... /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateProviderEntry entry = new SessionStateProviderEntry(Name, _implementingType, _helpFileName, this.Visibility); entry.SetPSSnapIn(this.PSSnapIn); entry.SetModule(this.Module); return entry; } /// /// /// public Type ImplementingType { get { return _implementingType; } } private Type _implementingType; /// /// /// public string HelpFileName { get { return _helpFileName; } } private string _helpFileName; } /// /// /// public sealed class SessionStateScriptEntry : SessionStateCommandEntry { /// /// Create a session state command entry instance. /// /// The path to the script public SessionStateScriptEntry(string path) : base(path, SessionStateEntryVisibility.Public) { _path = path; _commandType = CommandTypes.ExternalScript; } /// /// Create a session state command entry instance with the specified visiblity. /// /// The path to the script /// Visibility of the script. internal SessionStateScriptEntry(string path, SessionStateEntryVisibility visibility) : base(path, visibility) { _path = path; _commandType = CommandTypes.ExternalScript; } /// /// Shallow-clone this object... /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateScriptEntry entry = new SessionStateScriptEntry(_path, Visibility); entry.SetModule(this.Module); return entry; } /// /// /// public string Path { get { return _path; } } private string _path; } /// /// /// public sealed class SessionStateAliasEntry : SessionStateCommandEntry { /// /// Define an alias entry to add to the initial session state /// /// Name of the aliase /// The name of the command it resolves to public SessionStateAliasEntry(string name, string definition) : base(name, SessionStateEntryVisibility.Public) { _definition = definition; _commandType = CommandTypes.Alias; } /// /// Define an alias entry to add to the initial session state /// /// Name of the aliase /// The name of the command it resolves to /// A descripion of the purpose of the alias. public SessionStateAliasEntry(string name, string definition, string description) : base(name, SessionStateEntryVisibility.Public) { _definition = definition; _commandType = CommandTypes.Alias; _description = description; } /// /// Define an alias entry to add to the initial session state /// /// Name of the aliase /// The name of the command it resolves to /// A descripion of the purpose of the alias. /// Options defining the scope visiblity, readonly and constant public SessionStateAliasEntry(string name, string definition, string description, ScopedItemOptions options) : base(name, SessionStateEntryVisibility.Public) { _definition = definition; _commandType = CommandTypes.Alias; _description = description; _options = options; } /// /// Define an alias entry to add to the initial session state /// /// Name of the aliase /// The name of the command it resolves to /// A descripion of the purpose of the alias. /// Options defining the scope visiblity, readonly and constant /// internal SessionStateAliasEntry(string name, string definition, string description, ScopedItemOptions options, SessionStateEntryVisibility visibility) : base(name, visibility) { _definition = definition; _commandType = CommandTypes.Alias; _description = description; _options = options; } /// /// Shallow-clone this object... /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateAliasEntry entry = new SessionStateAliasEntry(Name, _definition, _description, _options, Visibility); entry.SetModule(this.Module); return entry; } /// /// The string defining the body of this alias... /// public string Definition { get { return _definition; } } private string _definition; /// /// A string describing this alias... /// public string Description { get { return _description; } } private string _description = String.Empty; /// /// Options controling scope visiblity and setability for this entry. /// public ScopedItemOptions Options { get { return _options; } } private ScopedItemOptions _options = ScopedItemOptions.None; } /// /// /// public sealed class SessionStateApplicationEntry : SessionStateCommandEntry { /// /// Used to define a permitted script in this session state. If the path is /// "*", then any path is permitted. /// /// The full path to the application public SessionStateApplicationEntry(string path) : base(path, SessionStateEntryVisibility.Public) { _path = path; _commandType = CommandTypes.Application; } /// /// Used to define a permitted script in this session state. If the path is /// "*", then any path is permitted. /// /// The full path to the application /// Sets the external visibilty of the path. internal SessionStateApplicationEntry(string path, SessionStateEntryVisibility visibility) : base(path, visibility) { _path = path; _commandType = CommandTypes.Application; } /// /// Shallow-clone this object... /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateApplicationEntry entry = new SessionStateApplicationEntry(_path, Visibility); entry.SetModule(this.Module); return entry; } /// /// The path to this application... /// public string Path { get { return _path; } } private string _path; } /// /// /// public sealed class SessionStateFunctionEntry : SessionStateCommandEntry { /// /// Represents a function definition in an Initial session state object. /// /// The name of the function /// The definition of the function /// Options controlling scope-related elements of this object /// The name of the help file associated with the function public SessionStateFunctionEntry(string name, string definition, ScopedItemOptions options, string helpFile) : base(name, SessionStateEntryVisibility.Public) { _definition = definition; _commandType = CommandTypes.Function; _options = options; _scriptBlock = ScriptBlock.Create(_definition); _scriptBlock.LanguageMode = PSLanguageMode.FullLanguage; _helpFile = helpFile; } /// /// Represents a function definition in an Initial session state object. /// /// The name of the function /// The definition of the function /// The name of the help file associated with the function public SessionStateFunctionEntry(string name, string definition, string helpFile) : this(name, definition, ScopedItemOptions.None, helpFile) { } /// /// Represents a function definition in an Initial session state object. /// /// The name of the function /// The definition of the function public SessionStateFunctionEntry(string name, string definition) : this(name, definition, ScopedItemOptions.None, null) { } /// /// This is an internal copy constructor. /// internal SessionStateFunctionEntry(string name, string definition, ScopedItemOptions options, SessionStateEntryVisibility visibility, ScriptBlock scriptBlock, string helpFile) : base(name, visibility) { _definition = definition; _commandType = CommandTypes.Function; _options = options; _scriptBlock = scriptBlock; _helpFile = helpFile; } internal static SessionStateFunctionEntry GetDelayParsedFunctionEntry(string name, string definition, bool isProductCode) { var sb = ScriptBlock.CreateDelayParsedScriptBlock(definition, isProductCode); return new SessionStateFunctionEntry(name, definition, ScopedItemOptions.None, SessionStateEntryVisibility.Public, sb, null); } internal static SessionStateFunctionEntry GetDelayParsedFunctionEntry(string name, string definition, ScriptBlock sb) { return new SessionStateFunctionEntry(name, definition, ScopedItemOptions.None, SessionStateEntryVisibility.Public, sb, null); } /// /// Shallow-clone this object... /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateFunctionEntry entry = new SessionStateFunctionEntry(Name, _definition, _options, Visibility, _scriptBlock, _helpFile); entry.SetModule(this.Module); return entry; } /// /// Sets the name of the help file associated with the function. /// internal void SetHelpFile(string help) { _helpFile = help; } /// /// The string to use to define this function... /// public string Definition { get { return _definition; } } private string _definition; /// /// The script block for this function. /// internal ScriptBlock ScriptBlock { get { return _scriptBlock; } set { _scriptBlock = value; } } private ScriptBlock _scriptBlock; /// /// Options controling scope visiblity and setability for this entry. /// public ScopedItemOptions Options { get { return _options; } } private ScopedItemOptions _options = ScopedItemOptions.None; /// /// The name of the help file associated with the function. /// public string HelpFile { get { return _helpFile; } } private string _helpFile; } #if !CORECLR // Workflow Not Supported On CSS /// /// /// public sealed class SessionStateWorkflowEntry : SessionStateCommandEntry { /// /// Represents a workflow definition in an Initial session state object. /// /// The name of the workflow /// The definition of the workflow /// Options controlling scope-related elements of this object /// The name of the help file associated with the workflow public SessionStateWorkflowEntry(string name, string definition, ScopedItemOptions options, string helpFile) : base(name, SessionStateEntryVisibility.Public) { _definition = definition; _commandType = CommandTypes.Workflow; _options = options; _helpFile = helpFile; } /// /// Represents a workflow definition in an Initial session state object. /// /// The name of the workflow /// The definition of the workflow /// The name of the help file associated with the workflow public SessionStateWorkflowEntry(string name, string definition, string helpFile) : this(name, definition, ScopedItemOptions.None, helpFile) { } /// /// Represents a workflow definition in an Initial session state object. /// /// The name of the workflow /// The definition of the workflow public SessionStateWorkflowEntry(string name, string definition) : this(name, definition, ScopedItemOptions.None, null) { } /// /// This is an internal copy constructor. /// internal SessionStateWorkflowEntry(string name, string definition, ScopedItemOptions options, SessionStateEntryVisibility visibility, WorkflowInfo workflow, string helpFile) : base(name, visibility) { _definition = definition; _options = options; _workflow = workflow; _helpFile = helpFile; } /// /// Shallow-clone this object... /// /// The cloned object public override InitialSessionStateEntry Clone() { SessionStateWorkflowEntry entry = new SessionStateWorkflowEntry(Name, _definition, _options, Visibility, _workflow, _helpFile); entry.SetModule(this.Module); return entry; } /// /// Sets the name of the help file associated with the function. /// internal void SetHelpFile(string help) { _helpFile = help; } /// /// The string to use to define this function... /// public string Definition { get { return _definition; } } private string _definition; /// /// The script block for this function. /// internal WorkflowInfo WorkflowInfo { get { return _workflow; } set { _workflow = value; } } private WorkflowInfo _workflow; /// /// Options controling scope visiblity and setability for this entry. /// public ScopedItemOptions Options { get { return _options; } } private ScopedItemOptions _options = ScopedItemOptions.None; /// /// The name of the help file associated with the function. /// public string HelpFile { get { return _helpFile; } } private string _helpFile; } #endif /// /// /// public sealed class SessionStateVariableEntry : ConstrainedSessionStateEntry { /// /// Is used to define a variable that should be created when /// the runspace is opened. Note - if this object is cloned, /// then the clone will contain a reference to the original object /// not a clone of it. /// /// The name of the variable /// The value to set the variable to /// A descriptive string to attach to the variable. public SessionStateVariableEntry(string name, object value, string description) : base(name, SessionStateEntryVisibility.Public) { _value = value; _description = description; } /// /// Is used to define a variable that should be created when /// the runspace is opened. Note - if this object is cloned, /// then the clone will contain a reference to the original object /// not a clone of it. /// /// The name of the variable /// The value to set the variable to /// A descriptive string to attach to the variable. /// Options like readonly, constant, allscope, etc. public SessionStateVariableEntry(string name, object value, string description, ScopedItemOptions options) : base(name, SessionStateEntryVisibility.Public) { _value = value; _description = description; _options = options; } /// /// Is used to define a variable that should be created when /// the runspace is opened. Note - if this object is cloned, /// then the clone will contain a reference to the original object /// not a clone of it. /// /// The name of the variable /// The value to set the variable to /// A descriptive string to attach to the variable. /// Options like readonly, constant, allscope, etc. /// A list of attributes to attach to the variable. public SessionStateVariableEntry(string name, object value, string description, ScopedItemOptions options, Collection attributes) : base(name, SessionStateEntryVisibility.Public) { _value = value; _description = description; _options = options; _attributes = attributes; } /// /// Is used to define a variable that should be created when /// the runspace is opened. Note - if this object is cloned, /// then the clone will contain a reference to the original object /// not a clone of it. /// /// The name of the variable /// The value to set the variable to /// A descriptive string to attach to the variable. /// Options like readonly, constant, allscope, etc. /// A single attribute to attach to the variable. public SessionStateVariableEntry(string name, object value, string description, ScopedItemOptions options, Attribute attribute) : base(name, SessionStateEntryVisibility.Public) { _value = value; _description = description; _options = options; _attributes = new Collection(); _attributes.Add(attribute); } /// /// Is used to define a variable that should be created when /// the runspace is opened. Note - if this object is cloned, /// then the clone will contain a reference to the original object /// not a clone of it. /// /// The name of the variable /// The value to set the variable to /// A descriptive string to attach to the variable. /// Options like readonly, constant, allscope, etc. /// A single attribute to attach to the variable. /// internal SessionStateVariableEntry(string name, object value, string description, ScopedItemOptions options, Collection attributes, SessionStateEntryVisibility visibility) : base(name, visibility) { _value = value; _description = description; _options = options; _attributes = attributes; } /// /// Shallow-clone this object... /// /// The cloned object public override InitialSessionStateEntry Clone() { // Copy the attribute collection if necessary... Collection attrs = null; if (_attributes != null && _attributes.Count > 0) attrs = new Collection(_attributes); return new SessionStateVariableEntry(Name, _value, _description, _options, attrs, Visibility); } /// /// The value to bind to this variable. /// public object Value { get { return _value; } } private object _value; /// /// The description associated with this variable. /// public string Description { get { return _description; } } private string _description = String.Empty; /// /// The options associated with this variable (e.g. readonly, allscope, etc.) /// public ScopedItemOptions Options { get { return _options; } } private ScopedItemOptions _options = ScopedItemOptions.None; /// /// The attributes that will be attached to this object. /// public Collection Attributes { get { if (_attributes == null) _attributes = new Collection(); return _attributes; } } private Collection _attributes; } /// /// /// /// public sealed class InitialSessionStateEntryCollection : IEnumerable where T : InitialSessionStateEntry { /// /// Create an empty collection... /// public InitialSessionStateEntryCollection() { _internalCollection = new Collection(); } /// /// Create an new collection, copying in the passed items... /// /// public InitialSessionStateEntryCollection(IEnumerable items) { if (items == null) { throw new ArgumentNullException("items"); } _internalCollection = new Collection(); foreach (T item in items) { _internalCollection.Add(item); } } /// /// Clone this collection /// /// The cloned object public InitialSessionStateEntryCollection Clone() { InitialSessionStateEntryCollection result; lock (_syncObject) { result = new InitialSessionStateEntryCollection(); foreach (T item in _internalCollection) { result.Add((T)item.Clone()); } } return result; } /// /// Reset the collection /// public void Reset() { lock (_syncObject) { _internalCollection.Clear(); } } /// /// Returns a count of the number of items in the collection... /// public int Count { get { return _internalCollection.Count; } } /// /// /// /// /// public T this[int index] { get { T result; lock (_syncObject) { result = _internalCollection[index]; } return result; } } //To find the entries based on name. //Why collection - Different SnapIn/modules and same entity names. //If used on command collection entry, then for the same name, one can have multiple output /// /// To find the entries based on name. /// Why collection - Different SnapIn/modules and same entity names. /// If used on command collection entry, then for the same name, one can have multiple output /// /// /// public Collection this[string name] { get { Collection result = new Collection(); lock (_syncObject) { foreach (T element in _internalCollection) { if (element.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) { result.Add(element); } } } return result; } } /// /// Find entries based on string name which can include wildcards. /// /// /// internal Collection LookUpByName(string name) { if (name == null) { throw new PSArgumentNullException("name"); } Collection result = new Collection(); WildcardPattern namePattern = WildcardPattern.Get(name, WildcardOptions.IgnoreCase); lock (_syncObject) { foreach (T element in _internalCollection) { if (namePattern.IsMatch(element.Name)) { result.Add(element); } } } return result; } /// /// /// /// public void RemoveItem(int index) { lock (_syncObject) { _internalCollection.RemoveAt(index); } } /// /// Remove a number of items starting at the specified index. /// /// /// public void RemoveItem(int index, int count) { lock (_syncObject) { while (count-- > 0) { _internalCollection.RemoveAt(index); } } } /// /// Clears the collection... /// public void Clear() { lock (_syncObject) { _internalCollection.Clear(); } } /// /// This overload exists so that we can remove items based on the item name, rather than /// its position in the collection. The type argument can be null but we'll throw an error if /// we can't distinguish between multiple entries of the same name but different types /// and the type hasn't been specified. /// BUGBUG - brucepay - the throw thing is not implemented yet... /// /// The name of the element to remove /// The type of object to remove, can be null to remove any type. public void Remove(string name, object type) { if (name == null) throw new ArgumentNullException("name"); lock (_syncObject) { Type objType = null; if (type != null) { objType = type as Type; if (objType == null) objType = type.GetType(); } // Work backwards through the collection... for (int i = _internalCollection.Count - 1; i >= 0; i--) { T element = _internalCollection[i]; if (element == null) continue; if ((objType == null || element.GetType() == objType) && String.Equals(element.Name, name, StringComparison.OrdinalIgnoreCase)) { _internalCollection.RemoveAt(i); } } } } /// /// Add an item to this collection. /// /// The item to add... public void Add(T item) { if (item == null) throw new ArgumentNullException("item"); lock (_syncObject) { _internalCollection.Add(item); } } /// /// /// /// public void Add(IEnumerable items) { if (items == null) throw new ArgumentNullException("items"); lock (_syncObject) { foreach (T element in items) { _internalCollection.Add(element); } } } /// /// Get enumerator for this collection. /// /// /// IEnumerator System.Collections.IEnumerable.GetEnumerator() { return _internalCollection.GetEnumerator(); } /// /// Get enumerator for this collection. /// /// /// IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { return _internalCollection.GetEnumerator(); } private Collection _internalCollection; //object to use for locking object _syncObject = new object(); } /// /// Allows you to define the set of elements that should be /// present when Session State is created. /// public class InitialSessionState { #region Helper methods for restricting commands needed by implicit and interactive remoting static private void RemoveDisallowedEntries(InitialSessionStateEntryCollection list, List allowedNames, Func nameGetter) where T : InitialSessionStateEntry { List namesToRemove = new List(); foreach (T entry in list) { string entryName = nameGetter(entry); // if entryName is not present in allowedNames list, then remove it if (!allowedNames.Exists(allowedName => allowedName.Equals(entryName, StringComparison.OrdinalIgnoreCase))) { namesToRemove.Add(entry.Name); } } foreach (string nameToRemove in namesToRemove) { list.Remove(nameToRemove, null /* remove any type with this name */); } } static private void MakeDisallowedEntriesPrivate(InitialSessionStateEntryCollection list, List allowedNames, Func nameGetter) where T : ConstrainedSessionStateEntry { foreach (T entry in list) { string entryName = nameGetter(entry); // Aliases to allowed commands are OK SessionStateAliasEntry aliasEntry = entry as SessionStateAliasEntry; if(aliasEntry != null) { if(allowedNames.Exists(allowedName => allowedName.Equals(aliasEntry.Definition, StringComparison.OrdinalIgnoreCase))) { aliasEntry.Visibility = SessionStateEntryVisibility.Public; continue; } } // if entryName is not present in allowedNames list, then remove it if (!allowedNames.Exists(allowedName => allowedName.Equals(entryName, StringComparison.OrdinalIgnoreCase))) { entry.Visibility = SessionStateEntryVisibility.Private; } } } /// /// Creates an initial session state from a PSSC configuration file /// /// The path to the PSSC session configuration file /// public static InitialSessionState CreateFromSessionConfigurationFile(string path) { return CreateFromSessionConfigurationFile(path, null); } /// /// Creates an initial session state from a PSSC configuration file /// /// The path to the PSSC session configuration file /// /// The verifier that PowerShell should call to determine if groups in the Role entry apply to the /// target session. If you have a WindowsPrincipal for a user, for example, create a Function that /// checks windowsPrincipal.IsInRole(). /// /// public static InitialSessionState CreateFromSessionConfigurationFile(string path, Func roleVerifier) { Remoting.DISCPowerShellConfiguration discConfiguration = new Remoting.DISCPowerShellConfiguration(path, roleVerifier); return discConfiguration.GetInitialSessionState(null); } /// /// Creates an instance that exposes only the minimal /// set of commands needed by give set of /// All commands that are not needed are made private in order to minimize the attack surface. /// /// /// What capabilities the session should have. /// /// static public InitialSessionState CreateRestricted(SessionCapabilities sessionCapabilities) { // only remote server has been requested if (SessionCapabilities.RemoteServer == sessionCapabilities) { return CreateRestrictedForRemoteServer(); } #if CORECLR // Workflow Not Supported On CSS if ((sessionCapabilities & SessionCapabilities.WorkflowServer) == SessionCapabilities.WorkflowServer) { throw PSTraceSource.NewNotSupportedException(ParserStrings.WorkflowNotSupportedInPowerShellCore); } #else // only workflow has been requested if (SessionCapabilities.WorkflowServer == sessionCapabilities) { return CreateRestrictedForWorkflowServerMinimum(); } // workflow server with remoting support has been requested if (sessionCapabilities == (SessionCapabilities.WorkflowServer | SessionCapabilities.RemoteServer)) { return CreateRestrictedForWorkflowServer(); } if (sessionCapabilities == (SessionCapabilities.WorkflowServer | SessionCapabilities.RemoteServer | SessionCapabilities.Language)) { return CreateRestrictedForWorkflowServerWithFullLanguage(); } #endif return Create(); } static private InitialSessionState CreateRestrictedForRemoteServer() { InitialSessionState iss = Create(); iss.LanguageMode = PSLanguageMode.NoLanguage; iss.ThrowOnRunspaceOpenError = true; iss.UseFullLanguageModeInDebugger = false; iss.Commands.Add(BuiltInFunctions); iss.Commands.Add(BuiltInAliases); // Load the default snapins - all commands will be private by default. Collection defaultSnapins = PSSnapInReader.ReadEnginePSSnapIns(); foreach (PSSnapInInfo si in defaultSnapins) { // ImportPSSnapIn always sets "out warning" to "null"; all our internal calls ignore/discard "out warning" PSSnapInException warning; iss.ImportPSSnapIn(si, out warning); } // // restrict what gets exposed // List allowedCommands = new List(); // required by implicit remoting and interactive remoting allowedCommands.Add("Get-Command"); allowedCommands.Add("Get-FormatData"); allowedCommands.Add("Clear-Host"); allowedCommands.Add("Select-Object"); // used to serialize exactly the properties that we need (+ at the right depth) // used if available by implicit remoting allowedCommands.Add("Get-Help"); // used when displaying help for implicit remoting proxy functions allowedCommands.Add("Measure-Object"); // used to have nice progress bars when import/export-pssession is running // required by interactive remoting allowedCommands.Add("Out-Default"); // appended to every command line allowedCommands.Add("Exit-PSSession"); // used by the user to exit the sesion // We don't remove these entries so that they can be called by commands in the runspace. // Setting them to 'Private' ensures that the user can't call them. MakeDisallowedEntriesPrivate( iss.Commands, allowedCommands, commandEntry => commandEntry.Name); // Ensure that only PowerShell core formats are included in the restricted session. IncludePowerShellCoreFormats(iss); List allowedTypes = new List(); allowedTypes.Add("types.ps1xml"); allowedTypes.Add("typesV3.ps1xml"); RemoveDisallowedEntries( iss.Types, allowedTypes, typeEntry => IO.Path.GetFileName(typeEntry.FileName)); // No providers are visible by default foreach(SessionStateProviderEntry provider in iss.Providers) { provider.Visibility = SessionStateEntryVisibility.Private; } // Add built-in variables. iss.Variables.Add(BuiltInVariables); // // wrap some commands in a proxy function to restrict their parameters // foreach (KeyValuePair proxyFunction in CommandMetadata.GetRestrictedCommands(SessionCapabilities.RemoteServer)) { string commandName = proxyFunction.Key; // make the cmdlet private Collection originalCmdlet = iss.Commands[commandName]; Diagnostics.Assert(originalCmdlet != null, "Proxied cmdlets should be imported at this point"); Diagnostics.Assert(originalCmdlet.Count == 1, "Exactly one cmdlet with a given name"); originalCmdlet[0].Visibility = SessionStateEntryVisibility.Private; // and add a public proxy function string proxyBody = ProxyCommand.Create(proxyFunction.Value, "", false); iss.Commands.Add(new SessionStateFunctionEntry(commandName, proxyBody)); } return iss; } // Porting note: moved to Platform so we have one list to maintain private static string[] PSCoreFormatFileNames = Platform.FormatFileNames.ToArray(); private static void IncludePowerShellCoreFormats(InitialSessionState iss) { string psHome = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID); if (string.IsNullOrEmpty(psHome)) { return; } iss.Formats.Clear(); foreach (var coreFormat in PSCoreFormatFileNames) { iss.Formats.Add(new SessionStateFormatEntry(Path.Combine(psHome, coreFormat))); } } #if !CORECLR // Workflow Not Supported On CSS private static List allowedAliases = new List { "compare", "diff", "%", "foreach", "exsn", "fc", "fl", "ft", "fw", "gcm", "gjb", "gmo", "gv", "group", "ipmo", "measure", "rv", "rcjb", "rjb", "rmo", "rujb", "select", "set", "sv", "sort", "spjb", "sujb", "wjb", "?", "where" }; static private InitialSessionState CreateRestrictedForWorkflowServer() { InitialSessionState iss = CreateDefault(); iss.LanguageMode = PSLanguageMode.NoLanguage; iss.ThrowOnRunspaceOpenError = true; iss.UseFullLanguageModeInDebugger = false; // WIN8:551312 M3P endpoint should have NO application exposed // foreach (SessionStateCommandEntry entry in iss.Commands) { if (entry.GetType() == typeof(SessionStateApplicationEntry)) { iss.Commands.Remove(entry.Name, entry); break; } } // // restrict what gets exposed // List allowedCommands = new List (); allowedCommands.AddRange(JobCmdlets); allowedCommands.AddRange(ImplicitRemotingCmdlets); allowedCommands.AddRange(MiscCmdlets); allowedCommands.AddRange(AutoDiscoveryCmdlets); // make all other commands private MakeDisallowedEntriesPrivate( iss.Commands, allowedCommands, commandEntry => commandEntry.Name); foreach (SessionStateCommandEntry entry in iss.Commands) { if (entry.GetType() == typeof(SessionStateAliasEntry)) { if(allowedAliases.Contains(entry.Name, StringComparer.OrdinalIgnoreCase)) { entry.Visibility = SessionStateEntryVisibility.Public; } else { entry.Visibility = SessionStateEntryVisibility.Private; } } } // Porting note: copy so it can be modified List allowedFormats = new List(Platform.FormatFileNames); RemoveDisallowedEntries( iss.Formats, allowedFormats, formatEntry => IO.Path.GetFileName(formatEntry.FileName)); // Porting note: type files were deprecated List allowedTypes = new List(); allowedTypes.AddRange(DefaultTypeFiles); RemoveDisallowedEntries( iss.Types, allowedTypes, typeEntry => IO.Path.GetFileName(typeEntry.FileName)); iss.Variables.Clear(); // no variables are needed for workflow server - remove all of them return iss; } static private InitialSessionState CreateRestrictedForWorkflowServerWithFullLanguage() { InitialSessionState iss = CreateDefault(); iss.LanguageMode = PSLanguageMode.FullLanguage; iss.ThrowOnRunspaceOpenError = true; iss.UseFullLanguageModeInDebugger = false; // WIN8:551312 M3P endpoint should have NO application exposed // foreach (SessionStateCommandEntry entry in iss.Commands) { if (entry.GetType() == typeof(SessionStateApplicationEntry)) { iss.Commands.Remove(entry.Name, entry); break; } } // // restrict what gets exposed // List allowedCommands = new List(); allowedCommands.AddRange(JobCmdlets); allowedCommands.AddRange(ImplicitRemotingCmdlets); allowedCommands.AddRange(MiscCmdlets); allowedCommands.AddRange(MiscCommands); allowedCommands.AddRange(AutoDiscoveryCmdlets); allowedCommands.AddRange(LanguageHelperCmdlets); // Exposing Debug cmdlets in only Full language WF server // because for debugging one needs full language capabilities allowedCommands.AddRange(DebugCmdlets); // make all other commands private MakeDisallowedEntriesPrivate( iss.Commands, allowedCommands, commandEntry => commandEntry.Name); foreach (SessionStateCommandEntry entry in iss.Commands) { if (entry.GetType() == typeof(SessionStateAliasEntry)) { if (allowedAliases.Contains(entry.Name, StringComparer.OrdinalIgnoreCase)) { entry.Visibility = SessionStateEntryVisibility.Public; } else { entry.Visibility = SessionStateEntryVisibility.Private; } } } // Porting note: copy so it can be modified List allowedFormats = new List(Platform.FormatFileNames); RemoveDisallowedEntries( iss.Formats, allowedFormats, formatEntry => IO.Path.GetFileName(formatEntry.FileName)); // Porting note: type files were deprecated List allowedTypes = new List(); allowedTypes.AddRange(DefaultTypeFiles); RemoveDisallowedEntries( iss.Types, allowedTypes, typeEntry => IO.Path.GetFileName(typeEntry.FileName)); iss.Variables.Clear(); // no variables are needed for workflow server - remove all of them // set a preference variable to indicate Get-Command should show // return only loaded public commands Hashtable parameters = new Hashtable {{"Get-Command:ListImported", true}}; iss.Variables.Add(new SessionStateVariableEntry("PSDefaultParameterValues", parameters, "Default Get-Command Action")); return iss; } static private InitialSessionState CreateRestrictedForWorkflowServerMinimum() { InitialSessionState iss = CreateDefault(); iss.LanguageMode = PSLanguageMode.NoLanguage; iss.ThrowOnRunspaceOpenError = true; iss.UseFullLanguageModeInDebugger = false; // WIN8:551312 M3P endpoint should have NO application exposed // foreach (SessionStateCommandEntry entry in iss.Commands) { if (entry.GetType() == typeof(SessionStateApplicationEntry)) { iss.Commands.Remove(entry.Name, entry); break; } } // // restrict what gets exposed // // required by implicit remoting and interactive remoting List allowedCommands = new List { "Get-Command" }; allowedCommands.AddRange(JobCmdlets); allowedCommands.AddRange(MiscCmdlets); // make all other commands private MakeDisallowedEntriesPrivate( iss.Commands, allowedCommands, commandEntry => commandEntry.Name); iss.Formats.Clear(); List allowedTypes = new List(); allowedTypes.AddRange(DefaultTypeFiles); RemoveDisallowedEntries( iss.Types, allowedTypes, typeEntry => IO.Path.GetFileName(typeEntry.FileName)); iss.Variables.Clear(); // no variables are needed for workflow server - remove all of them // Disable module autodiscovery SessionStateVariableEntry ssve = new SessionStateVariableEntry("PSDisableModuleAutoDiscovery", true, "True if we disable module autodiscovery", ScopedItemOptions.Constant); iss.Variables.Add(ssve); return iss; } private static readonly string[] JobCmdlets = { "Get-Job", "Stop-Job", "Wait-Job", "Suspend-Job", "Resume-Job", "Remove-Job", "Receive-Job" }; private static readonly string[] ImplicitRemotingCmdlets = { "Get-Command", "Select-Object", "Measure-Object", "Get-Help", "Get-FormatData", "Exit-PSSession", "Out-Default" }; private static readonly string[] AutoDiscoveryCmdlets = { "Get-Module" }; private static readonly string[] LanguageHelperCmdlets = { "Compare-Object", "ForEach-Object", "Group-Object", "Sort-Object", "Where-Object", "Out-File", "Out-Null", "Out-String", "Format-Custom", "Format-List", "Format-Table", "Format-Wide", "Remove-Module", "Get-Variable", "Set-Variable", "Remove-Variable", "Get-Credential", "Set-StrictMode" }; /// /// Following cmdlets are needed for debugging support starting WinBlue /// private static readonly string[] DebugCmdlets = { "Disable-PSBreakpoint", "Enable-PSBreakpoint", "Get-PSBreakpoint", "Remove-PSBreakpoint", "Set-PSBreakpoint" }; /// /// this cmdlets are exposed due to some bugs. Need to figure out if /// they are still required /// private static readonly string[] MiscCmdlets = {"Join-Path", "Import-Module"}; private static readonly string[] MiscCommands = { "TabExpansion2" }; private static readonly string[] DefaultTypeFiles = {"types.ps1xml", "typesv3.ps1xml"}; #endif #endregion /// /// ctor for Custom-Shell - Do we need this? /// protected InitialSessionState() { } // Creates an empty EE /// /// Creates an empty InitialSessionState object... /// /// public static InitialSessionState Create() { InitialSessionState iss = new InitialSessionState(); //TODO: the following code is probably needed for the hosted constrained runspace // There are too many things that depend on the built-in variables. At the same time, // these variables can't be public or they become a security issue. // This change still needs to be spec-reviewed before turning it on. It also seems to // be causing test failures - i suspect due to lack test isolation - brucepay Mar 06/2008 #if false // Add the default variables and make them private... iss.Variables.Add(BuiltInVariables); foreach (SessionStateVariableEntry v in iss.Variables) { v.Visibility = SessionStateEntryVisibility.Private; } #endif return iss; } /// /// Creates the default PowerShell one with default cmdlets, provider etc. /// BuiltIn functions, aliases need to be available through default /// InitialSessionstate constructor. Need to have this discussion for packaging as well. /// /// public static InitialSessionState CreateDefault() { // Read all of the registered PSSnapins Collection defaultSnapins; PSSnapInException warning; InitialSessionState ss = new InitialSessionState(); ss.Variables.Add(BuiltInVariables); ss.Commands.Add(new SessionStateApplicationEntry("*")); ss.Commands.Add(new SessionStateScriptEntry("*")); ss.Commands.Add(BuiltInFunctions); ss.Commands.Add(BuiltInAliases); defaultSnapins = PSSnapInReader.ReadEnginePSSnapIns(); foreach (PSSnapInInfo si in defaultSnapins) { try { ss.ImportPSSnapIn(si, out warning); } catch (PSSnapInException pse) { throw pse; } #if DEBUG //NOTE: // This code is for testing a module-based shell. It is only available when the shell is complied // in debug mode and is not intended to be a feature. // July 31 2008 - brucepay // Only load the core snapins at this point... if (Environment.GetEnvironmentVariable("PowerShellMinimal") != null) { if (si.Name.Equals("Microsoft.PowerShell.Host", StringComparison.OrdinalIgnoreCase)) break; } #endif } // Remove duplicated assemblies HashSet assemblyList = new HashSet(); for (int i = ss.Assemblies.Count - 1; i >= 0; i--) { string assembly = ss.Assemblies[i].FileName; if (!string.IsNullOrEmpty(assembly)) { if (assemblyList.Contains(assembly)) { ss.Assemblies.RemoveItem(i); } else { assemblyList.Add(assembly); } } } ss.LanguageMode = PSLanguageMode.FullLanguage; ss.AuthorizationManager = new Microsoft.PowerShell.PSAuthorizationManager(Utils.DefaultPowerShellShellID); return ss.Clone(); } /// /// Creates the default PowerShell one with default cmdlets, provider etc. /// The default cmdlets, provider, etc are loaded via Modules /// /// public static InitialSessionState CreateDefault2() { InitialSessionState ss = new InitialSessionState(); ss.Variables.Add(BuiltInVariables); ss.Commands.Add(new SessionStateApplicationEntry("*")); ss.Commands.Add(new SessionStateScriptEntry("*")); ss.Commands.Add(BuiltInFunctions); ss.Commands.Add(BuiltInAliases); ss.ImportCorePSSnapIn(); ss.LanguageMode = PSLanguageMode.FullLanguage; ss.AuthorizationManager = new Microsoft.PowerShell.PSAuthorizationManager(Utils.DefaultPowerShellShellID); return ss.Clone(); } internal static bool IsEngineModule(string moduleName) { return EngineModules.Contains(moduleName) || NestedEngineModules.Contains(moduleName); } internal static bool IsNestedEngineModule(string moduleName) { return NestedEngineModules.Contains(moduleName); } internal static bool IsConstantEngineModule(string moduleName) { return ConstantEngineModules.Contains(moduleName) || ConstantEngineNestedModules.Contains(moduleName); } /// /// Clone this InitialSessionState object. The collections are /// recursively cloned as well as the elements in the collections. /// Note however, that the contents of the individual entries /// are not deep-cloned. This is only an issue for variable /// entries which may have reference types. These objects /// will be added by reference rather than by value. /// /// The cloned object. public InitialSessionState Clone() { InitialSessionState ss = new InitialSessionState(); ss.Variables.Add(this.Variables.Clone()); ss.EnvironmentVariables.Add(this.EnvironmentVariables.Clone()); ss.Commands.Add(this.Commands.Clone()); ss.Assemblies.Add(this.Assemblies.Clone()); ss.Providers.Add(this.Providers.Clone()); ss.Types.Add(this.Types.Clone()); ss.Formats.Add(this.Formats.Clone()); foreach(string startupScript in this.StartupScripts) { ss.StartupScripts.Add(startupScript); } foreach (string unresolvedCommandsToExpose in this.UnresolvedCommandsToExpose) { ss.UnresolvedCommandsToExpose.Add(unresolvedCommandsToExpose); } foreach (Hashtable dynamicVariableToDefine in this.DynamicVariablesToDefine) { ss.DynamicVariablesToDefine.Add(dynamicVariableToDefine); } foreach (var pair in this.CommandModifications) { ss.CommandModifications.Add(pair.Key, pair.Value); } ss.DefaultCommandVisibility = this.DefaultCommandVisibility; ss.AuthorizationManager = this.AuthorizationManager; ss.LanguageMode = this.LanguageMode; ss.TranscriptDirectory = this.TranscriptDirectory; ss.UserDriveEnabled = this.UserDriveEnabled; ss.UserDriveUserName = this.UserDriveUserName; ss.UserDriveMaximumSize = this.UserDriveMaximumSize; if (this._wasExecutionPolicySet) { ss.ExecutionPolicy = this.ExecutionPolicy; } ss.UseFullLanguageModeInDebugger = this.UseFullLanguageModeInDebugger; ss.ThreadOptions = this.ThreadOptions; ss.ThrowOnRunspaceOpenError = this.ThrowOnRunspaceOpenError; #if !CORECLR // No ApartmentState In CoreCLR ss.ApartmentState = this.ApartmentState; #endif foreach (ModuleSpecification modSpec in this.ModuleSpecificationsToImport) { ss.ModuleSpecificationsToImport.Add(modSpec); } foreach (string mod in this.CoreModulesToImport) { ss.CoreModulesToImport.Add(mod); } ss.DisableFormatUpdates = this.DisableFormatUpdates; foreach (var s in this.defaultSnapins) { ss.defaultSnapins.Add(s); } foreach (var s in _importedSnapins) { ss.ImportedSnapins.Add(s.Key, s.Value); } return ss; } /// /// Want to get away from SnapIn and console file. Have modules and assemblies instead. /// Specify the registered SnapIn name or name collection /// /// /// public static InitialSessionState Create(string snapInName) { return new InitialSessionState(); } /// /// /// /// /// /// public static InitialSessionState Create(string[] snapInNameCollection, out PSConsoleLoadException warning) { warning = null; return new InitialSessionState(); } //This one is for module. Can take only one module, and not collection //public static InitialSessionState Create(Module); //Specify the unregistered module/snapIn path or path collection /// /// /// /// /// /// public static InitialSessionState CreateFrom(string snapInPath, out PSConsoleLoadException warnings) { warnings = null; return new InitialSessionState(); } /// /// /// /// /// /// public static InitialSessionState CreateFrom(string[] snapInPathCollection, out PSConsoleLoadException warnings) { warnings = null; return new InitialSessionState(); } /// /// Specifies the language mode to be used for this session state instance /// public PSLanguageMode LanguageMode { get { return _languageMode; } set { _languageMode = value; } } private PSLanguageMode _languageMode = PSLanguageMode.NoLanguage; /// /// Specifies the directory to be used for collection session transcripts /// public string TranscriptDirectory { get { return _transcriptDirectory; } set { _transcriptDirectory = value; } } private string _transcriptDirectory = null; /// /// True when session opted for a User PSDrive. /// internal bool UserDriveEnabled { get; set; } /// /// User name for the user drive. This will be part of the root path /// for the User PSDrive. /// internal string UserDriveUserName { get; set; } /// /// Optional maximum size value for User drive (in bytes). /// internal long UserDriveMaximumSize { get; set; } /// /// Forces all session script input parameters to have validation. /// internal bool EnforceInputParameterValidation { get; set; } /// /// Specifies the execution policy to be used for this session state instance /// public Microsoft.PowerShell.ExecutionPolicy ExecutionPolicy { get { return _executionPolicy; } set { _executionPolicy = value; _wasExecutionPolicySet = true; } } private Microsoft.PowerShell.ExecutionPolicy _executionPolicy = Microsoft.PowerShell.ExecutionPolicy.Default; private bool _wasExecutionPolicySet = false; /// /// If true the PowerShell debugger will use FullLanguage mode, otherwise it will use the current language mode /// public bool UseFullLanguageModeInDebugger { get { return _useFullLanguageModeInDebugger; } set { _useFullLanguageModeInDebugger = value; } } private bool _useFullLanguageModeInDebugger = false; #if !CORECLR // No ApartmentState In CoreCLR /// /// ApartmentState of the thread used to execute commands /// public ApartmentState ApartmentState { get { return this.apartmentState; } set { this.apartmentState = value; } } private ApartmentState apartmentState = Runspace.DefaultApartmentState; #endif /// /// This property determines whether a new thread is create for each invocation of a command /// public PSThreadOptions ThreadOptions { get { return this.createThreadOptions; } set { this.createThreadOptions = value; } } private PSThreadOptions createThreadOptions = PSThreadOptions.Default; /// /// If this property is set and there was a runspace creation error, then /// throw an exception, otherwise just continue creating the runspace even though it may /// be in an inconsistent state. /// public bool ThrowOnRunspaceOpenError { get { return this.throwOnRunspaceOpenError; } set { this.throwOnRunspaceOpenError = value; } } private bool throwOnRunspaceOpenError = false; /// /// This property will be set only if we are refreshing the Type/Format settings by calling UpdateTypes/UpdateFormats directly. /// In this case, we should wait until all type/format entries get processed. After that, if there were errors /// generated, we throw them as an exception. /// internal bool RefreshTypeAndFormatSetting = false; /// /// Specifies the authorization manager to be used for this session state instance. /// If no authorization manager is specified, then the default authroization manager /// for PowerShell will be used which checks the ExecutionPolicy before running a command. /// public virtual AuthorizationManager AuthorizationManager { get { return _authorizationManager; } set { _authorizationManager = value; } } private AuthorizationManager _authorizationManager = new Microsoft.PowerShell.PSAuthorizationManager(Utils.DefaultPowerShellShellID); internal PSHost Host = null; /// /// Add a list of modules to import when the runspace is created. /// /// The modules to add /// public void ImportPSModule(string[] name) { if (name == null) throw new ArgumentNullException("name"); foreach (string n in name) { _moduleSpecificationsToImport.Add(new ModuleSpecification(n)); } } /// /// Clears ImportPSModule list. /// internal void ClearPSModules() { _moduleSpecificationsToImport.Clear(); } /// /// Add a list of modules to import when the runspace is created. /// /// /// The modules, whose specificiations are specified by , /// to add. /// public void ImportPSModule(IEnumerable modules) { if (modules == null) { throw new ArgumentNullException("modules"); } foreach (var moduleSpecification in modules) { _moduleSpecificationsToImport.Add(moduleSpecification); } } /// /// Imports all the modules from the specified module /// path by default /// /// path from which all modules need /// to be imported public void ImportPSModulesFromPath(string path) { string expandedpath = Environment.ExpandEnvironmentVariables(path); var availableModuleFiles = ModuleUtils.GetDefaultAvailableModuleFiles(expandedpath); ImportPSModule(availableModuleFiles.ToArray()); } /// /// Add a list of core modules to import when the runspace is created. /// /// The modules to add /// internal void ImportPSCoreModule(string[] name) { if (name == null) throw new ArgumentNullException("name"); foreach (string n in name) { _coreModulesToImport.Add(n); } } /// /// Imported modules. /// public ReadOnlyCollection Modules { get { return new ReadOnlyCollection(_moduleSpecificationsToImport);} } internal Collection ModuleSpecificationsToImport { get { return _moduleSpecificationsToImport; } } private Collection _moduleSpecificationsToImport = new Collection(); HashSet _coreModulesToImport = new HashSet(); internal Dictionary ImportedSnapins { get { return _importedSnapins; } } private Dictionary _importedSnapins = new Dictionary(StringComparer.OrdinalIgnoreCase); /// /// Gets the dictionary of core modules to import on runspace creation... /// internal HashSet CoreModulesToImport { get { return _coreModulesToImport; } } /// /// The list of assemblies to load... /// public virtual InitialSessionStateEntryCollection Assemblies { get { if (_assemblies == null) Interlocked.CompareExchange(ref _assemblies, new InitialSessionStateEntryCollection(), null); return _assemblies; } } private InitialSessionStateEntryCollection _assemblies; /// /// List of types to use for this session state instance... /// public virtual InitialSessionStateEntryCollection Types { get { if (_types == null) Interlocked.CompareExchange(ref _types, new InitialSessionStateEntryCollection(), null); return _types; } } private InitialSessionStateEntryCollection _types; /// /// /// public virtual InitialSessionStateEntryCollection Formats { get { if (_formats == null) Interlocked.CompareExchange(ref _formats, new InitialSessionStateEntryCollection(), null); return _formats; } } private InitialSessionStateEntryCollection _formats; /// /// If set to true, disables any updates to format table. This includes disabling /// format table updates throught Update-FormatData, Import-Module etc. /// All the disabling happens silently ie., the user will not get any exception. /// By default, this is set to False. /// public bool DisableFormatUpdates { get; set; } /// /// /// public virtual InitialSessionStateEntryCollection Providers { get { if (_providers == null) Interlocked.CompareExchange(ref _providers, new InitialSessionStateEntryCollection(), null); return _providers; } } private InitialSessionStateEntryCollection _providers; /// /// List of commands (Alias, Application, Cmdlets, Function, Script) for this entry. /// public virtual InitialSessionStateEntryCollection Commands { get { if (_commands == null) Interlocked.CompareExchange(ref _commands, new InitialSessionStateEntryCollection(), null); return _commands; } } private InitialSessionStateEntryCollection _commands; internal SessionStateEntryVisibility DefaultCommandVisibility { get; set; } internal HashSet UnresolvedCommandsToExpose { get { if (_unresolvedCommandsToExpose == null) Interlocked.CompareExchange(ref _unresolvedCommandsToExpose, new HashSet(StringComparer.OrdinalIgnoreCase), null); return _unresolvedCommandsToExpose; } } private HashSet _unresolvedCommandsToExpose; internal Dictionary CommandModifications { get { if (_commandModifications == null) Interlocked.CompareExchange(ref _commandModifications, new Dictionary(StringComparer.OrdinalIgnoreCase), null); return _commandModifications; } } private Dictionary _commandModifications; internal List DynamicVariablesToDefine { get { if (_dynamicVariablesToDefine == null) Interlocked.CompareExchange(ref _dynamicVariablesToDefine, new List(), null); return _dynamicVariablesToDefine; } } private List _dynamicVariablesToDefine; /// /// /// public virtual InitialSessionStateEntryCollection Variables { get { if (_variables == null) Interlocked.CompareExchange(ref _variables, new InitialSessionStateEntryCollection(), null); return _variables; } } private InitialSessionStateEntryCollection _variables; /// /// /// public virtual InitialSessionStateEntryCollection EnvironmentVariables { get { if (_environmentVariables == null) Interlocked.CompareExchange(ref _environmentVariables, new InitialSessionStateEntryCollection(), null); return _environmentVariables; } } private InitialSessionStateEntryCollection _environmentVariables; /// /// /// public virtual HashSet StartupScripts { get { if (_startupScripts == null) Interlocked.CompareExchange(ref _startupScripts, new HashSet(), null); return _startupScripts; } } private HashSet _startupScripts = new HashSet(); Object _syncObject = new Object(); internal void Bind(ExecutionContext context, bool updateOnly) { Bind(context, updateOnly, null, /*noClobber*/false, /*local*/ false); } internal void Bind(ExecutionContext context, bool updateOnly, PSModuleInfo module, bool noClobber, bool local) { Host = context.EngineHostInterface; lock (_syncObject) { SessionStateInternal ss = context.EngineSessionState; // Clear the application and script collections... if (!updateOnly) { ss.Applications.Clear(); ss.Scripts.Clear(); } // If the initial session state made some commands private by way of // VisibleCmdlets / etc., then change the default command visibility for // the sesssion state so that newly imported modules aren't exposed accidentally. if (DefaultCommandVisibility == SessionStateEntryVisibility.Private) { ss.DefaultCommandVisibility = SessionStateEntryVisibility.Private; } try { // Load assemblies before anything else - we may need to resolve types in the loaded // assemblies as part of loading formats or types, and that can't be done in parallel. Bind_LoadAssemblies(context); var actions = new Action[] { () => Bind_UpdateTypes(context, updateOnly), () => Bind_UpdateFormats(context, updateOnly), () => Bind_BindCommands(module, noClobber, local, ss), () => Bind_LoadProviders(ss), () => Bind_SetVariables(ss), Bind_SetEnvironment }; if (updateOnly) { // We're typically called to import a module. It seems like this could // still happen in parallel, but calls to WriteError on the wrong thread // get silently swallowed, so instead just run the actions serially on this thread. foreach (var action in actions) { action(); } } else { Parallel.Invoke(actions); } } catch (AggregateException e) { e = e.Flatten(); foreach (var exception in e.InnerExceptions) { MshLog.LogEngineHealthEvent( context, MshLog.EVENT_ID_CONFIGURATION_FAILURE, exception, Severity.Warning); } if (this.ThrowOnRunspaceOpenError) { // Just throw the first error throw e.InnerExceptions[0]; } context.ReportEngineStartupError(e.Message); } catch (Exception e) { MshLog.LogEngineHealthEvent( context, MshLog.EVENT_ID_CONFIGURATION_FAILURE, e, Severity.Warning); if (this.ThrowOnRunspaceOpenError) { throw; } context.ReportEngineStartupError(e.Message); } // Set the language mode if (!updateOnly) { ss.LanguageMode = LanguageMode; } // Set the execution policy if (_wasExecutionPolicySet) { string shellId = context.ShellID; SecuritySupport.SetExecutionPolicy(Microsoft.PowerShell.ExecutionPolicyScope.Process, ExecutionPolicy, shellId); } } SetSessionStateDrive(context, setLocation:false); } private void Bind_SetVariables(SessionStateInternal ss) { bool etwEnabled = RunspaceEventSource.Log.IsEnabled(); if (etwEnabled) RunspaceEventSource.Log.LoadVariablesStart(); // Add all of the variables to session state... foreach (SessionStateVariableEntry var in Variables) { ss.AddSessionStateEntry(var); } if (etwEnabled) RunspaceEventSource.Log.LoadVariablesStop(); } private void Bind_SetEnvironment() { bool etwEnabled = RunspaceEventSource.Log.IsEnabled(); if (etwEnabled) RunspaceEventSource.Log.LoadEnvironmentVariablesStart(); foreach (SessionStateVariableEntry var in EnvironmentVariables) { Environment.SetEnvironmentVariable(var.Name, var.Value.ToString()); } if (etwEnabled) RunspaceEventSource.Log.LoadEnvironmentVariablesStop(); } private void Bind_UpdateTypes(ExecutionContext context, bool updateOnly) { bool etwEnabled = RunspaceEventSource.Log.IsEnabled(); if (etwEnabled) RunspaceEventSource.Log.UpdateTypeTableStart(); this.UpdateTypes(context, updateOnly); if (etwEnabled) RunspaceEventSource.Log.UpdateTypeTableStop(); } private void Bind_UpdateFormats(ExecutionContext context, bool updateOnly) { bool etwEnabled = RunspaceEventSource.Log.IsEnabled(); if (etwEnabled) RunspaceEventSource.Log.UpdateFormatTableStart(); this.UpdateFormats(context, updateOnly); if (etwEnabled) RunspaceEventSource.Log.UpdateFormatTableStop(); } private void Bind_LoadProviders(SessionStateInternal ss) { bool etwEnabled = RunspaceEventSource.Log.IsEnabled(); if (etwEnabled) RunspaceEventSource.Log.LoadProvidersStart(); // Add all of the providers to session state... foreach (SessionStateProviderEntry provider in Providers) { if (etwEnabled) RunspaceEventSource.Log.LoadProviderStart(provider.Name); ss.AddSessionStateEntry(provider); if (etwEnabled) RunspaceEventSource.Log.LoadProviderStop(provider.Name); } if (etwEnabled) RunspaceEventSource.Log.LoadProvidersStop(); } private void Bind_BindCommands(PSModuleInfo module, bool noClobber, bool local, SessionStateInternal ss) { bool etwEnabled = RunspaceEventSource.Log.IsEnabled(); if (etwEnabled) RunspaceEventSource.Log.LoadCommandsStart(); #if !CORECLR // Workflow Not Supported On CSS InitialSessionState cloneForWorkflowDefinitions = null; #endif foreach (SessionStateCommandEntry cmd in Commands) { if (etwEnabled) RunspaceEventSource.Log.LoadCommandStart(cmd.Name); SessionStateCmdletEntry ssce = cmd as SessionStateCmdletEntry; if (ssce != null) { if (noClobber && ModuleCmdletBase.CommandFound(ssce.Name, ss)) { ssce._isImported = false; continue; } ss.AddSessionStateEntry(ssce, local); cmd.SetModule(module); continue; } cmd.SetModule(module); SessionStateFunctionEntry ssfe = cmd as SessionStateFunctionEntry; if (ssfe != null) { ss.AddSessionStateEntry(ssfe); continue; } SessionStateAliasEntry ssae = cmd as SessionStateAliasEntry; if (ssae != null) { ss.AddSessionStateEntry(ssae, StringLiterals.Local); continue; } SessionStateApplicationEntry ssappe = cmd as SessionStateApplicationEntry; if (ssappe != null) { if (ssappe.Visibility == SessionStateEntryVisibility.Public) { ss.AddSessionStateEntry(ssappe); } continue; } SessionStateScriptEntry ssse = cmd as SessionStateScriptEntry; if (ssse != null) { if (ssse.Visibility == SessionStateEntryVisibility.Public) { ss.AddSessionStateEntry(ssse); } continue; } #if !CORECLR // Workflow Not Supported On CSS SessionStateWorkflowEntry sswe = cmd as SessionStateWorkflowEntry; if (sswe != null) { if (cloneForWorkflowDefinitions == null) { cloneForWorkflowDefinitions = this.Clone(); var commandsCopy = cloneForWorkflowDefinitions.Commands.Where(e => !(e is SessionStateWorkflowEntry)) .ToList(); cloneForWorkflowDefinitions.Commands.Clear(); foreach (var c in commandsCopy) { cloneForWorkflowDefinitions.Commands.Add(c); } } ss.AddSessionStateEntry(cloneForWorkflowDefinitions, sswe); } #endif if (etwEnabled) RunspaceEventSource.Log.LoadCommandStop(cmd.Name); } if (etwEnabled) RunspaceEventSource.Log.LoadCommandsStop(); } private void Bind_LoadAssemblies(ExecutionContext context) { bool etwEnabled = RunspaceEventSource.Log.IsEnabled(); if (etwEnabled) RunspaceEventSource.Log.LoadAssembliesStart(); // Load the assemblies and initialize the assembly cache... foreach (SessionStateAssemblyEntry ssae in Assemblies) { if (etwEnabled) RunspaceEventSource.Log.LoadAssemblyStart(ssae.Name, ssae.FileName); Exception error = null; Assembly asm = context.AddAssembly(ssae.Name, ssae.FileName, out error); if (asm == null || error != null) { // If no module was found but there was no specific error, then // create a not found error. if (error == null) { string msg = StringUtil.Format(global::Modules.ModuleAssemblyFound, ssae.Name); error = new DllNotFoundException(msg); } // If this occurs while loading a module manifest, just // throw the exception instead of writing it out... if ((!string.IsNullOrEmpty(context.ModuleBeingProcessed) && Path.GetExtension(context.ModuleBeingProcessed) .Equals(StringLiterals.PowerShellDataFileExtension, StringComparison.OrdinalIgnoreCase)) || throwOnRunspaceOpenError) { throw error; } else { context.ReportEngineStartupError(error.Message); } } if (etwEnabled) RunspaceEventSource.Log.LoadAssemblyStop(ssae.Name, ssae.FileName); } if (etwEnabled) RunspaceEventSource.Log.LoadAssembliesStop(); } internal Exception BindRunspace(Runspace initializedRunspace, PSTraceSource runspaceInitTracer) { // Get initial list of public commands in session. HashSet publicCommands = new HashSet(); foreach (CommandInfo sessionCommand in initializedRunspace.ExecutionContext.SessionState.InvokeCommand.GetCommands( "*", CommandTypes.Alias | CommandTypes.Function | CommandTypes.Filter | CommandTypes.Cmdlet, true)) { if (sessionCommand.Visibility == SessionStateEntryVisibility.Public) { publicCommands.Add(sessionCommand); } } // If a user has any module with the same name as that of the core module( or nested module inside the core module) // in his module path, then that will get loaded instead of the actual nested module (from the GAC - in our case) // Hence, searching only from the system module path while loading the core modules ProcessImportModule(initializedRunspace, CoreModulesToImport, ModuleIntrinsics.GetSystemwideModulePath(), publicCommands); // Win8:328748 - functions defined in global scope end up in a module // Since we import the core modules, EngineSessionState's module is set to the last imported module. So, if a function is defined in global scope, it ends up in that module. // Setting the module to null fixes that. initializedRunspace.ExecutionContext.EngineSessionState.Module = null; // Set the SessionStateDrive here since we have all the provider information at this point SetSessionStateDrive(initializedRunspace.ExecutionContext, true); Exception moduleImportException = ProcessImportModule(initializedRunspace, ModuleSpecificationsToImport, "", publicCommands); if(moduleImportException != null) { runspaceInitTracer.WriteLine( "Runspace open failed while loading module: First error {1}", moduleImportException); return moduleImportException; } // If we still have unresolved commands after importing specified modules, then try finding associated module for // each unresolved command and import that module. string[] foundModuleList = GetModulesForUnResolvedCommands(UnresolvedCommandsToExpose, initializedRunspace.ExecutionContext); if (foundModuleList.Length > 0) { ProcessImportModule(initializedRunspace, foundModuleList, "", publicCommands); } ProcessDynamicVariables(initializedRunspace); ProcessCommandModifications(initializedRunspace); // Process User: drive Exception userDriveException = ProcessUserDrive(initializedRunspace); if (userDriveException != null) { runspaceInitTracer.WriteLine( "Runspace open failed while processing user drive with error {1}", userDriveException); Exception result = PSTraceSource.NewInvalidOperationException(userDriveException, RemotingErrorIdStrings.UserDriveProcessingThrewTerminatingError, userDriveException.Message); return result; } // Process startup scripts Exception startupScriptException = ProcessStartupScripts(initializedRunspace); if (startupScriptException != null) { runspaceInitTracer.WriteLine( "Runspace open failed while running startup script: First error {1}", startupScriptException); Exception result = PSTraceSource.NewInvalidOperationException(startupScriptException, RemotingErrorIdStrings.StartupScriptThrewTerminatingError, startupScriptException.Message); return result; } // Start transcribing if(! String.IsNullOrEmpty(TranscriptDirectory)) { using (PowerShell psToInvoke = PowerShell.Create()) { psToInvoke.AddCommand(new Command("Start-Transcript")).AddParameter("OutputDirectory", TranscriptDirectory); Exception exceptionToReturn = ProcessPowerShellCommand(psToInvoke, initializedRunspace); if (exceptionToReturn != null) { // ThrowOnRunspaceOpenError handling is done by ProcessPowerShellCommand return exceptionToReturn; } } } return null; } private string[] GetModulesForUnResolvedCommands(IEnumerable unresolvedCommands, ExecutionContext context) { Collection modulesToImport = new Collection(); HashSet commandsToResolve = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var unresolvedCommand in unresolvedCommands) { string moduleName; string command = Utils.ParseCommandName(unresolvedCommand, out moduleName); if (!string.IsNullOrEmpty(moduleName)) { // Skip fully qualified module names since they are already processed. continue; } if (WildcardPattern.ContainsWildcardCharacters(command)) { // Skip names with wild cards. continue; } commandsToResolve.Add(command); } if (commandsToResolve.Count > 0) { Runspace restoreRunspace = Runspace.DefaultRunspace; try { // Create a temporary default runspace for the analysis cache to use. using (Runspace tempRunspace = RunspaceFactory.CreateRunspace()) { tempRunspace.Open(); Runspace.DefaultRunspace = tempRunspace; foreach (var unresolvedCommand in commandsToResolve) { // Use the analysis cache to find the first module containing the unresolved command. foreach (string modulePath in ModuleUtils.GetDefaultAvailableModuleFiles(true, true, context)) { string expandedModulePath = IO.Path.GetFullPath(modulePath); var exportedCommands = AnalysisCache.GetExportedCommands(expandedModulePath, false, context); if (exportedCommands != null && exportedCommands.ContainsKey(unresolvedCommand)) { modulesToImport.Add(System.IO.Path.GetFileNameWithoutExtension(expandedModulePath)); break; } } } } } finally { Runspace.DefaultRunspace = restoreRunspace; } } return modulesToImport.ToArray(); } private void ProcessCommandModifications(Runspace initializedRunspace) { foreach(var pair in CommandModifications) { string commandName = pair.Key; Hashtable commandModification = pair.Value; CommandInfo existingCommand = initializedRunspace.SessionStateProxy.InvokeCommand.GetCommand(commandName, CommandTypes.Cmdlet | CommandTypes.Function); if(existingCommand == null) { // Could not find the command - just continue, rather than generating an error. This could just be a missing module // or something similar. continue; } // If we are wrapping a function, rename it. FunctionInfo commandAsFunction = existingCommand as FunctionInfo; if(commandAsFunction != null) { string newCommandName = commandAsFunction.Name + "_" + Guid.NewGuid().ToString("N"); commandAsFunction.Rename(newCommandName); initializedRunspace.ExecutionContext.EngineSessionState.GlobalScope.FunctionTable.Add(newCommandName, commandAsFunction); initializedRunspace.ExecutionContext.EngineSessionState.GlobalScope.FunctionTable.Remove(commandName); existingCommand = initializedRunspace.SessionStateProxy.InvokeCommand.GetCommand(newCommandName, CommandTypes.Function); } CommandMetadata metadata = new CommandMetadata(existingCommand); List unprocessedCommandModifications = new List(); foreach (string commandModificationParameter in commandModification.Keys) { unprocessedCommandModifications.Add(commandModificationParameter); } // Visit all parameters of the command we're wrapping foreach(string existingParameter in metadata.Parameters.Keys.ToArray()) { // If it's not allowed, remove it if(! commandModification.ContainsKey(existingParameter)) { metadata.Parameters.Remove(existingParameter); } else { // Remember that we've processed this parameter, so that we can add the remainder // as virtual command modifications over (what we must assume to be) dynamic parameters. unprocessedCommandModifications.Remove(existingParameter); ProcessCommandModification(commandModification, metadata, existingParameter); } } // Now, process the command modifications that the user requested (but there was no parameter // in the cmdlet that matched the requested parameter) foreach (string unprocessedCommandModification in unprocessedCommandModifications) { ProcessCommandModification(commandModification, metadata, unprocessedCommandModification); } string proxyBody = ProxyCommand.Create(metadata, "", false); ScriptBlock proxyScriptBlock = ScriptBlock.Create(proxyBody); proxyScriptBlock.LanguageMode = PSLanguageMode.FullLanguage; initializedRunspace.ExecutionContext.EngineSessionState.GlobalScope.FunctionTable.Add( commandName, new FunctionInfo(commandName, proxyScriptBlock, initializedRunspace.ExecutionContext)); } } /// /// Process a command modification for a specific parameter /// /// The hashtable of command modifications for this command /// The metadata for the command being processed /// The parameter being modified private static void ProcessCommandModification(Hashtable commandModification, CommandMetadata metadata, string parameterName) { // If the metadata doesn't actually contain the parameter, then we need to create one. if(! metadata.Parameters.ContainsKey(parameterName)) { metadata.Parameters[parameterName] = new ParameterMetadata(parameterName); } // Add validation attributes Hashtable parameterValidations = (Hashtable)commandModification[parameterName]; foreach (object parameterValidation in parameterValidations.Keys) { string[] parameterValidationValues = ((HashSet)parameterValidations[parameterValidation]).ToList().ToArray(); switch (parameterValidation.ToString()) { case "ValidateSet": ValidateSetAttribute validateSet = new ValidateSetAttribute(parameterValidationValues); metadata.Parameters[parameterName].Attributes.Add(validateSet); break; case "ValidatePattern": string pattern = "^(" + String.Join("|", parameterValidationValues) + ")$"; ValidatePatternAttribute validatePattern = new ValidatePatternAttribute(pattern); metadata.Parameters[parameterName].Attributes.Add(validatePattern); break; } } } private Exception ProcessDynamicVariables(Runspace initializedRunspace) { foreach (Hashtable variable in DynamicVariablesToDefine) { if (variable.ContainsKey("Name")) { string name = variable["Name"].ToString(); ScriptBlock sb = variable["Value"] as ScriptBlock; if (!String.IsNullOrEmpty(name) && (sb != null)) { sb.SessionStateInternal = initializedRunspace.ExecutionContext.EngineSessionState; using (PowerShell psToInvoke = PowerShell.Create()) { psToInvoke.AddCommand(new Command("Invoke-Command")).AddParameter("ScriptBlock", sb).AddParameter("NoNewScope"); psToInvoke.AddCommand(new Command("Set-Variable")).AddParameter("Name", name); Exception exceptionToReturn = ProcessPowerShellCommand(psToInvoke, initializedRunspace); if (exceptionToReturn != null) { // ThrowOnRunspaceOpenError handling is done by ProcessPowerShellCommand return exceptionToReturn; } } } } } return null; } private Exception ProcessUserDrive(Runspace initializedRunspace) { if (!UserDriveEnabled) { return null; } Exception ex = null; try { List fileSystemProviders = initializedRunspace.ExecutionContext.EngineSessionState.Providers["FileSystem"]; if (fileSystemProviders.Count == 0) { throw new PSInvalidOperationException(RemotingErrorIdStrings.UserDriveCannotGetFileSystemProvider); } // Create the User drive path directory in current user local appdata location: // SystemDrive\Users\[user]\AppData\Local\Microsoft\Windows\PowerShell\DriveRoots\[UserName] // Or for virtual accounts // WinDir\System32\Microsoft\Windows\PowerShell\DriveRoots\[UserName] string directoryName = MakeUserNamePath(); string userDrivePath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\Windows\PowerShell\DriveRoots", directoryName); // Create directory if it doesn't exist. if (!System.IO.Directory.Exists(userDrivePath)) { System.IO.Directory.CreateDirectory(userDrivePath); } // Create the PSDrive. var newDriveInfo = new PSDriveInfo( "User", fileSystemProviders[0], userDrivePath, null, null); var userDriveInfo = initializedRunspace.ExecutionContext.SessionState.Drive.New(newDriveInfo, null); // Set User drive maximum size. Default maximum size is 50MB userDriveInfo.MaximumSize = (UserDriveMaximumSize > 0) ? UserDriveMaximumSize : 50000000; } catch (ArgumentNullException e) { ex = e; } catch (ArgumentException e) { ex = e; } catch (NotSupportedException e) { ex = e; } catch (ProviderNotFoundException e) { ex = e; } catch (ProviderInvocationException e) { ex = e; } catch (SessionStateOverflowException e) { ex = e; } catch (KeyNotFoundException e) { ex = e; } catch (IOException e) { ex = e; } catch (UnauthorizedAccessException e) { ex = e; } return ex; } private string MakeUserNamePath() { // Use the user name passsed to initial session state if avaiable, or // otherwise use the current user name. var userName = (!string.IsNullOrEmpty(this.UserDriveUserName)) ? this.UserDriveUserName : System.Security.Principal.WindowsIdentity.GetCurrent().Name; // Ensure that user name contains no invalid path characters. // MSDN indicates that logon names cannot contain any of these invalid characters, // but this check will ensure safety. if (userName.IndexOfAny(System.IO.Path.GetInvalidPathChars()) > -1) { throw new PSInvalidOperationException(RemotingErrorIdStrings.InvalidUserDriveName); } return userName.Replace("\\", "_"); } private Exception ProcessStartupScripts(Runspace initializedRunspace) { foreach (string startupScript in StartupScripts) { using (PowerShell psToInvoke = PowerShell.Create()) { psToInvoke.AddCommand(new Command(startupScript, false, false)); Exception exceptionToReturn = ProcessPowerShellCommand(psToInvoke, initializedRunspace); if (exceptionToReturn != null) { // ThrowOnRunspaceOpenError handling is done by ProcessPowerShellCommand return exceptionToReturn; } } } return null; } private Exception ProcessPowerShellCommand(PowerShell psToInvoke, Runspace initializedRunspace) { PSLanguageMode originalLanguageMode = initializedRunspace.SessionStateProxy.LanguageMode; try { initializedRunspace.SessionStateProxy.LanguageMode = PSLanguageMode.FullLanguage; psToInvoke.Runspace = initializedRunspace; foreach(Command command in psToInvoke.Commands.Commands) { command.CommandOrigin = CommandOrigin.Internal; } try { psToInvoke.Invoke(); } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); if (ThrowOnRunspaceOpenError) { return e; } } } finally { // Restore the langauge mode, but not if it was altered by the startup script itself. if(initializedRunspace.SessionStateProxy.LanguageMode == PSLanguageMode.FullLanguage) { initializedRunspace.SessionStateProxy.LanguageMode = originalLanguageMode; } } if(ThrowOnRunspaceOpenError) { // find out if there are any error records reported. If there is one, report the error.. // this will result in the runspace getting closed/broken. ArrayList errorList = (ArrayList) initializedRunspace.GetExecutionContext.DollarErrorVariable; if (errorList.Count > 0) { ErrorRecord lastErrorRecord = errorList[0] as ErrorRecord; if (lastErrorRecord != null) { return new Exception(lastErrorRecord.ToString()); } else { Exception lastException = errorList[0] as Exception; if (lastException != null) { return lastException; } else { return new Exception(errorList[0].ToString()); } } } } return null; } private RunspaceOpenModuleLoadException ProcessImportModule(Runspace initializedRunspace, IEnumerable moduleList, string path, HashSet publicCommands) { RunspaceOpenModuleLoadException exceptionToReturn = null; foreach (object module in moduleList) { string moduleName = module as string; if (null != moduleName) { exceptionToReturn = ProcessImportModule(initializedRunspace, moduleName, null, path, publicCommands); } else { ModuleSpecification moduleSpecification = module as ModuleSpecification; if (null != moduleSpecification) { if ((moduleSpecification.RequiredVersion == null) && (moduleSpecification.Version == null) && (moduleSpecification.MaximumVersion == null) && (moduleSpecification.Guid == null)) { // if only name is specified in the module spec, just try import the module // ie., don't take the performance overhead of calling GetModule. exceptionToReturn = ProcessImportModule(initializedRunspace, moduleSpecification.Name, null, path, publicCommands); } else { Collection moduleInfos = ModuleCmdletBase.GetModuleIfAvailable(moduleSpecification, initializedRunspace); if (moduleInfos != null && moduleInfos.Count > 0) { exceptionToReturn = ProcessImportModule(initializedRunspace, moduleSpecification.Name, moduleInfos[0], path, publicCommands); } else { var version = "0.0.0.0"; if (moduleSpecification.RequiredVersion != null) { version = moduleSpecification.RequiredVersion.ToString(); } else if (moduleSpecification.Version != null) { version = moduleSpecification.Version.ToString(); if (moduleSpecification.MaximumVersion != null) { version = version + " - " + moduleSpecification.MaximumVersion; } } else if (moduleSpecification.MaximumVersion != null) { version = moduleSpecification.MaximumVersion; } string message = StringUtil.Format(global::Modules.RequiredModuleNotFoundWrongGuidVersion, moduleSpecification.Name, moduleSpecification.Guid, version); RunspaceOpenModuleLoadException rome = new RunspaceOpenModuleLoadException(message); exceptionToReturn = ValidateAndReturnRunspaceOpenModuleLoadException(null, moduleSpecification.Name, rome); } } } else { Debug.Assert(false, "ProcessImportModule can import a module using name or module specification."); } } } if (exceptionToReturn == null) { // Now go through the list of commands not yet resolved to ensure they are public if requested foreach (string unresolvedCommand in UnresolvedCommandsToExpose.ToArray()) { string moduleName; string commandToMakeVisible = Utils.ParseCommandName(unresolvedCommand, out moduleName); bool found = false; foreach (CommandInfo cmd in LookupCommands(commandToMakeVisible, moduleName, initializedRunspace.ExecutionContext)) { if (!found) { found = true; } try { // Special case for wild card lookups. // "Import-Module" or "ipmo" cannot be visible when exposing commands via VisibleCmdlets, etc. if ((cmd.Name.Equals("Import-Module", StringComparison.OrdinalIgnoreCase) && (!string.IsNullOrEmpty(cmd.ModuleName) && cmd.ModuleName.Equals("Microsoft.PowerShell.Core", StringComparison.OrdinalIgnoreCase)) ) || cmd.Name.Equals("ipmo", StringComparison.OrdinalIgnoreCase) ) { cmd.Visibility = SessionStateEntryVisibility.Private; } else { cmd.Visibility = SessionStateEntryVisibility.Public; publicCommands.Add(cmd); } } // Some CommandInfo derivations throw on the Visibility setter. catch (PSNotImplementedException) { } } if (found && !WildcardPattern.ContainsWildcardCharacters(commandToMakeVisible)) { UnresolvedCommandsToExpose.Remove(unresolvedCommand); } } } return exceptionToReturn; } /// /// Helper method to search for commands matching the provided commandPattern. /// Supports wild cards and if the commandPattern contains wildcard characters then multiple /// results can be returned. Otherwise a single (and first) match will be returned. /// If a moduleName is provided then only commands associated with that module will be returned. /// Only public commands are searched to start with. If no results are found then a search on /// internal commands is performed. /// /// /// /// /// private IEnumerable LookupCommands( string commandPattern, string moduleName, ExecutionContext context) { bool isWildCardPattern = WildcardPattern.ContainsWildcardCharacters(commandPattern); var searchOptions = (isWildCardPattern) ? SearchResolutionOptions.CommandNameIsPattern | SearchResolutionOptions.ResolveFunctionPatterns | SearchResolutionOptions.SearchAllScopes : SearchResolutionOptions.ResolveFunctionPatterns | SearchResolutionOptions.SearchAllScopes; bool found = false; bool haveModuleName = !string.IsNullOrEmpty(moduleName); // Start with public search CommandOrigin cmdOrigin = CommandOrigin.Runspace; while (true) { foreach (CommandInfo commandInfo in context.SessionState.InvokeCommand.GetCommands(commandPattern, CommandTypes.All, searchOptions, cmdOrigin)) { // If module name is provided then use it to restrict returned results. if (haveModuleName && !moduleName.Equals(commandInfo.ModuleName, StringComparison.OrdinalIgnoreCase)) { continue; } if (!found) { found = true; } yield return commandInfo; // Return first match unless a wild card pattern is submitted. if (!isWildCardPattern) { break; } } if (found || (cmdOrigin == CommandOrigin.Internal)) { break; } // Next try internal search. cmdOrigin = CommandOrigin.Internal; } } /// /// if is null, import module using . Otherwise, /// import module using /// private RunspaceOpenModuleLoadException ProcessImportModule(Runspace initializedRunspace, string name, PSModuleInfo moduleInfoToLoad, string path, HashSet publicCommands) { using (PowerShell pse = PowerShell.Create()) { CommandInfo c = new CmdletInfo("Import-Module", typeof(ImportModuleCommand), null, null, initializedRunspace.ExecutionContext); Command cmd = new Command(c); if (null != moduleInfoToLoad) { cmd.Parameters.Add("ModuleInfo", moduleInfoToLoad); name = moduleInfoToLoad.Name; } else { // If FullyQualifiedPath is supplied then use it. // In this scenario, the FullyQualifiedPath would // refer to $pshome\Modules location where core // modules are deployed. if (!string.IsNullOrEmpty(path)) { name = Path.Combine(path, name); } cmd.Parameters.Add("Name", name); } if (! ThrowOnRunspaceOpenError) { cmd.MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); } pse.AddCommand(cmd); if (! ThrowOnRunspaceOpenError) { c = new CmdletInfo("Out-Default", typeof(OutDefaultCommand), null, null, initializedRunspace.ExecutionContext); pse.AddCommand(new Command(c)); } pse.Runspace = initializedRunspace; // Module import should be run in FullLanguage mode since it is running in // a trusted context. var savedLanguageMode = pse.Runspace.ExecutionContext.LanguageMode; pse.Runspace.ExecutionContext.LanguageMode = PSLanguageMode.FullLanguage; try { pse.Invoke(); } finally { pse.Runspace.ExecutionContext.LanguageMode = savedLanguageMode; } // Lock down the command visibility to respect default command visibility if (this.DefaultCommandVisibility != SessionStateEntryVisibility.Public) { foreach (CommandInfo importedCommand in initializedRunspace.ExecutionContext.SessionState.InvokeCommand.GetCommands( "*", CommandTypes.Alias | CommandTypes.Function | CommandTypes.Filter | CommandTypes.Cmdlet, true)) { try { // All commands except for the initial session public commands should be made private. if ((importedCommand.Visibility != this.DefaultCommandVisibility) && !publicCommands.Contains(importedCommand)) { importedCommand.Visibility = this.DefaultCommandVisibility; } } // Some CommandInfo derivations throw on the Visibility setter. catch (PSNotImplementedException) { } } } // Now see if there were any errors. Because the only way we have to // return an error at this point is a single exception, we'll take the first // error and throw it... return ValidateAndReturnRunspaceOpenModuleLoadException(pse, name, null); } } private RunspaceOpenModuleLoadException ValidateAndReturnRunspaceOpenModuleLoadException(PowerShell pse, string moduleName, RunspaceOpenModuleLoadException exception) { // Only throw the exception if ThrowOnRunspaceOpenError is set. if (ThrowOnRunspaceOpenError) { RunspaceOpenModuleLoadException rome = null; if (exception != null) { rome = exception; } else if (pse.Streams.Error.Count > 0) { ErrorRecord er; Exception firstError; // Merge errors from pse.Streams and errors PSDataCollection mergedErrors = new PSDataCollection(); er = pse.Streams.Error[0]; firstError = er.Exception; foreach (var e in pse.Streams.Error) { mergedErrors.Add(e); } rome = new RunspaceOpenModuleLoadException(moduleName, mergedErrors); } if (null != rome) { return rome; } } return null; } /// /// Reinitializes elements of the associated runspace to their initial values. /// This allows for runspace reuse with minimal chance for contamination. /// /// internal void ResetRunspaceState(ExecutionContext context) { lock (_syncObject) { SessionStateInternal ss = context.EngineSessionState; // Reset the global variable table ss.InitializeSessionStateInternalSpecialVariables(true); // Add the built-in variables foreach (SessionStateVariableEntry e in InitialSessionState.BuiltInVariables) { PSVariable v = new PSVariable(e.Name, e.Value, e.Options, e.Attributes, e.Description) { Visibility = e.Visibility }; ss.GlobalScope.SetVariable(e.Name, v, false, true, ss, fastPath: true); } ss.InitializeFixedVariables(); // Then re-initialize it with variables to session state... foreach (SessionStateVariableEntry e in Variables) { PSVariable v = new PSVariable(e.Name, e.Value, e.Options, e.Attributes, e.Description) { Visibility = e.Visibility }; ss.GlobalScope.SetVariable(e.Name, v, false, true, ss, fastPath: true); } InitialSessionState.CreateQuestionVariable(context); // Reset the path for this runspace. SetSessionStateDrive(context, true); // Reset the event, transaction and debug managers. context.ResetManagers(); // Reset tracing/debugging to the off state. context.PSDebugTraceLevel = 0; context.PSDebugTraceStep = false; } } internal static void SetSessionStateDrive(ExecutionContext context, bool setLocation) { // Set the starting location to the current process working directory // Ignore any errors as the file system provider may not be loaded or // a drive with the same name as the real file system drive may not have // been mounted. try { bool proceedWithSetLocation = true; if (context.EngineSessionState.ProviderCount > 0) { // NTRAID#Windows Out Of Band Releases-908481-2005/07/01-JeffJon // Make sure we have a CurrentDrive set so that we can deal with // UNC paths if (context.EngineSessionState.CurrentDrive == null) { bool fsDriveSet = false; try { // Set the current drive to the first FileSystem drive if it exists. ProviderInfo fsProvider = context.EngineSessionState.GetSingleProvider(context.ProviderNames.FileSystem); Collection fsDrives = fsProvider.Drives; if (fsDrives != null && fsDrives.Count > 0) { context.EngineSessionState.CurrentDrive = fsDrives[0]; fsDriveSet = true; } } catch (ProviderNotFoundException) { } if (!fsDriveSet) { Collection allDrives = context.EngineSessionState.Drives(null); if (allDrives != null && allDrives.Count > 0) { context.EngineSessionState.CurrentDrive = allDrives[0]; } else { ItemNotFoundException itemNotFound = new ItemNotFoundException(Directory.GetCurrentDirectory(), "PathNotFound", SessionStateStrings.PathNotFound); context.ReportEngineStartupError(itemNotFound); proceedWithSetLocation = false; } } } if (proceedWithSetLocation && setLocation) { CmdletProviderContext providerContext = new CmdletProviderContext(context); try { context.EngineSessionState.SetLocation(Directory.GetCurrentDirectory(), providerContext); } catch (ItemNotFoundException) { // If we can't access the Environment.CurrentDirectory, we may be in an AppContainer. Set the // default drive to $pshome System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess(); string defaultPath = System.IO.Path.GetDirectoryName(PsUtils.GetMainModule(currentProcess).FileName); context.EngineSessionState.SetLocation(defaultPath, providerContext); } } } } catch (Exception e) // swallow all non-severe exceptions { CommandProcessorBase.CheckForSevereException(e); } } internal static void CreateQuestionVariable(ExecutionContext context) { QuestionMarkVariable qv = new QuestionMarkVariable(context); context.EngineSessionState.SetVariableAtScope(qv, "global", true, CommandOrigin.Internal); } /// /// Remove anything that would have been bound by this ISS instance. /// At this point, it removes assemblies and cmdlet entries at the top level. /// It also removes types and formats. /// The other entry types - functions, variables, aliases /// are not removed by this function. /// /// internal void Unbind(ExecutionContext context) { lock (_syncObject) { SessionStateInternal ss = context.EngineSessionState; // Remove the assemblies from the assembly cache... foreach (SessionStateAssemblyEntry ssae in Assemblies) { context.RemoveAssembly(ssae.Name); } // Remove all of the commands from the top-level session state. foreach (SessionStateCommandEntry cmd in Commands) { SessionStateCmdletEntry ssce = cmd as SessionStateCmdletEntry; if (ssce != null) { List matches; if (context.TopLevelSessionState.GetCmdletTable().TryGetValue(ssce.Name, out matches)) { // Remove the name from the list... for (int i = matches.Count - 1; i >= 0; i--) { if (matches[i].ModuleName.Equals(cmd.PSSnapIn.Name)) { string name = matches[i].Name; matches.RemoveAt(i); context.TopLevelSessionState.RemoveCmdlet(name, i, /*force*/ true); } } // And remove the entry if the list is now empty... if (matches.Count == 0) { context.TopLevelSessionState.RemoveCmdletEntry(ssce.Name, true); } } continue; } } // Remove all of the providers from the top-level provider table. if (_providers != null && _providers.Count > 0) { Dictionary> providerTable = context.TopLevelSessionState.Providers; foreach (SessionStateProviderEntry sspe in _providers) { List pl; if (providerTable.TryGetValue(sspe.Name, out pl)) { Diagnostics.Assert(pl != null, "There should never be a null list of entries in the provider table"); // For each provider with the same name... for (int i = pl.Count - 1; i >= 0; i--) { ProviderInfo pi = pl[i]; // If it was implemented by this entry, remove it if (pi.ImplementingType == sspe.ImplementingType) { RemoveAllDrivesForProvider(pi, context.TopLevelSessionState); pl.RemoveAt(i); } } // If there are no providers left with this name, remove the key. if (pl.Count == 0) { providerTable.Remove(sspe.Name); } } } } List formatFilesToRemove = new List(); if (this.Formats != null) { formatFilesToRemove.AddRange(this.Formats.Select(f => f.FileName)); } List typeFilesToRemove = new List(); if (this.Types != null) { typeFilesToRemove.AddRange(this.Types.Select(t => t.FileName)); } RemoveTypesAndFormats(context, formatFilesToRemove, typeFilesToRemove); } } internal static void RemoveTypesAndFormats(ExecutionContext context, IList formatFilesToRemove, IList typeFilesToRemove) { // The formats and types tables are implemented in such a way that // we can't simply remove an entry. We need to edit the list, clear the // exiting composed table and then rebuild the entire table. if (formatFilesToRemove != null && formatFilesToRemove.Count > 0) { var newFormats = new InitialSessionStateEntryCollection(); HashSet formatFilesToRemoveSet = new HashSet(formatFilesToRemove, StringComparer.OrdinalIgnoreCase); foreach (SessionStateFormatEntry entry in context.InitialSessionState.Formats) { if (!formatFilesToRemoveSet.Contains(entry.FileName)) { newFormats.Add(entry); } } context.InitialSessionState.Formats.Clear(); context.InitialSessionState.Formats.Add(newFormats); context.InitialSessionState.UpdateFormats(context, false); } if (typeFilesToRemove != null && typeFilesToRemove.Count > 0) { // The types table has the same issue as the format table - we need to rebuild the entire table. var newTypes = new InitialSessionStateEntryCollection(); List resolvedTypeFilesToRemove = new List(); foreach (var typeFile in typeFilesToRemove) { resolvedTypeFilesToRemove.Add(ModuleCmdletBase.ResolveRootedFilePath(typeFile, context) ?? typeFile); } foreach (SessionStateTypeEntry entry in context.InitialSessionState.Types) { if (entry.FileName == null) { // The entry is associated with a TypeData instance newTypes.Add(entry); } else { // Resolving the file path because the path to the types file in module manifest is now specified as // ..\..\types.ps1xml which expands to C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Core\..\..\types.ps1xml string filePath = ModuleCmdletBase.ResolveRootedFilePath(entry.FileName, context) ?? entry.FileName; if (!resolvedTypeFilesToRemove.Contains(filePath)) { newTypes.Add(entry); } } } // If there are any types that need to be added to the typetable, update them. // Else, clear the typetable if (newTypes.Count > 0) { context.InitialSessionState.Types.Clear(); context.InitialSessionState.Types.Add(newTypes); context.InitialSessionState.UpdateTypes(context, false); } else { context.TypeTable.Clear(); } } } /// /// Update the type metadata loaded into this runspace /// /// The execution context for the runspace to update /// if true, re-initialize the metadata collection... internal void UpdateTypes(ExecutionContext context, bool updateOnly) { if (Types.Count == 1) { TypeTable typeTable = Types[0].TypeTable; if (typeTable != null) { // reuse the TypeTable instance specified in the sste. // this essentially allows for TypeTable sharing across // multiple runspaces. context.TypeTable = typeTable; Types.Clear(); Types.Add(typeTable.typesInfo); return; } } if (!updateOnly) { context.TypeTable.Clear(); } ConcurrentBag errors = new ConcurrentBag(); // Use at most 3 locks (we don't expect contention on that many cores anyways, // and typically we'll be processing just 2 or 3 files anyway, hence capacity=3. ConcurrentDictionary filesProcessed = new ConcurrentDictionary(/*concurrencyLevel*/3, /*capacity*/3, StringComparer.OrdinalIgnoreCase); Parallel.ForEach(Types, sste => // foreach (var sste in Types) { if (sste.FileName != null) { if (filesProcessed.TryAdd(sste.FileName, null)) { string moduleName = ""; if (sste.PSSnapIn != null && !String.IsNullOrEmpty(sste.PSSnapIn.Name)) { moduleName = sste.PSSnapIn.Name; } bool unused; context.TypeTable.Update(moduleName, sste.FileName, errors, context.AuthorizationManager, context.EngineHostInterface, out unused); } } else if (sste.TypeTable != null) { // We get here only if it's NOT updating the existing type table // because we cannot do the update with a type table instance errors.Add(TypesXmlStrings.TypeTableCannotCoExist); } else { context.TypeTable.Update(sste.TypeData, errors, sste.IsRemove); } }); // } context.TypeTable.ClearConsolidatedMembers(); if (updateOnly) { // Put the SessionStateTypeEntry into the cache if we are updating the type table foreach (var sste in Types) { context.InitialSessionState.Types.Add(sste); } } if (errors.Count > 0) { var allErrors = new StringBuilder('\n'); foreach (string error in errors) { if (!string.IsNullOrEmpty(error)) { if (this.ThrowOnRunspaceOpenError || this.RefreshTypeAndFormatSetting) { allErrors.Append(error); allErrors.Append('\n'); } else { context.ReportEngineStartupError(ExtendedTypeSystem.TypesXmlError, error); } } } if (this.ThrowOnRunspaceOpenError) { string resource = ExtendedTypeSystem.TypesXmlError; ThrowTypeOrFormatErrors(resource, allErrors.ToString(), "ErrorsUpdatingTypes"); } if (this.RefreshTypeAndFormatSetting) { string resource = ExtendedTypeSystem.TypesXmlError; ThrowTypeOrFormatErrors(resource, allErrors.ToString(), "ErrorsUpdatingTypes"); } } } /// /// Update the formatting information for a runspace /// /// The execution context for the runspace to be updated /// True if we only want to add stuff, false if we want to reinitialize internal void UpdateFormats(ExecutionContext context, bool update) { if (DisableFormatUpdates || this.Formats.Count == 0) { return; } Collection entries = new Collection(); InitialSessionStateEntryCollection formatsToLoad; // If we're just updating the current runspace, then we'll add our entries // to the current list otherwise, we'll build a new list... if (update && context.InitialSessionState != null) { formatsToLoad = context.InitialSessionState.Formats; formatsToLoad.Add(this.Formats); } else { formatsToLoad = this.Formats; } HashSet filesProcessed = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (SessionStateFormatEntry ssfe in formatsToLoad) { string name = ssfe.FileName; PSSnapInInfo snapin = ssfe.PSSnapIn; if (snapin != null && !string.IsNullOrEmpty(snapin.Name)) { name = snapin.Name; } if (ssfe.Formattable != null) { if (formatsToLoad.Count == 1) { context.FormatDBManager = ssfe.Formattable.FormatDBManager; } else { // if a SharedFormatTable is allowed then only one // entry can be specified. throw PSTraceSource.NewInvalidOperationException(FormatAndOutXmlLoadingStrings.FormatTableCannotCoExist); } } else if(ssfe.FormatData != null) { entries.Add(new PSSnapInTypeAndFormatErrors(name, ssfe.FormatData)); } else { if (!filesProcessed.Contains(ssfe.FileName)) { filesProcessed.Add(ssfe.FileName); entries.Add(new PSSnapInTypeAndFormatErrors(name, ssfe.FileName)); } } } if (entries.Count > 0) { context.FormatDBManager.UpdateDataBase(entries, context.AuthorizationManager, context.EngineHostInterface, true); var allErrors = new StringBuilder("\n"); bool hasErrors = false; // Now see if there were any errors in the format files and report them // if this is the case... foreach (PSSnapInTypeAndFormatErrors entry in entries) { if (entry.Errors != null && entry.Errors.Count > 0) { foreach (string error in entry.Errors) { if (!string.IsNullOrEmpty(error)) { hasErrors = true; if (this.ThrowOnRunspaceOpenError || this.RefreshTypeAndFormatSetting) { allErrors.Append(error); allErrors.Append('\n'); } else { context.ReportEngineStartupError(FormatAndOutXmlLoadingStrings.FormatLoadingErrors, error); } } } } } if ((this.ThrowOnRunspaceOpenError || this.RefreshTypeAndFormatSetting) && hasErrors) { string resource = FormatAndOutXmlLoadingStrings.FormatLoadingErrors; ThrowTypeOrFormatErrors(resource, allErrors.ToString(), "ErrorsUpdatingFormats"); } } } private static void ThrowTypeOrFormatErrors(string resourceString, string errorMsg, string errorId) { string message = StringUtil.Format(resourceString, errorMsg); var ex = new RuntimeException(message); ex.SetErrorId(errorId); throw ex; } /// /// Need to have SnapIn support till we move to modules /// /// /// /// public PSSnapInInfo ImportPSSnapIn(string name, out PSSnapInException warning) { if (string.IsNullOrEmpty(name)) { PSTraceSource.NewArgumentNullException("name"); } // Check whether the mshsnapin is present in the registry. // TODO: Note the hard-coded version number here, this was part of the SingleShell // implementation and should be refactored. PSSnapInInfo newPSSnapIn = PSSnapInReader.Read("2", name); if (!Utils.IsPSVersionSupported(newPSSnapIn.PSVersion.ToString())) { _PSSnapInTracer.TraceError("MshSnapin {0} and current monad engine's versions don't match.", name); throw PSTraceSource.NewArgumentException("mshSnapInID", ConsoleInfoErrorStrings.AddPSSnapInBadMonadVersion, newPSSnapIn.PSVersion.ToString(), "2.0"); } // Now actually load the snapin... PSSnapInInfo snapin = ImportPSSnapIn(newPSSnapIn, out warning); if (null != snapin) { _importedSnapins.Add(snapin.Name, snapin); } return snapin; } internal PSSnapInInfo ImportCorePSSnapIn() { // Load Microsoft.PowerShell.Core as a snapin PSSnapInInfo coreSnapin = PSSnapInReader.ReadCoreEngineSnapIn(); this.defaultSnapins.Add(coreSnapin); try { PSSnapInException warning; this.ImportPSSnapIn(coreSnapin, out warning); } catch (PSSnapInException pse) { throw pse; } return coreSnapin; } // WARNING: THIS CODE IS COMPLETELY DUPLICATED IN RunspaceConfigForSingleShell internal PSSnapInInfo ImportPSSnapIn(PSSnapInInfo psSnapInInfo, out PSSnapInException warning) { // See if the snapin is already loaded. If has been then there will be an entry in the // Assemblies list for it already... bool reload = true; foreach (SessionStateAssemblyEntry ae in this.Assemblies) { PSSnapInInfo loadedPSSnapInInfo = ae.PSSnapIn; if (loadedPSSnapInInfo != null) { // See if the assembly-qualified names match and return the existing PSSnapInInfo // if they do. string loadedSnapInName = ae.PSSnapIn.AssemblyName; if (!string.IsNullOrEmpty(loadedSnapInName) && string.Equals(loadedSnapInName, psSnapInInfo.AssemblyName, System.StringComparison.OrdinalIgnoreCase)) { warning = null; // the previous implementation used to return the // same loaded snap-in value. This results in the // commands/types/formats exposed in the snap-in // to be not populated in the InitialSessionState // object. This is being fixed reload = false; break; } } } Dictionary cmdlets = null; Dictionary> aliases = null; Dictionary providers = null; if (psSnapInInfo == null) { ArgumentNullException e = new ArgumentNullException("psSnapInInfo"); throw e; } #if !CORECLR // CustomPSSnapIn Not Supported On CSS. if (!String.IsNullOrEmpty(psSnapInInfo.CustomPSSnapInType)) { LoadCustomPSSnapIn(psSnapInInfo); warning = null; return psSnapInInfo; } #endif Assembly assembly = null; string helpFile = null; if (reload) { _PSSnapInTracer.WriteLine("Loading assembly for psSnapIn {0}", psSnapInInfo.Name); assembly = PSSnapInHelpers.LoadPSSnapInAssembly(psSnapInInfo, out cmdlets, out providers); if (assembly == null) { _PSSnapInTracer.TraceError("Loading assembly for psSnapIn {0} failed", psSnapInInfo.Name); warning = null; return null; //BUGBUG - should add something to the warnings list here instead of quitting... } _PSSnapInTracer.WriteLine("Loading assembly for psSnapIn {0} succeeded", psSnapInInfo.Name); PSSnapInHelpers.AnalyzePSSnapInAssembly(assembly, psSnapInInfo.Name, psSnapInInfo, null, true, out cmdlets, out aliases, out providers, out helpFile); } // We skip checking if the file exists when it's in $PSHOME because of magic // where we have the former contents of those files built into the engine directly. var psHome = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID); foreach (string file in psSnapInInfo.Types) { string path = Path.Combine(psSnapInInfo.ApplicationBase, file); if (!string.Equals(psHome, psSnapInInfo.ApplicationBase, StringComparison.OrdinalIgnoreCase) && !File.Exists(path)) { // Remove the application base directory if assembly doesn't exist in it. path = file; } SessionStateTypeEntry typeEntry = new SessionStateTypeEntry(path); typeEntry.SetPSSnapIn(psSnapInInfo); this.Types.Add(typeEntry); } foreach (string file in psSnapInInfo.Formats) { string path = Path.Combine(psSnapInInfo.ApplicationBase, file); if (!string.Equals(psHome, psSnapInInfo.ApplicationBase, StringComparison.OrdinalIgnoreCase) && !File.Exists(path)) { path = file; } SessionStateFormatEntry formatEntry = new SessionStateFormatEntry(path); formatEntry.SetPSSnapIn(psSnapInInfo); this.Formats.Add(formatEntry); } SessionStateAssemblyEntry assemblyEntry = new SessionStateAssemblyEntry(psSnapInInfo.AssemblyName, psSnapInInfo.AbsoluteModulePath); assemblyEntry.SetPSSnapIn(psSnapInInfo); this.Assemblies.Add(assemblyEntry); // entry from types.ps1xml references a type (Microsoft.PowerShell.Commands.SecurityDescriptorCommandsBase) in this assembly if (psSnapInInfo.Name.Equals(CoreSnapin, StringComparison.OrdinalIgnoreCase)) { assemblyEntry = new SessionStateAssemblyEntry("Microsoft.PowerShell.Security", null); this.Assemblies.Add(assemblyEntry); } if (cmdlets != null) { foreach (SessionStateCmdletEntry cmdlet in cmdlets.Values) { SessionStateCmdletEntry newEntry = (SessionStateCmdletEntry)cmdlet.Clone(); newEntry.Visibility = this.DefaultCommandVisibility; this.Commands.Add(newEntry); } } if (aliases != null) { foreach (var cmdletAliasesEntry in aliases.Values) { foreach (var sessionStateAliasEntry in cmdletAliasesEntry) { sessionStateAliasEntry.Visibility = this.DefaultCommandVisibility; this.Commands.Add(sessionStateAliasEntry); } } } if (providers != null) { foreach (SessionStateProviderEntry provider in providers.Values) { this.Providers.Add(provider); } } warning = null; // Add help file information for built-in functions if (psSnapInInfo.Name.Equals(CoreSnapin, StringComparison.OrdinalIgnoreCase)) { foreach (var f in BuiltInFunctions) { Collection funcList = Commands[f.Name]; foreach (var func in funcList) { if (func is SessionStateFunctionEntry) { ((SessionStateFunctionEntry) func).SetHelpFile(helpFile); } } } } return psSnapInInfo; } internal List GetPSSnapIn(string psSnapinName) { List loadedSnapins = null; foreach (var defaultSnapin in defaultSnapins) { if (defaultSnapin.Name.Equals(psSnapinName, StringComparison.OrdinalIgnoreCase)) { if (loadedSnapins == null) { loadedSnapins = new List(); } loadedSnapins.Add(defaultSnapin); } } PSSnapInInfo importedSnapin = null; if (_importedSnapins.TryGetValue(psSnapinName, out importedSnapin)) { if (loadedSnapins == null) { loadedSnapins = new List(); } loadedSnapins.Add(importedSnapin); } return loadedSnapins; } #if !CORECLR // CustomPSSnapIn Not Supported On CSS. /// /// This is a "proxy" snapin that loads a subset of cmdlets from another snapin... /// /// /// CustomPSSnapIn derives from System.Configuration.Install, which is not in CoreCLR. /// So CustomPSSnapIn is not supported on CSS. /// /// The snapin to examine. private void LoadCustomPSSnapIn(PSSnapInInfo psSnapInInfo) { if (psSnapInInfo == null) return; if (String.IsNullOrEmpty(psSnapInInfo.CustomPSSnapInType)) { return; } Dictionary cmdlets = null; Dictionary providers = null; Assembly assembly = null; _PSSnapInTracer.WriteLine("Loading assembly for mshsnapin {0}", psSnapInInfo.Name); assembly = PSSnapInHelpers.LoadPSSnapInAssembly(psSnapInInfo, out cmdlets, out providers); if (assembly == null) { _PSSnapInTracer.TraceError("Loading assembly for mshsnapin {0} failed", psSnapInInfo.Name); return; } CustomPSSnapIn customPSSnapIn = null; try { Type type = assembly.GetType(psSnapInInfo.CustomPSSnapInType, true); if (type != null) { customPSSnapIn = (CustomPSSnapIn)assembly.CreateInstance(psSnapInInfo.CustomPSSnapInType); } _PSSnapInTracer.WriteLine("Loading assembly for mshsnapin {0} succeeded", psSnapInInfo.Name); } catch (TypeLoadException tle) { throw new PSSnapInException(psSnapInInfo.Name, tle.Message); } catch (ArgumentException ae) { throw new PSSnapInException(psSnapInInfo.Name, ae.Message); } catch (MissingMethodException mme) { throw new PSSnapInException(psSnapInInfo.Name, mme.Message); } catch (InvalidCastException ice) { throw new PSSnapInException(psSnapInInfo.Name, ice.Message); } catch (TargetInvocationException tie) { if (tie.InnerException != null) { throw new PSSnapInException(psSnapInInfo.Name, tie.InnerException.Message); } throw new PSSnapInException(psSnapInInfo.Name, tie.Message); } MergeCustomPSSnapIn(psSnapInInfo, customPSSnapIn); } private void MergeCustomPSSnapIn(PSSnapInInfo psSnapInInfo, CustomPSSnapIn customPSSnapIn) { if (psSnapInInfo == null || customPSSnapIn == null) return; _PSSnapInTracer.WriteLine("Merging configuration from custom mshsnapin {0}", psSnapInInfo.Name); if (customPSSnapIn.Cmdlets != null) { foreach (CmdletConfigurationEntry entry in customPSSnapIn.Cmdlets) { SessionStateCmdletEntry cmdlet = new SessionStateCmdletEntry(entry.Name, entry.ImplementingType, entry.HelpFileName); cmdlet.SetPSSnapIn(psSnapInInfo); this.Commands.Add(cmdlet); } } if (customPSSnapIn.Providers != null) { foreach (ProviderConfigurationEntry entry in customPSSnapIn.Providers) { SessionStateProviderEntry provider = new SessionStateProviderEntry(entry.Name, entry.ImplementingType, entry.HelpFileName); provider.SetPSSnapIn(psSnapInInfo); this.Providers.Add(provider); } } if (customPSSnapIn.Types != null) { foreach (TypeConfigurationEntry entry in customPSSnapIn.Types) { string path = Path.Combine(psSnapInInfo.ApplicationBase, entry.FileName); SessionStateTypeEntry typeEntry = new SessionStateTypeEntry(path); typeEntry.SetPSSnapIn(psSnapInInfo); this.Types.Add(typeEntry); } } if (customPSSnapIn.Formats != null) { foreach (FormatConfigurationEntry entry in customPSSnapIn.Formats) { string path = Path.Combine(psSnapInInfo.ApplicationBase, entry.FileName); SessionStateFormatEntry formatEntry = new SessionStateFormatEntry(path); formatEntry.SetPSSnapIn(psSnapInInfo); this.Formats.Add(formatEntry); } } SessionStateAssemblyEntry assemblyEntry = new SessionStateAssemblyEntry(psSnapInInfo.AssemblyName, psSnapInInfo.AbsoluteModulePath); this.Assemblies.Add(assemblyEntry); } #endif [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom")] internal static Assembly LoadAssemblyFromFile(string fileName) { _PSSnapInTracer.WriteLine("Loading assembly for psSnapIn {0}", fileName); Assembly assembly = ClrFacade.LoadFrom(fileName); if (assembly == null) { _PSSnapInTracer.TraceError("Loading assembly for psSnapIn {0} failed", fileName); return null; } _PSSnapInTracer.WriteLine("Loading assembly for psSnapIn {0} succeeded", fileName); return assembly; } internal void ImportCmdletsFromAssembly(Assembly assembly, PSModuleInfo module) { if (assembly == null) { ArgumentNullException e = new ArgumentNullException("assembly"); throw e; } Dictionary cmdlets = null; Dictionary> aliases = null; Dictionary providers = null; string assemblyPath = assembly.Location; string throwAwayHelpFile = null; PSSnapInHelpers.AnalyzePSSnapInAssembly(assembly, assemblyPath, null, module, true, out cmdlets, out aliases, out providers, out throwAwayHelpFile); SessionStateAssemblyEntry assemblyEntry = new SessionStateAssemblyEntry(assembly.FullName, assemblyPath); this.Assemblies.Add(assemblyEntry); if (cmdlets != null) { foreach (SessionStateCmdletEntry cmdlet in cmdlets.Values) { this.Commands.Add(cmdlet); } } if (aliases != null) { foreach (var cmdletAliasesEntry in aliases.Values) { foreach (var sessionStateAliasEntry in cmdletAliasesEntry) { this.Commands.Add(sessionStateAliasEntry); } } } if (providers != null) { foreach (SessionStateProviderEntry provider in providers.Values) { this.Providers.Add(provider); } } } // // Now define a bunch of functions that describe the rest of the default session state... // internal const string FormatEnumerationLimit = "FormatEnumerationLimit"; internal const int DefaultFormatEnumerationLimit = 4; /// /// This is the default function to use for tab expansion. /// private static string TabExpansionFunctionText = @" <# Options include: RelativeFilePaths - [bool] Always resolve file paths using Resolve-Path -Relative. The default is to use some heuristics to guess if relative or absolute is better. To customize your own custom options, pass a hashtable to CompleteInput, e.g. return [System.Management.Automation.CommandCompletion]::CompleteInput($inputScript, $cursorColumn, @{ RelativeFilePaths=$false } #> [CmdletBinding(DefaultParameterSetName = 'ScriptInputSet')] Param( [Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 0)] [string] $inputScript, [Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 1)] [int] $cursorColumn, [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 0)] [System.Management.Automation.Language.Ast] $ast, [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 1)] [System.Management.Automation.Language.Token[]] $tokens, [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 2)] [System.Management.Automation.Language.IScriptPosition] $positionOfCursor, [Parameter(ParameterSetName = 'ScriptInputSet', Position = 2)] [Parameter(ParameterSetName = 'AstInputSet', Position = 3)] [Hashtable] $options = $null ) End { if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet') { return [System.Management.Automation.CommandCompletion]::CompleteInput( <#inputScript#> $inputScript, <#cursorColumn#> $cursorColumn, <#options#> $options) } else { return [System.Management.Automation.CommandCompletion]::CompleteInput( <#ast#> $ast, <#tokens#> $tokens, <#positionOfCursor#> $positionOfCursor, <#options#> $options) } } "; /// /// This is the default function to use for 'Import System Modules'. /// /// /// Win8: 320909. Retaining the original definition to ensure backward compatability. /// private static string ImportSystemModulesText = @""; /// /// This is the default function to use for clear-host. On Windows it rewrites the /// host, and on Linux, it delegates to the native binary, 'clear'. /// internal static string GetClearHostFunctionText() { if (Platform.IsWindows) { return @" $RawUI = $Host.UI.RawUI $RawUI.CursorPosition = @{X=0;Y=0} $RawUI.SetBufferContents( @{Top = -1; Bottom = -1; Right = -1; Left = -1}, @{Character = ' '; ForegroundColor = $rawui.ForegroundColor; BackgroundColor = $rawui.BackgroundColor}) # .Link # http://go.microsoft.com/fwlink/?LinkID=225747 # .ExternalHelp System.Management.Automation.dll-help.xml "; } else { // Porting note: non-Windows platforms use `clear` return "& (Get-Command -CommandType Application clear).Definition | Select-Object -First 1"; } } /// /// This is the default function to use for man/help. It uses /// splatting to pass in the parameters. /// internal static string GetHelpPagingFunctionText() { // We used to generate the text for this function so you could add a parameter // to Get-Help and not worry about adding it here. That was a little slow at // startup, so it's hard coded, with a test to make sure the parameters match. return @" <# .FORWARDHELPTARGETNAME Get-Help .FORWARDHELPCATEGORY Cmdlet #> [CmdletBinding(DefaultParameterSetName='AllUsersView', HelpUri='http://go.microsoft.com/fwlink/?LinkID=113316')] param( [Parameter(Position=0, ValueFromPipelineByPropertyName=$true)] [string] ${Name}, [string] ${Path}, [ValidateSet('Alias','Cmdlet','Provider','General','FAQ','Glossary','HelpFile','ScriptCommand','Function','Filter','ExternalScript','All','DefaultHelp','Workflow','DscResource','Class','Configuration')] [string[]] ${Category}, [string[]] ${Component}, [string[]] ${Functionality}, [string[]] ${Role}, [Parameter(ParameterSetName='DetailedView', Mandatory=$true)] [switch] ${Detailed}, [Parameter(ParameterSetName='AllUsersView')] [switch] ${Full}, [Parameter(ParameterSetName='Examples', Mandatory=$true)] [switch] ${Examples}, [Parameter(ParameterSetName='Parameters', Mandatory=$true)] [string] ${Parameter}, [Parameter(ParameterSetName='Online', Mandatory=$true)] [switch] ${Online}, [Parameter(ParameterSetName='ShowWindow', Mandatory=$true)] [switch] ${ShowWindow}) #Set the outputencoding to Console::OutputEncoding. More.com doesn't work well with Unicode. $outputEncoding=[System.Console]::OutputEncoding Get-Help @PSBoundParameters | more "; } internal static string GetMkdirFunctionText() { return @" <# .FORWARDHELPTARGETNAME New-Item .FORWARDHELPCATEGORY Cmdlet #> [CmdletBinding(DefaultParameterSetName='pathSet', SupportsShouldProcess=$true, SupportsTransactions=$true, ConfirmImpact='Medium')] [OutputType([System.IO.DirectoryInfo])] param( [Parameter(ParameterSetName='nameSet', Position=0, ValueFromPipelineByPropertyName=$true)] [Parameter(ParameterSetName='pathSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)] [System.String[]] ${Path}, [Parameter(ParameterSetName='nameSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [AllowNull()] [AllowEmptyString()] [System.String] ${Name}, [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [System.Object] ${Value}, [Switch] ${Force}, [Parameter(ValueFromPipelineByPropertyName=$true)] [System.Management.Automation.PSCredential] ${Credential} ) begin { try { $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('New-Item', [System.Management.Automation.CommandTypes]::Cmdlet) $scriptCmd = {& $wrappedCmd -Type Directory @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline() $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } } "; } internal static string GetGetVerbText() { return @" param( [Parameter(ValueFromPipeline=$true)] [string[]] $verb = '*' ) begin { $allVerbs = [System.Reflection.IntrospectionExtensions]::GetTypeInfo([PSObject]).Assembly.ExportedTypes | Microsoft.PowerShell.Core\Where-Object {$_.Name -match '^Verbs.'} | Microsoft.PowerShell.Utility\Get-Member -type Properties -static | Microsoft.PowerShell.Utility\Select-Object @{ Name='Verb' Expression = {$_.Name} }, @{ Name='Group' Expression = { $str = ""$($_.TypeName)"" $str.Substring($str.LastIndexOf('Verbs') + 5) } } } process { foreach ($v in $verb) { $allVerbs | Microsoft.PowerShell.Core\Where-Object { $_.Verb -like $v } } } # .Link # http://go.microsoft.com/fwlink/?LinkID=160712 # .ExternalHelp System.Management.Automation.dll-help.xml "; } internal static string GetOSTFunctionText() { return @" [CmdletBinding()] param( [ValidateRange(2, 2147483647)] [int] ${Width}, [Parameter(ValueFromPipeline=$true)] [psobject] ${InputObject}) begin { try { $PSBoundParameters['Stream'] = $true $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Out-String',[System.Management.Automation.CommandTypes]::Cmdlet) $scriptCmd = {& $wrappedCmd @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } } <# .ForwardHelpTargetName Out-String .ForwardHelpCategory Cmdlet #> "; } internal const ActionPreference defaultDebugPreference = ActionPreference.SilentlyContinue; internal const ActionPreference defaultErrorActionPreference = ActionPreference.Continue; internal const ActionPreference defaultProgressPreference = ActionPreference.Continue; internal const ActionPreference defaultVerbosePreference = ActionPreference.SilentlyContinue; internal const ActionPreference defaultWarningPreference = ActionPreference.Continue; internal const ActionPreference defaultInformationPreference = ActionPreference.SilentlyContinue; internal const bool defaultWhatIfPreference = false; internal const ConfirmImpact defaultConfirmPreference = ConfirmImpact.High; internal static SessionStateVariableEntry[] BuiltInVariables = new SessionStateVariableEntry[] { // Engine variables that should be precreated before running profile // Bug fix for Win7:2202228 Engine halts if initial command fulls up variable table // Anytime a new variable that the engine depends on to run is added, this table // must be updated... new SessionStateVariableEntry(SpecialVariables.LastToken, null, String.Empty), new SessionStateVariableEntry(SpecialVariables.FirstToken, null, String.Empty), new SessionStateVariableEntry(SpecialVariables.StackTrace, null, String.Empty), // Variable which controls the encoding for piping data to a NativeCommand new SessionStateVariableEntry( SpecialVariables.OutputEncoding, System.Text.Encoding.ASCII, RunspaceInit.OutputEncodingDescription, ScopedItemOptions.None, new ArgumentTypeConverterAttribute(typeof(System.Text.Encoding)) ), // Preferences // NTRAID#Windows Out Of Band Releases-931461-2006/03/13 // ArgumentTypeConverterAttribute is applied to these variables, // but this only reaches the global variable. If these are // redefined in script scope etc, the type conversion // is not applicable. // Variables typed to ActionPreference new SessionStateVariableEntry( SpecialVariables.ConfirmPreference, defaultConfirmPreference, RunspaceInit.ConfirmPreferenceDescription, ScopedItemOptions.None, new ArgumentTypeConverterAttribute(typeof(ConfirmImpact)) ), new SessionStateVariableEntry( SpecialVariables.DebugPreference, defaultDebugPreference, RunspaceInit.DebugPreferenceDescription, ScopedItemOptions.None, new ArgumentTypeConverterAttribute(typeof(ActionPreference)) ), new SessionStateVariableEntry( SpecialVariables.ErrorActionPreference, defaultErrorActionPreference, RunspaceInit.ErrorActionPreferenceDescription, ScopedItemOptions.None, new ArgumentTypeConverterAttribute(typeof(ActionPreference)) ), new SessionStateVariableEntry( SpecialVariables.ProgressPreference, defaultProgressPreference, RunspaceInit.ProgressPreferenceDescription, ScopedItemOptions.None, new ArgumentTypeConverterAttribute(typeof(ActionPreference)) ), new SessionStateVariableEntry( SpecialVariables.VerbosePreference, defaultVerbosePreference, RunspaceInit.VerbosePreferenceDescription, ScopedItemOptions.None, new ArgumentTypeConverterAttribute(typeof(ActionPreference)) ), new SessionStateVariableEntry( SpecialVariables.WarningPreference, defaultWarningPreference, RunspaceInit.WarningPreferenceDescription, ScopedItemOptions.None, new ArgumentTypeConverterAttribute(typeof(ActionPreference)) ), new SessionStateVariableEntry( SpecialVariables.InformationPreference, defaultInformationPreference, RunspaceInit.InformationPreferenceDescription, ScopedItemOptions.None, new ArgumentTypeConverterAttribute(typeof(ActionPreference)) ), new SessionStateVariableEntry( SpecialVariables.ErrorView, "NormalView", RunspaceInit.ErrorViewDescription ), new SessionStateVariableEntry( SpecialVariables.NestedPromptLevel, 0, RunspaceInit.NestedPromptLevelDescription ), new SessionStateVariableEntry( SpecialVariables.WhatIfPreference, defaultWhatIfPreference, RunspaceInit.WhatIfPreferenceDescription ), new SessionStateVariableEntry( FormatEnumerationLimit, DefaultFormatEnumerationLimit, RunspaceInit.FormatEnunmerationLimitDescription ), //variable for PSEmailServer new SessionStateVariableEntry( SpecialVariables.PSEmailServer, String.Empty, RunspaceInit.PSEmailServerDescription ), // Start: Variables which control remoting behavior new SessionStateVariableEntry( Microsoft.PowerShell.Commands.PSRemotingBaseCmdlet.DEFAULT_SESSION_OPTION, new System.Management.Automation.Remoting.PSSessionOption(), RemotingErrorIdStrings.PSDefaultSessionOptionDescription, ScopedItemOptions.None), new SessionStateVariableEntry( SpecialVariables.PSSessionConfigurationName, "http://schemas.microsoft.com/powershell/Microsoft.PowerShell", RemotingErrorIdStrings.PSSessionConfigurationName, ScopedItemOptions.None), new SessionStateVariableEntry( SpecialVariables.PSSessionApplicationName, "wsman", RemotingErrorIdStrings.PSSessionAppName, ScopedItemOptions.None), // End: Variables which control remoting behavior #region Platform new SessionStateVariableEntry( SpecialVariables.IsLinux, Platform.IsLinux, String.Empty, ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateVariableEntry( SpecialVariables.IsOSX, Platform.IsOSX, String.Empty, ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateVariableEntry( SpecialVariables.IsWindows, Platform.IsWindows, String.Empty, ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateVariableEntry( SpecialVariables.IsCore, Platform.IsCore, String.Empty, ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), #endregion }; /// /// Returns a new array of alias entries everytime it's called. This /// can't be static because the elements may be mutated in different session /// state objects so each session state must have a copy of the entry. /// internal static SessionStateAliasEntry[] BuiltInAliases { get { return new SessionStateAliasEntry[] { new SessionStateAliasEntry("foreach", "ForEach-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("%", "ForEach-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("where", "Where-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("?", "Where-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("clc", "Clear-Content", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("cli", "Clear-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("clp", "Clear-ItemProperty", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("clv", "Clear-Variable", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("cpi", "Copy-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("cvpa", "Convert-Path", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("dbp", "Disable-PSBreakpoint", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ebp", "Enable-PSBreakpoint", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("epal", "Export-Alias", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("epcsv", "Export-Csv", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("fl", "Format-List", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ft", "Format-Table", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("fw", "Format-Wide", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gal", "Get-Alias", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gbp", "Get-PSBreakpoint", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gc", "Get-Content", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gci", "Get-ChildItem", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gcm", "Get-Command", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gdr", "Get-PSDrive", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gcs", "Get-PSCallStack", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ghy", "Get-History", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gi", "Get-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gl", "Get-Location", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gm", "Get-Member", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gmo", "Get-Module", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gp", "Get-ItemProperty", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gpv", "Get-ItemPropertyValue", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gps", "Get-Process", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("group", "Group-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gsv", "Get-Service", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gu", "Get-Unique", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gv", "Get-Variable", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("iex", "Invoke-Expression", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ihy", "Invoke-History", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ii", "Invoke-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ipmo", "Import-Module", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ipal", "Import-Alias", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ipcsv", "Import-Csv", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("measure", "Measure-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("mi", "Move-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("mp", "Move-ItemProperty", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("nal", "New-Alias", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ndr", "New-PSDrive", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ni", "New-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("nv", "New-Variable", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("nmo", "New-Module", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("oh", "Out-Host", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rbp", "Remove-PSBreakpoint", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rdr", "Remove-PSDrive", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ri", "Remove-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rni", "Rename-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rnp", "Rename-ItemProperty", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rp", "Remove-ItemProperty", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rmo", "Remove-Module", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rv", "Remove-Variable", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rvpa", "Resolve-Path", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sal", "Set-Alias", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sasv", "Start-Service", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sbp", "Set-PSBreakpoint", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sc", "Set-Content", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), // this conflicts with sd.exe, and makes msh unusable by dev. // new SessionStateAliasEntry("sd", // "Set-Date", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.Constant | ScopedItemOptions.AllScope), new SessionStateAliasEntry("select", "Select-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("si", "Set-Item", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sl", "Set-Location", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sp", "Set-ItemProperty", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("saps", "Start-Process", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("spps", "Stop-Process", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("spsv", "Stop-Service", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sv", "Set-Variable", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), // Porting note: #if !LINUX is used to disable alises for cmdlets which conflict with Linux / OS X #if !LINUX // ac is a native command on OS X new SessionStateAliasEntry("ac", "Add-Content", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("compare", "Compare-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("cpp", "Copy-ItemProperty", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("diff", "Compare-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sleep", "Start-Sleep", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("sort", "Sort-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("start", "Start-Process", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("tee", "Tee-Object", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("write", "Write-Output", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), // These were traqnsferred from the "transferred from the profile" section new SessionStateAliasEntry("cat", "Get-Content", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("cp", "Copy-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("ls", "Get-ChildItem", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("man", "help", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("mount", "New-PSDrive", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("mv", "Move-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("ps", "Get-Process", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("rm", "Remove-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("rmdir", "Remove-Item", "", ScopedItemOptions.AllScope), #endif // Bash built-ins we purposefully keep even if they override native commands new SessionStateAliasEntry("cd", "Set-Location", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("dir", "Get-ChildItem", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("echo", "Write-Output", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("fc", "Format-Custom", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("kill", "Stop-Process", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("pwd", "Get-Location", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("type", "Get-Content", "", ScopedItemOptions.AllScope), // Native commands we keep because the functions act correctly on Linux new SessionStateAliasEntry("clear", "Clear-Host", "", ScopedItemOptions.AllScope), //#if !CORECLR is used to disable aliases for cmdlets which are not available on OneCore #if !CORECLR new SessionStateAliasEntry("asnp", "Add-PSSnapIn", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gsnp", "Get-PSSnapIn", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("gwmi", "Get-WmiObject", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("irm", "Invoke-RestMethod", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("iwr", "Invoke-WebRequest", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("iwmi", "Invoke-WMIMethod", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ogv", "Out-GridView", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ise", "powershell_ise.exe", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rsnp", "Remove-PSSnapin", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("rwmi", "Remove-WMIObject", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("swmi", "Set-WMIInstance", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("shcm", "Show-Command", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("trcm", "Trace-Command", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("wget", "Invoke-WebRequest", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("curl", "Invoke-WebRequest", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("lp", "Out-Printer", "", ScopedItemOptions.AllScope), #endif // Aliases transferred from the profile new SessionStateAliasEntry("h", "Get-History", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("history", "Get-History", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("md", "mkdir", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("popd", "Pop-Location", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("pushd", "Push-Location", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("r", "Invoke-History", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("cls", "Clear-Host", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("chdir", "Set-Location", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("copy", "Copy-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("del", "Remove-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("erase", "Remove-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("move", "Move-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("rd", "Remove-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("ren", "Rename-Item", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("set", "Set-Variable", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("icm", "Invoke-Command", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("clhy", "Clear-History", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), // Job Specific aliases new SessionStateAliasEntry("gjb", "Get-Job", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("rcjb", "Receive-Job", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("rjb", "Remove-Job", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("sajb", "Start-Job", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("spjb", "Stop-Job", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("wjb", "Wait-Job", "", ScopedItemOptions.AllScope), #if !CORECLR new SessionStateAliasEntry("sujb", "Suspend-Job", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("rujb", "Resume-Job", "", ScopedItemOptions.AllScope), // Remoting Cmdlets Specific aliases new SessionStateAliasEntry("npssc", "New-PSSessionConfigurationFile", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("ipsn", "Import-PSSession", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("epsn", "Export-PSSession", "", ScopedItemOptions.AllScope), #endif new SessionStateAliasEntry("cnsn", "Connect-PSSession", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("dnsn", "Disconnect-PSSession","", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("nsn", "New-PSSession", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("gsn", "Get-PSSession", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("rsn", "Remove-PSSession", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("etsn", "Enter-PSSession", "", ScopedItemOptions.AllScope), new SessionStateAliasEntry("rcsn", "Receive-PSSession", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope), new SessionStateAliasEntry("exsn", "Exit-PSSession", "", ScopedItemOptions.AllScope), // Win8: 121662/169179 Add "sls" alias for Select-String cmdlet // - do not use AllScope - this causes errors in profiles that set this somewhat commonly used alias. new SessionStateAliasEntry("sls", "Select-String", "", ScopedItemOptions.None), }; } } internal const string DefaultPromptFunctionText = @" ""PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ""; # .Link # http://go.microsoft.com/fwlink/?LinkID=225750 # .ExternalHelp System.Management.Automation.dll-help.xml "; internal const string DefaultMoreFunctionText = @" param([string[]]$paths) # Nano needs to use Unicode, but Windows and Linux need the default $OutputEncoding = if ($IsWindows -and $IsCore) { [System.Text.Encoding]::Unicode } else { [System.Console]::OutputEncoding } # Respect PAGER, use more on Windows, and use less on Linux if (Test-Path env:PAGER) { $moreCommand = (Get-Command -CommandType Application $env:PAGER).Definition | Select-Object -First 1 } elseif ($IsWindows) { $moreCommand = (Get-Command -CommandType Application more).Definition | Select-Object -First 1 } else { $moreCommand = (Get-Command -CommandType Application less).Definition | Select-Object -First 1 } if($paths) { foreach ($file in $paths) { Get-Content $file | & $moreCommand } } else { $input | & $moreCommand } "; internal const string DefaultSetDriveFunctionText = "Set-Location $MyInvocation.MyCommand.Name"; internal static ScriptBlock SetDriveScriptBlock = ScriptBlock.CreateDelayParsedScriptBlock(DefaultSetDriveFunctionText, isProductCode: true); internal static SessionStateFunctionEntry[] BuiltInFunctions = new SessionStateFunctionEntry[] { // Functions. Only the name and definitions are used SessionStateFunctionEntry.GetDelayParsedFunctionEntry("prompt", DefaultPromptFunctionText, isProductCode: true), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("TabExpansion2", TabExpansionFunctionText, isProductCode: true), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("Clear-Host", GetClearHostFunctionText(), isProductCode: true), // Porting note: we keep more because the function acts correctly on Linux SessionStateFunctionEntry.GetDelayParsedFunctionEntry("more", DefaultMoreFunctionText, isProductCode: true), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("help", GetHelpPagingFunctionText(), isProductCode: true), // Porting note: we remove mkdir on Linux because it is a conflict #if !LINUX SessionStateFunctionEntry.GetDelayParsedFunctionEntry("mkdir", GetMkdirFunctionText(), isProductCode: true), #endif SessionStateFunctionEntry.GetDelayParsedFunctionEntry("Get-Verb", GetGetVerbText(), isProductCode: true), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("oss", GetOSTFunctionText(), isProductCode: true), // Porting note: we remove the drive functions from Linux because they make no sense #if !LINUX // Default drives SessionStateFunctionEntry.GetDelayParsedFunctionEntry("A:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("B:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("C:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("D:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("E:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("F:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("G:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("H:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("I:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("J:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("K:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("L:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("M:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("N:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("O:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("P:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("Q:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("R:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("S:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("T:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("U:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("V:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("W:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("X:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("Y:", DefaultSetDriveFunctionText, SetDriveScriptBlock), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("Z:", DefaultSetDriveFunctionText, SetDriveScriptBlock), #endif SessionStateFunctionEntry.GetDelayParsedFunctionEntry("cd..", "Set-Location ..", isProductCode: true), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("cd\\", "Set-Location \\", isProductCode: true), // Win8: 320909. Retaining the original definition to ensure backward compatability. SessionStateFunctionEntry.GetDelayParsedFunctionEntry("ImportSystemModules", ImportSystemModulesText, isProductCode: true), SessionStateFunctionEntry.GetDelayParsedFunctionEntry("Pause", string.Concat("$null = Read-Host '", CodeGeneration.EscapeSingleQuotedStringContent(RunspaceInit.PauseDefinitionString),"'"), isProductCode: true) }; static internal void RemoveAllDrivesForProvider(ProviderInfo pi, SessionStateInternal ssi) { foreach (PSDriveInfo di in ssi.GetDrivesForProvider(pi.FullName)) { try { ssi.RemoveDrive(di, true, null); } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); } } } static private PSTraceSource _PSSnapInTracer = PSTraceSource.GetTracer("PSSnapInLoadUnload", "Loading and unloading mshsnapins", false); internal static string CoreSnapin = "Microsoft.PowerShell.Core"; internal static string CoreModule = "Microsoft.PowerShell.Core"; internal Collection defaultSnapins = new Collection(); // The list of engine modules to create warnings when you try to remove them internal static HashSet EngineModules = new HashSet(StringComparer.OrdinalIgnoreCase) { "Microsoft.PowerShell.Utility", "Microsoft.PowerShell.Management", "Microsoft.PowerShell.Diagnostics", "Microsoft.PowerShell.Host", "Microsoft.PowerShell.Security", "Microsoft.WSMan.Management" }; static internal HashSet NestedEngineModules = new HashSet(StringComparer.OrdinalIgnoreCase) { "Microsoft.PowerShell.Commands.Utility", "Microsoft.PowerShell.Commands.Management", "Microsoft.PowerShell.Commands.Diagnostics", "Microsoft.PowerShell.ConsoleHost" }; internal static Dictionary EngineModuleNestedModuleMapping = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Microsoft.PowerShell.Utility", "Microsoft.PowerShell.Commands.Utility"}, { "Microsoft.PowerShell.Management", "Microsoft.PowerShell.Commands.Management"}, { "Microsoft.PowerShell.Diagnostics", "Microsoft.PowerShell.Commands.Diagnostics"}, { "Microsoft.PowerShell.Host", "Microsoft.PowerShell.ConsoleHost"}, }; internal static Dictionary NestedModuleEngineModuleMapping = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Microsoft.PowerShell.Commands.Utility", "Microsoft.PowerShell.Utility"}, { "Microsoft.PowerShell.Commands.Management", "Microsoft.PowerShell.Management"}, { "Microsoft.PowerShell.Commands.Diagnostics", "Microsoft.PowerShell.Diagnostics"}, { "Microsoft.PowerShell.ConsoleHost", "Microsoft.PowerShell.Host"}, { "Microsoft.PowerShell.Security", "Microsoft.PowerShell.Security"}, { "Microsoft.WSMan.Management", "Microsoft.WSMan.Management"}, }; // The list of engine modules that we will not allow users to remove internal static HashSet ConstantEngineModules = new HashSet(StringComparer.OrdinalIgnoreCase) { CoreModule, }; // The list of nested engine modules that we will not allow users to remove internal static HashSet ConstantEngineNestedModules = new HashSet(StringComparer.OrdinalIgnoreCase) { "System.Management.Automation", }; internal static string GetNestedModuleDllName(string moduleName) { string result = null; if (!EngineModuleNestedModuleMapping.TryGetValue(moduleName, out result)) { result = string.Empty; } return result; } internal void SaveAsConsoleFile(string path) { if (null == path) { throw PSTraceSource.NewArgumentNullException("path"); } if (!path.EndsWith(StringLiterals.PowerShellConsoleFileExtension, StringComparison.OrdinalIgnoreCase)) { throw PSTraceSource.NewArgumentException("path", ConsoleInfoErrorStrings.BadConsoleExtension); } //ConsoleFileElement will write to file PSConsoleFileElement.WriteToFile(path, PSVersionInfo.PSVersion, this.ImportedSnapins.Values); } } /// /// Set of helper methods fro loading assemblies containing cmdlets... /// internal static class PSSnapInHelpers { [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom")] internal static Assembly LoadPSSnapInAssembly(PSSnapInInfo psSnapInInfo, out Dictionary cmdlets, out Dictionary providers) { Assembly assembly = null; cmdlets = null; providers = null; _PSSnapInTracer.WriteLine("Loading assembly from GAC. Assembly Name: {0}", psSnapInInfo.AssemblyName); try { // WARNING: DUPLICATE CODE see RunspaceConfigForSingleShell assembly = ClrFacade.Load(new AssemblyName(psSnapInInfo.AssemblyName)); } catch (BadImageFormatException e) { _PSSnapInTracer.TraceWarning("Not able to load assembly {0}: {1}", psSnapInInfo.AssemblyName, e.Message); } catch (FileNotFoundException e) { _PSSnapInTracer.TraceWarning("Not able to load assembly {0}: {1}", psSnapInInfo.AssemblyName, e.Message); } catch (FileLoadException e) { _PSSnapInTracer.TraceWarning("Not able to load assembly {0}: {1}", psSnapInInfo.AssemblyName, e.Message); } if (assembly != null) return assembly; _PSSnapInTracer.WriteLine("Loading assembly from path: {0}", psSnapInInfo.AssemblyName); try { AssemblyName assemblyName = ClrFacade.GetAssemblyName(psSnapInInfo.AbsoluteModulePath); // Porting note: the snapins still require 'ProcessorArchitecture=MSIL' in // the strong name, which is not in the strong name of assemblies created // by dotnet-cli if (!Platform.IsCore && !string.Equals(assemblyName.FullName, psSnapInInfo.AssemblyName, StringComparison.OrdinalIgnoreCase)) { string message = StringUtil.Format(ConsoleInfoErrorStrings.PSSnapInAssemblyNameMismatch, psSnapInInfo.AbsoluteModulePath, psSnapInInfo.AssemblyName); _PSSnapInTracer.TraceError(message); throw new PSSnapInException(psSnapInInfo.Name, message); } assembly = ClrFacade.LoadFrom(psSnapInInfo.AbsoluteModulePath); } catch (FileLoadException e) { _PSSnapInTracer.TraceError("Not able to load assembly {0}: {1}", psSnapInInfo.AssemblyName, e.Message); throw new PSSnapInException(psSnapInInfo.Name, e.Message); } catch (BadImageFormatException e) { _PSSnapInTracer.TraceError("Not able to load assembly {0}: {1}", psSnapInInfo.AssemblyName, e.Message); throw new PSSnapInException(psSnapInInfo.Name, e.Message); } catch (FileNotFoundException e) { _PSSnapInTracer.TraceError("Not able to load assembly {0}: {1}", psSnapInInfo.AssemblyName, e.Message); throw new PSSnapInException(psSnapInInfo.Name, e.Message); } return assembly; } private static T GetCustomAttribute(TypeInfo decoratedType) where T : Attribute { var attributes = CustomAttributeExtensions.GetCustomAttributes(decoratedType, false); var customAttrs = attributes.ToArray(); Debug.Assert(customAttrs.Length <= 1, "CmdletAttribute and/or CmdletProviderAttribute cannot normally appear more than once"); return customAttrs.Length == 0 ? null : customAttrs[0]; } internal static void AnalyzePSSnapInAssembly(Assembly assembly, string name, PSSnapInInfo psSnapInInfo, PSModuleInfo moduleInfo, bool isModuleLoad, out Dictionary cmdlets, out Dictionary> aliases, out Dictionary providers, out string helpFile) { helpFile = null; if (assembly == null) { throw new ArgumentNullException("assembly"); } cmdlets = null; aliases = null; providers = null; // See if this assembly has already been scanned... Dictionary>> cachedCmdlets; if (_cmdletCache.Value.TryGetValue(assembly, out cachedCmdlets)) { cmdlets = new Dictionary(_cmdletCache.Value.Count, StringComparer.OrdinalIgnoreCase); aliases = new Dictionary>(StringComparer.OrdinalIgnoreCase); foreach (var pair in cachedCmdlets) { var key = pair.Key; var entry = pair.Value; if (entry.Item1.PSSnapIn == null && psSnapInInfo != null) { entry.Item1.SetPSSnapIn(psSnapInInfo); } var newEntry = (SessionStateCmdletEntry)entry.Item1.Clone(); if (newEntry.PSSnapIn != null && psSnapInInfo == null) { newEntry.SetPSSnapIn(null); } cmdlets[key] = newEntry; if (entry.Item2 != null) { var aliasList = new List(); foreach (var alias in entry.Item2) { if (alias.PSSnapIn == null && psSnapInInfo != null) { alias.SetPSSnapIn(psSnapInInfo); } var newAliasEntry = (SessionStateAliasEntry) alias.Clone(); if (newAliasEntry.PSSnapIn != null && psSnapInInfo == null) { newAliasEntry.SetPSSnapIn(null); } aliasList.Add(newAliasEntry); } aliases[key] = aliasList; } } } Dictionary cachedProviders; if (_providerCache.Value.TryGetValue(assembly, out cachedProviders)) { providers = new Dictionary(_providerCache.Value.Count, StringComparer.OrdinalIgnoreCase); foreach (var pair in cachedProviders) { var key = pair.Key; var entry = pair.Value; if (entry.PSSnapIn == null && psSnapInInfo != null) { entry.SetPSSnapIn(psSnapInInfo); } var newEntry = (SessionStateProviderEntry)entry.Clone(); if (newEntry.PSSnapIn != null && psSnapInInfo == null) { newEntry.SetPSSnapIn(null); } providers[key] = newEntry; } } string assemblyPath = assembly.Location; Type[] assemblyTypes; if (cmdlets != null || providers != null) { if (!_assembliesWithModuleInitializerCache.Value.ContainsKey(assembly)) { _PSSnapInTracer.WriteLine("Returning cached cmdlet and provider entries for {0}", assemblyPath); return; } else { _PSSnapInTracer.WriteLine("Executing IModuleAssemblyInitializer.Import for {0}", assemblyPath); assemblyTypes = GetAssemblyTypes(assembly, name); ExecuteModuleInitializer(assembly, assemblyTypes, isModuleLoad); return; } } _PSSnapInTracer.WriteLine("Analyzing assembly {0} for cmdlet and providers", assemblyPath); helpFile = GetHelpFile(assemblyPath); Type randomCmdletToCheckLinkDemand = null; Type randomProviderToCheckLinkDemand = null; if (psSnapInInfo != null && psSnapInInfo.Name.Equals(InitialSessionState.CoreSnapin, StringComparison.OrdinalIgnoreCase)) { InitializeCoreCmdletsAndProviders(psSnapInInfo, out cmdlets, out providers, helpFile); #if DEBUG // Make sure the pre-built cmdlet and provider tables match what reflection finds. This will help // avoid issues where you add a cmdlet but forget to update the table in InitializeCoreCmdletsAndProviders. Dictionary cmdletsCheck = null; Dictionary providersCheck = null; Dictionary> aliasesCheck = null; Type unused1 = null; Type unused2 = null; AnalyzeModuleAssemblyWithReflection(assembly, name, psSnapInInfo, moduleInfo, isModuleLoad, ref cmdletsCheck, ref aliasesCheck, ref providersCheck, helpFile, ref unused1, ref unused2); Diagnostics.Assert(aliasesCheck == null, "InitializeCoreCmdletsAndProviders assumes no aliases are defined in System.Management.Automation.dll"); Diagnostics.Assert(providersCheck.Keys.Count == providers.Keys.Count, "new Provider added to System.Management.Automation.dll - update InitializeCoreCmdletsAndProviders"); foreach (var pair in providersCheck) { SessionStateProviderEntry other; if (providers.TryGetValue(pair.Key, out other)) { Diagnostics.Assert((object)pair.Value.HelpFileName == (object)other.HelpFileName, "Pre-generated Provider help file incorrect"); Diagnostics.Assert(pair.Value.ImplementingType == other.ImplementingType, "Pre-generated Provider implementing type incorrect"); Diagnostics.Assert(string.Equals(pair.Value.Name, other.Name, StringComparison.Ordinal), "Pre-generated Provider name incorrect"); Diagnostics.Assert(pair.Value.PSSnapIn == other.PSSnapIn, "Pre-generated Provider snappin type incorrect"); Diagnostics.Assert(pair.Value.Module == other.Module, "Pre-generated Provider module incorrect"); Diagnostics.Assert(pair.Value.Visibility == other.Visibility, "Pre-generated Provider visibility incorrect"); } else { Diagnostics.Assert(false, "Missing provider: " + pair.Key); } } Diagnostics.Assert(cmdletsCheck.Keys.Count == cmdlets.Keys.Count, "new Cmdlet added to System.Management.Automation.dll - update InitializeCoreCmdletsAndProviders"); foreach (var pair in cmdletsCheck) { SessionStateCmdletEntry other; if (cmdlets.TryGetValue(pair.Key, out other)) { Diagnostics.Assert((object)pair.Value.HelpFileName == (object)other.HelpFileName, "Pre-generated Provider help file incorrect"); Diagnostics.Assert(pair.Value.ImplementingType == other.ImplementingType, "Pre-generated Provider implementing type incorrect"); Diagnostics.Assert(string.Equals(pair.Value.Name, other.Name, StringComparison.Ordinal), "Pre-generated Provider name incorrect"); Diagnostics.Assert(pair.Value.PSSnapIn == other.PSSnapIn, "Pre-generated Provider snappin type incorrect"); Diagnostics.Assert(pair.Value.Module == other.Module, "Pre-generated Provider module incorrect"); Diagnostics.Assert(pair.Value.Visibility == other.Visibility, "Pre-generated Provider visibility incorrect"); } else { Diagnostics.Assert(false, "Pre-generated Cmdlet missing: " + pair.Key); } } #endif } else { AnalyzeModuleAssemblyWithReflection(assembly, name, psSnapInInfo, moduleInfo, isModuleLoad, ref cmdlets, ref aliases, ref providers, helpFile, ref randomCmdletToCheckLinkDemand, ref randomProviderToCheckLinkDemand); } // force a LinkDemand check to get an explicit exception if // Cmdlet[Provider]Attributes are silently swallowed by Type.GetCustomAttributes // bug Win7:705573 if ((providers == null || providers.Count == 0) && (cmdlets == null || cmdlets.Count == 0)) { try { if (randomCmdletToCheckLinkDemand != null) { ConstructorInfo constructor = randomCmdletToCheckLinkDemand.GetConstructor(PSTypeExtensions.EmptyTypes); if (constructor != null) { constructor.Invoke(null); // this is how we artificially force a LinkDemand check } } if (randomProviderToCheckLinkDemand != null) { ConstructorInfo constructor = randomProviderToCheckLinkDemand.GetConstructor(PSTypeExtensions.EmptyTypes); if (constructor != null) { constructor.Invoke(null); // this is how we artificially force a LinkDemand check } } } catch (TargetInvocationException e) { throw e.InnerException; } } // Cache the cmdlet and provider info for this assembly... // We need to cache a clone of this data *before* the // module info is set on it since module info can't be shared // across runspaces. When these entries are hit in the cache, // copies will be returned to ensure that the cache is never tied to a runspace. if (cmdlets != null) { var clone = new Dictionary>>(cmdlets.Count, StringComparer.OrdinalIgnoreCase); List aliasesCloneList = null; foreach (var entry in cmdlets) { List aliasEntries; if (aliases != null && aliases.TryGetValue(entry.Key, out aliasEntries)) { aliasesCloneList = new List(aliases.Count); foreach (var aliasEntry in aliasEntries) { aliasesCloneList.Add((SessionStateAliasEntry)aliasEntry.Clone()); } } clone[entry.Key] = new Tuple>((SessionStateCmdletEntry)entry.Value.Clone(), aliasesCloneList); } _cmdletCache.Value[assembly] = clone; } if (providers != null) { var clone = new Dictionary(providers.Count, StringComparer.OrdinalIgnoreCase); foreach (var entry in providers) { clone[entry.Key] = (SessionStateProviderEntry) entry.Value.Clone(); } _providerCache.Value[assembly] = providers; } } private static void AnalyzeModuleAssemblyWithReflection(Assembly assembly, string name, PSSnapInInfo psSnapInInfo, PSModuleInfo moduleInfo, bool isModuleLoad, ref Dictionary cmdlets, ref Dictionary> aliases, ref Dictionary providers, string helpFile, ref Type randomCmdletToCheckLinkDemand, ref Type randomProviderToCheckLinkDemand) { var assemblyTypes = GetAssemblyTypes(assembly, name); ExecuteModuleInitializer(assembly, assemblyTypes, isModuleLoad); foreach (Type type in assemblyTypes) { var typeInfo = type.GetTypeInfo(); if (!(typeInfo.IsPublic || typeInfo.IsNestedPublic) || typeInfo.IsAbstract) continue; // Check for cmdlets if (IsCmdletClass(type) && HasDefaultConstructor(type)) { randomCmdletToCheckLinkDemand = type; CmdletAttribute cmdletAttribute = GetCustomAttribute(typeInfo); if (cmdletAttribute == null) { continue; } string cmdletName = GetCmdletName(cmdletAttribute); if (string.IsNullOrEmpty(cmdletName)) { continue; } if (cmdlets != null && cmdlets.ContainsKey(cmdletName)) { string message = StringUtil.Format(ConsoleInfoErrorStrings.PSSnapInDuplicateCmdlets, cmdletName, name); _PSSnapInTracer.TraceError(message); throw new PSSnapInException(name, message); } SessionStateCmdletEntry cmdlet = new SessionStateCmdletEntry(cmdletName, type, helpFile); cmdlet.SetPSSnapIn(psSnapInInfo); if (cmdlets == null) { cmdlets = new Dictionary(StringComparer.OrdinalIgnoreCase); } cmdlets.Add(cmdletName, cmdlet); var aliasAttribute = GetCustomAttribute(typeInfo); if (aliasAttribute != null) { if (aliases == null) { aliases = new Dictionary>(StringComparer.OrdinalIgnoreCase); } var aliasList = new List(); foreach (var alias in aliasAttribute.AliasNames) { var aliasEntry = new SessionStateAliasEntry(alias, cmdletName, "", ScopedItemOptions.None); if (psSnapInInfo != null) { aliasEntry.SetPSSnapIn(psSnapInInfo); } aliasList.Add(aliasEntry); } aliases.Add(cmdletName, aliasList); } _PSSnapInTracer.WriteLine("{0} from type {1} is added as a cmdlet. ", cmdletName, type.FullName); continue; } // Check for providers if (IsProviderClass(type) && HasDefaultConstructor(type)) { randomProviderToCheckLinkDemand = type; CmdletProviderAttribute providerAttribute = GetCustomAttribute(typeInfo); if (providerAttribute == null) { continue; } string providerName = GetProviderName(providerAttribute); if (string.IsNullOrEmpty(providerName)) { continue; } if (providers != null && providers.ContainsKey(providerName)) { string message = StringUtil.Format(ConsoleInfoErrorStrings.PSSnapInDuplicateProviders, providerName, psSnapInInfo.Name); _PSSnapInTracer.TraceError(message); throw new PSSnapInException(psSnapInInfo.Name, message); } SessionStateProviderEntry provider = new SessionStateProviderEntry(providerName, type, helpFile); provider.SetPSSnapIn(psSnapInInfo); // After converting core snapins to load as modules, the providers will have Module property populated if (moduleInfo != null) { provider.SetModule(moduleInfo); } if (providers == null) { providers = new Dictionary(StringComparer.OrdinalIgnoreCase); } providers.Add(providerName, provider); _PSSnapInTracer.WriteLine("{0} from type {1} is added as a provider. ", providerName, type.FullName); } } } private static void InitializeCoreCmdletsAndProviders( PSSnapInInfo psSnapInInfo, out Dictionary cmdlets, out Dictionary providers, string helpFile) { cmdlets = new Dictionary(StringComparer.OrdinalIgnoreCase) { {"Add-History", new SessionStateCmdletEntry("Add-History", typeof(AddHistoryCommand), helpFile) }, {"Clear-History", new SessionStateCmdletEntry("Clear-History", typeof(ClearHistoryCommand), helpFile) }, {"Connect-PSSession", new SessionStateCmdletEntry("Connect-PSSession", typeof(ConnectPSSessionCommand), helpFile) }, {"Debug-Job", new SessionStateCmdletEntry("Debug-Job", typeof(DebugJobCommand), helpFile) }, {"Disable-PSSessionConfiguration", new SessionStateCmdletEntry("Disable-PSSessionConfiguration", typeof(DisablePSSessionConfigurationCommand), helpFile) }, {"Disconnect-PSSession", new SessionStateCmdletEntry("Disconnect-PSSession", typeof(DisconnectPSSessionCommand), helpFile) }, {"Enable-PSSessionConfiguration", new SessionStateCmdletEntry("Enable-PSSessionConfiguration", typeof(EnablePSSessionConfigurationCommand), helpFile) }, {"Enter-PSHostProcess", new SessionStateCmdletEntry("Enter-PSHostProcess", typeof(EnterPSHostProcessCommand), helpFile) }, {"Enter-PSSession", new SessionStateCmdletEntry("Enter-PSSession", typeof(EnterPSSessionCommand), helpFile) }, {"Exit-PSHostProcess", new SessionStateCmdletEntry("Exit-PSHostProcess", typeof(ExitPSHostProcessCommand), helpFile) }, {"Exit-PSSession", new SessionStateCmdletEntry("Exit-PSSession", typeof(ExitPSSessionCommand), helpFile) }, {"Export-ModuleMember", new SessionStateCmdletEntry("Export-ModuleMember", typeof(ExportModuleMemberCommand), helpFile) }, {"ForEach-Object", new SessionStateCmdletEntry("ForEach-Object", typeof(ForEachObjectCommand), helpFile) }, {"Get-Command", new SessionStateCmdletEntry("Get-Command", typeof(GetCommandCommand), helpFile) }, {"Get-Help", new SessionStateCmdletEntry("Get-Help", typeof(GetHelpCommand), helpFile) }, {"Get-History", new SessionStateCmdletEntry("Get-History", typeof(GetHistoryCommand), helpFile) }, {"Get-Job", new SessionStateCmdletEntry("Get-Job", typeof(GetJobCommand), helpFile) }, {"Get-Module", new SessionStateCmdletEntry("Get-Module", typeof(GetModuleCommand), helpFile) }, {"Get-PSHostProcessInfo", new SessionStateCmdletEntry("Get-PSHostProcessInfo", typeof(GetPSHostProcessInfoCommand), helpFile) }, {"Get-PSSession", new SessionStateCmdletEntry("Get-PSSession", typeof(GetPSSessionCommand), helpFile) }, {"Get-PSSessionCapability", new SessionStateCmdletEntry("Get-PSSessionCapability", typeof(GetPSSessionCapabilityCommand), helpFile) }, {"Get-PSSessionConfiguration", new SessionStateCmdletEntry("Get-PSSessionConfiguration", typeof(GetPSSessionConfigurationCommand), helpFile) }, {"Import-Module", new SessionStateCmdletEntry("Import-Module", typeof(ImportModuleCommand), helpFile) }, {"Invoke-Command", new SessionStateCmdletEntry("Invoke-Command", typeof(InvokeCommandCommand), helpFile) }, {"Invoke-History", new SessionStateCmdletEntry("Invoke-History", typeof(InvokeHistoryCommand), helpFile) }, {"New-Module", new SessionStateCmdletEntry("New-Module", typeof(NewModuleCommand), helpFile) }, {"New-ModuleManifest", new SessionStateCmdletEntry("New-ModuleManifest", typeof(NewModuleManifestCommand), helpFile) }, {"New-PSRoleCapabilityFile", new SessionStateCmdletEntry("New-PSRoleCapabilityFile", typeof(NewPSRoleCapabilityFileCommand), helpFile) }, {"New-PSSession", new SessionStateCmdletEntry("New-PSSession", typeof(NewPSSessionCommand), helpFile) }, {"New-PSSessionConfigurationFile", new SessionStateCmdletEntry("New-PSSessionConfigurationFile", typeof(NewPSSessionConfigurationFileCommand), helpFile) }, {"New-PSSessionOption", new SessionStateCmdletEntry("New-PSSessionOption", typeof(NewPSSessionOptionCommand), helpFile) }, {"New-PSTransportOption", new SessionStateCmdletEntry("New-PSTransportOption", typeof(NewPSTransportOptionCommand), helpFile) }, {"Out-Default", new SessionStateCmdletEntry("Out-Default", typeof(OutDefaultCommand), helpFile) }, {"Out-Host", new SessionStateCmdletEntry("Out-Host", typeof(OutHostCommand), helpFile) }, {"Out-Null", new SessionStateCmdletEntry("Out-Null", typeof(OutNullCommand), helpFile) }, {"Receive-Job", new SessionStateCmdletEntry("Receive-Job", typeof(ReceiveJobCommand), helpFile) }, {"Receive-PSSession", new SessionStateCmdletEntry("Receive-PSSession", typeof(ReceivePSSessionCommand), helpFile) }, {"Register-ArgumentCompleter", new SessionStateCmdletEntry("Register-ArgumentCompleter", typeof(RegisterArgumentCompleterCommand), helpFile) }, {"Register-PSSessionConfiguration", new SessionStateCmdletEntry("Register-PSSessionConfiguration", typeof(RegisterPSSessionConfigurationCommand), helpFile) }, {"Remove-Job", new SessionStateCmdletEntry("Remove-Job", typeof(RemoveJobCommand), helpFile) }, {"Remove-Module", new SessionStateCmdletEntry("Remove-Module", typeof(RemoveModuleCommand), helpFile) }, {"Remove-PSSession", new SessionStateCmdletEntry("Remove-PSSession", typeof(RemovePSSessionCommand), helpFile) }, {"Save-Help", new SessionStateCmdletEntry("Save-Help", typeof(SaveHelpCommand), helpFile) }, {"Set-PSDebug", new SessionStateCmdletEntry("Set-PSDebug", typeof(SetPSDebugCommand), helpFile) }, {"Set-PSSessionConfiguration", new SessionStateCmdletEntry("Set-PSSessionConfiguration", typeof(SetPSSessionConfigurationCommand), helpFile) }, {"Set-StrictMode", new SessionStateCmdletEntry("Set-StrictMode", typeof(SetStrictModeCommand), helpFile) }, {"Start-Job", new SessionStateCmdletEntry("Start-Job", typeof(StartJobCommand), helpFile) }, {"Stop-Job", new SessionStateCmdletEntry("Stop-Job", typeof(StopJobCommand), helpFile) }, {"Test-ModuleManifest", new SessionStateCmdletEntry("Test-ModuleManifest", typeof(TestModuleManifestCommand), helpFile) }, {"Test-PSSessionConfigurationFile", new SessionStateCmdletEntry("Test-PSSessionConfigurationFile", typeof(TestPSSessionConfigurationFileCommand), helpFile) }, {"Unregister-PSSessionConfiguration", new SessionStateCmdletEntry("Unregister-PSSessionConfiguration", typeof(UnregisterPSSessionConfigurationCommand), helpFile) }, {"Update-Help", new SessionStateCmdletEntry("Update-Help", typeof(UpdateHelpCommand), helpFile) }, {"Wait-Job", new SessionStateCmdletEntry("Wait-Job", typeof(WaitJobCommand), helpFile) }, {"Where-Object", new SessionStateCmdletEntry("Where-Object", typeof(WhereObjectCommand), helpFile) }, #if !CORECLR {"Add-PSSnapin", new SessionStateCmdletEntry("Add-PSSnapin", typeof(AddPSSnapinCommand), helpFile) }, {"Disable-PSRemoting", new SessionStateCmdletEntry("Disable-PSRemoting", typeof(DisablePSRemotingCommand), helpFile) }, {"Enable-PSRemoting", new SessionStateCmdletEntry("Enable-PSRemoting", typeof(EnablePSRemotingCommand), helpFile) }, {"Export-Console", new SessionStateCmdletEntry("Export-Console", typeof(ExportConsoleCommand), helpFile) }, {"Get-PSSnapin", new SessionStateCmdletEntry("Get-PSSnapin", typeof(GetPSSnapinCommand), helpFile) }, {"Remove-PSSnapin", new SessionStateCmdletEntry("Remove-PSSnapin", typeof(RemovePSSnapinCommand), helpFile) }, {"Resume-Job", new SessionStateCmdletEntry("Resume-Job", typeof(ResumeJobCommand), helpFile) }, {"Suspend-Job", new SessionStateCmdletEntry("Suspend-Job", typeof(SuspendJobCommand), helpFile) }, #endif // Not exported, but are added via reflection so added here as well, though maybe they shouldn't be {"Out-LineOutput", new SessionStateCmdletEntry("Out-LineOutput", typeof(OutLineOutputCommand), helpFile) }, {"Format-Default", new SessionStateCmdletEntry("Format-Default", typeof(FormatDefaultCommand), helpFile) }, }; foreach (var val in cmdlets.Values) { val.SetPSSnapIn(psSnapInInfo); } providers = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Registry", new SessionStateProviderEntry("Registry", typeof(RegistryProvider), helpFile) }, { "Alias", new SessionStateProviderEntry("Alias", typeof(AliasProvider), helpFile) }, { "Environment", new SessionStateProviderEntry("Environment", typeof(EnvironmentProvider), helpFile) }, { "FileSystem" , new SessionStateProviderEntry("FileSystem", typeof(FileSystemProvider), helpFile) }, { "Function", new SessionStateProviderEntry("Function", typeof(FunctionProvider), helpFile) }, { "Variable", new SessionStateProviderEntry("Variable", typeof(VariableProvider), helpFile) }, }; foreach (var val in providers.Values) { val.SetPSSnapIn(psSnapInInfo); } } private static void ExecuteModuleInitializer(Assembly assembly, Type[] assemblyTypes, bool isModuleLoad) { for (int i = 0; i < assemblyTypes.Length; i++) { Type type = assemblyTypes[i]; TypeInfo typeInfo = type.GetTypeInfo(); if (!(typeInfo.IsPublic || typeInfo.IsNestedPublic) || typeInfo.IsAbstract) { continue; } if (isModuleLoad && typeof(IModuleAssemblyInitializer).IsAssignableFrom(type) && type != typeof(IModuleAssemblyInitializer)) { _assembliesWithModuleInitializerCache.Value[assembly] = true; IModuleAssemblyInitializer moduleInitializer = (IModuleAssemblyInitializer)Activator.CreateInstance(type, true); moduleInitializer.OnImport(); } } } internal static Type[] GetAssemblyTypes(Assembly assembly, string name) { Type[] assemblyTypes = null; try { var exportedTypes = assembly.ExportedTypes; assemblyTypes = exportedTypes as Type[] ?? exportedTypes.ToArray(); } catch (ReflectionTypeLoadException e) { string message; message = e.Message; message += "\nLoader Exceptions: \n"; if (e.LoaderExceptions != null) { foreach (Exception exception in e.LoaderExceptions) { message += "\n" + exception.Message; } } _PSSnapInTracer.TraceError(message); throw new PSSnapInException(name, message); } return assemblyTypes; } // cmdletCache holds the list of cmdlets along with its aliases per each assembly. static private Lazy>>>> _cmdletCache = new Lazy>>>>(); static private Lazy>> _providerCache = new Lazy>>(); // Using a ConcurrentDictionary for this so that we can avoid having a private lock variable. We use only the keys for checking. private static Lazy> _assembliesWithModuleInitializerCache = new Lazy>(); static private string GetCmdletName(CmdletAttribute cmdletAttribute) { string verb = cmdletAttribute.VerbName; string noun = cmdletAttribute.NounName; return verb + "-" + noun; } static private string GetProviderName(CmdletProviderAttribute providerAttribute) { return providerAttribute.ProviderName; } static private bool IsCmdletClass(Type type) { if (type == null) return false; return type.IsSubclassOf(typeof(System.Management.Automation.Cmdlet)); } static private bool IsProviderClass(Type type) { if (type == null) return false; return type.IsSubclassOf(typeof(System.Management.Automation.Provider.CmdletProvider)); } static internal bool IsModuleAssemblyInitializerClass(Type type) { if (type == null) { return false; } return type.IsSubclassOf(typeof(System.Management.Automation.IModuleAssemblyInitializer)); } static private bool HasDefaultConstructor(Type type) { return !(type.GetConstructor(PSTypeExtensions.EmptyTypes) == null); } static private string GetHelpFile(string assemblyPath) { return Path.GetFileName(assemblyPath) + StringLiterals.HelpFileExtension; } static private PSTraceSource _PSSnapInTracer = PSTraceSource.GetTracer("PSSnapInLoadUnload", "Loading and unloading mshsnapins", false); } // Guid is {15d4c170-2f29-5689-a0e2-d95b0c7b4ea0} [EventSource(Name = "Microsoft-PowerShell-Runspaces")] internal class RunspaceEventSource : EventSource { internal static RunspaceEventSource Log = new RunspaceEventSource(); public void OpenRunspaceStart() { WriteEvent(1); } public void OpenRunspaceStop() { WriteEvent(2); } public void LoadAssembliesStart() { WriteEvent(3); } public void LoadAssembliesStop() { WriteEvent(4); } public void UpdateFormatTableStart() { WriteEvent(5); } public void UpdateFormatTableStop() { WriteEvent(6); } public void UpdateTypeTableStart() { WriteEvent(7); } public void UpdateTypeTableStop() { WriteEvent(8); } public void LoadProvidersStart() { WriteEvent(9); } public void LoadProvidersStop() { WriteEvent(10); } public void LoadCommandsStart() { WriteEvent(11); } public void LoadCommandsStop() { WriteEvent(12); } public void LoadVariablesStart() { WriteEvent(13); } public void LoadVariablesStop() { WriteEvent(14); } public void LoadEnvironmentVariablesStart() { WriteEvent(15); } public void LoadEnvironmentVariablesStop() { WriteEvent(16); } public void LoadAssemblyStart(string Name, string FileName) { WriteEvent(17, Name, FileName); } public void LoadAssemblyStop(string Name, string FileName) { WriteEvent(18, Name, FileName); } public void ProcessFormatFileStart(string FileName) { WriteEvent(19, FileName); } public void ProcessFormatFileStop(string FileName) { WriteEvent(20, FileName); } public void ProcessTypeFileStart(string FileName) { WriteEvent(21, FileName); } public void ProcessTypeFileStop(string FileName) { WriteEvent(22, FileName); } public void LoadProviderStart(string Name) { WriteEvent(23, Name); } public void LoadProviderStop(string Name) { WriteEvent(24, Name); } public void LoadCommandStart(string Name) { WriteEvent(25, Name); } public void LoadCommandStop(string Name) { WriteEvent(26, Name); } } }