Example #1
0
        private IList<PSModuleInfo> ImportModule_RemotelyViaPsrpSession(
            ImportModuleOptions importModuleOptions,
            string moduleName,
            ModuleSpecification fullyQualifiedName,
            PSSession psSession)
        {
            //
            // import the module in the remote session first
            //
            List<PSObject> remotelyImportedModules;
            using (var powerShell = System.Management.Automation.PowerShell.Create())
            {
                powerShell.Runspace = psSession.Runspace;
                powerShell.AddCommand("Import-Module");
                powerShell.AddParameter("DisableNameChecking", this.DisableNameChecking);
                powerShell.AddParameter("PassThru", true);

                if (fullyQualifiedName != null)
                {
                    powerShell.AddParameter("FullyQualifiedName", fullyQualifiedName);
                }
                else
                {
                    powerShell.AddParameter("Name", moduleName);

                    if (this.MinimumVersion != null)
                    {
                        powerShell.AddParameter("Version", this.MinimumVersion);
                    }
                    if (this.RequiredVersion != null)
                    {
                        powerShell.AddParameter("RequiredVersion", this.RequiredVersion);
                    }
                    if (this.MaximumVersion != null)
                    {
                        powerShell.AddParameter("MaximumVersion", this.MaximumVersion);
                    }
                }
                if (this.ArgumentList != null)
                {
                    powerShell.AddParameter("ArgumentList", this.ArgumentList);
                }
                if (this.BaseForce)
                {
                    powerShell.AddParameter("Force", true);
                }

                string errorMessageTemplate = string.Format(
                    CultureInfo.InvariantCulture,
                    Modules.RemoteDiscoveryRemotePsrpCommandFailed,
                    string.Format(CultureInfo.InvariantCulture, "Import-Module -Name '{0}'", moduleName));
                remotelyImportedModules = RemoteDiscoveryHelper.InvokePowerShell(
                    powerShell,
                    this.CancellationToken,
                    this,
                    errorMessageTemplate).ToList();
            }

            List<PSModuleInfo> result = new List<PSModuleInfo>();
            foreach (PSObject remotelyImportedModule in remotelyImportedModules)
            {
                PSPropertyInfo nameProperty = remotelyImportedModule.Properties["Name"];
                if (nameProperty != null)
                {
                    string remoteModuleName = (string)LanguagePrimitives.ConvertTo(
                        nameProperty.Value,
                        typeof(string),
                        CultureInfo.InvariantCulture);

                    PSPropertyInfo helpInfoProperty = remotelyImportedModule.Properties["HelpInfoUri"];
                    string remoteHelpInfoUri = null;
                    if (helpInfoProperty != null)
                    {
                        remoteHelpInfoUri = (string)LanguagePrimitives.ConvertTo(
                            helpInfoProperty.Value,
                            typeof(string),
                            CultureInfo.InvariantCulture);
                    }

                    PSPropertyInfo guidProperty = remotelyImportedModule.Properties["Guid"];
                    Guid remoteModuleGuid = Guid.Empty;
                    if (guidProperty != null)
                    {
                        LanguagePrimitives.TryConvertTo(guidProperty.Value, out remoteModuleGuid);
                    }

                    PSPropertyInfo versionProperty = remotelyImportedModule.Properties["Version"];
                    Version remoteModuleVersion = null;
                    if (versionProperty != null)
                    {
                        Version tmp;
                        if (LanguagePrimitives.TryConvertTo<Version>(versionProperty.Value, CultureInfo.InvariantCulture, out tmp))
                        {
                            remoteModuleVersion = tmp;
                        }
                    }

                    PSModuleInfo moduleInfo = ImportModule_RemotelyViaPsrpSession_SinglePreimportedModule(
                        importModuleOptions,
                        remoteModuleName,
                        remoteModuleVersion,
                        psSession);

                    // Set the HelpInfoUri and Guid as necessary, so that Save-Help can work with this module object
                    // to retrieve help files from the remote site.
                    if (moduleInfo != null)
                    {
                        // set the HelpInfoUri if it's needed
                        if (string.IsNullOrEmpty(moduleInfo.HelpInfoUri) && !string.IsNullOrEmpty(remoteHelpInfoUri))
                        {
                            moduleInfo.SetHelpInfoUri(remoteHelpInfoUri);
                        }

                        // set the Guid if it's needed
                        if (remoteModuleGuid != Guid.Empty)
                        {
                            moduleInfo.SetGuid(remoteModuleGuid);
                        }

                        result.Add(moduleInfo);
                    }
                }
            }

            return result;
        }
Example #2
0
 internal void AddRequiredModuleSpecification(ModuleSpecification requiredModuleSpecification)
 {
     this._requiredModulesSpecification.Add(requiredModuleSpecification);
 }
        /// <summary>
        /// Gets a list of modules from the given pattern or ModuleSpecification
        /// </summary>
        /// <param name="pattern">pattern to match</param>
        /// <param name="fullyQualifiedName">ModuleSpecification</param>
        /// <param name="noErrors">skip errors</param>
        /// <returns>a list of modules</returns>
        internal Dictionary<Tuple<string, Version>, UpdatableHelpModuleInfo> GetModuleInfo(string pattern, ModuleSpecification fullyQualifiedName, bool noErrors)
        {
            Dictionary<Tuple<string, Version>, UpdatableHelpModuleInfo> modules = GetModuleInfo(Context, pattern, fullyQualifiedName, noErrors);

            if (modules.Count == 0 && _exceptions.Count == 0 && !noErrors)
            {
                var errorMessage = fullyQualifiedName != null ? StringUtil.Format(HelpDisplayStrings.ModuleNotFoundWithFullyQualifiedName, fullyQualifiedName)
                                                              : StringUtil.Format(HelpDisplayStrings.CannotMatchModulePattern, pattern);

                ErrorRecord errorRecord = new ErrorRecord(new Exception(errorMessage),
                    "ModuleNotFound", ErrorCategory.InvalidArgument, pattern);

                WriteError(errorRecord);
            }

            return modules;
        }
