Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
ModuleIntrinsics.cs1760 linesDownload Raw Back to Modules
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.IO;7using System.Linq;8using System.Management.Automation.Configuration;9using System.Management.Automation.Internal;10using System.Management.Automation.Language;11using System.Text;12using System.Threading;13using Microsoft.PowerShell.Commands;14 15using Dbg = System.Management.Automation.Diagnostics;16 17namespace System.Management.Automation18{19    internal static class Constants20    {21        public const string PSModulePathEnvVar = "PSModulePath";22    }23 24    /// <summary>25    /// Encapsulates the basic module operations for a PowerShell engine instance...26    /// </summary>27    public class ModuleIntrinsics28    {29        /// <summary>30        /// Tracer for module analysis.31        /// </summary>32        [TraceSource("Modules", "Module loading and analysis")]33        internal static readonly PSTraceSource Tracer = PSTraceSource.GetTracer("Modules", "Module loading and analysis");34 35        // The %WINDIR%\System32\WindowsPowerShell\v1.0\Modules module path,36        // to load forward compatible Windows PowerShell modules from37        private static readonly string s_windowsPowerShellPSHomeModulePath =38            Path.Combine(System.Environment.SystemDirectory, "WindowsPowerShell", "v1.0", "Modules");39 40        static ModuleIntrinsics()41        {42            // Initialize the module path.43            SetModulePath();44        }45 46        internal ModuleIntrinsics(ExecutionContext context)47        {48            _context = context;49            ModuleTable = new Dictionary<string, PSModuleInfo>(StringComparer.OrdinalIgnoreCase);50        }51 52        private readonly ExecutionContext _context;53 54        // Holds the module collection...55        internal Dictionary<string, PSModuleInfo> ModuleTable { get; }56 57        private const int MaxModuleNestingDepth = 10;58 59        internal void IncrementModuleNestingDepth(PSCmdlet cmdlet, string path)60        {61            if (++ModuleNestingDepth > MaxModuleNestingDepth)62            {63                string message = StringUtil.Format(Modules.ModuleTooDeeplyNested, path, MaxModuleNestingDepth);64                InvalidOperationException ioe = new InvalidOperationException(message);65                ErrorRecord er = new ErrorRecord(ioe, "Modules_ModuleTooDeeplyNested",66                    ErrorCategory.InvalidOperation, path);67                // NOTE: this call will throw68                cmdlet.ThrowTerminatingError(er);69            }70        }71 72        internal void DecrementModuleNestingCount()73        {74            --ModuleNestingDepth;75        }76 77        internal int ModuleNestingDepth { get; private set; }78 79        /// <summary>80        /// Create a new module object from a scriptblock specifying the path to set for the module.81        /// </summary>82        /// <param name="name">The name of the module.</param>83        /// <param name="path">The path where the module is rooted.</param>84        /// <param name="scriptBlock">85        /// ScriptBlock that is executed to initialize the module...86        /// </param>87        /// <param name="arguments">88        /// The arguments to pass to the scriptblock used to initialize the module89        /// </param>90        /// <param name="ss">The session state instance to use for this module - may be null.</param>91        /// <param name="results">The results produced from evaluating the scriptblock.</param>92        /// <returns>The newly created module info object.</returns>93        internal PSModuleInfo CreateModule(string name, string path, ScriptBlock scriptBlock, SessionState ss, out List<object> results, params object[] arguments)94        {95            return CreateModuleImplementation(name, path, scriptBlock, null, ss, null, out results, arguments);96        }97 98        /// <summary>99        /// Create a new module object from a ScriptInfo object.100        /// </summary>101        /// <param name="path">The path where the module is rooted.</param>102        /// <param name="scriptInfo">The script info to use to create the module.</param>103        /// <param name="scriptPosition">The position for the command that loaded this module.</param>104        /// <param name="arguments">Optional arguments to pass to the script while executing.</param>105        /// <param name="ss">The session state instance to use for this module - may be null.</param>106        /// <param name="privateData">The private data to use for this module - may be null.</param>107        /// <returns>The constructed module object.</returns>108        internal PSModuleInfo CreateModule(string path, ExternalScriptInfo scriptInfo, IScriptExtent scriptPosition, SessionState ss, object privateData, params object[] arguments)109        {110            List<object> result;111            return CreateModuleImplementation(ModuleIntrinsics.GetModuleName(path), path, scriptInfo, scriptPosition, ss, privateData, out result, arguments);112        }113 114        /// <summary>115        /// Create a new module object from code specifying the path to set for the module.116        /// </summary>117        /// <param name="name">The name of the module.</param>118        /// <param name="path">The path to use for the module root.</param>119        /// <param name="moduleCode">120        /// The code to use to create the module. This can be one of ScriptBlock, string121        /// or ExternalScriptInfo122        /// </param>123        /// <param name="arguments">124        /// Arguments to pass to the module scriptblock during evaluation.125        /// </param>126        /// <param name="result">127        /// The results of the evaluation of the scriptblock.128        /// </param>129        /// <param name="scriptPosition">130        /// The position of the caller of this function so you can tell where the call131        /// to Import-Module (or whatever) occurred. This can be null.132        /// </param>133        /// <param name="ss">The session state instance to use for this module - may be null.</param>134        /// <param name="privateData">The private data to use for this module - may be null.</param>135        /// <returns>The created module.</returns>136        private PSModuleInfo CreateModuleImplementation(string name, string path, object moduleCode, IScriptExtent scriptPosition, SessionState ss, object privateData, out List<object> result, params object[] arguments)137        {138            ScriptBlock sb;139 140            // By default the top-level scope in a session state object is the global scope for the instance.141            // For modules, we need to set its global scope to be another scope object and, chain the top142            // level scope for this sessionstate instance to be the parent. The top level scope for this ss is the143            // script scope for the ss.144 145            // Allocate the session state instance for this module.146            ss ??= new SessionState(_context, true, true);147 148            // Now set up the module's session state to be the current session state149            SessionStateInternal oldSessionState = _context.EngineSessionState;150            PSModuleInfo module = new PSModuleInfo(name, path, _context, ss);151            ss.Internal.Module = module;152            module.PrivateData = privateData;153 154            bool setExitCode = false;155            int exitCode = 0;156 157            try158            {159                _context.EngineSessionState = ss.Internal;160 161                // Build the scriptblock at this point so the references to the module162                // context are correct...163                ExternalScriptInfo scriptInfo = moduleCode as ExternalScriptInfo;164                if (scriptInfo != null)165                {166                    sb = scriptInfo.ScriptBlock;167 168                    _context.Debugger.RegisterScriptFile(scriptInfo);169                }170                else171                {172                    sb = moduleCode as ScriptBlock;173                    if (sb != null)174                    {175                        PSLanguageMode? moduleLanguageMode = sb.LanguageMode;176                        sb = sb.Clone();177                        sb.LanguageMode = moduleLanguageMode;178 179                        sb.SessionState = ss;180                    }181                    else if (moduleCode is string sbText)182                    {183                        sb = ScriptBlock.Create(_context, sbText);184                    }185                }186 187                if (sb == null)188                    throw PSTraceSource.NewInvalidOperationException();189 190                sb.SessionStateInternal = ss.Internal;191                module.LanguageMode = sb.LanguageMode;192 193                InvocationInfo invocationInfo = new InvocationInfo(scriptInfo, scriptPosition);194 195                // Save the module string196                module._definitionExtent = sb.Ast.Extent;197                var ast = sb.Ast;198                while (ast.Parent != null)199                {200                    ast = ast.Parent;201                }202 203                // The variables set in the interpreted case get set by InvokeWithPipe in the compiled case.204                Diagnostics.Assert(_context.SessionState.Internal.CurrentScope.LocalsTuple == null,205                                    "No locals tuple should have been created yet.");206 207                List<object> resultList = new List<object>();208 209                try210                {211                    Pipe outputPipe = new Pipe(resultList);212 213                    // And run the scriptblock...214                    sb.InvokeWithPipe(215                        useLocalScope: false,216                        errorHandlingBehavior: ScriptBlock.ErrorHandlingBehavior.WriteToCurrentErrorPipe,217                        dollarUnder: AutomationNull.Value,218                        input: AutomationNull.Value,219                        scriptThis: AutomationNull.Value,220                        outputPipe: outputPipe,221                        invocationInfo: invocationInfo,222                        args: arguments ?? Array.Empty<object>());223                }224                catch (ExitException ee)225                {226                    exitCode = (int)ee.Argument;227                    setExitCode = true;228                }229 230                result = resultList;231            }232            finally233            {234                _context.EngineSessionState = oldSessionState;235            }236 237            if (setExitCode)238            {239                _context.SetVariable(SpecialVariables.LastExitCodeVarPath, exitCode);240            }241 242            module.ImplementingAssembly = sb.AssemblyDefiningPSTypes;243            // We force re-population of ExportedTypeDefinitions, now with the actual RuntimeTypes, created above.244            module.CreateExportedTypeDefinitions(sb.Ast as ScriptBlockAst);245 246            return module;247        }248 249        /// <summary>250        /// Allocate a new dynamic module then return a new scriptblock251        /// bound to the module instance.252        /// </summary>253        /// <param name="context">Context to use to create bounded script.</param>254        /// <param name="sb">The scriptblock to bind.</param>255        /// <param name="linkToGlobal">Whether it should be linked to the global session state or not.</param>256        /// <returns>A new scriptblock.</returns>257        internal ScriptBlock CreateBoundScriptBlock(ExecutionContext context, ScriptBlock sb, bool linkToGlobal)258        {259            PSModuleInfo module = new PSModuleInfo(context, linkToGlobal);260            return module.NewBoundScriptBlock(sb, context);261        }262 263        internal List<PSModuleInfo> GetModules(string[] patterns, bool all)264        {265            return GetModuleCore(patterns, all, false);266        }267 268        internal List<PSModuleInfo> GetExactMatchModules(string moduleName, bool all, bool exactMatch)269        {270            moduleName ??= string.Empty;271 272            return GetModuleCore(new string[] { moduleName }, all, exactMatch);273        }274 275        private List<PSModuleInfo> GetModuleCore(string[] patterns, bool all, bool exactMatch)276        {277            string targetModuleName = null;278            List<WildcardPattern> wcpList = new List<WildcardPattern>();279 280            if (exactMatch)281            {282                Dbg.Assert(patterns.Length == 1, "The 'patterns' should only contain one element when it is for an exact match");283                targetModuleName = patterns[0];284            }285            else286            {287                patterns ??= new string[] { "*" };288 289                foreach (string pattern in patterns)290                {291                    wcpList.Add(WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase));292                }293            }294 295            List<PSModuleInfo> modulesMatched = new List<PSModuleInfo>();296 297            if (all)298            {299                foreach (PSModuleInfo module in ModuleTable.Values)300                {301                    // See if this is the requested module...302                    if ((exactMatch && module.Name.Equals(targetModuleName, StringComparison.OrdinalIgnoreCase)) ||303                        (!exactMatch && SessionStateUtilities.MatchesAnyWildcardPattern(module.Name, wcpList, false)))304                    {305                        modulesMatched.Add(module);306                    }307                }308            }309            else310            {311                // Create a joint list of local and global modules. Only report a module once.312                // Local modules are reported before global modules...313                Dictionary<string, bool> found = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);314                foreach (var pair in _context.EngineSessionState.ModuleTable)315                {316                    string path = pair.Key;317                    PSModuleInfo module = pair.Value;318                    // See if this is the requested module...319                    if ((exactMatch && module.Name.Equals(targetModuleName, StringComparison.OrdinalIgnoreCase)) ||320                        (!exactMatch && SessionStateUtilities.MatchesAnyWildcardPattern(module.Name, wcpList, false)))321                    {322                        modulesMatched.Add(module);323                        found[path] = true;324                    }325                }326 327                if (_context.EngineSessionState != _context.TopLevelSessionState)328                {329                    foreach (var pair in _context.TopLevelSessionState.ModuleTable)330                    {331                        string path = pair.Key;332                        if (!found.ContainsKey(path))333                        {334                            PSModuleInfo module = pair.Value;335                            // See if this is the requested module...336                            if ((exactMatch && module.Name.Equals(targetModuleName, StringComparison.OrdinalIgnoreCase)) ||337                                (!exactMatch && SessionStateUtilities.MatchesAnyWildcardPattern(module.Name, wcpList, false)))338                            {339                                modulesMatched.Add(module);340                            }341                        }342                    }343                }344            }345 346            return modulesMatched.OrderBy(static m => m.Name).ToList();347        }348 349        internal List<PSModuleInfo> GetModules(ModuleSpecification[] fullyQualifiedName, bool all)350        {351            List<PSModuleInfo> modulesMatched = new List<PSModuleInfo>();352 353            if (all)354            {355                foreach (var moduleSpec in fullyQualifiedName)356                {357                    foreach (PSModuleInfo module in ModuleTable.Values)358                    {359                        // See if this is the requested module...360                        if (IsModuleMatchingModuleSpec(module, moduleSpec))361                        {362                            modulesMatched.Add(module);363                        }364                    }365                }366            }367            else368            {369                foreach (var moduleSpec in fullyQualifiedName)370                {371                    // Create a joint list of local and global modules. Only report a module once.372                    // Local modules are reported before global modules...373                    Dictionary<string, bool> found = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);374                    foreach (var pair in _context.EngineSessionState.ModuleTable)375                    {376                        string path = pair.Key;377                        PSModuleInfo module = pair.Value;378                        // See if this is the requested module...379                        if (IsModuleMatchingModuleSpec(module, moduleSpec))380                        {381                            modulesMatched.Add(module);382                            found[path] = true;383                        }384                    }385 386                    if (_context.EngineSessionState != _context.TopLevelSessionState)387                    {388                        foreach (var pair in _context.TopLevelSessionState.ModuleTable)389                        {390                            string path = pair.Key;391                            if (!found.ContainsKey(path))392                            {393                                PSModuleInfo module = pair.Value;394                                // See if this is the requested module...395                                if (IsModuleMatchingModuleSpec(module, moduleSpec))396                                {397                                    modulesMatched.Add(module);398                                }399                            }400                        }401                    }402                }403            }404 405            return modulesMatched.OrderBy(static m => m.Name).ToList();406        }407 408        /// <summary>409        /// Check if a given module info object matches a given module specification.410        /// </summary>411        /// <param name="moduleInfo">The module info object to check.</param>412        /// <param name="moduleSpec">The module specification to match the module info object against.</param>413        /// <param name="skipNameCheck">True if we should skip the name check on the module specification.</param>414        /// <returns>True if the module info object meets all the constraints on the module specification, false otherwise.</returns>415        internal static bool IsModuleMatchingModuleSpec(416            PSModuleInfo moduleInfo,417            ModuleSpecification moduleSpec,418            bool skipNameCheck = false)419        {420            return IsModuleMatchingModuleSpec(out ModuleMatchFailure matchFailureReason, moduleInfo, moduleSpec, skipNameCheck);421        }422 423        /// <summary>424        /// Check if a given module info object matches a given module specification.425        /// </summary>426        /// <param name="matchFailureReason">The constraint that caused the match failure, if any.</param>427        /// <param name="moduleInfo">The module info object to check.</param>428        /// <param name="moduleSpec">The module specification to match the module info object against.</param>429        /// <param name="skipNameCheck">True if we should skip the name check on the module specification.</param>430        /// <returns>True if the module info object meets all the constraints on the module specification, false otherwise.</returns>431        internal static bool IsModuleMatchingModuleSpec(432            out ModuleMatchFailure matchFailureReason,433            PSModuleInfo moduleInfo,434            ModuleSpecification moduleSpec,435            bool skipNameCheck = false)436        {437            if (moduleSpec == null)438            {439                matchFailureReason = ModuleMatchFailure.NullModuleSpecification;440                return false;441            }442 443            return IsModuleMatchingConstraints(444                out matchFailureReason,445                moduleInfo,446                skipNameCheck ? null : moduleSpec.Name,447                moduleSpec.Guid,448                moduleSpec.RequiredVersion,449                moduleSpec.Version,450                moduleSpec.MaximumVersion == null ? null : ModuleCmdletBase.GetMaximumVersion(moduleSpec.MaximumVersion));451        }452 453        /// <summary>454        /// Check if a given module info object matches the given constraints.455        /// Constraints given as null are ignored.456        /// </summary>457        /// <param name="moduleInfo">The module info object to check.</param>458        /// <param name="name">The name or normalized absolute path of the expected module.</param>459        /// <param name="guid">The guid of the expected module.</param>460        /// <param name="requiredVersion">The required version of the expected module.</param>461        /// <param name="minimumVersion">The minimum required version of the expected module.</param>462        /// <param name="maximumVersion">The maximum required version of the expected module.</param>463        /// <returns>True if the module info object matches all given constraints, false otherwise.</returns>464        internal static bool IsModuleMatchingConstraints(465            PSModuleInfo moduleInfo,466            string name = null,467            Guid? guid = null,468            Version requiredVersion = null,469            Version minimumVersion = null,470            Version maximumVersion = null)471        {472            return IsModuleMatchingConstraints(473                out ModuleMatchFailure matchFailureReason,474                moduleInfo,475                name,476                guid,477                requiredVersion,478                minimumVersion,479                maximumVersion);480        }481 482        /// <summary>483        /// Check if a given module info object matches the given constraints.484        /// Constraints given as null are ignored.485        /// </summary>486        /// <param name="matchFailureReason">The reason for the module constraint match failing.</param>487        /// <param name="moduleInfo">The module info object to check.</param>488        /// <param name="name">The name or normalized absolute path of the expected module.</param>489        /// <param name="guid">The guid of the expected module.</param>490        /// <param name="requiredVersion">The required version of the expected module.</param>491        /// <param name="minimumVersion">The minimum required version of the expected module.</param>492        /// <param name="maximumVersion">The maximum required version of the expected module.</param>493        /// <returns>True if the module info object matches all given constraints, false otherwise.</returns>494        internal static bool IsModuleMatchingConstraints(495            out ModuleMatchFailure matchFailureReason,496            PSModuleInfo moduleInfo,497            string name,498            Guid? guid,499            Version requiredVersion,500            Version minimumVersion,501            Version maximumVersion)502        {503            // Define that a null module does not meet any constraints504            if (moduleInfo == null)505            {506                matchFailureReason = ModuleMatchFailure.NullModule;507                return false;508            }509 510            return AreModuleFieldsMatchingConstraints(511                out matchFailureReason,512                moduleInfo.Name,513                moduleInfo.Path,514                moduleInfo.Guid,515                moduleInfo.Version,516                name,517                guid,518                requiredVersion,519                minimumVersion,520                maximumVersion521            );522        }523 524        /// <summary>525        /// Check that given module fields meet any given constraints.526        /// </summary>527        /// <param name="moduleName">The name of the module to check.</param>528        /// <param name="modulePath">The path of the module to check.</param>529        /// <param name="moduleGuid">The GUID of the module to check.</param>530        /// <param name="moduleVersion">The version of the module to check.</param>531        /// <param name="requiredName">The name or normalized absolute path the module must have, if any.</param>532        /// <param name="requiredGuid">The GUID the module must have, if any.</param>533        /// <param name="requiredVersion">The exact version the module must have, if any.</param>534        /// <param name="minimumRequiredVersion">The minimum version the module may have, if any.</param>535        /// <param name="maximumRequiredVersion">The maximum version the module may have, if any.</param>536        /// <returns>True if the module parameters match all given constraints, false otherwise.</returns>537        internal static bool AreModuleFieldsMatchingConstraints(538            string moduleName = null,539            string modulePath = null,540            Guid? moduleGuid = null,541            Version moduleVersion = null,542            string requiredName = null,543            Guid? requiredGuid = null,544            Version requiredVersion = null,545            Version minimumRequiredVersion = null,546            Version maximumRequiredVersion = null)547        {548            return AreModuleFieldsMatchingConstraints(549                out ModuleMatchFailure matchFailureReason,550                moduleName,551                modulePath,552                moduleGuid,553                moduleVersion,554                requiredName,555                requiredGuid,556                requiredVersion,557                minimumRequiredVersion,558                maximumRequiredVersion);559        }560 561        /// <summary>562        /// Check that given module fields meet any given constraints.563        /// </summary>564        /// <param name="matchFailureReason">The reason the match failed, if any.</param>565        /// <param name="moduleName">The name of the module to check.</param>566        /// <param name="modulePath">The path of the module to check.</param>567        /// <param name="moduleGuid">The GUID of the module to check.</param>568        /// <param name="moduleVersion">The version of the module to check.</param>569        /// <param name="requiredName">The name or normalized absolute path the module must have, if any.</param>570        /// <param name="requiredGuid">The GUID the module must have, if any.</param>571        /// <param name="requiredVersion">The exact version the module must have, if any.</param>572        /// <param name="minimumRequiredVersion">The minimum version the module may have, if any.</param>573        /// <param name="maximumRequiredVersion">The maximum version the module may have, if any.</param>574        /// <returns>True if the module parameters match all given constraints, false otherwise.</returns>575        internal static bool AreModuleFieldsMatchingConstraints(576            out ModuleMatchFailure matchFailureReason,577            string moduleName,578            string modulePath,579            Guid? moduleGuid,580            Version moduleVersion,581            string requiredName,582            Guid? requiredGuid,583            Version requiredVersion,584            Version minimumRequiredVersion,585            Version maximumRequiredVersion)586        {587            // If a name is required, check that it matches.588            // A required module name may also be an absolute path, so check it against the given module's path as well.589            if (requiredName != null590                && !requiredName.Equals(moduleName, StringComparison.OrdinalIgnoreCase)591                && !MatchesModulePath(modulePath, requiredName))592            {593                matchFailureReason = ModuleMatchFailure.Name;594                return false;595            }596 597            // If a GUID is required, check it matches598            if (requiredGuid != null && !requiredGuid.Equals(moduleGuid))599            {600                matchFailureReason = ModuleMatchFailure.Guid;601                return false;602            }603 604            // Check the versions605            return IsVersionMatchingConstraints(out matchFailureReason, moduleVersion, requiredVersion, minimumRequiredVersion, maximumRequiredVersion);606        }607 608        /// <summary>609        /// Check that a given module version matches the required or minimum/maximum version constraints.610        /// Null constraints are not checked.611        /// </summary>612        /// <param name="version">The module version to check. Must not be null.</param>613        /// <param name="requiredVersion">The version that the given version must be, if not null.</param>614        /// <param name="minimumVersion">The minimum version that the given version must be greater than or equal to, if not null.</param>615        /// <param name="maximumVersion">The maximum version that the given version must be less then or equal to, if not null.</param>616        /// <returns>617        /// True if the version matches the required version, or if it is absent, is between the minimum and maximum versions, and false otherwise.618        /// </returns>619        internal static bool IsVersionMatchingConstraints(620            Version version,621            Version requiredVersion = null,622            Version minimumVersion = null,623            Version maximumVersion = null)624        {625            return IsVersionMatchingConstraints(out ModuleMatchFailure matchFailureReason, version, requiredVersion, minimumVersion, maximumVersion);626        }627 628        /// <summary>629        /// Check that a given module version matches the required or minimum/maximum version constraints.630        /// Null constraints are not checked.631        /// </summary>632        /// <param name="matchFailureReason">The reason why the match failed.</param>633        /// <param name="version">The module version to check. Must not be null.</param>634        /// <param name="requiredVersion">The version that the given version must be, if not null.</param>635        /// <param name="minimumVersion">The minimum version that the given version must be greater than or equal to, if not null.</param>636        /// <param name="maximumVersion">The maximum version that the given version must be less then or equal to, if not null.</param>637        /// <returns>638        /// True if the version matches the required version, or if it is absent, is between the minimum and maximum versions, and false otherwise.639        /// </returns>640        internal static bool IsVersionMatchingConstraints(641            out ModuleMatchFailure matchFailureReason,642            Version version,643            Version requiredVersion = null,644            Version minimumVersion = null,645            Version maximumVersion = null)646        {647            Dbg.Assert(version != null, $"Caller to verify that {nameof(version)} is not null");648 649            // If a RequiredVersion is given it overrides other version settings650            if (requiredVersion != null)651            {652                matchFailureReason = ModuleMatchFailure.RequiredVersion;653                return requiredVersion.Equals(version);654            }655 656            // Check the version is at least the minimum version657            if (minimumVersion != null && version < minimumVersion)658            {659                matchFailureReason = ModuleMatchFailure.MinimumVersion;660                return false;661            }662 663            // Check the version is at most the maximum version664            if (maximumVersion != null && version > maximumVersion)665            {666                matchFailureReason = ModuleMatchFailure.MaximumVersion;667                return false;668            }669 670            matchFailureReason = ModuleMatchFailure.None;671            return true;672        }673 674        /// <summary>675        /// Checks whether a given module path is the same as676        /// a required path.677        /// </summary>678        /// <param name="modulePath">The path of the module whose path to check. This must be the path to the module file (.psd1, .psm1, .dll, etc).</param>679        /// <param name="requiredPath">The path of the required module. This may be the module directory path or the file path. Only normalized absolute paths will work for this.</param>680        /// <returns>True if the module path matches the required path, false otherwise.</returns>681        internal static bool MatchesModulePath(string modulePath, string requiredPath)682        {683            Dbg.Assert(requiredPath != null, $"Caller to verify that {nameof(requiredPath)} is not null");684 685            if (modulePath == null)686            {687                return false;688            }689 690#if UNIX691            const StringComparison strcmp = StringComparison.Ordinal;692#else693            const StringComparison strcmp = StringComparison.OrdinalIgnoreCase;694#endif695 696            // We must check modulePath (e.g. /path/to/module/module.psd1) against several possibilities:697            // 1. "/path/to/module"                 - Module dir path698            // 2. "/path/to/module/module.psd1"     - Module root file path699            // 3. "/path/to/module/2.1/module.psd1" - Versioned module path700 701            // If the required module just matches the module path (case 1), we are done702            if (modulePath.Equals(requiredPath, strcmp))703            {704                return true;705            }706 707            // At this point we are looking for the module directory (case 2 or 3).708            // We can some allocations here if module path doesn't sit under the required path709            // (the required path may still refer to some nested module though)710            if (!modulePath.StartsWith(requiredPath, strcmp))711            {712                return false;713            }714 715            string moduleDirPath = Path.GetDirectoryName(modulePath);716 717            // The module itself may be in a versioned directory (case 3)718            if (Version.TryParse(Path.GetFileName(moduleDirPath), out _))719            {720                moduleDirPath = Path.GetDirectoryName(moduleDirPath);721            }722 723            return moduleDirPath.Equals(requiredPath, strcmp);724        }725 726        /// <summary>727        /// Takes the name of a module as used in a module specification728        /// and either returns it as a simple name (if it was a simple name)729        /// or a fully qualified, PowerShell-resolved path.730        /// </summary>731        /// <param name="moduleName">The name or path of the module from the specification.</param>732        /// <param name="basePath">The path to base relative paths off.</param>733        /// <param name="executionContext">The current execution context.</param>734        /// <returns>735        /// The simple module name if the given one was simple,736        /// otherwise a fully resolved, absolute path to the module.737        /// </returns>738        /// <remarks>739        /// 2018-11-09 rjmholt:740        /// There are several, possibly inconsistent, path handling mechanisms741        /// in the module cmdlets. After looking through all of them and seeing742        /// they all make some assumptions about their caller I wrote this method.743        /// Hopefully we can find a standard path resolution API to settle on.744        /// </remarks>745        internal static string NormalizeModuleName(746            string moduleName,747            string basePath,748            ExecutionContext executionContext)749        {750            if (moduleName == null)751            {752                return null;753            }754 755            // Check whether the module is a path -- if not, it is a simple name and we just return it.756            if (!IsModuleNamePath(moduleName))757            {758                return moduleName;759            }760 761            // Standardize directory separators -- Path.IsPathRooted() will return false for "\path\here" on *nix and for "/path/there" on Windows762            moduleName = moduleName.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator);763 764            // Note: Path.IsFullyQualified("\default\root") is false on Windows, but Path.IsPathRooted returns true765            if (!Path.IsPathRooted(moduleName))766            {767                moduleName = Path.Join(basePath, moduleName);768            }769 770            // Use the PowerShell filesystem provider to fully resolve the path771            // If there is a problem, null could be returned -- so default back to the pre-normalized path772            string normalizedPath = ModuleCmdletBase.GetResolvedPath(moduleName, executionContext)?.TrimEnd(StringLiterals.DefaultPathSeparator);773 774            // ModuleCmdletBase.GetResolvePath will return null in the unlikely event that it failed.775            // If it does, we return the fully qualified path generated before.776            return normalizedPath ?? Path.GetFullPath(moduleName);777        }778 779        /// <summary>780        /// Check if a given module name is a path to a module rather than a simple name.781        /// </summary>782        /// <param name="moduleName">The module name to check.</param>783        /// <returns>True if the module name is a path, false otherwise.</returns>784        internal static bool IsModuleNamePath(string moduleName)785        {786            return moduleName.Contains(StringLiterals.DefaultPathSeparator)787                || moduleName.Contains(StringLiterals.AlternatePathSeparator)788                || moduleName.Equals("..")789                || moduleName.Equals(".");790        }791 792        internal static Version GetManifestModuleVersion(string manifestPath)793        {794            try795            {796                Hashtable dataFileSetting =797                    PsUtils.GetModuleManifestProperties(798                        manifestPath,799                        PsUtils.ManifestModuleVersionPropertyName);800 801                object versionValue = dataFileSetting["ModuleVersion"];802                if (versionValue != null)803                {804                    Version moduleVersion;805                    if (LanguagePrimitives.TryConvertTo(versionValue, out moduleVersion))806                    {807                        return moduleVersion;808                    }809                }810            }811            catch (PSInvalidOperationException) { }812 813            return new Version(0, 0);814        }815 816        internal static Guid GetManifestGuid(string manifestPath)817        {818            try819            {820                Hashtable dataFileSetting =821                    PsUtils.GetModuleManifestProperties(822                        manifestPath,823                        PsUtils.ManifestGuidPropertyName);824 825                object guidValue = dataFileSetting["GUID"];826                if (guidValue != null)827                {828                    Guid guidID;829                    if (LanguagePrimitives.TryConvertTo(guidValue, out guidID))830                    {831                        return guidID;832                    }833                }834            }835            catch (PSInvalidOperationException) { }836 837            return new Guid();838        }839 840        internal static ExperimentalFeature[] GetExperimentalFeature(string manifestPath)841        {842            try843            {844                Hashtable dataFileSetting =845                    PsUtils.GetModuleManifestProperties(846                        manifestPath,847                        PsUtils.ManifestPrivateDataPropertyName);848 849                object privateData = dataFileSetting["PrivateData"];850                if (privateData is Hashtable hashData && hashData["PSData"] is Hashtable psData)851                {852                    object expFeatureValue = psData["ExperimentalFeatures"];853                    if (expFeatureValue != null &&854                        LanguagePrimitives.TryConvertTo(expFeatureValue, out Hashtable[] features) &&855                        features.Length > 0)856                    {857                        string moduleName = ModuleIntrinsics.GetModuleName(manifestPath);858                        var expFeatureList = new List<ExperimentalFeature>();859                        foreach (Hashtable feature in features)860                        {861                            string featureName = feature["Name"] as string;862                            if (string.IsNullOrEmpty(featureName))863                            {864                                continue;865                            }866 867                            if (ExperimentalFeature.IsModuleFeatureName(featureName, moduleName))868                            {869                                string featureDescription = feature["Description"] as string;870                                expFeatureList.Add(new ExperimentalFeature(featureName, featureDescription, manifestPath,871                                                                           ExperimentalFeature.IsEnabled(featureName)));872                            }873                        }874 875                        return expFeatureList.ToArray();876                    }877                }878            }879            catch (PSInvalidOperationException) { }880 881            return Array.Empty<ExperimentalFeature>();882        }883 884        // The extensions of all of the files that can be processed with Import-Module, put the ni.dll in front of .dll to have higher priority to be loaded.885        internal static readonly string[] PSModuleProcessableExtensions = new string[]886        {887            StringLiterals.PowerShellDataFileExtension,888            StringLiterals.PowerShellScriptFileExtension,889            StringLiterals.PowerShellModuleFileExtension,890            StringLiterals.PowerShellCmdletizationFileExtension,891            StringLiterals.PowerShellNgenAssemblyExtension,892            StringLiterals.PowerShellILAssemblyExtension,893            StringLiterals.PowerShellILExecutableExtension,894        };895 896        // A list of the extensions to check for implicit module loading and discovery, put the ni.dll in front of .dll to have higher priority to be loaded.897        internal static readonly string[] PSModuleExtensions = new string[]898        {899            StringLiterals.PowerShellDataFileExtension,900            StringLiterals.PowerShellModuleFileExtension,901            StringLiterals.PowerShellCmdletizationFileExtension,902            StringLiterals.PowerShellNgenAssemblyExtension,903            StringLiterals.PowerShellILAssemblyExtension,904            StringLiterals.PowerShellILExecutableExtension,905        };906 907        // A list of the extensions to check for required assemblies.908        internal static readonly string[] ProcessableAssemblyExtensions = new string[]909        {910            StringLiterals.PowerShellNgenAssemblyExtension,911            StringLiterals.PowerShellILAssemblyExtension,912            StringLiterals.PowerShellILExecutableExtension913        };914 915        /// <summary>916        /// Returns true if the extension is one of the module extensions...917        /// </summary>918        /// <param name="extension">The extension to check.</param>919        /// <returns>True if it was a module extension...</returns>920        internal static bool IsPowerShellModuleExtension(string extension)921        {922            foreach (string ext in PSModuleProcessableExtensions)923            {924                if (extension.Equals(ext, StringComparison.OrdinalIgnoreCase))925                {926                    return true;927                }928            }929 930            return false;931        }932 933        /// <summary>934        /// Gets the module name from module path.935        /// </summary>936        /// <param name="path">The path to the module.</param>937        /// <returns>The module name.</returns>938        internal static string GetModuleName(string path)939        {940            string fileName = path == null ? string.Empty : Path.GetFileName(path);941            string ext;942            if (fileName.EndsWith(StringLiterals.PowerShellNgenAssemblyExtension, StringComparison.OrdinalIgnoreCase))943            {944                ext = StringLiterals.PowerShellNgenAssemblyExtension;945            }946            else947            {948                ext = Path.GetExtension(fileName);949            }950 951            if (!string.IsNullOrEmpty(ext) && IsPowerShellModuleExtension(ext))952            {953                return fileName.Substring(0, fileName.Length - ext.Length);954            }955            else956            {957                return fileName;958            }959        }960 961        /// <summary>962        /// Gets the personal module path.963        /// </summary>964        /// <returns>Personal module path.</returns>965        internal static string GetPersonalModulePath()966        {967#if UNIX968            return Platform.SelectProductNameForDirectory(Platform.XDG_Type.USER_MODULES);969#else970            string myDocumentsPath = InternalTestHooks.SetMyDocumentsSpecialFolderToBlank ? string.Empty : Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);971            return string.IsNullOrEmpty(myDocumentsPath) ? null : Path.Combine(myDocumentsPath, Utils.ModuleDirectory);972#endif973        }974 975        /// <summary>976        /// Gets the PSHome module path, as known as the "system wide module path" in windows powershell.977        /// </summary>978        /// <returns>The PSHome module path.</returns>979        internal static string GetPSHomeModulePath()980        {981            if (s_psHomeModulePath != null)982            {983                return s_psHomeModulePath;984            }985 986            try987            {988                string psHome = Utils.DefaultPowerShellAppBase;989#if !UNIX990                // Win8: 584267 Powershell Modules are listed twice in x86, and cannot be removed.991                // This happens because 'ModuleTable' uses Path as the key and x86 WinPS has "SysWOW64" in its $PSHOME.992                // Because of this, the module that is getting loaded during startup (through LocalRunspace) is using993                // "SysWow64" in the key. Later, when 'Import-Module' is called, it loads the module using ""System32"994                // in the key.995                // For the cross-platform PowerShell, a user can choose to install it under "C:\Windows\SysWOW64", and996                // thus it may have the same problem as described above. So we keep this line of code.997                psHome = psHome.ToLowerInvariant().Replace(@"\syswow64\", @"\system32\");998#endif999                Interlocked.CompareExchange(ref s_psHomeModulePath, Path.Combine(psHome, "Modules"), null);1000            }1001            catch (System.Security.SecurityException)1002            {1003            }1004 1005            return s_psHomeModulePath;1006        }1007 1008        private static string s_psHomeModulePath;1009 1010        /// <summary>1011        /// Get the module path that is shared among different users.1012        /// It's known as "Program Files" module path in windows powershell.1013        /// </summary>1014        /// <returns></returns>1015        internal static string GetSharedModulePath()1016        {1017#if UNIX1018            return Platform.SelectProductNameForDirectory(Platform.XDG_Type.SHARED_MODULES);1019#else1020            string sharedModulePath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);1021 1022            if (!string.IsNullOrEmpty(sharedModulePath))1023            {1024                sharedModulePath = Path.Combine(sharedModulePath, Utils.ModuleDirectory);1025            }1026 1027            return sharedModulePath;1028#endif1029        }1030 1031#if !UNIX1032        /// <summary>1033        /// Get the path to the Windows PowerShell module directory under the1034        /// System32 directory on Windows (the Windows PowerShell $PSHOME).1035        /// </summary>1036        /// <returns>The path of the Windows PowerShell system module directory.</returns>1037        internal static string GetWindowsPowerShellPSHomeModulePath()1038        {1039            if (!string.IsNullOrEmpty(InternalTestHooks.TestWindowsPowerShellPSHomeLocation))1040            {1041                return InternalTestHooks.TestWindowsPowerShellPSHomeLocation;1042            }1043 1044            return s_windowsPowerShellPSHomeModulePath;1045        }1046#endif1047 1048        /// <summary>1049        /// Combine the PS system-wide module path and the DSC module path1050        /// to get the system module paths.1051        /// </summary>1052        /// <returns></returns>1053        private static string CombineSystemModulePaths()1054        {1055            string psHomeModulePath = GetPSHomeModulePath();1056            string sharedModulePath = GetSharedModulePath();1057 1058            bool isPSHomePathNullOrEmpty = string.IsNullOrEmpty(psHomeModulePath);1059            bool isSharedPathNullOrEmpty = string.IsNullOrEmpty(sharedModulePath);1060 1061            if (!isPSHomePathNullOrEmpty && !isSharedPathNullOrEmpty)1062            {1063                return (sharedModulePath + Path.PathSeparator + psHomeModulePath);1064            }1065 1066            if (!isPSHomePathNullOrEmpty || !isSharedPathNullOrEmpty)1067            {1068                return isPSHomePathNullOrEmpty ? sharedModulePath : psHomeModulePath;1069            }1070 1071            return null;1072        }1073 1074        internal static string GetExpandedEnvironmentVariable(string name, EnvironmentVariableTarget target)1075        {1076            string result = Environment.GetEnvironmentVariable(name, target);1077            if (!string.IsNullOrEmpty(result))1078            {1079                result = Environment.ExpandEnvironmentVariables(result);1080            }1081 1082            return result;1083        }1084 1085        /// <summary>1086        /// Adds paths to a 'combined path' string (like %Path% or %PSModulePath%) if they are not already there.1087        /// </summary>1088        /// <param name="basePath">Path string (like %Path% or %PSModulePath%).</param>1089        /// <param name="pathToAdd">An individual path to add, or multiple paths separated by the path separator character.</param>1090        /// <param name="insertPosition">-1 to append to the end; 0 to insert in the beginning of the string; etc...</param>1091        /// <returns>Result string.</returns>1092        private static string UpdatePath(string basePath, string pathToAdd, ref int insertPosition)1093        {1094            // we don't support if any of the args are null - parent function should ensure this; empty values are ok1095            Dbg.Assert(basePath != null, "basePath should not be null according to contract of the function");1096            Dbg.Assert(pathToAdd != null, "pathToAdd should not be null according to contract of the function");1097 1098            // The 'pathToAdd' could be a 'combined path' (path-separator-separated).1099            string[] newPaths = pathToAdd.Split(1100                Path.PathSeparator,1101                StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);1102 1103            if (newPaths.Length is 0)1104            {1105                // The 'pathToAdd' doesn't really contain any paths to add.1106                return basePath;1107            }1108 1109            var result = new StringBuilder(basePath, capacity: basePath.Length + pathToAdd.Length + newPaths.Length);1110            var addedPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);1111            string[] initialPaths = basePath.Split(1112                Path.PathSeparator,1113                StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);1114 1115            foreach (string p in initialPaths)1116            {1117                // Remove the trailing directory separators.1118                // Trailing white spaces were already removed by 'StringSplitOptions.TrimEntries'.1119                addedPaths.Add(Path.TrimEndingDirectorySeparator(p));1120            }1121 1122            foreach (string subPathToAdd in newPaths)1123            {1124                // Remove the trailing directory separators.1125                // Trailing white spaces were already removed by 'StringSplitOptions.TrimEntries'.1126                string normalizedPath = Path.TrimEndingDirectorySeparator(subPathToAdd);1127                if (addedPaths.Contains(normalizedPath))1128                {1129                    // The normalized sub path was already added - skip it.1130                    continue;1131                }1132 1133                // The normalized sub path was not found - add it.1134                if (insertPosition is -1 || insertPosition >= result.Length)1135                {1136                    // Append the normalized sub path to the end.1137                    if (result.Length > 0 && result[^1] != Path.PathSeparator)1138                    {1139                        result.Append(Path.PathSeparator);1140                    }1141 1142                    result.Append(normalizedPath);1143                    // Next insertion should happen at the end.1144                    insertPosition = result.Length;1145                }1146                else1147                {1148                    // Insert at the requested location.1149                    // This is used by the user-specific module path, the shared module path (<Program Files> location), and the PSHome module path.1150                    string strToInsert = normalizedPath + Path.PathSeparator;1151                    result.Insert(insertPosition, strToInsert);1152 1153                    // Next insertion should happen after the just inserted string.1154                    insertPosition += strToInsert.Length;1155                }1156 1157                // Add it to the set.1158                addedPaths.Add(normalizedPath);1159            }1160 1161            return result.ToString();1162        }1163 1164        /// <summary>1165        /// The available module path scopes.1166        /// </summary>1167        public enum PSModulePathScope1168        {1169            /// <summary>The users module path.</summary>1170            User,1171 1172            /// <summary>The Builtin module path. This is where PowerShell is installed (PSHOME).</summary>1173            Builtin,1174 1175            /// <summary>The machine module path. This is the shared location for all users of the system.</summary>1176            Machine1177        }1178 1179        /// <summary>1180        /// Retrieve the current PSModulePath for the specified scope.1181        /// </summary>1182        /// <param name="scope">The scope of module path to retrieve. This can be User, Builtin, or Machine.</param>1183        /// <returns>The string representing the requested module path type.</returns>1184        public static string GetPSModulePath(PSModulePathScope scope)1185        {1186            if (scope == PSModulePathScope.User)1187            {1188                return GetPersonalModulePath();1189            }1190            else if (scope == PSModulePathScope.Builtin)1191            {1192                return GetPSHomeModulePath();1193            }1194            else1195            {1196                return GetSharedModulePath();1197            }1198        }1199 1200        /// <summary>

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