Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
CommandDiscovery.cs1647 linesDownload Raw Back to engine
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Collections.ObjectModel;6using System.Diagnostics.Tracing;7using System.Globalization;8using System.IO;9using System.Linq;10using System.Management.Automation.Host;11using System.Management.Automation.Internal;12using System.Management.Automation.Runspaces;13using System.Security;14 15using Microsoft.PowerShell.Commands;16using Microsoft.Win32;17 18using Dbg = System.Management.Automation.Diagnostics;19 20namespace System.Management.Automation21{22    /// <summary>23    /// EventArgs for the ScriptCmdletVariableUpdate event.24    /// </summary>25    public class CommandLookupEventArgs : EventArgs26    {27        /// <summary>28        /// Constructor for event args object.29        /// </summary>30        /// <param name="commandName">The name of the command we're searching for.</param>31        /// <param name="commandOrigin">The origin of the command internal or runspace (external).</param>32        /// <param name="context">The execution context for this command.</param>33        internal CommandLookupEventArgs(string commandName, CommandOrigin commandOrigin, ExecutionContext context)34        {35            CommandName = commandName;36            CommandOrigin = commandOrigin;37            _context = context;38        }39 40        private readonly ExecutionContext _context;41 42        /// <summary>43        /// The name of the command we're looking for.44        /// </summary>45        public string CommandName { get; }46 47        /// <summary>48        /// The origin of the command internal or runspace (external)49        /// </summary>50        public CommandOrigin CommandOrigin { get; }51 52        /// <summary>53        /// If true on return from event handler, the search is stopped.54        /// </summary>55        public bool StopSearch { get; set; }56 57        /// <summary>58        /// The CommandInfo object for the command that was found.59        /// </summary>60        public CommandInfo Command { get; set; }61 62        /// <summary>63        /// Scriptblock to be returned as the found command. If it is set to64        /// null, then the command to return and the StopSearch flag will be reset.65        /// </summary>66        public ScriptBlock CommandScriptBlock67        {68            get69            {70                return _scriptBlock;71            }72 73            set74            {75                _scriptBlock = value;76                if (_scriptBlock != null)77                {78                    string dynamicName = "LookupHandlerReplacementFor<<" + CommandName + ">>";79                    Command = new FunctionInfo(dynamicName, _scriptBlock, _context);80                    StopSearch = true;81                }82                else83                {84                    Command = null;85                    StopSearch = false;86                }87            }88        }89 90        private ScriptBlock _scriptBlock;91    }92 93    /// <summary>94    /// Defines the preference options for the Module Auto-loading feature.95    /// </summary>96    public enum PSModuleAutoLoadingPreference97    {98        /// <summary>99        /// Do not auto-load modules when a command is not found.100        /// </summary>101        None = 0,102 103        /// <summary>104        /// Only auto-load modules when a command is not found, and the command105        /// is module-qualified.106        /// </summary>107        ModuleQualified = 1,108 109        /// <summary>110        /// Auto-load modules when a command is not found.111        /// </summary>112        All = 2113    }114 115    /// <summary>116    /// CommandDiscovery...117    /// </summary>118    internal class CommandDiscovery119    {120        [TraceSource("CommandDiscovery", "Traces the discovery of cmdlets, scripts, functions, applications, etc.")]121        internal static readonly PSTraceSource discoveryTracer =122            PSTraceSource.GetTracer(123                "CommandDiscovery",124                "Traces the discovery of cmdlets, scripts, functions, applications, etc.",125                false);126 127        #region ctor128 129        /// <summary>130        /// Default constructor...131        /// </summary>132        /// <exception cref="ArgumentNullException">133        /// If <paramref name="context"/> is null.134        /// </exception>135        internal CommandDiscovery(ExecutionContext context)136        {137            if (context == null)138            {139                throw PSTraceSource.NewArgumentNullException(nameof(context));140            }141 142            Context = context;143            discoveryTracer.ShowHeaders = false;144        }145 146        /// <summary>147        /// Determines if the cmdlet is a cmdlet that shouldn't be in the discovery list.148        /// </summary>149        /// <param name="implementingType">150        /// Type implementing the cmdlet151        /// </param>152        /// <returns>153        /// True if the cmdlet is a special cmdlet that shouldn't be part of the discovery list. Or false otherwise.154        /// </returns>155        private static bool IsSpecialCmdlet(Type implementingType)156        {157            // These commands should never be put in the discovery list.  They are an internal implementation158            // detail of the formatting and output component. That component uses these cmdlets by creating159            // an instance of the CommandProcessor class directly.160            return implementingType == typeof(OutLineOutputCommand) || implementingType == typeof(FormatDefaultCommand);161        }162 163        private CmdletInfo NewCmdletInfo(SessionStateCmdletEntry entry)164        {165            return NewCmdletInfo(entry, Context);166        }167 168        internal static CmdletInfo NewCmdletInfo(SessionStateCmdletEntry entry, ExecutionContext context)169        {170            CmdletInfo ci = new CmdletInfo(entry.Name, entry.ImplementingType, entry.HelpFileName, entry.PSSnapIn, context)171            {172                Visibility = entry.Visibility,173                Module = entry.Module174            };175            return ci;176        }177 178        internal static AliasInfo NewAliasInfo(SessionStateAliasEntry entry, ExecutionContext context)179        {180            AliasInfo ci = new AliasInfo(entry.Name, entry.Definition, context, entry.Options)181            {182                Visibility = entry.Visibility,183                Module = entry.Module184            };185            return ci;186        }187 188        /// <summary>189        /// Adds the CmdletInfo to the cmdlet cache in the current scope object.190        /// </summary>191        /// <param name="name">192        /// The name of the cmdlet to add.193        /// </param>194        /// <param name="newCmdletInfo">195        /// The CmdletInfo to add.196        /// </param>197        /// <param name="isGlobal">198        /// If true, the cmdlet is added to the Module Scope of the session state.199        /// </param>200        /// <exception cref="PSNotSupportedException">201        /// If a cmdlet with the same module and cmdlet name already exists202        /// but has a different implementing type.203        /// </exception>204        internal CmdletInfo AddCmdletInfoToCache(string name, CmdletInfo newCmdletInfo, bool isGlobal)205        {206            if (string.IsNullOrEmpty(name))207            {208                throw PSTraceSource.NewArgumentException(nameof(name));209            }210 211            if (newCmdletInfo == null)212            {213                throw PSTraceSource.NewArgumentNullException("cmdlet");214            }215 216            if (isGlobal)217            {218                // When cmdlet cache was not scope-based, we used to import cmdlets to the module scope.219                // We need to do the same as the default action (setting "isGlobal" is done as a default action in the caller)220                return Context.EngineSessionState.ModuleScope.AddCmdletToCache(newCmdletInfo.Name, newCmdletInfo, CommandOrigin.Internal, Context);221            }222 223            return Context.EngineSessionState.CurrentScope.AddCmdletToCache(newCmdletInfo.Name, newCmdletInfo, CommandOrigin.Internal, Context);224        }225 226        /// <summary>227        /// Add a SessionStateCmdletEntry to the cmdlet cache...228        /// </summary>229        /// <param name="entry"></param>230        internal void AddSessionStateCmdletEntryToCache(SessionStateCmdletEntry entry)231        {232            AddSessionStateCmdletEntryToCache(entry, /*local*/false);233        }234 235        /// <summary>236        /// Add a SessionStateCmdletEntry to the cmdlet cache...237        /// </summary>238        /// <param name="entry"></param>239        /// <param name="local"></param>240        internal void AddSessionStateCmdletEntryToCache(SessionStateCmdletEntry entry, bool local)241        {242            if (!IsSpecialCmdlet(entry.ImplementingType))243            {244                CmdletInfo nci = NewCmdletInfo(entry);245                AddCmdletInfoToCache(nci.Name, nci, !local);246            }247        }248 249        #endregion ctor250 251        #region internal methods252 253        /// <summary>254        /// Look up a command named by the argument string and return its CommandProcessorBase.255        /// </summary>256        /// <param name="commandName">257        /// The command name to lookup.258        /// </param>259        /// <param name="commandOrigin">Location where the command was dispatched from.</param>260        /// <param name="useLocalScope">261        /// True if command processor should use local scope to execute the command,262        /// False if not.  Null if command discovery should default to something reasonable263        /// for the command discovered.264        /// </param>265        /// <param name="forCompletion">266        /// True if this for parameter completion and script requirements should be ignored.267        /// </param>268        /// <returns>269        /// </returns>270        /// <exception cref="CommandNotFoundException">271        /// If the command, <paramref name="commandName"/>, could not be found.272        /// </exception>273        /// <exception cref="System.Security.SecurityException">274        /// If the security manager is preventing the command from running.275        /// </exception>276        internal CommandProcessorBase LookupCommandProcessor(string commandName,277            CommandOrigin commandOrigin, bool? useLocalScope, bool forCompletion = false)278        {279            CommandProcessorBase processor = null;280            CommandInfo commandInfo = LookupCommandInfo(commandName, commandOrigin);281 282            if (commandInfo != null)283            {284                processor = LookupCommandProcessor(commandInfo, commandOrigin, useLocalScope, null, forCompletion);285 286                // commandInfo.Name might be different than commandName - restore the original invocation name287                processor.Command.MyInvocation.InvocationName = commandName;288            }289 290            return processor;291        }292 293        internal static void VerifyRequiredModules(ExternalScriptInfo scriptInfo, ExecutionContext context, bool forCompletion = false)294        {295            // Check Required Modules296            if (scriptInfo.RequiresModules != null)297            {298                foreach (var requiredModule in scriptInfo.RequiresModules)299                {300                    ErrorRecord error = null;301                    ModuleCmdletBase.LoadRequiredModule(302                        context: context,303                        currentModule: null,304                        requiredModuleSpecification: requiredModule,305                        moduleManifestPath: null,306                        manifestProcessingFlags: ModuleCmdletBase.ManifestProcessingFlags.LoadElements | ModuleCmdletBase.ManifestProcessingFlags.WriteErrors,307                        error: out error);308                    if (!forCompletion && error is not null)309                    {310                        ScriptRequiresException scriptRequiresException =311                            new ScriptRequiresException(312                                scriptInfo.Name,313                                new Collection<string> { requiredModule.GetRequiredModuleNotFoundVersionMessage() },314                                "ScriptRequiresMissingModules",315                                false,316                                error);317                        throw scriptRequiresException;318                    }319                }320            }321        }322 323        private CommandProcessorBase CreateScriptProcessorForSingleShell(ExternalScriptInfo scriptInfo, ExecutionContext context, bool useLocalScope, SessionStateInternal sessionState, bool forCompletion = false)324        {325            VerifyScriptRequirements(scriptInfo, Context, forCompletion);326 327            if (!string.IsNullOrEmpty(scriptInfo.RequiresApplicationID))328            {329                ScriptRequiresException sre =330                    new ScriptRequiresException(331                        scriptInfo.Name,332                        string.Empty,333                        string.Empty,334                        "RequiresShellIDInvalidForSingleShell");335 336                throw sre;337            }338 339            return CreateCommandProcessorForScript(scriptInfo, Context, useLocalScope, sessionState);340        }341 342        // This method verifies the following 3 elements of #Requires statement343        // #Requires -RunAsAdministrator344        // #Requires -PSVersion345        // #Requires -PSEdition346        // #Requires -Module347        internal static void VerifyScriptRequirements(ExternalScriptInfo scriptInfo, ExecutionContext context, bool forCompletion = false)348        {349            // When completing script parameters we don't care if these requirements are met.350            // VerifyRequiredModules will attempt to load the required modules which is useful for completion (so the correct types are loaded).351            if (!forCompletion)352            {353                VerifyElevatedPrivileges(scriptInfo);354                VerifyPSVersion(scriptInfo);355                VerifyPSEdition(scriptInfo);356            }357 358            VerifyRequiredModules(scriptInfo, context, forCompletion);359        }360 361        internal static void VerifyPSVersion(ExternalScriptInfo scriptInfo)362        {363            Version requiresPSVersion = scriptInfo.RequiresPSVersion;364            // in single shell mode365            if (requiresPSVersion != null)366            {367                if (!PSVersionInfo.IsValidPSVersion(requiresPSVersion))368                {369                    ScriptRequiresException scriptRequiresException =370                        new ScriptRequiresException(371                            scriptInfo.Name,372                            requiresPSVersion,373                            PSVersionInfo.PSVersion.ToString(),374                            "ScriptRequiresUnmatchedPSVersion");375                    throw scriptRequiresException;376                }377            }378        }379 380        internal static void VerifyPSEdition(ExternalScriptInfo scriptInfo)381        {382            if (scriptInfo.RequiresPSEditions != null)383            {384                var isCurrentEditionListed = false;385                var isRequiresPSEditionSpecified = false;386                foreach (var edition in scriptInfo.RequiresPSEditions)387                {388                    isRequiresPSEditionSpecified = true;389                    isCurrentEditionListed = Utils.IsPSEditionSupported(edition);390                    if (isCurrentEditionListed)391                    {392                        break;393                    }394                }395 396                // Throw an error if required PowerShell editions are specified and without the current PowerShell Edition.397                //398                if (isRequiresPSEditionSpecified && !isCurrentEditionListed)399                {400                    var specifiedEditionsString = string.Join(',', scriptInfo.RequiresPSEditions);401                    var message = StringUtil.Format(DiscoveryExceptions.RequiresPSEditionNotCompatible,402                        scriptInfo.Name,403                        specifiedEditionsString,404                        PSVersionInfo.PSEditionValue);405                    var ex = new RuntimeException(message);406                    ex.SetErrorId("ScriptRequiresUnmatchedPSEdition");407                    ex.SetTargetObject(scriptInfo.Name);408                    throw ex;409                }410            }411        }412 413        internal static void VerifyElevatedPrivileges(ExternalScriptInfo scriptInfo)414        {415            bool requiresElevation = scriptInfo.RequiresElevation;416            bool isAdministrator = Utils.IsAdministrator();417            if (requiresElevation && !isAdministrator)418            {419                ScriptRequiresException scriptRequiresException =420                        new ScriptRequiresException(421                            scriptInfo.Name,422                            "ScriptRequiresElevation");423                throw scriptRequiresException;424            }425        }426 427        /// <summary>428        /// Look up a command using a CommandInfo object and return its CommandProcessorBase.429        /// </summary>430        /// <param name="commandInfo">431        /// The commandInfo for the command to lookup.432        /// </param>433        /// <param name="commandOrigin">Location where the command was dispatched from.</param>434        /// <param name="useLocalScope">435        /// True if command processor should use local scope to execute the command,436        /// False if not.  Null if command discovery should default to something reasonable437        /// for the command discovered.438        /// </param>439        /// <param name="forCompletion">440        /// True if this for parameter completion and script requirements should be ignored.441        /// </param>442        /// <param name="sessionState">The session state the commandInfo should be run in.</param>443        /// <returns>444        /// </returns>445        /// <exception cref="CommandNotFoundException">446        /// If the command, <paramref name="commandName"/>, could not be found.447        /// </exception>448        /// <exception cref="System.Management.Automation.PSSecurityException">449        /// If the security manager is preventing the command from running.450        /// </exception>451        internal CommandProcessorBase LookupCommandProcessor(CommandInfo commandInfo,452            CommandOrigin commandOrigin, bool? useLocalScope, SessionStateInternal sessionState, bool forCompletion = false)453        {454            CommandProcessorBase processor = null;455 456            HashSet<string> processedAliases = new HashSet<string>(StringComparer.OrdinalIgnoreCase);457 458            while (commandInfo.CommandType == CommandTypes.Alias &&459                (!processedAliases.Contains(commandInfo.Name)) &&460                (commandOrigin == CommandOrigin.Internal || commandInfo.Visibility == SessionStateEntryVisibility.Public))461            {462                processedAliases.Add(commandInfo.Name);463 464                AliasInfo aliasCommandInfo = (AliasInfo)commandInfo;465                commandInfo = aliasCommandInfo.ResolvedCommand ??466                              LookupCommandInfo(aliasCommandInfo.Definition, commandOrigin, Context);467 468                // If we didn't have the alias target already resolved, see if it can be loaded.469 470                if (commandInfo == null)471                {472                    CommandNotFoundException e =473                        new CommandNotFoundException(474                            aliasCommandInfo.Name,475                            null,476                            "AliasNotResolvedException",477                            DiscoveryExceptions.AliasNotResolvedException,478                            aliasCommandInfo.UnresolvedCommandName);479                    throw e;480                }481            }482 483            ShouldRun(Context, Context.EngineHostInterface, commandInfo, commandOrigin);484 485            switch (commandInfo.CommandType)486            {487                case CommandTypes.Application:488                    processor = new NativeCommandProcessor((ApplicationInfo)commandInfo, Context);489                    break;490                case CommandTypes.Cmdlet:491                    processor = new CommandProcessor((CmdletInfo)commandInfo, Context);492                    break;493                case CommandTypes.ExternalScript:494                    ExternalScriptInfo scriptInfo = (ExternalScriptInfo)commandInfo;495                    scriptInfo.SignatureChecked = true;496                    try497                    {498                        processor = CreateScriptProcessorForSingleShell(scriptInfo, Context, useLocalScope ?? true, sessionState, forCompletion);499                    }500                    catch (ScriptRequiresSyntaxException reqSyntaxException)501                    {502                        CommandNotFoundException e =503                            new CommandNotFoundException(reqSyntaxException.Message, reqSyntaxException);504                        throw e;505                    }506 507                    break;508                case CommandTypes.Filter:509                case CommandTypes.Function:510                case CommandTypes.Configuration:511                    FunctionInfo functionInfo = (FunctionInfo)commandInfo;512                    processor = CreateCommandProcessorForScript(functionInfo, Context, useLocalScope ?? true, sessionState);513                    break;514                case CommandTypes.Script:515                    processor = CreateCommandProcessorForScript((ScriptInfo)commandInfo, Context, useLocalScope ?? true, sessionState);516                    break;517                case CommandTypes.Alias:518                default:519                    {520                        CommandNotFoundException e =521                            new CommandNotFoundException(522                                commandInfo.Name,523                                null,524                                "CommandNotFoundException",525                                DiscoveryExceptions.CommandNotFoundException);526                        throw e;527                    }528            }529 530            // Set the internal command origin member on the command object at this point...531            processor.Command.CommandOriginInternal = commandOrigin;532 533            processor.Command.MyInvocation.InvocationName = commandInfo.Name;534 535            return processor;536        }537 538        internal static void ShouldRun(ExecutionContext context, PSHost host, CommandInfo commandInfo, CommandOrigin commandOrigin)539        {540            // ShouldRunInternal throws PSSecurityException if run is not allowed541            try542            {543                if (commandOrigin == CommandOrigin.Runspace && commandInfo.Visibility != SessionStateEntryVisibility.Public)544                {545                    CommandNotFoundException e = new CommandNotFoundException(546                        commandInfo.Name, null, "CommandNotFoundException", DiscoveryExceptions.CommandNotFoundException);547                    throw e;548                }549 550                context.AuthorizationManager.ShouldRunInternal(commandInfo, commandOrigin, host);551            }552            catch (PSSecurityException reason)553            {554                MshLog.LogCommandHealthEvent(context,555                                reason,556                                Severity.Warning);557 558                MshLog.LogCommandLifecycleEvent(context,559                                CommandState.Terminated,560                                commandInfo.Name);561 562                throw;563            }564        }565 566        private static CommandProcessorBase CreateCommandProcessorForScript(ScriptInfo scriptInfo, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState)567        {568            sessionState ??= scriptInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState;569            CommandProcessorBase scriptAsCmdletProcessor = GetScriptAsCmdletProcessor(scriptInfo, context, useNewScope, true, sessionState);570            if (scriptAsCmdletProcessor != null)571            {572                return scriptAsCmdletProcessor;573            }574 575            return new DlrScriptCommandProcessor(scriptInfo, context, useNewScope, sessionState);576        }577 578        private static CommandProcessorBase CreateCommandProcessorForScript(ExternalScriptInfo scriptInfo, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState)579        {580            sessionState ??= scriptInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState;581            CommandProcessorBase scriptAsCmdletProcessor = GetScriptAsCmdletProcessor(scriptInfo, context, useNewScope, true, sessionState);582            if (scriptAsCmdletProcessor != null)583            {584                return scriptAsCmdletProcessor;585            }586 587            return new DlrScriptCommandProcessor(scriptInfo, context, useNewScope, sessionState);588        }589 590        internal static CommandProcessorBase CreateCommandProcessorForScript(FunctionInfo functionInfo, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState)591        {592            sessionState ??= functionInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState;593            CommandProcessorBase scriptAsCmdletProcessor = GetScriptAsCmdletProcessor(functionInfo, context, useNewScope, false, sessionState);594            if (scriptAsCmdletProcessor != null)595            {596                return scriptAsCmdletProcessor;597            }598 599            return new DlrScriptCommandProcessor(functionInfo, context, useNewScope, sessionState);600        }601 602        internal static CommandProcessorBase CreateCommandProcessorForScript(ScriptBlock scriptblock, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState)603        {604            sessionState ??= scriptblock.SessionStateInternal ?? context.EngineSessionState;605 606            if (scriptblock.UsesCmdletBinding)607            {608                FunctionInfo fi = new FunctionInfo(string.Empty, scriptblock, context);609                return GetScriptAsCmdletProcessor(fi, context, useNewScope, false, sessionState);610            }611 612            return new DlrScriptCommandProcessor(scriptblock, context, useNewScope, CommandOrigin.Internal, sessionState);613        }614 615        private static CommandProcessorBase GetScriptAsCmdletProcessor(IScriptCommandInfo scriptCommandInfo, ExecutionContext context, bool useNewScope, bool fromScriptFile, SessionStateInternal sessionState)616        {617            if (scriptCommandInfo.ScriptBlock == null || !scriptCommandInfo.ScriptBlock.UsesCmdletBinding)618            {619                return null;620            }621 622            sessionState ??= scriptCommandInfo.ScriptBlock.SessionStateInternal ?? context.EngineSessionState;623 624            return new CommandProcessor(scriptCommandInfo, context, useNewScope, fromScriptFile, sessionState);625        }626 627        /// <summary>628        /// Look up a command and return its CommandInfo.629        /// </summary>630        /// <param name="commandName">631        /// The command name to lookup.632        /// </param>633        /// <returns>634        /// An instance of a CommandInfo object that represents the635        /// command. If the command is resolved as an alias, an AliasInfo636        /// is returned with the ReferencedCommand info intact.637        /// </returns>638        /// <exception cref="CommandNotFoundException">639        /// If the command, <paramref name="commandName"/>, could not be found.640        /// </exception>641        internal CommandInfo LookupCommandInfo(string commandName)642        {643            return LookupCommandInfo(commandName, CommandOrigin.Internal);644        }645 646        internal CommandInfo LookupCommandInfo(string commandName, CommandOrigin commandOrigin)647        {648            return LookupCommandInfo(commandName, commandOrigin, Context);649        }650 651        internal static CommandInfo LookupCommandInfo(string commandName, CommandOrigin commandOrigin, ExecutionContext context)652        {653            return LookupCommandInfo(commandName, CommandTypes.All, SearchResolutionOptions.ResolveLiteralThenPathPatterns, commandOrigin, context);654        }655 656        internal static CommandInfo LookupCommandInfo(657            string commandName,658            CommandTypes commandTypes,659            SearchResolutionOptions searchResolutionOptions,660            CommandOrigin commandOrigin,661            ExecutionContext context)662        {663            if (string.IsNullOrEmpty(commandName))664            {665                return null;666            }667 668            bool etwEnabled = CommandDiscoveryEventSource.Log.IsEnabled();669            if (etwEnabled) CommandDiscoveryEventSource.Log.CommandLookupStart(commandName);670 671            CommandInfo result = null;672            string originalCommandName = commandName;673 674            Exception lastError = null;675 676            // Check to see if there is a pre-search look-up event handler...677            CommandLookupEventArgs eventArgs = null;678            EventHandler<CommandLookupEventArgs> preCommandLookupEvent = context.EngineIntrinsics.InvokeCommand.PreCommandLookupAction;679 680            if (preCommandLookupEvent != null)681            {682                discoveryTracer.WriteLine("Executing PreCommandLookupAction: {0}", commandName);683                try684                {685                    context.CommandDiscovery.RegisterLookupCommandInfoAction("ActivePreLookup", originalCommandName);686                    eventArgs = new CommandLookupEventArgs(originalCommandName, commandOrigin, context);687                    preCommandLookupEvent.Invoke(originalCommandName, eventArgs);688 689                    discoveryTracer.WriteLine("PreCommandLookupAction returned: {0}", eventArgs.Command);690                }691                catch (Exception)692                {693                }694                finally { context.CommandDiscovery.UnregisterLookupCommandInfoAction("ActivePreLookup", commandName); }695            }696 697            // Check the module auto-loading preference698            PSModuleAutoLoadingPreference moduleAutoLoadingPreference = GetCommandDiscoveryPreference(context, SpecialVariables.PSModuleAutoLoadingPreferenceVarPath, "PSModuleAutoLoadingPreference");699 700            if (eventArgs == null || !eventArgs.StopSearch)701            {702                do703                {704                    discoveryTracer.WriteLine("Looking up command: {0}", commandName);705 706                    // Use the CommandSearcher to find the first command. If there are duplicate707                    // command names, then take the first one...708 709                    result = TryNormalSearch(commandName, context, commandOrigin, searchResolutionOptions, commandTypes, ref lastError);710 711                    if (result != null)712                        break;713 714                    // Try the module-qualified auto-loading (unless module auto-loading has been entirely disabled)715                    if (moduleAutoLoadingPreference != PSModuleAutoLoadingPreference.None)716                    {717                        result = TryModuleAutoLoading(commandName, context, originalCommandName, commandOrigin, ref lastError);718                    }719 720                    if (result != null)721                        break;722 723                    // See if the this was not module-qualified. In that case, we should look for the first module724                    // that contains the command and load that.725                    if (moduleAutoLoadingPreference == PSModuleAutoLoadingPreference.All)726                    {727                        result = TryModuleAutoDiscovery(commandName, context, originalCommandName, commandOrigin,728                                                        searchResolutionOptions, commandTypes, ref lastError);729                    }730 731                    // Otherwise, invoke the CommandNotFound handler732                    result ??= InvokeCommandNotFoundHandler(commandName, context, originalCommandName, commandOrigin);733                } while (false);734            }735            else736            {737                if (eventArgs.Command != null)738                {739                    result = eventArgs.Command;740                }741            }742 743            // If we resolved a command, give the PostCommandLookup a chance to change it744            if (result != null)745            {746                System.EventHandler<CommandLookupEventArgs> postAction = context.EngineIntrinsics.InvokeCommand.PostCommandLookupAction;747                if (postAction != null)748                {749                    discoveryTracer.WriteLine("Executing PostCommandLookupAction: {0}", originalCommandName);750                    try751                    {752                        context.CommandDiscovery.RegisterLookupCommandInfoAction("ActivePostCommand", originalCommandName);753 754                        eventArgs = new CommandLookupEventArgs(originalCommandName, commandOrigin, context);755                        eventArgs.Command = result;756                        postAction.Invoke(originalCommandName, eventArgs);757 758                        if (eventArgs != null)759                        {760                            result = eventArgs.Command;761                            discoveryTracer.WriteLine("PreCommandLookupAction returned: {0}", eventArgs.Command);762                        }763                    }764                    catch (Exception)765                    {766                    }767                    finally768                    {769                        context.CommandDiscovery.UnregisterLookupCommandInfoAction("ActivePostCommand", originalCommandName);770                    }771                }772            }773 774            // After all command lookup is done, throw a CommandNotFound if we have no result.775            if (result == null)776            {777                discoveryTracer.TraceError(778                    "'{0}' is not recognized as a cmdlet, function, executable program or script file.",779                    commandName);780 781                CommandNotFoundException e =782                    new CommandNotFoundException(783                        originalCommandName,784                        lastError,785                        "CommandNotFoundException",786                        DiscoveryExceptions.CommandNotFoundException);787                throw e;788            }789 790            if (etwEnabled) CommandDiscoveryEventSource.Log.CommandLookupStop(commandName);791 792            return result;793        }794 795        internal static void AutoloadModulesWithJobSourceAdapters(System.Management.Automation.ExecutionContext context, CommandOrigin commandOrigin)796        {797            /* This function is used by *-Job cmdlets (JobCmdletBase.BeginProcessing(), StartJobCommand.BeginProcessing())798            It attempts to load modules from a fixed ModulesWithJobSourceAdapters list that currently has only `PSScheduledJob` module that is not PS-Core compatible.799            Because this function does not check the result of a (currently failing) `PSScheduledJob` module autoload, it provides no value.800            After discussion it was decided to comment out this code as it may be useful if ModulesWithJobSourceAdapters list changes in the future.801 802            if (!context.IsModuleWithJobSourceAdapterLoaded)803            {804                PSModuleAutoLoadingPreference moduleAutoLoadingPreference = GetCommandDiscoveryPreference(context, SpecialVariables.PSModuleAutoLoadingPreferenceVarPath, "PSModuleAutoLoadingPreference");805                if (moduleAutoLoadingPreference != PSModuleAutoLoadingPreference.None)806                {807                    CmdletInfo cmdletInfo = context.SessionState.InvokeCommand.GetCmdlet("Microsoft.PowerShell.Core\\Import-Module");808                    if ((commandOrigin == CommandOrigin.Internal) ||809                        ((cmdletInfo != null) && (cmdletInfo.Visibility == SessionStateEntryVisibility.Public)))810                    {811                        foreach (var module in System.Management.Automation.ExecutionContext.ModulesWithJobSourceAdapters)812                        {813                            List<PSModuleInfo> existingModule = context.Modules.GetModules(new string[] { module }, false);814                            if (existingModule == null || existingModule.Count == 0)815                            {816                                Exception unUsedException = null;817                                AutoloadSpecifiedModule(module, context, cmdletInfo.Visibility, out unUsedException);818                            }819                        }820 821                        context.IsModuleWithJobSourceAdapterLoaded = true;822                    }823                }824            }*/825        }826 827        internal static Collection<PSModuleInfo> AutoloadSpecifiedModule(string moduleName, ExecutionContext context, SessionStateEntryVisibility visibility, out Exception exception)828        {829            exception = null;830            Collection<PSModuleInfo> matchingModules = null;831            CommandInfo commandInfo = new CmdletInfo("Import-Module", typeof(ImportModuleCommand), null, null, context);832            commandInfo.Visibility = visibility;833            Command importModuleCommand = new Command(commandInfo);834 835            discoveryTracer.WriteLine("Attempting to load module: {0}", moduleName);836 837            PowerShell ps = null;838            try839            {840                ps = PowerShell.Create(RunspaceMode.CurrentRunspace)841                    .AddCommand(importModuleCommand)842                    .AddParameter("Name", moduleName)843                     .AddParameter("Scope", StringLiterals.Global)844                     .AddParameter("PassThru")845                     .AddParameter("ErrorAction", ActionPreference.Ignore)846                     .AddParameter("WarningAction", ActionPreference.Ignore)847                     .AddParameter("InformationAction", ActionPreference.Ignore)848                     .AddParameter("Verbose", false)849                     .AddParameter("Debug", false);850                matchingModules = (Collection<PSModuleInfo>)ps.Invoke<PSModuleInfo>();851            }852            catch (Exception e)853            {854                exception = e;855                discoveryTracer.WriteLine("Encountered error importing module: {0}", e.Message);856                // Call-out to user code, catch-all OK857            }858 859            return matchingModules;860        }861 862        private static CommandInfo InvokeCommandNotFoundHandler(string commandName, ExecutionContext context, string originalCommandName, CommandOrigin commandOrigin)863        {864            CommandInfo result = null;865            CommandLookupEventArgs eventArgs;866            System.EventHandler<CommandLookupEventArgs> cmdNotFoundHandler = context.EngineIntrinsics.InvokeCommand.CommandNotFoundAction;867            if (cmdNotFoundHandler != null)868            {869                discoveryTracer.WriteLine("Executing CommandNotFoundAction: {0}", commandName);870                try871                {872                    context.CommandDiscovery.RegisterLookupCommandInfoAction("ActiveCommandNotFound", originalCommandName);873                    eventArgs = new CommandLookupEventArgs(originalCommandName, commandOrigin, context);874                    cmdNotFoundHandler.Invoke(originalCommandName, eventArgs);875                    result = eventArgs.Command;876                }877                catch (Exception)878                {879                }880                finally { context.CommandDiscovery.UnregisterLookupCommandInfoAction("ActiveCommandNotFound", originalCommandName); }881            }882 883            return result;884        }885 886        private static CommandInfo TryNormalSearch(string commandName,887                                                   ExecutionContext context,888                                                   CommandOrigin commandOrigin,889                                                   SearchResolutionOptions searchResolutionOptions,890                                                   CommandTypes commandTypes,891                                                   ref Exception lastError)892        {893            CommandInfo result = null;894 895            CommandSearcher searcher =896                new CommandSearcher(897                    commandName,898                    searchResolutionOptions,899                    commandTypes,900                    context);901            searcher.CommandOrigin = commandOrigin;902 903            try904            {905                if (!searcher.MoveNext())906                {907                    if (!commandName.Contains('-') && !commandName.Contains('\\'))908                    {909                        discoveryTracer.WriteLine(910                            "The command [{0}] was not found, trying again with get- prepended",911                            commandName);912 913                        commandName = StringLiterals.DefaultCommandVerb + StringLiterals.CommandVerbNounSeparator + commandName;914 915                        try916                        {917                            result = LookupCommandInfo(commandName, commandTypes, searchResolutionOptions, commandOrigin, context);918                        }919                        catch (CommandNotFoundException) { }920                    }921                }922                else923                {924                    result = ((IEnumerator<CommandInfo>)searcher).Current;925                }926            }927            catch (ArgumentException argException)928            {929                lastError = argException;930            }931            catch (PathTooLongException pathTooLong)932            {933                lastError = pathTooLong;934            }935            catch (FileLoadException fileLoadException)936            {937                lastError = fileLoadException;938            }939            catch (FormatException formatException)940            {941                lastError = formatException;942            }943            catch (MetadataException metadataException)944            {945                lastError = metadataException;946            }947 948            return result;949        }950 951        private static CommandInfo TryModuleAutoDiscovery(string commandName,952                                                          ExecutionContext context,953                                                          string originalCommandName,954                                                          CommandOrigin commandOrigin,955                                                          SearchResolutionOptions searchResolutionOptions,956                                                          CommandTypes commandTypes,957                                                          ref Exception lastError)958        {959            bool etwEnabled = CommandDiscoveryEventSource.Log.IsEnabled();960            if (etwEnabled) CommandDiscoveryEventSource.Log.ModuleAutoDiscoveryStart(commandName);961 962            CommandInfo result = null;963            try964            {965                // If commandName had a slash, it was module-qualified or path-qualified.966                // In that case, we should not return anything (module-qualified is handled967                // by the previous call to TryModuleAutoLoading().968                int colonOrBackslash = commandName.AsSpan().IndexOfAny('\\', ':');969                if (colonOrBackslash != -1)970                    return null;971 972                CmdletInfo cmdletInfo = context.SessionState.InvokeCommand.GetCmdlet("Microsoft.PowerShell.Core\\Get-Module");973                if (commandOrigin == CommandOrigin.Internal || cmdletInfo?.Visibility == SessionStateEntryVisibility.Public)974                {975                    // Search for a module with a matching command, as long as the user would have the ability to976                    // import the module.977                    cmdletInfo = context.SessionState.InvokeCommand.GetCmdlet("Microsoft.PowerShell.Core\\Import-Module");978                    if (commandOrigin == CommandOrigin.Internal || cmdletInfo?.Visibility == SessionStateEntryVisibility.Public)979                    {980                        discoveryTracer.WriteLine("Executing non module-qualified search: {0}", commandName);981                        context.CommandDiscovery.RegisterLookupCommandInfoAction("ActiveModuleSearch", commandName);982 983                        // Get the available module files, preferring modules from $PSHOME so that user modules don't984                        // override system modules during auto-loading985                        if (etwEnabled) CommandDiscoveryEventSource.Log.SearchingForModuleFilesStart();986                        var defaultAvailableModuleFiles = ModuleUtils.GetDefaultAvailableModuleFiles(isForAutoDiscovery: true, context);987                        if (etwEnabled) CommandDiscoveryEventSource.Log.SearchingForModuleFilesStop();988 989                        foreach (string modulePath in defaultAvailableModuleFiles)990                        {991                            // WinBlue:69141 - We need to get the full path here because the module path might be C:\Users\User1\DOCUME~1992                            // While the exportedCommands are cached, they are cached with the full path993                            string expandedModulePath = Path.GetFullPath(modulePath);994                            string moduleShortName = Path.GetFileNameWithoutExtension(expandedModulePath);995                            var exportedCommands = AnalysisCache.GetExportedCommands(expandedModulePath, false, context);996 997                            if (exportedCommands == null) { continue; }998 999                            // Skip if module only has class or other types and no commands.1000                            if (exportedCommands.TryGetValue(commandName, out CommandTypes exportedCommandTypes))1001                            {1002                                discoveryTracer.WriteLine("Found in module: {0}", expandedModulePath);1003                                Collection<PSModuleInfo> matchingModule = AutoloadSpecifiedModule(1004                                    expandedModulePath,1005                                    context,1006                                    cmdletInfo != null ? cmdletInfo.Visibility : SessionStateEntryVisibility.Private,1007                                    out lastError);1008 1009                                if (matchingModule is null || matchingModule.Count == 0)1010                                {1011                                    string errorMessage = lastError is null1012                                        ? StringUtil.Format(DiscoveryExceptions.CouldNotAutoImportMatchingModule, commandName, moduleShortName)1013                                        : StringUtil.Format(DiscoveryExceptions.CouldNotAutoImportMatchingModuleWithErrorMessage, commandName, moduleShortName, lastError.Message);1014 1015                                    throw new CommandNotFoundException(1016                                        originalCommandName,1017                                        lastError,1018                                        "CouldNotAutoloadMatchingModule",1019                                        errorMessage);1020                                }1021 1022                                result = LookupCommandInfo(commandName, commandTypes, searchResolutionOptions, commandOrigin, context);1023                            }1024 1025                            if (result != null)1026                            {1027                                break;1028                            }1029                        }1030 1031#if !CORECLR1032                        // Close the progress pane that may have popped up from analyzing UNC paths.1033                        if (context.CurrentCommandProcessor != null)1034                        {1035                            ProgressRecord analysisProgress = new ProgressRecord(0, Modules.ScriptAnalysisPreparing, " ");1036                            analysisProgress.RecordType = ProgressRecordType.Completed;1037                            context.CurrentCommandProcessor.CommandRuntime.WriteProgress(analysisProgress);1038                        }1039#endif1040                    }1041                }1042            }1043            catch (CommandNotFoundException) { throw; }1044            catch (Exception)1045            {1046            }1047            finally1048            {1049                context.CommandDiscovery.UnregisterLookupCommandInfoAction("ActiveModuleSearch", commandName);1050            }1051 1052            if (etwEnabled) CommandDiscoveryEventSource.Log.ModuleAutoDiscoveryStop(commandName);1053 1054            return result;1055        }1056 1057        private static CommandInfo TryModuleAutoLoading(string commandName, ExecutionContext context, string originalCommandName, CommandOrigin commandOrigin, ref Exception lastError)1058        {1059            CommandInfo result = null;1060 1061            // If commandName was module-qualified. In that case, we should load the module.1062            var colonOrBackslash = commandName.AsSpan().IndexOfAny('\\', ':');1063 1064            // If we don't see '\', there is no module specified, so no module to load.1065            // If we see ':' before '\', then we probably have a drive qualified path, not a module name1066            if (colonOrBackslash == -1 || commandName[colonOrBackslash] == ':')1067                return null;1068 1069            string moduleCommandName = commandName.Substring(colonOrBackslash + 1, commandName.Length - colonOrBackslash - 1);1070            string moduleName;1071 1072            // Now we check if there exists the second '\'1073            var secondBackslash = moduleCommandName.IndexOf('\\');1074            if (secondBackslash == -1)1075            {1076                moduleName = commandName.Substring(0, colonOrBackslash);1077            }1078            else1079            {1080                string versionString = moduleCommandName.Substring(0, secondBackslash);1081                // The second '\' could be version specified. eg: "Microsoft.PowerShell.Archive\1.0.0.0\Compress-Archive", we need to support this scenario1082                Version version;1083                if (Version.TryParse(versionString, out version))1084                {1085                    moduleCommandName = moduleCommandName.Substring(secondBackslash + 1, moduleCommandName.Length - secondBackslash - 1);1086                    moduleName = commandName.Substring(0, colonOrBackslash) + "\\" + versionString + "\\" + commandName.Substring(0, colonOrBackslash) + ".psd1";1087                }1088                else1089                {1090                    moduleName = commandName.Substring(0, colonOrBackslash);1091                }1092            }1093 1094            if (string.IsNullOrEmpty(moduleName) || string.IsNullOrEmpty(moduleCommandName) || moduleName.EndsWith('.'))1095                return null;1096 1097            bool etwEnabled = CommandDiscoveryEventSource.Log.IsEnabled();1098            if (etwEnabled) CommandDiscoveryEventSource.Log.ModuleAutoLoadingStart(commandName);1099 1100            try1101            {1102                discoveryTracer.WriteLine("Executing module-qualified search: {0}", commandName);1103                context.CommandDiscovery.RegisterLookupCommandInfoAction("ActiveModuleSearch", commandName);1104 1105                // Verify that auto-loading is only done on for internal commands if it's not public1106                CmdletInfo cmdletInfo = context.SessionState.InvokeCommand.GetCmdlet("Microsoft.PowerShell.Core\\Import-Module");1107                if ((commandOrigin == CommandOrigin.Internal) ||1108                    ((cmdletInfo != null) && (cmdletInfo.Visibility == SessionStateEntryVisibility.Public)))1109                {1110                    List<PSModuleInfo> existingModule = context.Modules.GetModules(new string[] { moduleName }, false);1111                    PSModuleInfo discoveredModule = null;1112 1113                    if (existingModule == null || existingModule.Count == 0)1114                    {1115                        discoveryTracer.WriteLine("Attempting to load module: {0}", moduleName);1116                        Exception exception;1117                        Collection<PSModuleInfo> importedModule = AutoloadSpecifiedModule(moduleName, context, cmdletInfo.Visibility, out exception);1118                        lastError = exception;1119 1120                        if ((importedModule == null) || (importedModule.Count == 0))1121                        {1122                            string error = StringUtil.Format(DiscoveryExceptions.CouldNotAutoImportModule, moduleName);1123                            CommandNotFoundException commandNotFound = new CommandNotFoundException(1124                                originalCommandName,1125                                lastError,1126                                "CouldNotAutoLoadModule",1127                                error);1128                            throw commandNotFound;1129                        }1130 1131                        discoveredModule = importedModule[0];1132                    }1133                    else1134                    {1135                        discoveredModule = existingModule[0];1136                    }1137 1138                    CommandInfo exportedResult;1139                    if (discoveredModule.ExportedCommands.TryGetValue(moduleCommandName, out exportedResult))1140                    {1141                        // Return the command if we found a module1142                        result = exportedResult;1143                    }1144                }1145            }1146            catch (CommandNotFoundException) { throw; }1147            catch (Exception)1148            {1149            }1150            finally { context.CommandDiscovery.UnregisterLookupCommandInfoAction("ActiveModuleSearch", commandName); }1151 1152            if (etwEnabled) CommandDiscoveryEventSource.Log.ModuleAutoLoadingStop(commandName);1153            return result;1154        }1155 1156        internal void RegisterLookupCommandInfoAction(string currentAction, string command)1157        {1158            HashSet<string> currentActionSet = null;1159            switch (currentAction)1160            {1161                case "ActivePreLookup": currentActionSet = _activePreLookup; break;1162                case "ActiveModuleSearch": currentActionSet = _activeModuleSearch; break;1163                case "ActiveCommandNotFound": currentActionSet = _activeCommandNotFound; break;1164                case "ActivePostCommand": currentActionSet = _activePostCommand; break;1165            }1166 1167            if (!currentActionSet.Add(command))1168                throw new InvalidOperationException();1169        }1170 1171        internal void UnregisterLookupCommandInfoAction(string currentAction, string command)1172        {1173            HashSet<string> currentActionSet = null;1174            switch (currentAction)1175            {1176                case "ActivePreLookup": currentActionSet = _activePreLookup; break;1177                case "ActiveModuleSearch": currentActionSet = _activeModuleSearch; break;1178                case "ActiveCommandNotFound": currentActionSet = _activeCommandNotFound; break;1179                case "ActivePostCommand": currentActionSet = _activePostCommand; break;1180            }1181 1182            currentActionSet.Remove(command);1183        }1184 1185        private readonly HashSet<string> _activePreLookup = new HashSet<string>(StringComparer.OrdinalIgnoreCase);1186        private readonly HashSet<string> _activeModuleSearch = new HashSet<string>(StringComparer.OrdinalIgnoreCase);1187        private readonly HashSet<string> _activeCommandNotFound = new HashSet<string>(StringComparer.OrdinalIgnoreCase);1188        private readonly HashSet<string> _activePostCommand = new HashSet<string>(StringComparer.OrdinalIgnoreCase);1189 1190        /// <summary>1191        /// Gets the resolved paths contained in the PATH environment1192        /// variable.1193        /// </summary>1194        /// <returns>1195        /// The contents of the PATH environment variable split on System.IO.Path.PathSeparator.1196        /// </returns>1197        /// <remarks>1198        /// The result is an ordered list of paths with paths starting with "." unresolved until lookup time.1199        /// </remarks>1200        internal LookupPathCollection GetLookupDirectoryPaths()

Showing the first 1,200 of 1647 lines. Download the file for the rest.