Example #4
0
        /// <summary>
        /// Resolves using module to a collection of PSModuleInfos. Doesn't throw.
        /// PSModuleInfo objects are returned in the right order: i.e. if multiply versions of the module
        /// is presented on the system and user didn't specify version, we will return all of them, but newer one would go first.
        /// </summary>
        /// <param name="usingStatementAst">using statement</param>
        /// <param name="exception">If exception happens, return exception object.</param>
        /// <param name="wildcardCharactersUsed">
        /// True if in the module name uses wildcardCharacter. 
        /// We don't want to resolve any wild-cards in using module.
        /// </param>
        /// <param name="isConstant">True if module hashtable contains constant value (it's our requirement).</param>
        /// <returns>Modules, if can resolve it. null if any problems happens.</returns>
        private Collection<PSModuleInfo> GetModulesFromUsingModule(UsingStatementAst usingStatementAst, out Exception exception, out bool wildcardCharactersUsed, out bool isConstant)
        {
            exception = null;
            wildcardCharactersUsed = false;
            isConstant = true;

            // fullyQualifiedName can be string or hashtable
            object fullyQualifiedName;
            if (usingStatementAst.ModuleSpecification != null)
            {
                object resultObject;
                if (!IsConstantValueVisitor.IsConstant(usingStatementAst.ModuleSpecification, out resultObject, forAttribute: false, forRequires: true))
                {
                    isConstant = false;
                    return null;
                }

                var hashtable = resultObject as System.Collections.Hashtable;
                var ms = new ModuleSpecification();
                exception = ModuleSpecification.ModuleSpecificationInitHelper(ms, hashtable);
                if (exception != null)
                {
                    return null;
                }

                if (WildcardPattern.ContainsWildcardCharacters(ms.Name))
                {
                    wildcardCharactersUsed = true;
                    return null;
                }

                fullyQualifiedName = ms;
            }
            else
            {
                string fullyQualifiedNameStr = usingStatementAst.Name.Value;

                if (WildcardPattern.ContainsWildcardCharacters(fullyQualifiedNameStr))
                {
                    wildcardCharactersUsed = true;
                    return null;
                }

                // case 1: relative path. Relative for file in the same folder should include .\
                bool isPath = fullyQualifiedNameStr.Contains(@"\");
                if (isPath && !LocationGlobber.IsAbsolutePath(fullyQualifiedNameStr))
                {
                    string rootPath = Path.GetDirectoryName(_parser._fileName);
                    if (rootPath != null)
                    {
                        fullyQualifiedNameStr = Path.Combine(rootPath, fullyQualifiedNameStr);
                    }
                }

                // case 2: Module by name
                // case 3: Absolute Path
                // We don't need to do anything for these cases, FullyQualifiedName already handle it.

                fullyQualifiedName = fullyQualifiedNameStr;
            }

            var commandInfo = new CmdletInfo("Get-Module", typeof(GetModuleCommand));
            // TODO(sevoroby): we should consider an async call with cancellation here.
            UsingStatementResolvePowerShell.Commands.Clear();
            try
            {
                return UsingStatementResolvePowerShell.AddCommand(commandInfo)
                    .AddParameter("FullyQualifiedName", fullyQualifiedName)
                    .AddParameter("ListAvailable", true)
                    .Invoke<PSModuleInfo>();
            }
            catch (Exception e)
            {
                exception = e;
                return null;
            }
        }
        /// <summary>
        /// Gets a list of modules from the given pattern
        /// </summary>
        /// <param name="context">execution context</param>
        /// <param name="pattern">pattern to search</param>
        /// <param name="fullyQualifiedName">Module Specification</param>
        /// <param name="noErrors">do not generate errors for modules without HelpInfoUri</param>
        /// <returns>a list of modules</returns>
        private Dictionary<Tuple<string, Version>, UpdatableHelpModuleInfo> GetModuleInfo(ExecutionContext context, string pattern, ModuleSpecification fullyQualifiedName, bool noErrors)
        {
            List<PSModuleInfo> modules = null;
            string moduleNamePattern = null;

            if (pattern != null)
            {
                moduleNamePattern = pattern;
                modules = Utils.GetModules(pattern, context);
            }
            else if (fullyQualifiedName != null)
            {
                moduleNamePattern = fullyQualifiedName.Name;
                modules = Utils.GetModules(fullyQualifiedName, context);
            }

            var helpModules = new Dictionary<Tuple<string, Version>, UpdatableHelpModuleInfo>();
            if (modules != null)
            {
                foreach (PSModuleInfo module in modules)
                {
                    ProcessSingleModuleObject(module, context, helpModules, noErrors);
                }
            }

            // Match wildcards
            WildcardOptions wildcardOptions = WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant;
            IEnumerable<WildcardPattern> patternList = SessionStateUtilities.CreateWildcardsFromStrings(new string[1] { moduleNamePattern }, wildcardOptions);

            foreach (KeyValuePair<string, string> name in s_metadataCache)
            {
                if (SessionStateUtilities.MatchesAnyWildcardPattern(name.Key, patternList, true))
                {
                    // For core snapin, there are no GUIDs. So, we need to construct the HelpInfo slightly differently
                    if (!name.Key.Equals(InitialSessionState.CoreSnapin, StringComparison.OrdinalIgnoreCase))
                    {
                        var keyTuple = new Tuple<string, Version>(name.Key, new Version("1.0"));
                        if (!helpModules.ContainsKey(keyTuple))
                        {
                            List<PSModuleInfo> availableModules = Utils.GetModules(name.Key, context);
                            if (null != availableModules)
                            {
                                foreach (PSModuleInfo module in availableModules)
                                {
                                    keyTuple = new Tuple<string, Version>(module.Name, module.Version);
                                    if (!helpModules.ContainsKey(keyTuple))
                                    {
                                        WriteDebug(StringUtil.Format("Found engine module: {0}, {1}.", module.Name, module.Guid));

                                        helpModules.Add(keyTuple, new UpdatableHelpModuleInfo(module.Name,
                                            module.Guid, Utils.GetApplicationBase(context.ShellID), s_metadataCache[module.Name]));
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        var keyTuple2 = new Tuple<string, Version>(name.Key, new Version("1.0"));
                        if (!helpModules.ContainsKey(keyTuple2))
                        {
                            helpModules.Add(keyTuple2,
                                            new UpdatableHelpModuleInfo(name.Key, Guid.Empty,
                                                                        Utils.GetApplicationBase(context.ShellID),
                                                                        name.Value));
                        }
                    }
                }
            }

            return helpModules;
        }
 /// <summary>
 /// Processes a ModuleSpecification with potential globbing
 /// </summary>
 /// <param name="fullyQualifiedName">ModuleSpecification</param>
 private void ProcessModuleWithGlobbing(ModuleSpecification fullyQualifiedName)
 {
     foreach (KeyValuePair<Tuple<string, Version>, UpdatableHelpModuleInfo> module in GetModuleInfo(null, fullyQualifiedName, false))
     {
         ProcessModule(module.Value);
     }
 }
        private static string GetModuleVersionStringFromModuleSpecification(ModuleSpecification moduleSpecification)
        {
            StringBuilder result = new StringBuilder();
            result.Append("(").Append(moduleSpecification.Name);
            if (moduleSpecification.Version != null)
            {
                result.Append(",").Append(moduleSpecification.Version).Append(")");
            }
            else
            {
                result.Append(")");
            }

            return result.ToString();
        }
Example #8
0
        /// <summary>
        /// Load DSC resources from specified module.
        /// </summary>
        /// <param name="scriptExtent">Script statement loading the module, can be null</param>
        /// <param name="moduleSpecifications">Module information, can be null.</param>
        /// <param name="resourceNames">Name of the resource to be loaded from module</param>
        /// <param name="errorList">List of errors reported by the method</param>
        public static void LoadResourcesFromModule(IScriptExtent scriptExtent,
                                                           ModuleSpecification[] moduleSpecifications,
                                                           string[] resourceNames,
                                                           List<ParseError> errorList)
        {
            // get all required modules
            var modules = new Collection<PSModuleInfo>();
            if (moduleSpecifications != null)
            {
                foreach (var moduleToImport in moduleSpecifications)
                {
                    bool foundModule = false;
                    var moduleInfos = ModuleCmdletBase.GetModuleIfAvailable(moduleToImport);

                    if (moduleInfos.Count >= 1 && (moduleToImport.Version != null || moduleToImport.Guid != null))
                    {
                        foreach (var psModuleInfo in moduleInfos)
                        {
                            if ((moduleToImport.Guid.HasValue && moduleToImport.Guid.Equals(psModuleInfo.Guid)) ||
                                (moduleToImport.Version != null &&
                                 moduleToImport.Version.Equals(psModuleInfo.Version)))
                            {
                                modules.Add(psModuleInfo);
                                foundModule = true;
                                break;
                            }
                        }
                    }
                    else if (moduleInfos.Count == 1)
                    {
                        modules.Add(moduleInfos[0]);
                        foundModule = true;
                    }

                    if (!foundModule)
                    {
                        if (moduleInfos.Count > 1)
                        {
                            errorList.Add(new ParseError(scriptExtent,
                                                         "MultipleModuleEntriesFoundDuringParse",
                                                         string.Format(CultureInfo.CurrentCulture,
                                                                       ParserStrings.MultipleModuleEntriesFoundDuringParse,
                                                                       moduleToImport.Name)));
                        }
                        else
                        {
                            string moduleString = moduleToImport.Version == null
                                ? moduleToImport.Name
                                : string.Format(CultureInfo.CurrentCulture, "<{0}, {1}>", moduleToImport.Name, moduleToImport.Version);

                            errorList.Add(new ParseError(scriptExtent, "ModuleNotFoundDuringParse",
                                string.Format(CultureInfo.CurrentCulture, ParserStrings.ModuleNotFoundDuringParse, moduleString)));
                        }
                        return;
                    }
                }
            }
            else if (resourceNames != null)
            {
                // Lookup the required resources under available PowerShell modules when modulename is not specified
                using (var powerShell = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace))
                {
                    powerShell.AddCommand("Get-Module");
                    powerShell.AddParameter("ListAvailable");
                    modules = powerShell.Invoke<PSModuleInfo>();
                }
            }

            // When ModuleName only specified, we need to import all resources from that module
            var resourcesToImport = new List<string>();
            if (resourceNames == null || resourceNames.Length == 0)
            {
                resourcesToImport.Add("*");
            }
            else
            {
                resourcesToImport.AddRange(resourceNames);
            }

            foreach (var moduleInfo in modules)
            {
                var dscResourcesPath = Path.Combine(moduleInfo.ModuleBase, "DscResources");

                var resourcesFound = new List<String>();
                LoadPowerShellClassResourcesFromModule(moduleInfo, moduleInfo, resourcesToImport, resourcesFound, errorList, null, true, scriptExtent);

                if (Directory.Exists(dscResourcesPath))
                {
                    foreach (var resourceToImport in resourcesToImport)
                    {
                        bool foundResources = false;
                        foreach (var resourceDir in Directory.EnumerateDirectories(dscResourcesPath, resourceToImport))
                        {
                            var resourceName = Path.GetFileName(resourceDir);

                            bool foundCimSchema = false;
                            bool foundScriptSchema = false;
                            string schemaMofFilePath = string.Empty;

                            try
                            {
                                foundCimSchema = ImportCimKeywordsFromModule(moduleInfo, resourceName, out schemaMofFilePath);
                            }
                            catch (FileNotFoundException)
                            {
                                errorList.Add(new ParseError(scriptExtent,
                                                             "SchemaFileNotFound",
                                                             string.Format(CultureInfo.CurrentCulture, ParserStrings.SchemaFileNotFound, schemaMofFilePath)));
                            }
                            catch (PSInvalidOperationException e)
                            {
                                errorList.Add(new ParseError(scriptExtent,
                                                            e.ErrorRecord.FullyQualifiedErrorId,
                                                            e.Message));
                            }
                            catch (Exception e)
                            {
                                CommandProcessorBase.CheckForSevereException(e);
                                errorList.Add(new ParseError(scriptExtent,
                                                             "ExceptionParsingMOFFile",
                                                             string.Format(CultureInfo.CurrentCulture, ParserStrings.ExceptionParsingMOFFile, schemaMofFilePath, e.Message)));
                            }

                            var schemaScriptFilePath = string.Empty;

                            try
                            {
                                foundScriptSchema = ImportScriptKeywordsFromModule(moduleInfo, resourceName, out schemaScriptFilePath);
                            }
                            catch (FileNotFoundException)
                            {
                                errorList.Add(new ParseError(scriptExtent,
                                                             "SchemaFileNotFound",
                                                             string.Format(CultureInfo.CurrentCulture, ParserStrings.SchemaFileNotFound, schemaScriptFilePath)));
                            }
                            catch (Exception e)
                            {
                                // This shouldn't happen so just report the error as is
                                CommandProcessorBase.CheckForSevereException(e);
                                errorList.Add(new ParseError(scriptExtent,
                                                             "UnexpectedParseError",
                                                             string.Format(CultureInfo.CurrentCulture, e.ToString())));
                            }

                            if (foundCimSchema || foundScriptSchema)
                            {
                                foundResources = true;
                            }
                        }

                        //
                        // resourceToImport may be the friendly name of the DSC resource
                        //
                        if (!foundResources)
                        {
                            try
                            {
                                string unused;
                                foundResources = ImportCimKeywordsFromModule(moduleInfo, resourceToImport, out unused);
                            }
                            catch (Exception)
                            {
                            }
                        }

                        // resource name without wildcard (*) should be imported only once
                        if (!resourceToImport.Contains("*") && foundResources)
                        {
                            resourcesFound.Add(resourceToImport);
                        }
                    }
                }

                foreach (var resource in resourcesFound)
                {
                    resourcesToImport.Remove(resource);
                }

                if (resourcesToImport.Count == 0)
                {
                    break;
                }
            }

            if (resourcesToImport.Count > 0)
            {
                foreach (var resourceNameToImport in resourcesToImport)
                {
                    if (!resourceNameToImport.Contains("*"))
                    {
                        errorList.Add(new ParseError(scriptExtent,
                                                     "DscResourcesNotFoundDuringParsing",
                                                     string.Format(CultureInfo.CurrentCulture, ParserStrings.DscResourcesNotFoundDuringParsing, resourceNameToImport)));
                    }
                }
            }
        }
        // Installs one module
        // This includes the following steps
        // 1. Unzip the file
        // 2. Validate checksum
        // 3. Validate that the module is a proper DSC module
        // 4. Install the module
        private static MiResult ValidateAndInstallOneModule(string downloadLocation, ModuleSpecification moduleSpecification, 
                                                            IEnumerable<string> requiredResources,
                                                            bool allowModuleOverwrite, out ErrorRecord errorRecord, out UInt32 getActionStatusCode)
        {
            Debug.Assert(((requiredResources != null) && requiredResources.Any()), "requiredResources can not be null and should contain one or more required resources");
            // DownloadLocation contain .zip file
            try
            {
                string zipFileToSearchFor;
                if (moduleSpecification.Version == null)
                {
                    zipFileToSearchFor = moduleSpecification.Name + ".zip";
                }
                else
                {
                    zipFileToSearchFor = moduleSpecification.Name + "_" + moduleSpecification.Version + ".zip";
                }
                var zipFiles = Directory.GetFiles(downloadLocation, zipFileToSearchFor);
                if (zipFiles.Length < 1)
                {
                    errorRecord = GetErrorRecord("DownloadedModulesNotFound", ErrorCategory.InvalidResult,
                                                                            PSinfrastructureStrings.DownloadedModulesNotFound, _pluginModuleName);
                    getActionStatusCode = (int)GetActionStatusCodeTypes.ModuleNotFound;
                    return MiResult.NOT_FOUND;
                }
                var dirPath = GetPsProgramFilesModulePath();
                var moduleName = String.Empty;
                var zipFilePath = String.Empty;
                string moduleToMatch;
                if (moduleSpecification.Version != null && !string.IsNullOrEmpty(moduleSpecification.Version.ToString()))
                {
                    moduleToMatch = string.Format(CultureInfo.InvariantCulture, "{0}_{1}.zip", moduleSpecification.Name, moduleSpecification.Version);
                }
                else
                {
                    moduleToMatch = string.Format(CultureInfo.InvariantCulture, "{0}.zip", moduleSpecification.Name);
                }

                string zipFile = zipFiles[0];
                //extract it in $pshome.
                var localPath = zipFile.Substring(zipFile.LastIndexOf('\\') + 1);
                if (string.Compare(localPath, moduleToMatch, StringComparison.OrdinalIgnoreCase) != 0)
                {
                    getActionStatusCode = (int)GetActionStatusCodeTypes.GetDscModuleCommandFailure;
                    errorRecord = GetErrorRecord("DownloadedModulesNotFound", ErrorCategory.InvalidResult,
                                                                                PSinfrastructureStrings.DownloadedModulesNotFound, _pluginModuleName);
                    return MiResult.NOT_FOUND;
                }

                moduleName = moduleSpecification.Name;
                zipFilePath = zipFile;

                if (string.IsNullOrEmpty(moduleName))
                {
                    getActionStatusCode = (int)GetActionStatusCodeTypes.GetDscModuleCommandFailure;
                    errorRecord = GetErrorRecord("DownloadedModulesNotFound", ErrorCategory.InvalidResult,
                                                                                PSinfrastructureStrings.DownloadedModulesNotFound, _pluginModuleName);
                    return MiResult.NOT_FOUND;
                }

                if (!File.Exists(zipFilePath + ".checksum"))
                {
                    getActionStatusCode = (int)GetActionStatusCodeTypes.ModuleChecksumFileNotFound;
                    errorRecord = GetErrorRecord("ModuleChecksumFileNotExist", ErrorCategory.InvalidResult,
                                                                                PSinfrastructureStrings.ModuleChecksumFileNotExist, _pluginModuleName, zipFilePath);
                    return MiResult.NOT_FOUND;
                }

                //compute checksum
                var statusCode = ValidateModuleWithChecksum(zipFilePath, zipFilePath + ".checksum", out errorRecord, out getActionStatusCode);
                S_DscCoreR.EventWriteLCMPullModuleChecksumValidationResult(S_DscCoreR.JobGuidString, moduleName, (uint)statusCode);
                if (statusCode != MiResult.OK)
                {
                    return statusCode;
                }
                var modulePath = dirPath + moduleName;
                if (Directory.Exists(modulePath) && allowModuleOverwrite == false)
                {
                    S_DscCoreR.EventWriteLCMPullModuleDirectoryAlreadyExists(S_DscCoreR.JobGuidString, moduleName, modulePath);
                    errorRecord = GetErrorRecord("ModuleDirectoryAlreadyExists", ErrorCategory.ResourceExists,
                                                        PSinfrastructureStrings.ModuleDirectoryAlreadyExists, moduleName, modulePath);
                    getActionStatusCode = (int)GetActionStatusCodeTypes.ModuleExtractionFailure;
                    statusCode = MiResult.FAILED;
                    return statusCode;
                }
                if (Directory.Exists(modulePath) && allowModuleOverwrite)
                {
                    S_DscCoreR.EventWriteLCMPullModuleDirectoryOverwrite(S_DscCoreR.JobGuidString, moduleName, GetModuleVersionStringFromModuleSpecification(moduleSpecification));
                    Directory.Move(modulePath, modulePath + "_tmp");
                }
                Directory.CreateDirectory(modulePath);

                //Validate if module is a valid module.
                //It is expected that we will get a valid module from the server
                //hence optimizing for that.

                try
                {
                    using (var archive = ZipFile.OpenRead(zipFilePath))
                    {
                        // Zip file can be in two format.
                        // 1) zip was created at root level and zip content starts with Module folder
                        // 2) zip was created inside the module and top level directly contain the file. It may contain
                        // sub directories and one of them could be same as module name. hence we need to first determine
                        // whether it is type(1) or type(2).
                        var bZipTypeRoot = archive.Entries.All(entry => entry.FullName.StartsWith(moduleName, StringComparison.OrdinalIgnoreCase));
                        foreach (var entry in archive.Entries)
                        {
                            string fullPath = Path.Combine(bZipTypeRoot ? dirPath : modulePath, entry.FullName);
                            var dirTempIndex = fullPath.LastIndexOf('/');

                            // This is a directory so we'll create it if necessary.
                            if (dirTempIndex == fullPath.Length - 1) // file is a directory.
                            {
                                if (!Directory.Exists(fullPath))
                                {
                                    Directory.CreateDirectory(fullPath);
                                }
                            }
                            else
                            {
                                entry.ExtractToFile(fullPath, true);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Directory.Delete(modulePath, true);
                    errorRecord = GetErrorRecord("ModuleExtractionFailed", ex, ErrorCategory.InvalidResult,
                                                 PSinfrastructureStrings.ModuleExtractionFailed, zipFilePath, _pluginModuleName);
                    getActionStatusCode = (int)GetActionStatusCodeTypes.ModuleExtractionFailure;
                    return MiResult.FAILED;
                }
                finally
                {
                    // The modulePath would have been deleted if there had been any exception.
                    // In that case, restore the old module if any
                    if (!Directory.Exists(modulePath) && Directory.Exists(modulePath + "_tmp"))
                    {
                        Directory.Move(modulePath + "_tmp", modulePath);
                    }
                    // In case of no exception , delete the tmp path
                    else if (Directory.Exists(modulePath + "_tmp"))
                    {
                        Directory.Delete(modulePath + "_tmp");
                    }
                }

                var allResourcesAreValid = MiResult.OK;
                if ((requiredResources != null) && requiredResources.Any())
                {
                    foreach (var resourceName in requiredResources)
                    {
                        //Validate the module
                        var resourceModulePath = Path.Combine(Path.Combine(modulePath, Constants.DscResources), resourceName);
                        var schemaFileName = Path.Combine(resourceModulePath, resourceName + Constants.CimSchemaMofFileExtension);
                        var result = ValidatePsdscModule(resourceModulePath, schemaFileName, out getActionStatusCode, out errorRecord);

                        if (result != MiResult.OK)
                        {
                            allResourcesAreValid = result;
                            break;
                        }
                    }
                }

                S_DscCoreR.EventWriteLCMPullModuleContentValidationResult(S_DscCoreR.JobGuidString, moduleName, (uint)allResourcesAreValid);

                if (allResourcesAreValid == MiResult.OK)
                {
                    try
                    {
                        if (Directory.Exists(modulePath + "_tmp"))
                            Directory.Delete(modulePath + "_tmp", true);
                    }
                    catch (IOException) { }
                    catch (UnauthorizedAccessException) { }
                    catch (ArgumentException) { }

                    S_DscCoreR.EventWriteLCMPullModuleInstallLocation(S_DscCoreR.JobGuidString, moduleName, modulePath);
                }
                else
                {
                    try
                    {
                        Directory.Delete(modulePath, true);
                    }
                    catch (IOException) { }
                    catch (UnauthorizedAccessException) { }
                    catch (ArgumentException) { }

                    //Move back old module if any
                    if (Directory.Exists(modulePath + "_tmp"))
                    {
                        Directory.Move(modulePath + "_tmp", modulePath);
                    }

                    if (errorRecord == null)
                    {
                        errorRecord = GetErrorRecord("DownloadedModuleInvalid", ErrorCategory.InvalidResult,
                                                        PSinfrastructureStrings.DownloadedModuleInvalid, zipFilePath,
                                                        _pluginModuleName);
                    }
                    getActionStatusCode = (int) GetActionStatusCodeTypes.InvalidDownloadedModule;
                    return MiResult.FAILED;
                }
            }
            catch (Exception ex)
            {
                getActionStatusCode = (int)GetActionStatusCodeTypes.ModuleExtractionFailure;
                errorRecord = GetErrorRecord("ModuleExtractionGenericFailure", ex, ErrorCategory.InvalidResult,
                                                                PSinfrastructureStrings.ModuleExtractionGenericFailure, _pluginModuleName);
                return MiResult.FAILED;
            }

            getActionStatusCode = (int)GetActionStatusCodeTypes.Success;
            return MiResult.OK;
        }
        // Does the initialization for Get-DscModule. This initialization needs to only happen once for all the modules.
        // As part of this initialization, the following is done
        // 1) Download manager is imported
        // 2) Configuration is parsed to get the list of modules and the download-manager specific properties
        // 3) For the download manager specific properties, we create PSObjects so we can pass those down to the download manager cmdlets.
        // 4) We construct a PowerShell that has all the parameters added (except for the Module parameter. This parameter gets added for each module)
        private static MiResult DoInitializationForGetModule(IntPtr metaConfigHandle, Dictionary<string, Tuple<string, List<string>>> moduleNameVersionTable, 
                                                            string downloadLocation, out string configurationId, out ModuleSpecification[] moduleSpecifications,
                                                            System.Management.Automation.PowerShell powershell, out PSCommand powershellCommand, out Hashtable arguments, out Collection<PSObject> argumentParameters,
                                                            out ErrorRecord errorRecord, out UInt32 getActionStatusCode)
        {
            configurationId = null;
            powershellCommand = null;
            moduleSpecifications = null;
            argumentParameters = null;
            arguments = new Hashtable();
            // Initialize DownloadManager
            MiResult statusCode = InitializePlugin(metaConfigHandle, out errorRecord);
            if (statusCode != MiResult.OK)
            {
                getActionStatusCode = (int)GetActionStatusCodeTypes.DownloadManagerInitializationFailure;
                return statusCode;
            }

            //Get parameters for Get-Module cmdlet
            PSCredential pscredential;
            statusCode = GetGetModuleParams(metaConfigHandle, out pscredential, arguments, out configurationId, out errorRecord, out getActionStatusCode);
            if (statusCode != MiResult.OK)
            {
                return statusCode;
            }

            moduleSpecifications = GetModuleSpecification(moduleNameVersionTable);

            powershell.Runspace = _pluginRunspace;
            if (arguments.Count > 0)
            {
                argumentParameters = powershell.AddCommand("New-Object").AddParameter("Type", "psobject").AddParameter("Property", arguments).Invoke();
                powershell.Commands.Clear();
            }
            powershellCommand = new PSCommand();
            powershellCommand.AddCommand(_pluginModuleName + "\\" + DownloadManagerGetModules);
            powershellCommand.AddParameter(ParamConfigurationId, configurationId);
            powershellCommand.AddParameter(ParamDestinationPath, downloadLocation);
            if (pscredential != null)
            {
                powershellCommand.AddParameter(ParamCredential, pscredential);
            }

            return MiResult.OK;
        }
        // Powershell object passed here will be disposed off by the caller
        private static MiResult PullOneModule(System.Management.Automation.PowerShell powershell, ModuleSpecification moduleSpecification, string configurationId, string downloadLocation,
                                              Hashtable arguments, Collection<PSObject> argumentParameters, out string downloadedModule, out Collection<PSObject> pullOneModuleResult,
                                              out ErrorRecord errorRecord, out UInt32 getActionStatusCode)
        {
            pullOneModuleResult = null;
            downloadedModule = null;
            string moduleVersionString = GetModuleVersionStringFromModuleSpecification(moduleSpecification);
            try
            {
                powershell.AddParameter(ParamModules, moduleSpecification);

                // Log to ETW Channel:Microsoft-Windows-DSC/Operational
                S_DscCoreR.EventWriteLCMPullGetModuleAttempt(S_DscCoreR.JobGuidString, _pluginModuleName, configurationId, moduleVersionString);

                powershell.Streams.Error.Clear();
                pullOneModuleResult = arguments.Count > 0 ? powershell.Invoke(argumentParameters) : powershell.Invoke();
                if (powershell.Streams.Error.Count > 0)
                {
                    errorRecord = powershell.Streams.Error[0];
                    powershell.Dispose();
                    if( string.Compare(errorRecord.FullyQualifiedErrorId, "WebDownloadManagerUnknownChecksumAlgorithm", StringComparison.OrdinalIgnoreCase) == 0 )
                    {
                        getActionStatusCode = (int)GetActionStatusCodeTypes.InvalidChecksumAlgorithm;
                    }
                    else
                    {
                        getActionStatusCode = (int)GetActionStatusCodeTypes.GetDscModuleCommandFailure;
                    }
                    return MiResult.FAILED;
                }
            }
            catch (Exception ex)
            {
                errorRecord = GetErrorRecord("GetModuleExecutionFailure", ex, ErrorCategory.InvalidType,
                                                    PSinfrastructureStrings.GetModuleExecutionFailure, _pluginModuleName);
                getActionStatusCode = (int)GetActionStatusCodeTypes.GetDscModuleCommandFailure;
                return MiResult.FAILED;
            }
            S_DscCoreR.EventWriteLCMPullModuleDownloadLocation(S_DscCoreR.JobGuidString, moduleVersionString, downloadLocation);
            errorRecord = null;
            getActionStatusCode = (int)GetActionStatusCodeTypes.Success;
            return MiResult.OK;
        }
Example #12
0
        /// <summary>
        /// Takes a collection of "module specifications" (string or hashtable)
        /// and returns the collection as a string that can be inserted into a module manifest.
        /// </summary>
        /// <param name="moduleSpecs">The list to quote.</param>
        /// <param name="streamWriter">Streamwriter to get end of line character from.</param>
        /// <returns>The quoted list.</returns>
        private string QuoteModules(IEnumerable moduleSpecs, StreamWriter streamWriter)
        {
            StringBuilder result = new StringBuilder();

            result.Append("@(");

            if (moduleSpecs != null)
            {
                bool firstModule = true;
                foreach (object spec in moduleSpecs)
                {
                    if (spec == null)
                    {
                        continue;
                    }

                    ModuleSpecification moduleSpecification = (ModuleSpecification)
                                                              LanguagePrimitives.ConvertTo(
                        spec,
                        typeof(ModuleSpecification),
                        CultureInfo.InvariantCulture);

                    if (!firstModule)
                    {
                        result.Append(", ");
                        result.Append(streamWriter.NewLine);
                        result.Append("               ");
                    }

                    firstModule = false;

                    if ((moduleSpecification.Guid == null) && (moduleSpecification.Version == null) && (moduleSpecification.MaximumVersion == null) && (moduleSpecification.RequiredVersion == null))
                    {
                        result.Append(QuoteName(moduleSpecification.Name));
                    }
                    else
                    {
                        result.Append("@{");

                        result.Append("ModuleName = ");
                        result.Append(QuoteName(moduleSpecification.Name));
                        result.Append("; ");

                        if (moduleSpecification.Guid != null)
                        {
                            result.Append("GUID = ");
                            result.Append(QuoteName(moduleSpecification.Guid.ToString()));
                            result.Append("; ");
                        }

                        if (moduleSpecification.Version != null)
                        {
                            result.Append("ModuleVersion = ");
                            result.Append(QuoteName(moduleSpecification.Version.ToString()));
                            result.Append("; ");
                        }

                        if (moduleSpecification.MaximumVersion != null)
                        {
                            result.Append("MaximumVersion = ");
                            result.Append(QuoteName(moduleSpecification.MaximumVersion));
                            result.Append("; ");
                        }

                        if (moduleSpecification.RequiredVersion != null)
                        {
                            result.Append("RequiredVersion = ");
                            result.Append(QuoteName(moduleSpecification.RequiredVersion.ToString()));
                            result.Append("; ");
                        }

                        result.Append('}');
                    }
                }
            }

            result.Append(')');
            return(result.ToString());
        }
Example #13
0
        /// <summary>
        /// Gets a list of modules from the given pattern or ModuleSpecification.
        /// </summary>
        /// <param name="pattern">Pattern to match.</param>
        /// <param name="fullyQualifiedName">ModuleSpecification.</param>
        /// <param name="noErrors">Skip errors.</param>
        /// <returns>A list of modules.</returns>
        internal Dictionary <Tuple <string, Version>, UpdatableHelpModuleInfo> GetModuleInfo(string pattern, ModuleSpecification fullyQualifiedName, bool noErrors)
        {
            Dictionary <Tuple <string, Version>, UpdatableHelpModuleInfo> modules = GetModuleInfo(Context, pattern, fullyQualifiedName, noErrors);

            if (modules.Count == 0 && _exceptions.Count == 0 && !noErrors)
            {
                var errorMessage = fullyQualifiedName != null?StringUtil.Format(HelpDisplayStrings.ModuleNotFoundWithFullyQualifiedName, fullyQualifiedName)
                                       : StringUtil.Format(HelpDisplayStrings.CannotMatchModulePattern, pattern);

                ErrorRecord errorRecord = new ErrorRecord(new Exception(errorMessage),
                                                          "ModuleNotFound", ErrorCategory.InvalidArgument, pattern);

                WriteError(errorRecord);
            }

            return(modules);
        }
Example #14
0
        /// <summary>
        /// Gets a list of modules from the given pattern.
        /// </summary>
        /// <param name="context">Execution context.</param>
        /// <param name="pattern">Pattern to search.</param>
        /// <param name="fullyQualifiedName">Module Specification.</param>
        /// <param name="noErrors">Do not generate errors for modules without HelpInfoUri.</param>
        /// <returns>A list of modules.</returns>
        private Dictionary <Tuple <string, Version>, UpdatableHelpModuleInfo> GetModuleInfo(ExecutionContext context, string pattern, ModuleSpecification fullyQualifiedName, bool noErrors)
        {
            List <PSModuleInfo> modules = null;
            string moduleNamePattern    = null;

            if (pattern != null)
            {
                moduleNamePattern = pattern;
                modules           = Utils.GetModules(pattern, context);
            }
            else if (fullyQualifiedName != null)
            {
                moduleNamePattern = fullyQualifiedName.Name;
                modules           = Utils.GetModules(fullyQualifiedName, context);
            }

            var helpModules = new Dictionary <Tuple <string, Version>, UpdatableHelpModuleInfo>();

            if (modules != null)
            {
                foreach (PSModuleInfo module in modules)
                {
                    ProcessSingleModuleObject(module, context, helpModules, noErrors);
                }
            }

            // Match wildcards
            WildcardOptions wildcardOptions           = WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant;
            IEnumerable <WildcardPattern> patternList = SessionStateUtilities.CreateWildcardsFromStrings(new string[1] {
                moduleNamePattern
            }, wildcardOptions);

            foreach (KeyValuePair <string, string> name in s_metadataCache)
            {
                if (SessionStateUtilities.MatchesAnyWildcardPattern(name.Key, patternList, true))
                {
                    // For core snapin, there are no GUIDs. So, we need to construct the HelpInfo slightly differently
                    if (!name.Key.Equals(InitialSessionState.CoreSnapin, StringComparison.OrdinalIgnoreCase))
                    {
                        var keyTuple = new Tuple <string, Version>(name.Key, new Version("1.0"));
                        if (!helpModules.ContainsKey(keyTuple))
                        {
                            List <PSModuleInfo> availableModules = Utils.GetModules(name.Key, context);
                            if (availableModules != null)
                            {
                                foreach (PSModuleInfo module in availableModules)
                                {
                                    keyTuple = new Tuple <string, Version>(module.Name, module.Version);
                                    if (!helpModules.ContainsKey(keyTuple))
                                    {
                                        WriteDebug(StringUtil.Format("Found engine module: {0}, {1}.", module.Name, module.Guid));

                                        helpModules.Add(keyTuple, new UpdatableHelpModuleInfo(module.Name,
                                                                                              module.Guid, Utils.GetApplicationBase(context.ShellID), s_metadataCache[module.Name]));
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        var keyTuple2 = new Tuple <string, Version>(name.Key, new Version("1.0"));
                        if (!helpModules.ContainsKey(keyTuple2))
                        {
                            helpModules.Add(keyTuple2,
                                            new UpdatableHelpModuleInfo(name.Key, Guid.Empty,
                                                                        Utils.GetApplicationBase(context.ShellID),
                                                                        name.Value));
                        }
                    }
                }
            }

            return(helpModules);
        }
        /// <summary>
        /// Initialize moduleSpecification from hashtable. Return exception object, if hashtable cannot be converted.
        /// Return null, in the success case.
        /// </summary>
        /// <param name="moduleSpecification">object to initialize</param>
        /// <param name="hashtable">contains info about object to initialize.</param>
        /// <returns></returns>
        internal static Exception ModuleSpecificationInitHelper(ModuleSpecification moduleSpecification, Hashtable hashtable)
        {
            StringBuilder badKeys = new StringBuilder();

            try
            {
                foreach (DictionaryEntry entry in hashtable)
                {
                    if (entry.Key.ToString().Equals("ModuleName", StringComparison.OrdinalIgnoreCase))
                    {
                        moduleSpecification.Name = LanguagePrimitives.ConvertTo <string>(entry.Value);
                    }
                    else if (entry.Key.ToString().Equals("ModuleVersion", StringComparison.OrdinalIgnoreCase))
                    {
                        moduleSpecification.Version = LanguagePrimitives.ConvertTo <Version>(entry.Value);
                    }
                    else if (entry.Key.ToString().Equals("RequiredVersion", StringComparison.OrdinalIgnoreCase))
                    {
                        moduleSpecification.RequiredVersion = LanguagePrimitives.ConvertTo <Version>(entry.Value);
                    }
                    else if (entry.Key.ToString().Equals("MaximumVersion", StringComparison.OrdinalIgnoreCase))
                    {
                        moduleSpecification.MaximumVersion = LanguagePrimitives.ConvertTo <String>(entry.Value);
                        ModuleCmdletBase.GetMaximumVersion(moduleSpecification.MaximumVersion);
                    }
                    else if (entry.Key.ToString().Equals("GUID", StringComparison.OrdinalIgnoreCase))
                    {
                        moduleSpecification.Guid = LanguagePrimitives.ConvertTo <Guid?>(entry.Value);
                    }
                    else
                    {
                        if (badKeys.Length > 0)
                        {
                            badKeys.Append(", ");
                        }
                        badKeys.Append("'");
                        badKeys.Append(entry.Key.ToString());
                        badKeys.Append("'");
                    }
                }
            }
            // catch all exceptions here, we are going to report them via return value.
            // Example of catched exception: one of conversions to Version failed.
            catch (Exception e)
            {
                return(e);
            }

            string message;

            if (badKeys.Length != 0)
            {
                message = StringUtil.Format(Modules.InvalidModuleSpecificationMember, "ModuleName, ModuleVersion, RequiredVersion, GUID", badKeys);
                return(new ArgumentException(message));
            }

            if (string.IsNullOrEmpty(moduleSpecification.Name))
            {
                message = StringUtil.Format(Modules.RequiredModuleMissingModuleName);
                return(new MissingMemberException(message));
            }

            if (moduleSpecification.RequiredVersion == null && moduleSpecification.Version == null && moduleSpecification.MaximumVersion == null)
            {
                message = StringUtil.Format(Modules.RequiredModuleMissingModuleVersion);
                return(new MissingMemberException(message));
            }

            if (moduleSpecification.RequiredVersion != null && moduleSpecification.Version != null)
            {
                message = StringUtil.Format(SessionStateStrings.GetContent_TailAndHeadCannotCoexist, "ModuleVersion", "RequiredVersion");
                return(new ArgumentException(message));
            }

            if (moduleSpecification.RequiredVersion != null && moduleSpecification.MaximumVersion != null)
            {
                message = StringUtil.Format(SessionStateStrings.GetContent_TailAndHeadCannotCoexist, "MaximumVersion", "RequiredVersion");
                return(new ArgumentException(message));
            }
            return(null);
        }