/// <summary> /// </summary> protected override void ProcessRecord() { var dirsToSearch = new List <string>(); if (_path != null) { dirsToSearch.AddRange(Directory.GetDirectories(_path).ToList()); } else { var isWindows = OsPlatform.ToLower().Contains("windows"); // should just check the psmodules path???? // PSModules path var psModulePath = Environment.GetEnvironmentVariable("PSModulePath"); var modulePaths = psModulePath.Split(';'); // if not core var isWindowsPS = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory().ToLower().Contains("windows") ? true : false; if (isWindowsPS) { programFilesPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.ProgramFiles), "WindowsPowerShell"); /// TODO: Come back to this var userENVpath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), "Documents"); myDocumentsPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.MyDocuments), "WindowsPowerShell"); } else { programFilesPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.ProgramFiles), "PowerShell"); myDocumentsPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.MyDocuments), "PowerShell"); } /*** Will search first in PSModulePath, then will search in default paths ***/ // 1) Create a list of either // Of all names try { foreach (var path in modulePaths) { dirsToSearch.AddRange(Directory.GetDirectories(path).ToList()); } } catch { } var pfModulesPath = System.IO.Path.Combine(programFilesPath, "Modules"); if (Directory.Exists(pfModulesPath)) { dirsToSearch.AddRange(Directory.GetDirectories(pfModulesPath).ToList()); } var pfScriptsPath = System.IO.Path.Combine(programFilesPath, "Scripts"); if (Directory.Exists(pfScriptsPath)) { dirsToSearch.AddRange(Directory.GetDirectories(pfScriptsPath).ToList()); } var mdModulesPath = System.IO.Path.Combine(myDocumentsPath, "Modules"); // change programfiles to mydocuments if (Directory.Exists(mdModulesPath)) { dirsToSearch.AddRange(Directory.GetDirectories(mdModulesPath).ToList()); } var mdScriptsPath = System.IO.Path.Combine(myDocumentsPath, "Scripts"); // change programFiles to myDocuments if (Directory.Exists(mdScriptsPath)) { dirsToSearch.AddRange(Directory.GetDirectories(mdScriptsPath).ToList()); } // uniqueify dirsToSearch = dirsToSearch.Distinct().ToList(); } // Or a list of the passed in names if (_name != null && !_name[0].Equals("*")) { var nameLowerCased = new List <string>(); Array.ForEach(_name, n => nameLowerCased.Add(n.ToLower())); dirsToSearch = dirsToSearch.FindAll(p => nameLowerCased.Contains(new DirectoryInfo(p).Name.ToLower())); } // try to parse into a specific NuGet version VersionRange versionRange = null; if (_version != null) { NuGetVersion specificVersion; NuGetVersion.TryParse(_version, out specificVersion); if (specificVersion != null) { // exact version versionRange = new VersionRange(specificVersion, true, specificVersion, true, null, null); } else { // check if version range versionRange = VersionRange.Parse(_version); } } List <string> installedPkgsToReturn = new List <string>(); IEnumerable <string> returnPkgs = null; var versionDirs = new List <string>(); //2) use above list to check // if the version specificed is a version range if (versionRange != null) { foreach (var pkgPath in dirsToSearch) { var versionsDirs = Directory.GetDirectories(pkgPath); foreach (var versionPath in versionsDirs) { NuGetVersion dirAsNugetVersion; var dirInfo = new DirectoryInfo(versionPath); NuGetVersion.TryParse(dirInfo.Name, out dirAsNugetVersion); if (versionRange.Satisfies(dirAsNugetVersion)) { // just search scripts paths if (pkgPath.ToLower().Contains("scripts")) { // TODO check if scripts are installed var scriptXmls = Directory.GetFiles(pkgPath); if (_name == null || _name[0].Equals("*")) { // Add all the script xmls installedPkgsToReturn.AddRange(scriptXmls); } else { // Just add the xmls of the names specified foreach (var name in _name) { var scriptXMLPath = System.IO.Path.Combine(pkgPath, name, "_InstalledScriptInfo"); if (File.Exists(scriptXMLPath)) { installedPkgsToReturn.Add(scriptXMLPath); } } } } else { // modules paths versionsDirs = Directory.GetDirectories(pkgPath); // Check if the pkg path actually has version sub directories. if (versionsDirs.Length != 0) { Array.Sort(versionsDirs, StringComparer.OrdinalIgnoreCase); Array.Reverse(versionsDirs); var pkgXmlFilePath = System.IO.Path.Combine(versionsDirs.First(), "PSGetModuleInfo.xml"); // TODO: check if this xml file exists, if it doesn't check if it exists in a previous version installedPkgsToReturn.Add(pkgXmlFilePath); } } installedPkgsToReturn.Add(versionPath); } } } } else { // THIS SHOULD BE DONE // if no version is specified, just get the latest version foreach (var pkgPath in dirsToSearch) { // just search scripts paths if (pkgPath.ToLower().Contains("scripts")) { // TODO check if scripts are installed var scriptXmls = Directory.GetFiles(pkgPath); if (_name == null || _name[0].Equals("*")) { // Add all the script xmls installedPkgsToReturn.AddRange(scriptXmls); } else { // Just add the xmls of the names specified foreach (var name in _name) { var scriptXMLPath = System.IO.Path.Combine(pkgPath, name, "_InstalledScriptInfo"); if (File.Exists(scriptXMLPath)) { installedPkgsToReturn.Add(scriptXMLPath); } } } } else { // modules paths string[] versionsDirs = new string[0]; versionsDirs = Directory.GetDirectories(pkgPath); // Check if the pkg path actually has version sub directories. if (versionsDirs.Length != 0) { Array.Sort(versionsDirs, StringComparer.OrdinalIgnoreCase); Array.Reverse(versionsDirs); var pkgXmlFilePath = System.IO.Path.Combine(versionsDirs.First(), "PSGetModuleInfo.xml"); // TODO: check if this xml file exists, if it doesn't check if it exists in a previous version installedPkgsToReturn.Add(pkgXmlFilePath); } } } } // Flatten returned pkgs before displaying output returnedPkgsFound.Flatten().ToList()[0] var flattenedPkgs = installedPkgsToReturn.Flatten(); foreach (string xmlFilePath in flattenedPkgs) { // Open xml and read metadata from it if (File.Exists(xmlFilePath)) { ReadOnlyPSMemberInfoCollection <PSPropertyInfo> nameInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> versionInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> additionalMetadataInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> psDataInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> repositoryInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> descriptionversionInfo; var isPrelease = false; using (StreamReader sr = new StreamReader(xmlFilePath)) { string text = sr.ReadToEnd(); var deserializedObj = (PSObject)PSSerializer.Deserialize(text); nameInfo = deserializedObj.Properties.Match("Name"); /* // testing adding prerelease parameter * additionalMetadataInfo = deserializedObj.Properties.Match("AdditionalMetadata"); * if (additionalMetadataInfo.Any()) * { * isPrelease = additionalMetadataInfo.FirstOrDefault().Value.ToString().Contains("IsPrerelease=true"); * if ((isPrelease == true) && _prerelease) // find a stable version of the pkg {} * } */ versionInfo = deserializedObj.Properties.Match("Version"); repositoryInfo = deserializedObj.Properties.Match("Repository"); descriptionversionInfo = deserializedObj.Properties.Match("Description"); }; // if -Prerelease is not passed in as a parameter, don't allow prerelease pkgs to be returned, // we still want all pkgs to be returned if -Prerelease is passed in as a param //if ((_prerelease == false && isPrelease == false) || _prerelease == true) //{ PSObject pkgAsPSObject = new PSObject(); try { pkgAsPSObject.Members.Add(new PSNoteProperty("Name", nameInfo.FirstOrDefault().Value)); // need to fix output pkgAsPSObject.Members.Add(new PSNoteProperty("Version", versionInfo.FirstOrDefault().Value)); pkgAsPSObject.Members.Add(new PSNoteProperty("Repository", repositoryInfo.FirstOrDefault().Value)); pkgAsPSObject.Members.Add(new PSNoteProperty("Description", descriptionversionInfo.FirstOrDefault().Value)); WriteObject(pkgAsPSObject); } catch { } //} } } }
/// <summary> /// Converts an object into string /// </summary> /// <param name="Item">The arbitrary object to serialize</param> /// <param name="Depth">Overrrides the default serialization depth</param> /// <returns>A string containing the serialized inputobject</returns> public static string ToString(object Item, int Depth) { return(PSSerializer.Serialize(Item, Depth)); }
/* Uninstall script helper */ private bool UninstallScriptHelper(string pkgName, string scriptsPath, string fullScriptPath, CancellationToken cancellationToken) { /* Currently the way PSGet operates is that only one script can be installed at a time. * I think it's worth seeing if we want allow for multiple scripts to be instlled at a time, * and if so, we need to rethink the architecture of the scripts installation path. */ var successfullyUninstalledPkg = false; // TODO: open xml and read from it var xmlFileName = string.Concat(pkgName, "_InstalledScriptInfo.xml"); var scriptXMLPath = Path.Combine(scriptsPath, "InstalledScriptInfos", xmlFileName); ReadOnlyPSMemberInfoCollection <PSPropertyInfo> versionInfo; NuGetVersion nugetVersion; using (StreamReader sr = new StreamReader(scriptXMLPath)) { string text = sr.ReadToEnd(); var deserializedObj = (PSObject)PSSerializer.Deserialize(text); versionInfo = deserializedObj.Properties.Match("Version"); }; NuGetVersion.TryParse(versionInfo.FirstOrDefault().Value.ToString(), out nugetVersion); // If prereleaseOnly is specified, we'll only take into account prerelease versions of pkgs if (_prereleaseOnly) { // If the installed script is a prerelease, we can continue processing it if (nugetVersion.IsPrerelease) { dirsToDelete.Add(fullScriptPath); } else { return(successfullyUninstalledPkg); } } if (_version == null) { // if no version is specified, just delete the latest version (right now the only version) dirsToDelete.Add(fullScriptPath); } // if the version specificed is a version range else { // Parse the version passed in and compare it to the script version NuGetVersion argNugetVersion; NuGetVersion.TryParse(_version, out argNugetVersion); VersionRange versionRange; if (argNugetVersion != null) { // exact version versionRange = new VersionRange(argNugetVersion, true, argNugetVersion, true, null, null); } else { // check if version range versionRange = VersionRange.Parse(_version); } if (versionRange.Satisfies(nugetVersion)) { dirsToDelete.Add(fullScriptPath); } } // if dirsToDelete is empty... meaning we didn't find any scripts if (dirsToDelete.Any()) { /// This is a primitive implementation /// TODO: implement a dependencies database for querying dependency info /// Cannot uninstall a package if another module is dependent on it using (System.Management.Automation.PowerShell pwsh = System.Management.Automation.PowerShell.Create()) { // Check all modules for dependencies var results = pwsh.AddCommand("Get-Module").AddParameter("ListAvailable").Invoke(); // Structure of LINQ call: // Results is a collection of PSModuleInfo objects that contain a property listing module dependencies, "RequiredModules". // RequiredModules is collection of PSModuleInfo objects that need to be iterated through to see if any of them are the pkg we're trying to uninstall // If we anything from the final call gets returned, there is a dependency on this pkg. // check for nested modules as well var pkgsWithRequiredModules = results.Where(p => ((ReadOnlyCollection <PSModuleInfo>)p.Properties["RequiredModules"].Value).Where(rm => rm.Name.Equals(pkgName, StringComparison.InvariantCultureIgnoreCase)).Any()); if (pkgsWithRequiredModules.Any()) { var uniquePkgNames = pkgsWithRequiredModules.Select(p => p.Properties["Name"].Value).Distinct().ToArray(); var strUniquePkgNames = string.Join(",", uniquePkgNames); throw new System.ArgumentException(string.Format(CultureInfo.InvariantCulture, "Cannot uninstall {0}, the following package(s) take a dependency on this package: {1}", pkgName, strUniquePkgNames)); } } // Delete the appropriate file if (File.Exists(fullScriptPath)) { File.Delete(fullScriptPath); successfullyUninstalledPkg = true; } // Finally: // Delete the xml from the InstalledModulesInfo directory var scriptXML = Path.Combine(scriptsPath, "InstalledScriptInfos", pkgName + "_InstalledScriptInfo.xml"); if (File.Exists(scriptXML)) { File.Delete(scriptXML); } } return(successfullyUninstalledPkg); }
public List <string> InstallHelper(string repositoryUrl, List <string> pkgsLeftToInstall, CancellationToken cancellationToken) { PackageSource source = new PackageSource(repositoryUrl); if (_credential != null) { string password = new NetworkCredential(string.Empty, _credential.Password).Password; source.Credentials = PackageSourceCredential.FromUserInput(repositoryUrl, _credential.UserName, password, true, null); } var provider = FactoryExtensionsV3.GetCoreV3(NuGet.Protocol.Core.Types.Repository.Provider); SourceRepository repository = new SourceRepository(source, provider); SearchFilter filter = new SearchFilter(_prerelease); ////////////////////// packages from source /// PackageSource source2 = new PackageSource(repositoryUrl); if (_credential != null) { string password = new NetworkCredential(string.Empty, _credential.Password).Password; source2.Credentials = PackageSourceCredential.FromUserInput(repositoryUrl, _credential.UserName, password, true, null); } var provider2 = FactoryExtensionsV3.GetCoreV3(NuGet.Protocol.Core.Types.Repository.Provider); SourceRepository repository2 = new SourceRepository(source2, provider2); // TODO: proper error handling here PackageMetadataResource resourceMetadata2 = null; try { resourceMetadata2 = repository.GetResourceAsync <PackageMetadataResource>().GetAwaiter().GetResult(); } catch { } SearchFilter filter2 = new SearchFilter(_prerelease); SourceCacheContext context2 = new SourceCacheContext(); foreach (var n in _name) { IPackageSearchMetadata filteredFoundPkgs = null; // Check version first to narrow down the number of pkgs before potential searching through tags VersionRange versionRange = null; if (_version == null) { // ensure that the latst version is returned first (the ordering of versions differ // TODO: proper error handling try { filteredFoundPkgs = (resourceMetadata2.GetMetadataAsync(n, _prerelease, false, context2, NullLogger.Instance, cancellationToken).GetAwaiter().GetResult() .OrderByDescending(p => p.Identity.Version, VersionComparer.VersionRelease) .FirstOrDefault()); } catch { } } else { // check if exact version NuGetVersion nugetVersion; //VersionRange versionRange = VersionRange.Parse(version); NuGetVersion.TryParse(_version, out nugetVersion); // throw if (nugetVersion != null) { // exact version versionRange = new VersionRange(nugetVersion, true, nugetVersion, true, null, null); } else { // check if version range versionRange = VersionRange.Parse(_version); } // Search for packages within a version range // ensure that the latst version is returned first (the ordering of versions differ filteredFoundPkgs = (resourceMetadata2.GetMetadataAsync(n, _prerelease, false, context2, NullLogger.Instance, cancellationToken).GetAwaiter().GetResult() .Where(p => versionRange.Satisfies(p.Identity.Version)) .OrderByDescending(p => p.Identity.Version, VersionComparer.VersionRelease) .FirstOrDefault()); } List <IPackageSearchMetadata> foundDependencies = new List <IPackageSearchMetadata>(); // found a package to install and looking for dependencies // Search for dependencies if (filteredFoundPkgs != null) { // need to parse the depenency and version and such // need to improve this later // this function recursively finds all dependencies // might need to do add instead of AddRange foundDependencies.AddRange(FindDependenciesFromSource(filteredFoundPkgs, resourceMetadata2, context2)); } /// end dep conditional // check which pkgs you actually need to install List <IPackageSearchMetadata> pkgsToInstall = new List <IPackageSearchMetadata>(); // install pkg, then install any dependencies to a temp directory pkgsToInstall.Add(filteredFoundPkgs); pkgsToInstall.AddRange(foundDependencies); if (_asNupkg) { // CreateFolderFeedV3Async(_path, PackageSaveMode.Nupkg | PackageSaveMode.Nuspec, packages). var tempInstallPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString()); var dir = Directory.CreateDirectory(tempInstallPath); // should check it gets created properly //dir.SetAccessControl(new DirectorySecurity(dir.FullName, AccessControlSections.Owner)); // To delete file attributes from the existing ones get the current file attributes first and use AND (&) operator // with a mask (bitwise complement of desired attributes combination). dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly; //remove any null pkgs pkgsToInstall.Remove(null); // install everything to a temp path foreach (var p in pkgsToInstall) { var pkgIdentity = new PackageIdentity(p.Identity.Id, p.Identity.Version); var resource = new DownloadResourceV2FeedProvider(); var resource2 = resource.TryCreate(repository, cancellationToken); var cacheContext = new SourceCacheContext(); var downloadResource = repository.GetResourceAsync <DownloadResource>().GetAwaiter().GetResult(); var result = downloadResource.GetDownloadResourceResultAsync( pkgIdentity, new PackageDownloadContext(cacheContext), tempInstallPath, logger: NullLogger.Instance, CancellationToken.None).GetAwaiter().GetResult(); // need to close the .nupkg result.Dispose(); // 4) copy to proper path // TODO: test installing a script when it already exists // or move to script path // check for failures // var newPath = Directory.CreateDirectory(Path.Combine(psModulesPath, p.Identity.Id, p.Identity.Version.ToNormalizedString())); var installPath = _path; // when we move the directory over, we'll change the casing of the module directory name from lower case to proper casing. // if script, just move the files over, if module, move the version directory overp var tempPkgIdPath = System.IO.Path.Combine(tempInstallPath, p.Identity.Id, p.Identity.Version.ToString()); var tempPkgVersionPath = System.IO.Path.Combine(tempPkgIdPath, p.Identity.Id.ToLower() + "." + p.Identity.Version + ".nupkg"); var newPath = System.IO.Path.Combine(_path, p.Identity.Id + "." + p.Identity.Version + ".nupkg"); File.Move(tempPkgVersionPath, newPath); // 2) TODO: Verify that all the proper modules installed correctly // remove temp directory recursively Directory.Delete(tempInstallPath, true); pkgsLeftToInstall.Remove(n); } } else { var tempInstallPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString()); var dir = Directory.CreateDirectory(tempInstallPath); // should check it gets created properly //dir.SetAccessControl(new DirectorySecurity(dir.FullName, AccessControlSections.Owner)); // To delete file attributes from the existing ones get the current file attributes first and use AND (&) operator // with a mask (bitwise complement of desired attributes combination). dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly; //remove any null pkgs pkgsToInstall.Remove(null); // install everything to a temp path foreach (var p in pkgsToInstall) { var pkgIdentity = new PackageIdentity(p.Identity.Id, p.Identity.Version); var resource = new DownloadResourceV2FeedProvider(); var resource2 = resource.TryCreate(repository, cancellationToken); var cacheContext = new SourceCacheContext(); var downloadResource = repository.GetResourceAsync <DownloadResource>().GetAwaiter().GetResult(); var result = downloadResource.GetDownloadResourceResultAsync( pkgIdentity, new PackageDownloadContext(cacheContext), tempInstallPath, logger: NullLogger.Instance, CancellationToken.None).GetAwaiter().GetResult(); // need to close the .nupkg result.Dispose(); // create a download count to see if everything was installed properly // 1) remove the *.nupkg file // may need to modify due to capitalization var dirNameVersion = System.IO.Path.Combine(tempInstallPath, p.Identity.Id, p.Identity.Version.ToNormalizedString()); var nupkgMetadataToDelete = System.IO.Path.Combine(dirNameVersion, ".nupkg.metadata"); var nupkgToDelete = System.IO.Path.Combine(dirNameVersion, (p.Identity.ToString() + ".nupkg").ToLower()); var nupkgSHAToDelete = System.IO.Path.Combine(dirNameVersion, (p.Identity.ToString() + ".nupkg.sha512").ToLower()); var nuspecToDelete = System.IO.Path.Combine(dirNameVersion, (p.Identity.Id + ".nuspec").ToLower()); File.Delete(nupkgMetadataToDelete); File.Delete(nupkgSHAToDelete); File.Delete(nuspecToDelete); File.Delete(nupkgToDelete); // if it's not a script, do the following: var scriptPath = System.IO.Path.Combine(dirNameVersion, (p.Identity.Id.ToString() + ".ps1").ToLower()); var isScript = File.Exists(scriptPath) ? true : false; // 3) create xml //Create PSGetModuleInfo.xml //Set attribute as hidden [System.IO.File]::SetAttributes($psgetItemInfopath, [System.IO.FileAttributes]::Hidden) var fullinstallPath = isScript ? System.IO.Path.Combine(dirNameVersion, (p.Identity.Id + "_InstalledScriptInfo.xml")) : System.IO.Path.Combine(dirNameVersion, "PSGetModuleInfo.xml"); // Create XMLs using (StreamWriter sw = new StreamWriter(fullinstallPath)) { var psModule = "PSModule"; var tags = p.Tags.Split(' '); var module = tags.Contains("PSModule") ? "Module" : null; var script = tags.Contains("PSScript") ? "Script" : null; List <string> includesDscResource = new List <string>(); List <string> includesCommand = new List <string>(); List <string> includesFunction = new List <string>(); List <string> includesRoleCapability = new List <string>(); List <string> filteredTags = new List <string>(); var psDscResource = "PSDscResource_"; var psCommand = "PSCommand_"; var psFunction = "PSFunction_"; var psRoleCapability = "PSRoleCapability_"; foreach (var tag in tags) { if (tag.StartsWith(psDscResource)) { includesDscResource.Add(tag.Remove(0, psDscResource.Length)); } else if (tag.StartsWith(psCommand)) { includesCommand.Add(tag.Remove(0, psCommand.Length)); } else if (tag.StartsWith(psFunction)) { includesFunction.Add(tag.Remove(0, psFunction.Length)); } else if (tag.StartsWith(psRoleCapability)) { includesRoleCapability.Add(tag.Remove(0, psRoleCapability.Length)); } else if (!tag.StartsWith("PSWorkflow_") && !tag.StartsWith("PSCmdlet_") && !tag.StartsWith("PSIncludes_") && !tag.Equals("PSModule") && !tag.Equals("PSScript")) { filteredTags.Add(tag); } } Dictionary <string, List <string> > includes = new Dictionary <string, List <string> >() { { "DscResource", includesDscResource }, { "Command", includesCommand }, { "Function", includesFunction }, { "RoleCapability", includesRoleCapability } }; Dictionary <string, VersionRange> dependencies = new Dictionary <string, VersionRange>(); foreach (var depGroup in p.DependencySets) { PackageDependency depPkg = depGroup.Packages.FirstOrDefault(); dependencies.Add(depPkg.Id, depPkg.VersionRange); } var psGetModuleInfoObj = new PSObject(); // TODO: Add release notes psGetModuleInfoObj.Members.Add(new PSNoteProperty("Name", p.Identity.Id)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("Version", p.Identity.Version)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("Type", module != null ? module : (script != null ? script : null))); psGetModuleInfoObj.Members.Add(new PSNoteProperty("Description", p.Description)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("Author", p.Authors)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("CompanyName", p.Owners)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("PublishedDate", p.Published)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("InstalledDate", System.DateTime.Now)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("LicenseUri", p.LicenseUrl)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("ProjectUri", p.ProjectUrl)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("IconUri", p.IconUrl)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("Includes", includes.ToList())); // TODO: check if getting deserialized properly psGetModuleInfoObj.Members.Add(new PSNoteProperty("PowerShellGetFormatVersion", "3")); psGetModuleInfoObj.Members.Add(new PSNoteProperty("Dependencies", dependencies.ToList())); psGetModuleInfoObj.Members.Add(new PSNoteProperty("RepositorySourceLocation", repositoryUrl)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("Repository", repositoryUrl)); psGetModuleInfoObj.Members.Add(new PSNoteProperty("InstalledLocation", null)); // TODO: add installation location psGetModuleInfoObj.TypeNames.Add("Microsoft.PowerShell.Commands.PSRepositoryItemInfo"); var serializedObj = PSSerializer.Serialize(psGetModuleInfoObj); sw.Write(serializedObj); // set the xml attribute to hidden //System.IO.File.SetAttributes("c:\\code\\temp\\installtestpath\\PSGetModuleInfo.xml", FileAttributes.Hidden); } // 4) copy to proper path // TODO: test installing a script when it already exists // or move to script path // check for failures // var newPath = Directory.CreateDirectory(Path.Combine(psModulesPath, p.Identity.Id, p.Identity.Version.ToNormalizedString())); var installPath = _path; var newPath = isScript ? installPath : System.IO.Path.Combine(installPath, p.Identity.Id.ToString()); // when we move the directory over, we'll change the casing of the module directory name from lower case to proper casing. // if script, just move the files over, if module, move the version directory overp var tempModuleVersionDir = isScript ? System.IO.Path.Combine(tempInstallPath, p.Identity.Id.ToLower(), p.Identity.Version.ToNormalizedString()) : System.IO.Path.Combine(tempInstallPath, p.Identity.Id.ToLower()); if (isScript) { var scriptXML = p.Identity.Id + "_InstalledScriptInfo.xml"; File.Move(System.IO.Path.Combine(tempModuleVersionDir, scriptXML), System.IO.Path.Combine(_path, "InstalledScriptInfos", scriptXML)); File.Move(System.IO.Path.Combine(tempModuleVersionDir, p.Identity.Id.ToLower() + ".ps1"), System.IO.Path.Combine(newPath, p.Identity.Id + ".ps1")); } else { if (!Directory.Exists(newPath)) { Directory.Move(tempModuleVersionDir, newPath); } else { // If the module directory path already exists, Directory.Move throws an exception, so we'll just move the version directory over instead tempModuleVersionDir = System.IO.Path.Combine(tempModuleVersionDir, p.Identity.Version.ToNormalizedString()); Directory.Move(tempModuleVersionDir, System.IO.Path.Combine(newPath, p.Identity.Version.ToNormalizedString())); } } // 2) TODO: Verify that all the proper modules installed correctly // remove temp directory recursively Directory.Delete(tempInstallPath, true); pkgsLeftToInstall.Remove(n); } } } return(pkgsLeftToInstall); }
/// <summary> /// Converts any object into its persisted state. /// </summary> /// <param name="Item">The item to convert.</param> /// <returns>Its persisted state representation.</returns> public static ConfigurationValue ConvertToPersistedValue(object Item) { if (Item == null) { return(new ConfigurationValue("null", ConfigurationValueType.Null)); } switch (Item.GetType().FullName) { case "System.Boolean": if ((bool)Item) { return(new ConfigurationValue("true", ConfigurationValueType.Bool)); } return(new ConfigurationValue("false", ConfigurationValueType.Bool)); case "System.Int16": return(new ConfigurationValue(Item.ToString(), ConfigurationValueType.Int)); case "System.Int32": return(new ConfigurationValue(Item.ToString(), ConfigurationValueType.Int)); case "System.Int64": return(new ConfigurationValue(Item.ToString(), ConfigurationValueType.Long)); case "System.UInt16": return(new ConfigurationValue(Item.ToString(), ConfigurationValueType.Int)); case "System.UInt32": return(new ConfigurationValue(Item.ToString(), ConfigurationValueType.Long)); case "System.UInt64": return(new ConfigurationValue(Item.ToString(), ConfigurationValueType.Long)); case "System.Double": return(new ConfigurationValue(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", Item), ConfigurationValueType.Double)); case "System.String": return(new ConfigurationValue(Item.ToString(), ConfigurationValueType.String)); case "System.TimeSpan": return(new ConfigurationValue(((TimeSpan)Item).Ticks.ToString(), ConfigurationValueType.Timespan)); case "System.DateTime": return(new ConfigurationValue(((DateTime)Item).Ticks.ToString(), ConfigurationValueType.Datetime)); case "System.ConsoleColor": return(new ConfigurationValue(Item.ToString(), ConfigurationValueType.ConsoleColor)); case "System.Collections.Hashtable": List <string> hashItems = new List <string>(); Hashtable tempTable = Item as Hashtable; foreach (object key in tempTable.Keys) { hashItems.Add(String.Format("{0}þEþ{1}", Utf8ToBase64(key.ToString()), Utf8ToBase64(ConvertToPersistedValue(tempTable[key]).TypeQualifiedPersistedValue))); } return(new ConfigurationValue(String.Join("þHþ", hashItems), ConfigurationValueType.Hashtable)); case "System.Object[]": List <string> items = new List <string>(); foreach (object item in (object[])Item) { ConfigurationValue temp = ConvertToPersistedValue(item); if (temp.PersistedValue == "<type not supported>") { return(temp); } items.Add(String.Format("{0}:{1}", temp.PersistedType, temp.PersistedValue)); } return(new ConfigurationValue(String.Join("þþþ", items), ConfigurationValueType.Array)); default: return(new ConfigurationValue(Utility.UtilityHost.CompressString((PSSerializer.Serialize(Item))), ConfigurationValueType.Object)); } }
private PSSenderInfo(SerializationInfo info, StreamingContext context) { if (info != null) { string source = null; try { source = info.GetValue("CliXml", typeof(string)) as string; } catch (Exception) { return; } if (source != null) { try { PSSenderInfo info2 = DeserializingTypeConverter.RehydratePSSenderInfo(PSObject.AsPSObject(PSSerializer.Deserialize(source))); this.userPrinicpal = info2.userPrinicpal; this.clientTimeZone = info2.ClientTimeZone; this.connectionString = info2.connectionString; this.applicationArguments = info2.applicationArguments; } catch (Exception) { return; } } } }
/// <summary> /// Converts a persisted value back to its original data type /// </summary> /// <param name="PersistedValue">The value in its persisted state</param> /// <param name="Type">The type of the persisted value</param> /// <returns>The natural state of the value originally persisted</returns> public static object ConvertFromPersistedValue(string PersistedValue, ConfigurationValueType Type) { switch (Type) { case ConfigurationValueType.Null: return(null); case ConfigurationValueType.Bool: return(PersistedValue == "true"); case ConfigurationValueType.Int: return(Int32.Parse(PersistedValue)); case ConfigurationValueType.Long: return(Int64.Parse(PersistedValue)); case ConfigurationValueType.Double: return(Double.Parse(PersistedValue, System.Globalization.CultureInfo.InvariantCulture)); case ConfigurationValueType.String: return(PersistedValue); case ConfigurationValueType.Timespan: return(new TimeSpan(long.Parse(PersistedValue))); case ConfigurationValueType.Datetime: return(new DateTime(long.Parse(PersistedValue))); case ConfigurationValueType.ConsoleColor: return(Enum.Parse(typeof(ConsoleColor), PersistedValue)); case ConfigurationValueType.Hashtable: string[] hashItems = PersistedValue.Split(new string[1] { "þHþ" }, StringSplitOptions.None); Hashtable tempTable = new Hashtable(); foreach (string tempValue in hashItems) { string[] tempPair = tempValue.Split(new string[1] { "þEþ" }, StringSplitOptions.None); tempTable[Base64ToUtf8(tempPair[0])] = ConvertFromPersistedValue(Base64ToUtf8(tempPair[1])); } return(tempTable); case ConfigurationValueType.Array: string[] items = PersistedValue.Split(new string[1] { "þþþ" }, StringSplitOptions.None); List <object> results = new List <object>(); foreach (string item in items) { int index = item.IndexOf(':'); if (index > 0) { results.Add(ConvertFromPersistedValue(item.Substring(index + 1), (ConfigurationValueType)Enum.Parse(typeof(ConfigurationValueType), item.Substring(0, index), true))); } } return(results.ToArray()); case ConfigurationValueType.Object: return(PSSerializer.Deserialize(Utility.UtilityHost.ExpandString(PersistedValue))); default: return("<type not supported>"); } }
protected override void ProcessRecord() { WriteDebug("Entering GetPSResource"); var dirsToSearch = new List <string>(); if (_path != null) { WriteDebug(string.Format("Provided path is: '{0}'", _path)); dirsToSearch.AddRange(Directory.GetDirectories(_path).ToList()); } else { var isWindows = OsPlatform.ToLower().Contains("windows"); // PSModules path var psModulePath = Environment.GetEnvironmentVariable("PSModulePath"); var modulePaths = psModulePath.Split(';'); #if NET472 programFilesPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.ProgramFiles), "WindowsPowerShell"); myDocumentsPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.MyDocuments), "WindowsPowerShell"); #else // If PS6+ on Windows if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { myDocumentsPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.MyDocuments), "PowerShell"); programFilesPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.ProgramFiles), "PowerShell"); } else { // Paths are the same for both Linux and MacOS myDocumentsPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.LocalApplicationData), "powershell"); programFilesPath = System.IO.Path.Combine("/usr", "local", "share", "powershell"); } #endif WriteDebug(string.Format("Current user scope path: '{0}'", myDocumentsPath)); WriteDebug(string.Format("All users scope path: '{0}'", programFilesPath)); /*** Will search first in PSModulePath, then will search in default paths ***/ try { foreach (var path in modulePaths) { dirsToSearch.AddRange(Directory.GetDirectories(path).ToList()); } WriteDebug(string.Format("PSModulePath directories: '{0}'", dirsToSearch.ToString())); } catch { } var pfModulesPath = System.IO.Path.Combine(programFilesPath, "Modules"); if (Directory.Exists(pfModulesPath)) { dirsToSearch.AddRange(Directory.GetDirectories(pfModulesPath).ToList()); } var mdModulesPath = System.IO.Path.Combine(myDocumentsPath, "Modules"); if (Directory.Exists(mdModulesPath)) { dirsToSearch.AddRange(Directory.GetDirectories(mdModulesPath).ToList()); } var pfScriptsPath = System.IO.Path.Combine(programFilesPath, "Scripts", "InstalledScriptInfos"); if (Directory.Exists(pfScriptsPath)) { dirsToSearch.AddRange(Directory.GetFiles(pfScriptsPath).ToList()); } var mdScriptsPath = System.IO.Path.Combine(myDocumentsPath, "Scripts", "InstalledScriptInfos"); if (Directory.Exists(mdScriptsPath)) { dirsToSearch.AddRange(Directory.GetFiles(mdScriptsPath).ToList()); } // uniqueify dirsToSearch = dirsToSearch.Distinct().ToList(); } foreach (var dir in dirsToSearch) { WriteDebug(string.Format("All directories to search: '{0}'", dir)); } // Or a list of the passed in names if (_name != null && !_name[0].Equals("*")) { var nameLowerCased = new List <string>(); var scriptXMLnames = new List <string>(); Array.ForEach(_name, n => nameLowerCased.Add(n.ToLower())); Array.ForEach(_name, n => scriptXMLnames.Add((n + "_InstalledScriptInfo.xml").ToLower())); /* * foreach (var name in nameLowerCased) * { * WriteDebug(string.Format("Name in nameLowerCased: '{0}'", name)); * } * * * * foreach (var dir in dirsToSearch) * { * WriteDebug((System.IO.Path.GetFileNameWithoutExtension(dir)).ToLower()); * } */ dirsToSearch = dirsToSearch.FindAll(p => (nameLowerCased.Contains(new DirectoryInfo(p).Name.ToLower()) || scriptXMLnames.Contains((System.IO.Path.GetFileName(p)).ToLower()))); WriteDebug(dirsToSearch.Any().ToString()); } // try to parse into a specific NuGet version VersionRange versionRange = null; if (_version != null) { NuGetVersion specificVersion; NuGetVersion.TryParse(_version, out specificVersion); if (specificVersion != null) { // exact version versionRange = new VersionRange(specificVersion, true, specificVersion, true, null, null); WriteDebug(string.Format("A specific version, '{0}', is specified", versionRange.ToString())); } else { // check if version range versionRange = VersionRange.Parse(_version); WriteDebug(string.Format("A version range, '{0}', is specified", versionRange.ToString())); } } List <string> installedPkgsToReturn = new List <string>(); IEnumerable <string> returnPkgs = null; var versionDirs = new List <string>(); //2) use above list to check // if the version specificed is a version range if (versionRange != null) { foreach (var pkgPath in dirsToSearch) { WriteDebug(string.Format("Searching through package path: '{0}'", pkgPath)); var versionsDirs = Directory.GetDirectories(pkgPath); foreach (var versionPath in versionsDirs) { WriteDebug(string.Format("Searching through package version path: '{0}'", versionPath)); NuGetVersion dirAsNugetVersion; var dirInfo = new DirectoryInfo(versionPath); NuGetVersion.TryParse(dirInfo.Name, out dirAsNugetVersion); WriteDebug(string.Format("Directory parsed as NuGet version: '{0}'", dirAsNugetVersion)); if (versionRange.Satisfies(dirAsNugetVersion)) { // just search scripts paths if (pkgPath.ToLower().Contains("Scripts")) { if (File.Exists(pkgPath)) { installedPkgsToReturn.Add(pkgPath); } } else { // modules paths versionsDirs = Directory.GetDirectories(pkgPath); WriteDebug(string.Format("Getting sub directories from : '{0}'", pkgPath)); // Check if the pkg path actually has version sub directories. if (versionsDirs.Length != 0) { Array.Sort(versionsDirs, StringComparer.OrdinalIgnoreCase); Array.Reverse(versionsDirs); var pkgXmlFilePath = System.IO.Path.Combine(versionsDirs.First(), "PSGetModuleInfo.xml"); // TODO: check if this xml file exists, if it doesn't check if it exists in a previous version WriteDebug(string.Format("Found module XML: '{0}'", pkgXmlFilePath)); installedPkgsToReturn.Add(pkgXmlFilePath); } } installedPkgsToReturn.Add(versionPath); } } } } else { WriteDebug(string.Format("No version provided-- check each path for the requested package")); // if no version is specified, just get the latest version foreach (var pkgPath in dirsToSearch) { WriteDebug(string.Format("Searching through package path: '{0}'", pkgPath)); // just search scripts paths if (pkgPath.ToLower().Contains("scripts")) { if (File.Exists(pkgPath)) //check to make sure properly formatted { installedPkgsToReturn.Add(pkgPath); } } else { // modules paths string[] versionsDirs = new string[0]; versionsDirs = Directory.GetDirectories(pkgPath); // Check if the pkg path actually has version sub directories. if (versionsDirs.Length != 0) { Array.Sort(versionsDirs, StringComparer.OrdinalIgnoreCase); Array.Reverse(versionsDirs); var pkgXmlFilePath = System.IO.Path.Combine(versionsDirs.First(), "PSGetModuleInfo.xml"); // TODO: check if this xml file exists, if it doesn't check if it exists in a previous version WriteDebug(string.Format("Found package XML: '{0}'", pkgXmlFilePath)); installedPkgsToReturn.Add(pkgXmlFilePath); } } } } // Flatten returned pkgs before displaying output returnedPkgsFound.Flatten().ToList()[0] var flattenedPkgs = installedPkgsToReturn.Flatten(); foreach (string xmlFilePath in flattenedPkgs) { WriteDebug(string.Format("Reading package metadata from: '{0}'", xmlFilePath)); // Open xml and read metadata from it if (File.Exists(xmlFilePath)) { ReadOnlyPSMemberInfoCollection <PSPropertyInfo> nameInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> versionInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> additionalMetadataInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> psDataInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> repositoryInfo; ReadOnlyPSMemberInfoCollection <PSPropertyInfo> descriptionversionInfo; var isPrelease = false; using (StreamReader sr = new StreamReader(xmlFilePath)) { string text = sr.ReadToEnd(); var deserializedObj = (PSObject)PSSerializer.Deserialize(text); nameInfo = deserializedObj.Properties.Match("Name"); /* // testing adding prerelease parameter * additionalMetadataInfo = deserializedObj.Properties.Match("AdditionalMetadata"); * if (additionalMetadataInfo.Any()) * { * isPrelease = additionalMetadataInfo.FirstOrDefault().Value.ToString().Contains("IsPrerelease=true"); * if ((isPrelease == true) && _prerelease) // find a stable version of the pkg {} * } */ versionInfo = deserializedObj.Properties.Match("Version"); repositoryInfo = deserializedObj.Properties.Match("Repository"); descriptionversionInfo = deserializedObj.Properties.Match("Description"); }; // if -Prerelease is not passed in as a parameter, don't allow prerelease pkgs to be returned, // we still want all pkgs to be returned if -Prerelease is passed in as a param //if ((_prerelease == false && isPrelease == false) || _prerelease == true) //{ PSObject pkgAsPSObject = new PSObject(); try { pkgAsPSObject.Members.Add(new PSNoteProperty("Name", nameInfo.FirstOrDefault().Value)); // need to fix output pkgAsPSObject.Members.Add(new PSNoteProperty("Version", versionInfo.FirstOrDefault().Value)); pkgAsPSObject.Members.Add(new PSNoteProperty("Repository", repositoryInfo.FirstOrDefault().Value)); pkgAsPSObject.Members.Add(new PSNoteProperty("Description", descriptionversionInfo.FirstOrDefault().Value)); WriteObject(pkgAsPSObject); } catch { } //} } } }
/// <summary> /// Validates an ARM template. /// </summary> /// <param name="resourceGroupName">The name of the resource group to validate against.</param> /// <param name="templateFilePath">Path to the ARM template file to validate.</param> /// <param name="templateParametersFilePath">Path to the ARM template parameters file to use with validation.</param> /// <returns>True if valid, and false if invalid.</returns> public static bool ValidateTemplate(string resourceGroupName, string templateFilePath, string templateParametersFilePath) { if (!Directory.Exists(_tempArmDir)) { Directory.CreateDirectory(_tempArmDir); } ArmTemplateHelper.LoadArmTemplateParameters(templateParametersFilePath); IEnumerable <string> parameterNames = ArmTemplateHelper.GetParameterNames(templateParametersFilePath); foreach (string parameterName in parameterNames) { ArmTemplateHelper.SetParameterValue( templateParametersFilePath, parameterName, ArmTemplateHelper.GetParameterValue( templateParametersFilePath, parameterName)); } string templateParameterFileName = Path.GetFileName(templateParametersFilePath); string tempParametersFilePath = $@"{_tempArmDir}\{templateParameterFileName}"; ArmTemplateHelper.SaveConfiguration(templateParametersFilePath, tempParametersFilePath); using (PowerShell powerShellInstance = PowerShell.Create()) { powerShellInstance.AddCommand("Test-AzResourceGroupDeployment"); powerShellInstance.AddParameter("-ResourceGroupName", resourceGroupName); powerShellInstance.AddParameter("-TemplateFile", templateFilePath); powerShellInstance.AddParameter("-TemplateParameterFile", tempParametersFilePath); PSDataCollection <PSObject> outputCollection = new PSDataCollection <PSObject>(); powerShellInstance.Streams.Error.DataAdded += Error_DataAdded; IAsyncResult result = powerShellInstance.BeginInvoke <PSObject, PSObject>(null, outputCollection); while (!result.IsCompleted) { Debug.WriteLine("Waiting for pipeline to finish."); Thread.Sleep(1000); } Debug.WriteLine("Execution has stopped. The pipeline state: " + powerShellInstance.InvocationStateInfo.State); string serializedOutput = PSSerializer.Serialize(outputCollection); XNamespace ns = "http://schemas.microsoft.com/powershell/2004/04"; XDocument output = XDocument.Parse(serializedOutput); List <XElement> messageElements = output.Root.Descendants(ns + "S") .Where(x => x.Attribute("N") != null && x.Attribute("N").Value == "Message") .ToList(); foreach (XElement messageElement in messageElements) { Debug.WriteLine($"ERROR: {messageElement.Value}"); } if (messageElements.Count() != 0) { return(false); } if (powerShellInstance.Streams.Error.Count() > 0) { return(false); } return(true); } }
public PSObject DeserializeHosts(String serializedhosts) { PSObject hosts = (PSObject)PSSerializer.Deserialize(serializedhosts); return(hosts); }
/// <summary> /// Reads a PSGet resource xml (PowerShell serialized) file and returns /// a PSResourceInfo object containing the file contents. /// </summary> public static bool TryRead( string filePath, out PSResourceInfo psGetInfo, out string errorMsg) { psGetInfo = null; errorMsg = string.Empty; if (string.IsNullOrWhiteSpace(filePath)) { errorMsg = "TryReadPSGetInfo: Invalid file path. Filepath cannot be empty or whitespace."; return(false); } try { // Read and deserialize information xml file. var psObjectInfo = (PSObject)PSSerializer.Deserialize( System.IO.File.ReadAllText( filePath)); var additionalMetadata = GetProperty <Dictionary <string, string> >(nameof(PSResourceInfo.AdditionalMetadata), psObjectInfo); Version version = GetVersionInfo(psObjectInfo, additionalMetadata, out string prereleaseLabel); psGetInfo = new PSResourceInfo( additionalMetadata: additionalMetadata, author: GetStringProperty(nameof(PSResourceInfo.Author), psObjectInfo), companyName: GetStringProperty(nameof(PSResourceInfo.CompanyName), psObjectInfo), copyright: GetStringProperty(nameof(PSResourceInfo.Copyright), psObjectInfo), dependencies: GetDependencies(GetProperty <ArrayList>(nameof(PSResourceInfo.Dependencies), psObjectInfo)), description: GetStringProperty(nameof(PSResourceInfo.Description), psObjectInfo), iconUri: GetProperty <Uri>(nameof(PSResourceInfo.IconUri), psObjectInfo), includes: new ResourceIncludes(GetProperty <Hashtable>(nameof(PSResourceInfo.Includes), psObjectInfo)), installedDate: GetProperty <DateTime>(nameof(PSResourceInfo.InstalledDate), psObjectInfo), installedLocation: GetStringProperty(nameof(PSResourceInfo.InstalledLocation), psObjectInfo), isPrelease: GetProperty <bool>(nameof(PSResourceInfo.IsPrerelease), psObjectInfo), licenseUri: GetProperty <Uri>(nameof(PSResourceInfo.LicenseUri), psObjectInfo), name: GetStringProperty(nameof(PSResourceInfo.Name), psObjectInfo), packageManagementProvider: GetStringProperty(nameof(PSResourceInfo.PackageManagementProvider), psObjectInfo), powershellGetFormatVersion: GetStringProperty(nameof(PSResourceInfo.PowerShellGetFormatVersion), psObjectInfo), prereleaseLabel: prereleaseLabel, projectUri: GetProperty <Uri>(nameof(PSResourceInfo.ProjectUri), psObjectInfo), publishedDate: GetProperty <DateTime>(nameof(PSResourceInfo.PublishedDate), psObjectInfo), releaseNotes: GetStringProperty(nameof(PSResourceInfo.ReleaseNotes), psObjectInfo), repository: GetStringProperty(nameof(PSResourceInfo.Repository), psObjectInfo), repositorySourceLocation: GetStringProperty(nameof(PSResourceInfo.RepositorySourceLocation), psObjectInfo), tags: Utils.GetStringArray(GetProperty <ArrayList>(nameof(PSResourceInfo.Tags), psObjectInfo)), type: Enum.TryParse( GetProperty <string>(nameof(PSResourceInfo.Type), psObjectInfo) ?? nameof(ResourceType.Module), out ResourceType currentReadType) ? currentReadType : ResourceType.Module, updatedDate: GetProperty <DateTime>(nameof(PSResourceInfo.UpdatedDate), psObjectInfo), version: version); return(true); } catch (Exception ex) { errorMsg = string.Format( CultureInfo.InvariantCulture, @"TryReadPSGetInfo: Cannot read the PowerShellGet information file with error: {0}", ex.Message); return(false); } }