PSModule.psm1
Import-LocalizedData LocalizedData -filename PSGet.Resource.psd1 ######################################################################################### # # Copyright (c) Microsoft Corporation. All rights reserved. # # PowerShellGet Module # ######################################################################################### Microsoft.PowerShell.Core\Set-StrictMode -Version Latest #region script variables $script:IsInbox = $PSHOME.EndsWith('\WindowsPowerShell\v1.0', [System.StringComparison]::OrdinalIgnoreCase) $script:IsWindows = (-not (Get-Variable -Name IsWindows -ErrorAction Ignore)) -or $IsWindows $script:IsLinux = (Get-Variable -Name IsLinux -ErrorAction Ignore) -and $IsLinux $script:IsMacOS = (Get-Variable -Name IsMacOS -ErrorAction Ignore) -and $IsMacOS $script:IsCoreCLR = $PSVersionTable.ContainsKey('PSEdition') -and $PSVersionTable.PSEdition -eq 'Core' $script:IsNanoServer = & { if (!$script:IsWindows) { return $false } $serverLevelsPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels\' if (Test-Path -Path $serverLevelsPath) { $NanoItem = Get-ItemProperty -Name NanoServer -Path $serverLevelsPath -ErrorAction Ignore if ($NanoItem -and ($NanoItem.NanoServer -eq 1)) { return $true } } return $false } if ($script:IsInbox) { $script:ProgramFilesPSPath = Microsoft.PowerShell.Management\Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell" } elseif ($script:IsCoreCLR) { if ($script:IsWindows) { $script:ProgramFilesPSPath = Microsoft.PowerShell.Management\Join-Path -Path $env:ProgramFiles -ChildPath 'PowerShell' } else { $script:ProgramFilesPSPath = Microsoft.PowerShell.Management\Split-Path -Path ([System.Management.Automation.Platform]::SelectProductNameForDirectory('SHARED_MODULES')) -Parent } } try { $script:MyDocumentsFolderPath = [Environment]::GetFolderPath("MyDocuments") } catch { $script:MyDocumentsFolderPath = $null } if ($script:IsInbox) { $script:MyDocumentsPSPath = if ($script:MyDocumentsFolderPath) { Microsoft.PowerShell.Management\Join-Path -Path $script:MyDocumentsFolderPath -ChildPath "WindowsPowerShell" } else { Microsoft.PowerShell.Management\Join-Path -Path $env:USERPROFILE -ChildPath "Documents\WindowsPowerShell" } } elseif ($script:IsCoreCLR) { if ($script:IsWindows) { $script:MyDocumentsPSPath = if ($script:MyDocumentsFolderPath) { Microsoft.PowerShell.Management\Join-Path -Path $script:MyDocumentsFolderPath -ChildPath 'PowerShell' } else { Microsoft.PowerShell.Management\Join-Path -Path $HOME -ChildPath "Documents\PowerShell" } } else { $script:MyDocumentsPSPath = Microsoft.PowerShell.Management\Split-Path -Path ([System.Management.Automation.Platform]::SelectProductNameForDirectory('USER_MODULES')) -Parent } } $script:ProgramFilesModulesPath = Microsoft.PowerShell.Management\Join-Path -Path $script:ProgramFilesPSPath -ChildPath 'Modules' $script:MyDocumentsModulesPath = Microsoft.PowerShell.Management\Join-Path -Path $script:MyDocumentsPSPath -ChildPath 'Modules' $script:ProgramFilesScriptsPath = Microsoft.PowerShell.Management\Join-Path -Path $script:ProgramFilesPSPath -ChildPath 'Scripts' $script:MyDocumentsScriptsPath = Microsoft.PowerShell.Management\Join-Path -Path $script:MyDocumentsPSPath -ChildPath 'Scripts' $script:PSGetPath = [pscustomobject]@{ AllUsersModules = $script:ProgramFilesModulesPath AllUsersScripts = $script:ProgramFilesScriptsPath CurrentUserModules = $script:MyDocumentsModulesPath CurrentUserScripts = $script:MyDocumentsScriptsPath PSTypeName = 'Microsoft.PowerShell.Commands.PSGetPath' } $script:TempPath = [System.IO.Path]::GetTempPath() $script:PSGetItemInfoFileName = "PSGetModuleInfo.xml" if ($script:IsWindows) { $script:PSGetProgramDataPath = Microsoft.PowerShell.Management\Join-Path -Path $env:ProgramData -ChildPath 'Microsoft\Windows\PowerShell\PowerShellGet\' $script:PSGetAppLocalPath = Microsoft.PowerShell.Management\Join-Path -Path $env:LOCALAPPDATA -ChildPath 'Microsoft\Windows\PowerShell\PowerShellGet\' } else { $script:PSGetProgramDataPath = Microsoft.PowerShell.Management\Join-Path -Path ([System.Management.Automation.Platform]::SelectProductNameForDirectory('CONFIG')) -ChildPath 'PowerShellGet' $script:PSGetAppLocalPath = Microsoft.PowerShell.Management\Join-Path -Path ([System.Management.Automation.Platform]::SelectProductNameForDirectory('CACHE')) -ChildPath 'PowerShellGet' } $script:PSGetModuleSourcesFilePath = Microsoft.PowerShell.Management\Join-Path -Path $script:PSGetAppLocalPath -ChildPath "PSRepositories.xml" $script:PSGetModuleSources = $null $script:PSGetInstalledModules = $null $script:PSGetSettingsFilePath = Microsoft.PowerShell.Management\Join-Path -Path $script:PSGetAppLocalPath -ChildPath "PowerShellGetSettings.xml" $script:PSGetSettings = $null $script:MyDocumentsInstalledScriptInfosPath = Microsoft.PowerShell.Management\Join-Path -Path $script:MyDocumentsScriptsPath -ChildPath 'InstalledScriptInfos' $script:ProgramFilesInstalledScriptInfosPath = Microsoft.PowerShell.Management\Join-Path -Path $script:ProgramFilesScriptsPath -ChildPath 'InstalledScriptInfos' $script:IsRunningAsElevated = $true $script:IsRunningAsElevatedTested = $false $script:InstalledScriptInfoFileName = 'InstalledScriptInfo.xml' $script:PSGetInstalledScripts = $null # Public PSGallery module source name and location $Script:PSGalleryModuleSource = "PSGallery" $Script:PSGallerySourceUri = 'https://www.powershellgallery.com/api/v2' $Script:PSGalleryPublishUri = 'https://www.powershellgallery.com/api/v2/package/' $Script:PSGalleryScriptSourceUri = 'https://www.powershellgallery.com/api/v2/items/psscript' # PSGallery V3 Source $Script:PSGalleryV3SourceUri = 'https://www.powershellgallery.com/api/v3' $Script:ResponseUri = "ResponseUri" $Script:StatusCode = "StatusCode" $Script:Exception = "Exception" $script:PSModuleProviderName = 'PowerShellGet' $script:PackageManagementProviderParam = "PackageManagementProvider" $script:PublishLocation = "PublishLocation" $script:ScriptSourceLocation = 'ScriptSourceLocation' $script:ScriptPublishLocation = 'ScriptPublishLocation' $script:Proxy = 'Proxy' $script:ProxyCredential = 'ProxyCredential' $script:Credential = 'Credential' $script:VSTSAuthenticatedFeedsDocUrl = 'https://go.microsoft.com/fwlink/?LinkID=698608' $script:Prerelease = "Prerelease" $script:NuGetProviderName = "NuGet" $script:NuGetProviderVersion = [Version]'2.8.5.201' $script:SupportsPSModulesFeatureName = "supports-powershell-modules" $script:FastPackRefHashtable = @{ } $script:NuGetBinaryProgramDataPath = if ($script:IsWindows) { "$env:ProgramFiles\PackageManagement\ProviderAssemblies" } $script:NuGetBinaryLocalAppDataPath = if ($script:IsWindows) { "$env:LOCALAPPDATA\PackageManagement\ProviderAssemblies" } # go fwlink for 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' $script:NuGetClientSourceURL = 'https://aka.ms/psget-nugetexe' $script:NuGetExeMinRequiredVersion = [Version]'4.1.0' $script:NuGetExeName = 'NuGet.exe' $script:NuGetExePath = $null $script:NuGetExeVersion = $null $script:NuGetProvider = $null $script:DotnetCommandName = 'dotnet' $script:MinimumDotnetCommandVersion = [Version]'2.0.0' $script:DotnetInstallUrl = 'https://aka.ms/dotnet-install-script' $script:DotnetCommandPath = $null # PowerShellGetFormatVersion will be incremented when we change the .nupkg format structure. # PowerShellGetFormatVersion is in the form of Major.Minor. # Minor is incremented for the backward compatible format change. # Major is incremented for the breaking change. $script:PSGetRequireLicenseAcceptanceFormatVersion = [Version]'2.0' $script:CurrentPSGetFormatVersion = $script:PSGetRequireLicenseAcceptanceFormatVersion $script:PSGetFormatVersion = "PowerShellGetFormatVersion" $script:SupportedPSGetFormatVersionMajors = @("1", "2") $script:ModuleReferences = 'Module References' $script:AllVersions = "AllVersions" $script:AllowPrereleaseVersions = "AllowPrereleaseVersions" $script:Filter = "Filter" $script:IncludeValidSet = @('DscResource', 'Cmdlet', 'Function', 'Workflow', 'RoleCapability') $script:DscResource = "PSDscResource" $script:Command = "PSCommand" $script:Cmdlet = "PSCmdlet" $script:Function = "PSFunction" $script:Workflow = "PSWorkflow" $script:RoleCapability = 'PSRoleCapability' $script:Includes = "PSIncludes" $script:Tag = "Tag" $script:NotSpecified = '_NotSpecified_' $script:PSGetModuleName = 'PowerShellGet' $script:FindByCanonicalId = 'FindByCanonicalId' $script:InstalledLocation = 'InstalledLocation' $script:PSArtifactType = 'Type' $script:PSArtifactTypeModule = 'Module' $script:PSArtifactTypeScript = 'Script' $script:All = 'All' $script:Name = 'Name' $script:Version = 'Version' $script:Guid = 'Guid' $script:Path = 'Path' $script:ScriptBase = 'ScriptBase' $script:Description = 'Description' $script:Author = 'Author' $script:CompanyName = 'CompanyName' $script:Copyright = 'Copyright' $script:Tags = 'Tags' $script:LicenseUri = 'LicenseUri' $script:ProjectUri = 'ProjectUri' $script:IconUri = 'IconUri' $script:RequiredModules = 'RequiredModules' $script:ExternalModuleDependencies = 'ExternalModuleDependencies' $script:ReleaseNotes = 'ReleaseNotes' $script:RequiredScripts = 'RequiredScripts' $script:ExternalScriptDependencies = 'ExternalScriptDependencies' $script:DefinedCommands = 'DefinedCommands' $script:DefinedFunctions = 'DefinedFunctions' $script:DefinedWorkflows = 'DefinedWorkflows' $script:TextInfo = (Get-Culture).TextInfo $script:PrivateData = 'PrivateData' $script:PSScriptInfoProperties = @($script:Name $script:Version, $script:Guid, $script:Path, $script:ScriptBase, $script:Description, $script:Author, $script:CompanyName, $script:Copyright, $script:Tags, $script:ReleaseNotes, $script:RequiredModules, $script:ExternalModuleDependencies, $script:RequiredScripts, $script:ExternalScriptDependencies, $script:LicenseUri, $script:ProjectUri, $script:IconUri, $script:DefinedCommands, $script:DefinedFunctions, $script:DefinedWorkflows, $script:PrivateData ) $script:SystemEnvironmentKey = 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' $script:UserEnvironmentKey = 'HKCU:\Environment' $script:SystemEnvironmentVariableMaximumLength = 1024 $script:UserEnvironmentVariableMaximumLength = 255 $script:EnvironmentVariableTarget = @{ Process = 0; User = 1; Machine = 2 } # Wildcard pattern matching configuration. $script:wildcardOptions = [System.Management.Automation.WildcardOptions]::CultureInvariant -bor ` [System.Management.Automation.WildcardOptions]::IgnoreCase $script:DynamicOptionTypeMap = @{ 0 = [string]; # String 1 = [string[]]; # StringArray 2 = [int]; # Int 3 = [switch]; # Switch 4 = [string]; # Folder 5 = [string]; # File 6 = [string]; # Path 7 = [Uri]; # Uri 8 = [SecureString]; #SecureString } #endregion script variables #region Module message resolvers $script:PackageManagementMessageResolverScriptBlock = { param($i, $Message) return (PackageManagementMessageResolver -MsgId $i, -Message $Message) } $script:PackageManagementSaveModuleMessageResolverScriptBlock = { param($i, $Message) $PackageTarget = $LocalizedData.InstallModulewhatIfMessage $QuerySaveUntrustedPackage = $LocalizedData.QuerySaveUntrustedPackage switch ($i) { 'ActionInstallPackage' { return "Save-Module" } 'QueryInstallUntrustedPackage' { return $QuerySaveUntrustedPackage } 'TargetPackage' { return $PackageTarget } Default { $Message = $Message -creplace "Install", "Download" $Message = $Message -creplace "install", "download" return (PackageManagementMessageResolver -MsgId $i, -Message $Message) } } } $script:PackageManagementInstallModuleMessageResolverScriptBlock = { param($i, $Message) $PackageTarget = $LocalizedData.InstallModulewhatIfMessage switch ($i) { 'ActionInstallPackage' { return "Install-Module" } 'TargetPackage' { return $PackageTarget } Default { return (PackageManagementMessageResolver -MsgId $i, -Message $Message) } } } $script:PackageManagementUnInstallModuleMessageResolverScriptBlock = { param($i, $Message) $PackageTarget = $LocalizedData.InstallModulewhatIfMessage switch ($i) { 'ActionUninstallPackage' { return "Uninstall-Module" } 'TargetPackageVersion' { return $PackageTarget } Default { return (PackageManagementMessageResolver -MsgId $i, -Message $Message) } } } $script:PackageManagementUpdateModuleMessageResolverScriptBlock = { param($i, $Message) $PackageTarget = ($LocalizedData.UpdateModulewhatIfMessage -replace "__OLDVERSION__", $($psgetItemInfo.Version)) switch ($i) { 'ActionInstallPackage' { return "Update-Module" } 'TargetPackage' { return $PackageTarget } Default { return (PackageManagementMessageResolver -MsgId $i, -Message $Message) } } } # Modules allowed to install non-Microsoft signed modules over Microsoft signed modules $script:WhitelistedModules = @{ "Pester" = $true "PSReadline" = $true } function PackageManagementMessageResolver($MsgID, $Message) { $NoMatchFound = $LocalizedData.NoMatchFound $SourceNotFound = $LocalizedData.SourceNotFound $ModuleIsNotTrusted = $LocalizedData.ModuleIsNotTrusted $RepositoryIsNotTrusted = $LocalizedData.RepositoryIsNotTrusted $QueryInstallUntrustedPackage = $LocalizedData.QueryInstallUntrustedPackage switch ($MsgID) { 'NoMatchFound' { return $NoMatchFound } 'SourceNotFound' { return $SourceNotFound } 'CaptionPackageNotTrusted' { return $ModuleIsNotTrusted } 'CaptionSourceNotTrusted' { return $RepositoryIsNotTrusted } 'QueryInstallUntrustedPackage' { return $QueryInstallUntrustedPackage } Default { if ($Message) { $tempMessage = $Message -creplace "PackageSource", "PSRepository" $tempMessage = $tempMessage -creplace "packagesource", "psrepository" $tempMessage = $tempMessage -creplace "Package", "Module" $tempMessage = $tempMessage -creplace "package", "module" $tempMessage = $tempMessage -creplace "Sources", "Repositories" $tempMessage = $tempMessage -creplace "sources", "repositories" $tempMessage = $tempMessage -creplace "Source", "Repository" $tempMessage = $tempMessage -creplace "source", "repository" return $tempMessage } } } } #endregion Module message resolvers #region Script message resolvers $script:PackageManagementMessageResolverScriptBlockForScriptCmdlets = { param($i, $Message) return (PackageManagementMessageResolverForScripts -MsgId $i, -Message $Message) } $script:PackageManagementSaveScriptMessageResolverScriptBlock = { param($i, $Message) $PackageTarget = $LocalizedData.InstallScriptwhatIfMessage $QuerySaveUntrustedPackage = $LocalizedData.QuerySaveUntrustedScriptPackage switch ($i) { 'ActionInstallPackage' { return "Save-Script" } 'QueryInstallUntrustedPackage' { return $QuerySaveUntrustedPackage } 'TargetPackage' { return $PackageTarget } Default { $Message = $Message -creplace "Install", "Download" $Message = $Message -creplace "install", "download" return (PackageManagementMessageResolverForScripts -MsgId $i, -Message $Message) } } } $script:PackageManagementInstallScriptMessageResolverScriptBlock = { param($i, $Message) $PackageTarget = $LocalizedData.InstallScriptwhatIfMessage switch ($i) { 'ActionInstallPackage' { return "Install-Script" } 'TargetPackage' { return $PackageTarget } Default { return (PackageManagementMessageResolverForScripts -MsgId $i, -Message $Message) } } } $script:PackageManagementUnInstallScriptMessageResolverScriptBlock = { param($i, $Message) $PackageTarget = $LocalizedData.InstallScriptwhatIfMessage switch ($i) { 'ActionUninstallPackage' { return "Uninstall-Script" } 'TargetPackageVersion' { return $PackageTarget } Default { return (PackageManagementMessageResolverForScripts -MsgId $i, -Message $Message) } } } $script:PackageManagementUpdateScriptMessageResolverScriptBlock = { param($i, $Message) $PackageTarget = ($LocalizedData.UpdateScriptwhatIfMessage -replace "__OLDVERSION__", $($psgetItemInfo.Version)) switch ($i) { 'ActionInstallPackage' { return "Update-Script" } 'TargetPackage' { return $PackageTarget } Default { return (PackageManagementMessageResolverForScripts -MsgId $i, -Message $Message) } } } function PackageManagementMessageResolverForScripts($MsgID, $Message) { $NoMatchFound = $LocalizedData.NoMatchFoundForScriptName $SourceNotFound = $LocalizedData.SourceNotFound $ScriptIsNotTrusted = $LocalizedData.ScriptIsNotTrusted $RepositoryIsNotTrusted = $LocalizedData.RepositoryIsNotTrusted $QueryInstallUntrustedPackage = $LocalizedData.QueryInstallUntrustedScriptPackage switch ($MsgID) { 'NoMatchFound' { return $NoMatchFound } 'SourceNotFound' { return $SourceNotFound } 'CaptionPackageNotTrusted' { return $ScriptIsNotTrusted } 'CaptionSourceNotTrusted' { return $RepositoryIsNotTrusted } 'QueryInstallUntrustedPackage' { return $QueryInstallUntrustedPackage } Default { if ($Message) { $tempMessage = $Message -creplace "PackageSource", "PSRepository" $tempMessage = $tempMessage -creplace "packagesource", "psrepository" $tempMessage = $tempMessage -creplace "Package", "Script" $tempMessage = $tempMessage -creplace "package", "script" $tempMessage = $tempMessage -creplace "Sources", "Repositories" $tempMessage = $tempMessage -creplace "sources", "repositories" $tempMessage = $tempMessage -creplace "Source", "Repository" $tempMessage = $tempMessage -creplace "source", "repository" return $tempMessage } } } } #endregion Script message resolvers #region Add .Net type for Telemetry APIs and WebProxy # Check and add InternalWebProxy type if ( -not ('Microsoft.PowerShell.Commands.PowerShellGet.InternalWebProxy' -as [Type])) { $RequiredAssembliesForInternalWebProxy = @( [System.Net.IWebProxy].Assembly.FullName, [System.Uri].Assembly.FullName ) $InternalWebProxySource = @' using System; using System.Net; namespace Microsoft.PowerShell.Commands.PowerShellGet { /// <summary> /// Used by Ping-Endpoint function to supply webproxy to HttpClient /// We cannot use System.Net.WebProxy because this is not available on CoreClr /// </summary> public class InternalWebProxy : IWebProxy { Uri _proxyUri; ICredentials _credentials; public InternalWebProxy(Uri uri, ICredentials credentials) { Credentials = credentials; _proxyUri = uri; } /// <summary> /// Credentials used by WebProxy /// </summary> public ICredentials Credentials { get { return _credentials; } set { _credentials = value; } } public Uri GetProxy(Uri destination) { return _proxyUri; } public bool IsBypassed(Uri host) { return false; } } } '@ try { $AddType_prams = @{ TypeDefinition = $InternalWebProxySource Language = 'CSharp' ErrorAction = 'SilentlyContinue' } if (-not $script:IsCoreCLR -or $script:IsNanoServer) { $AddType_prams['ReferencedAssemblies'] = $RequiredAssembliesForInternalWebProxy } Add-Type @AddType_prams } catch { Write-Warning -Message "InternalWebProxy: $_" } } # Check and add Telemetry type if (('Microsoft.PowerShell.Telemetry.Internal.TelemetryAPI' -as [Type]) -and -not ('Microsoft.PowerShell.Commands.PowerShellGet.Telemetry' -as [Type])) { $RequiredAssembliesForTelemetry = @( [System.Management.Automation.PSCmdlet].Assembly.FullName ) $TelemetrySource = @' using System; using System.Management.Automation; namespace Microsoft.PowerShell.Commands.PowerShellGet { public static class Telemetry { public static void TraceMessageArtifactsNotFound(string[] artifactsNotFound, string operationName) { Microsoft.PowerShell.Telemetry.Internal.TelemetryAPI.TraceMessage(operationName, new { ArtifactsNotFound = artifactsNotFound }); } public static void TraceMessageNonPSGalleryRegistration(string sourceLocationType, string sourceLocationHash, string installationPolicy, string packageManagementProvider, string publishLocationHash, string scriptSourceLocationHash, string scriptPublishLocationHash, string operationName) { Microsoft.PowerShell.Telemetry.Internal.TelemetryAPI.TraceMessage(operationName, new { SourceLocationType = sourceLocationType, SourceLocationHash = sourceLocationHash, InstallationPolicy = installationPolicy, PackageManagementProvider = packageManagementProvider, PublishLocationHash = publishLocationHash, ScriptSourceLocationHash = scriptSourceLocationHash, ScriptPublishLocationHash = scriptPublishLocationHash }); } } } '@ try { $AddType_prams = @{ TypeDefinition = $TelemetrySource Language = 'CSharp' ErrorAction = 'SilentlyContinue' } $AddType_prams['ReferencedAssemblies'] = $RequiredAssembliesForTelemetry Add-Type @AddType_prams } catch { Write-Warning -Message "Telemetry: $_" } } # Turn ON Telemetry if the infrastructure is present on the machine $script:TelemetryEnabled = $false if ('Microsoft.PowerShell.Commands.PowerShellGet.Telemetry' -as [Type]) { $telemetryMethods = ([Microsoft.PowerShell.Commands.PowerShellGet.Telemetry] | Get-Member -Static).Name if ($telemetryMethods.Contains("TraceMessageArtifactsNotFound") -and $telemetryMethods.Contains("TraceMessageNonPSGalleryRegistration")) { $script:TelemetryEnabled = $true } } # Check and add Win32Helpers type $script:IsSafeX509ChainHandleAvailable = ($null -ne ('Microsoft.Win32.SafeHandles.SafeX509ChainHandle' -as [Type])) if ($script:IsWindows -and -not ('Microsoft.PowerShell.Commands.PowerShellGet.Win32Helpers' -as [Type])) { $RequiredAssembliesForWin32Helpers = @() if ($script:IsSafeX509ChainHandleAvailable) { # It is not possible to define a single internal SafeHandle class in PowerShellGet namespace for all the supported versions of .Net Framework including .Net Core. # SafeHandleZeroOrMinusOneIsInvalid is not a public class on .Net Core, # therefore SafeX509ChainHandle will be used if it is available otherwise InternalSafeX509ChainHandle is defined below. # # ChainContext is not available on .Net Core, we must have to use SafeX509ChainHandle on .Net Core. # $SafeX509ChainHandleClassName = 'SafeX509ChainHandle' $RequiredAssembliesForWin32Helpers += [Microsoft.Win32.SafeHandles.SafeX509ChainHandle].Assembly.FullName } else { # SafeX509ChainHandle is not available on .Net Framework 4.5 or older versions, # therefore InternalSafeX509ChainHandle is defined below. # $SafeX509ChainHandleClassName = 'InternalSafeX509ChainHandle' } $Win32HelpersSource = @" using System; using System.Net; using Microsoft.Win32.SafeHandles; using System.Security.Cryptography; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Security; namespace Microsoft.PowerShell.Commands.PowerShellGet { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] public struct CERT_CHAIN_POLICY_PARA { public CERT_CHAIN_POLICY_PARA(int size) { cbSize = (uint) size; dwFlags = 0; pvExtraPolicyPara = IntPtr.Zero; } public uint cbSize; public uint dwFlags; public IntPtr pvExtraPolicyPara; } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] public struct CERT_CHAIN_POLICY_STATUS { public CERT_CHAIN_POLICY_STATUS(int size) { cbSize = (uint) size; dwError = 0; lChainIndex = IntPtr.Zero; lElementIndex = IntPtr.Zero; pvExtraPolicyStatus = IntPtr.Zero; } public uint cbSize; public uint dwError; public IntPtr lChainIndex; public IntPtr lElementIndex; public IntPtr pvExtraPolicyStatus; } // Internal SafeHandleZeroOrMinusOneIsInvalid class to remove the dependency on .Net Framework 4.6. public abstract class InternalSafeHandleZeroOrMinusOneIsInvalid : SafeHandle { protected InternalSafeHandleZeroOrMinusOneIsInvalid(bool ownsHandle) : base(IntPtr.Zero, ownsHandle) { } public override bool IsInvalid { get { return handle == IntPtr.Zero || handle == new IntPtr(-1); } } } // Internal SafeX509ChainHandle class to remove the dependency on .Net Framework 4.6. [SecurityCritical] public sealed class InternalSafeX509ChainHandle : InternalSafeHandleZeroOrMinusOneIsInvalid { private InternalSafeX509ChainHandle () : base(true) {} internal InternalSafeX509ChainHandle (IntPtr handle) : base (true) { SetHandle(handle); } internal static InternalSafeX509ChainHandle InvalidHandle { get { return new InternalSafeX509ChainHandle(IntPtr.Zero); } } [SecurityCritical] override protected bool ReleaseHandle() { CertFreeCertificateChain(handle); return true; } [DllImport("Crypt32.dll", SetLastError=true)] $(if(-not $script:IsCoreCLR) { ' [SuppressUnmanagedCodeSecurity, ResourceExposure(ResourceScope.None), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] ' }) private static extern void CertFreeCertificateChain(IntPtr handle); } public class Win32Helpers { [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)] public extern static bool CertVerifyCertificateChainPolicy( [In] IntPtr pszPolicyOID, [In] $SafeX509ChainHandleClassName pChainContext, [In] ref CERT_CHAIN_POLICY_PARA pPolicyPara, [In,Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus); [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern $SafeX509ChainHandleClassName CertDuplicateCertificateChain( [In] IntPtr pChainContext); $(if($script:IsSafeX509ChainHandleAvailable) { @" [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)] $(if(-not $script:IsCoreCLR) { ' [ResourceExposure(ResourceScope.None)] ' }) public static extern SafeX509ChainHandle CertDuplicateCertificateChain( [In] SafeX509ChainHandle pChainContext); "@ }) public static bool IsMicrosoftCertificate([In] $SafeX509ChainHandleClassName pChainContext) { //------------------------------------------------------------------------- // CERT_CHAIN_POLICY_MICROSOFT_ROOT // // Checks if the last element of the first simple chain contains a // Microsoft root public key. If it doesn't contain a Microsoft root // public key, dwError is set to CERT_E_UNTRUSTEDROOT. // // pPolicyPara is optional. However, // MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG can be set in // the dwFlags in pPolicyPara to also check for the Microsoft Test Roots. // // MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG can be set // in the dwFlags in pPolicyPara to check for the Microsoft root for // application signing instead of the Microsoft product root. This flag // explicitly checks for the application root only and cannot be combined // with the test root flag. // // MICROSOFT_ROOT_CERT_CHAIN_POLICY_DISABLE_FLIGHT_ROOT_FLAG can be set // in the dwFlags in pPolicyPara to always disable the Flight root. // // pvExtraPolicyPara and pvExtraPolicyStatus aren't used and must be set // to NULL. //-------------------------------------------------------------------------- const uint MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG = 0x00010000; const uint MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG = 0x00020000; //const uint MICROSOFT_ROOT_CERT_CHAIN_POLICY_DISABLE_FLIGHT_ROOT_FLAG = 0x00040000; CERT_CHAIN_POLICY_PARA PolicyPara = new CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_PARA))); CERT_CHAIN_POLICY_STATUS PolicyStatus = new CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_STATUS))); int CERT_CHAIN_POLICY_MICROSOFT_ROOT = 7; PolicyPara.dwFlags = (uint) MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG; bool isMicrosoftRoot = false; if(CertVerifyCertificateChainPolicy(new IntPtr(CERT_CHAIN_POLICY_MICROSOFT_ROOT), pChainContext, ref PolicyPara, ref PolicyStatus)) { isMicrosoftRoot = (PolicyStatus.dwError == 0); } // Also check for the Microsoft root for application signing if the Microsoft product root verification is unsuccessful. if(!isMicrosoftRoot) { // Some Microsoft modules can be signed with Microsoft Application Root instead of Microsoft Product Root, // So we need to use the MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG for the certificate verification. // MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG can not be used // with MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG, // so additional CertVerifyCertificateChainPolicy call is required to verify the given certificate is in Microsoft Application Root. // CERT_CHAIN_POLICY_PARA PolicyPara2 = new CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_PARA))); CERT_CHAIN_POLICY_STATUS PolicyStatus2 = new CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_STATUS))); PolicyPara2.dwFlags = (uint) MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG; if(CertVerifyCertificateChainPolicy(new IntPtr(CERT_CHAIN_POLICY_MICROSOFT_ROOT), pChainContext, ref PolicyPara2, ref PolicyStatus2)) { isMicrosoftRoot = (PolicyStatus2.dwError == 0); } } return isMicrosoftRoot; } } } "@ try { $AddType_prams = @{ TypeDefinition = $Win32HelpersSource Language = 'CSharp' ErrorAction = 'SilentlyContinue' } if ((-not $script:IsCoreCLR -or $script:IsNanoServer) -and $RequiredAssembliesForWin32Helpers) { $AddType_prams['ReferencedAssemblies'] = $RequiredAssembliesForWin32Helpers } Add-Type @AddType_prams } catch { Write-Warning -Message "Win32Helpers: $_" } } #endregion #region Private Functions function Add-ArgumentCompleter() { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string[]]$cmdlets, [Parameter(Mandatory=$true)] [string]$parameterName ) try { if(Get-Command -Name Register-ArgumentCompleter -ErrorAction SilentlyContinue) { Register-ArgumentCompleter -CommandName $cmdlets -ParameterName $parameterName -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) Get-PSRepository -Name "$wordTocomplete*"-ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Foreach-Object { [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Name) } } } } catch { # All this functionality is optional, so suppress errors Write-Debug -Message "Error registering argument completer: $_" } } function Compare-PrereleaseVersions { [CmdletBinding()] param( [ValidateNotNullOrEmpty()] [string] $FirstItemVersion, [string] $FirstItemPrerelease, [ValidateNotNullOrEmpty()] [string] $SecondItemVersion, [string] $SecondItemPrerelease ) <# This function compares one item to another to determine if it has a greater version (and/or prerelease). It returns true if item TWO is GREATER/newer than item ONE, it returns false otherwise. First Order: Compare Versions =========== *** Version is never NULL. Item #1 Comparison Item #2 Version of Values Version Notes about item #2 ------- ---------- ------- ------------------- Value > Value An older release version Value < Value * A newer release version Value == Value Inconclusive, must compare prerelease strings now Second Order: Compare Prereleases ============= *** Prerelease may be NULL, indicates a release version. Item #1 Comparison Item #2 Prerelease of Values Prerelease Notes about item #2 ---------- ----------- ---------- ------------------- NULL == NULL Exact same release version NULL > Value Older (prerelease) version Value < NULL * A newer, release version Value == Value Exact same prerelease (and same version) Value > Value An older prerelease Value < Value * A newer prerelease Item #2 is newer/greater than item #1 in the starred (*) combinations. Those are the conditions tested for below. #> [version]$itemOneVersion = $null # try parsing version string if (-not ( [System.Version]::TryParse($FirstItemVersion.Trim(), [ref]$itemOneVersion) )) { $message = $LocalizedData.InvalidVersion -f ($FirstItemVersion) Write-Error -Message $message -ErrorId "InvalidVersion" -Category InvalidArgument return } [Version]$itemTwoVersion = $null # try parsing version string if (-not ( [System.Version]::TryParse($SecondItemVersion.Trim(), [ref]$itemTwoVersion) )) { $message = $LocalizedData.InvalidVersion -f ($SecondItemVersion) Write-Error -Message $message -ErrorId "InvalidVersion" -Category InvalidArgument return } return (($itemOneVersion -lt $itemTwoVersion) -or ` (($itemOneVersion -eq $itemTwoVersion) -and ` (($FirstItemPrerelease -and -not $SecondItemPrerelease) -or ` ($FirstItemPrerelease -lt $SecondItemPrerelease)))) } function Copy-Module { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $SourcePath, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $DestinationPath, [Parameter(Mandatory=$true)] [ValidateNotNull()] [PSCustomObject] $PSGetItemInfo, [Parameter(Mandatory=$false)] [Switch] $IsSavePackage ) $ev = $null if(-not $IsSavePackage) { $message = $LocalizedData.AdministratorRightsNeededOrSpecifyCurrentUserScope $errorId = 'AdministratorRightsNeededOrSpecifyCurrentUserScope' } else { $message = $LocalizedData.UnauthorizedAccessError -f $DestinationPath $errorId = 'UnauthorizedAccessError' } if(Microsoft.PowerShell.Management\Test-Path $DestinationPath) { Microsoft.PowerShell.Management\Remove-Item -Path $DestinationPath ` -Recurse ` -Force ` -ErrorVariable ev ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue ` -Confirm:$false ` -WhatIf:$false if($ev) { $script:IsRunningAsElevated = $false ThrowError -ExceptionName "System.ArgumentException" ` -ExceptionMessage $message ` -ErrorId $errorId ` -CallerPSCmdlet $PSCmdlet ` -ErrorCategory InvalidArgument ` -ExceptionObject $ev } } # Copy the module to destination $null = Microsoft.PowerShell.Management\New-Item -Path $DestinationPath ` -ItemType Directory ` -Force ` -ErrorVariable ev ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue ` -Confirm:$false ` -WhatIf:$false if($ev) { $script:IsRunningAsElevated = $false ThrowError -ExceptionName "System.ArgumentException" ` -ExceptionMessage $message ` -ErrorId $errorId ` -CallerPSCmdlet $PSCmdlet ` -ErrorCategory InvalidArgument ` -ExceptionObject $ev } Microsoft.PowerShell.Management\Copy-Item -Path (Microsoft.PowerShell.Management\Join-Path -Path $SourcePath -ChildPath '*') ` -Destination $DestinationPath ` -Force ` -Recurse ` -ErrorVariable ev ` -ErrorAction SilentlyContinue ` -Confirm:$false ` -WhatIf:$false if($ev) { $script:IsRunningAsElevated = $false ThrowError -ExceptionName "System.ArgumentException" ` -ExceptionMessage $message ` -ErrorId $errorId ` -CallerPSCmdlet $PSCmdlet ` -ErrorCategory InvalidArgument ` -ExceptionObject $ev } # Remove the *.nupkg file $NupkgFilePath = Join-PathUtility -Path $DestinationPath -ChildPath "$($PSGetItemInfo.Name).nupkg" -PathType File if(Microsoft.PowerShell.Management\Test-Path -Path $NupkgFilePath -PathType Leaf) { Microsoft.PowerShell.Management\Remove-Item -Path $NupkgFilePath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false } # Create PSGetModuleInfo.xml $psgetItemInfopath = Microsoft.PowerShell.Management\Join-Path $DestinationPath $script:PSGetItemInfoFileName Microsoft.PowerShell.Utility\Out-File -FilePath $psgetItemInfopath -Force -InputObject ([System.Management.Automation.PSSerializer]::Serialize($PSGetItemInfo)) [System.IO.File]::SetAttributes($psgetItemInfopath, [System.IO.FileAttributes]::Hidden) } function Copy-ScriptFile { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $SourcePath, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $DestinationPath, [Parameter(Mandatory=$true)] [ValidateNotNull()] [PSCustomObject] $PSGetItemInfo, [Parameter()] [string] $Scope ) $ev = $null $message = $LocalizedData.AdministratorRightsNeededOrSpecifyCurrentUserScope # Copy the script file to destination if(-not (Microsoft.PowerShell.Management\Test-Path -Path $DestinationPath)) { $null = Microsoft.PowerShell.Management\New-Item -Path $DestinationPath ` -ItemType Directory ` -Force ` -ErrorVariable ev ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue ` -Confirm:$false ` -WhatIf:$false if($ev) { $script:IsRunningAsElevated = $false ThrowError -ExceptionName "System.ArgumentException" ` -ExceptionMessage $message ` -ErrorId "AdministratorRightsNeededOrSpecifyCurrentUserScope" ` -CallerPSCmdlet $PSCmdlet ` -ErrorCategory InvalidArgument ` -ExceptionObject $ev } } Microsoft.PowerShell.Management\Copy-Item -Path $SourcePath ` -Destination $DestinationPath ` -Force ` -Confirm:$false ` -WhatIf:$false ` -ErrorVariable ev ` -ErrorAction SilentlyContinue if($ev) { $script:IsRunningAsElevated = $false ThrowError -ExceptionName "System.ArgumentException" ` -ExceptionMessage $message ` -ErrorId "AdministratorRightsNeededOrSpecifyCurrentUserScope" ` -CallerPSCmdlet $PSCmdlet ` -ErrorCategory InvalidArgument ` -ExceptionObject $ev } if($Scope) { # Create <Name>_InstalledScriptInfo.xml $InstalledScriptInfoFileName = "$($PSGetItemInfo.Name)_$script:InstalledScriptInfoFileName" if($scope -eq 'AllUsers') { $scriptInfopath = Microsoft.PowerShell.Management\Join-Path -Path $script:ProgramFilesInstalledScriptInfosPath ` -ChildPath $InstalledScriptInfoFileName } else { $scriptInfopath = Microsoft.PowerShell.Management\Join-Path -Path $script:MyDocumentsInstalledScriptInfosPath ` -ChildPath $InstalledScriptInfoFileName } Microsoft.PowerShell.Utility\Out-File -FilePath $scriptInfopath ` -Force ` -InputObject ([System.Management.Automation.PSSerializer]::Serialize($PSGetItemInfo)) } } function DeSerialize-PSObject { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] $Path ) $filecontent = Microsoft.PowerShell.Management\Get-Content -Path $Path [System.Management.Automation.PSSerializer]::Deserialize($filecontent) } function Get-AuthenticodePublisher { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [System.Management.Automation.Signature] $AuthenticodeSignature ) if($AuthenticodeSignature.SignerCertificate) { $chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain $null = $chain.Build($AuthenticodeSignature.SignerCertificate) $certStoreLocations = @('cert:\LocalMachine\Root', 'cert:\LocalMachine\AuthRoot', 'cert:\CurrentUser\Root', 'cert:\CurrentUser\AuthRoot') foreach($element in $chain.ChainElements.Certificate) { foreach($certStoreLocation in $certStoreLocations) { $rootCertificateAuthority = Microsoft.PowerShell.Management\Get-ChildItem -Path $certStoreLocation | Microsoft.PowerShell.Core\Where-Object { ($_.Subject -eq $element.Subject) -and ($_.thumbprint -eq $element.thumbprint) } if($rootCertificateAuthority) { # Select-Object writes an error 'System Error' into the error stream. # Using below workaround for getting the first element when there are multiple certificates with the same subject name. if($rootCertificateAuthority.PSTypeNames -contains 'System.Array') { $rootCertificateAuthority = $rootCertificateAuthority[0] } $publisherInfo = @{ publisher = $AuthenticodeSignature.SignerCertificate.Subject publisherRootCA = $rootCertificateAuthority.Subject } Write-Output -InputObject $publisherInfo return } } } } } function Get-AvailableRoleCapabilityName { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [PSModuleInfo] $PSModuleInfo ) $RoleCapabilityNames = @() $RoleCapabilitiesDir = Join-PathUtility -Path $PSModuleInfo.ModuleBase -ChildPath 'RoleCapabilities' -PathType Directory if(Microsoft.PowerShell.Management\Test-Path -Path $RoleCapabilitiesDir -PathType Container) { $RoleCapabilityNames = Microsoft.PowerShell.Management\Get-ChildItem -Path $RoleCapabilitiesDir ` -Name -Filter *.psrc | ForEach-Object {[System.IO.Path]::GetFileNameWithoutExtension($_)} } return $RoleCapabilityNames } function Get-AvailableScriptFilePath { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter()] [string] $Name ) $scriptInfo = $null $scriptFileName = '*.ps1' $scriptBasePaths = @($script:ProgramFilesScriptsPath, $script:MyDocumentsScriptsPath) $scriptFilePaths = @() $wildcardPattern = $null if($Name) { if(Test-WildcardPattern -Name $Name) { $wildcardPattern = New-Object System.Management.Automation.WildcardPattern $Name,$script:wildcardOptions } else { $scriptFileName = "$Name.ps1" } } foreach ($location in $scriptBasePaths) { $scriptFiles = Get-ChildItem -Path $location ` -Filter $scriptFileName ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue if($wildcardPattern) { $scriptFiles | Microsoft.PowerShell.Core\ForEach-Object { if($wildcardPattern.IsMatch($_.BaseName)) { $scriptFilePaths += $_.FullName } } } else { $scriptFiles | Microsoft.PowerShell.Core\ForEach-Object { $scriptFilePaths += $_.FullName } } } return $scriptFilePaths } function Get-DynamicParameters { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [Uri] $Location, [Parameter(Mandatory=$true)] [REF] $PackageManagementProvider ) $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $dynamicOptions = $null $loc = Get-LocationString -LocationUri $Location if(-not $loc) { return $paramDictionary } # Ping and resolve the specified location $loc = Resolve-Location -Location $loc ` -LocationParameterName 'Location' ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue if(-not $loc) { return $paramDictionary } $providers = PackageManagement\Get-PackageProvider | Where-Object { $_.Features.ContainsKey($script:SupportsPSModulesFeatureName) } if ($PackageManagementProvider.Value) { # Skip the PowerShellGet provider if($PackageManagementProvider.Value -ne $script:PSModuleProviderName) { $SelectedProvider = $providers | Where-Object {$_.ProviderName -eq $PackageManagementProvider.Value} if($SelectedProvider) { $res = Get-PackageSource -Location $loc -Provider $PackageManagementProvider.Value -ErrorAction SilentlyContinue if($res) { $dynamicOptions = $SelectedProvider.DynamicOptions } } } } else { $PackageManagementProvider.Value = Get-PackageManagementProviderName -Location $Location if($PackageManagementProvider.Value) { $provider = $providers | Where-Object {$_.ProviderName -eq $PackageManagementProvider.Value} $dynamicOptions = $provider.DynamicOptions } } foreach ($option in $dynamicOptions) { # Skip the Destination parameter if( $option.IsRequired -and ($option.Name -eq "Destination") ) { continue } $paramAttribute = New-Object System.Management.Automation.ParameterAttribute $paramAttribute.Mandatory = $option.IsRequired $message = $LocalizedData.DynamicParameterHelpMessage -f ($option.Name, $PackageManagementProvider.Value, $loc, $option.Name) $paramAttribute.HelpMessage = $message $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute] $attributeCollection.Add($paramAttribute) $ageParam = New-Object System.Management.Automation.RuntimeDefinedParameter($option.Name, $script:DynamicOptionTypeMap[$option.Type.value__], $attributeCollection) $paramDictionary.Add($option.Name, $ageParam) } return $paramDictionary } function Get-EntityName { param ( [Parameter(Mandatory=$true)] $SoftwareIdentity, [Parameter(Mandatory=$true)] $Role ) foreach( $entity in $SoftwareIdentity.Entities ) { if( $entity.Role -eq $Role) { $entity.Name } } } function Get-EnvironmentVariable { param ( [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [parameter(Mandatory = $true)] [int] $Target ) if ($Target -eq $script:EnvironmentVariableTarget.Process) { return [System.Environment]::GetEnvironmentVariable($Name) } elseif ($Target -eq $script:EnvironmentVariableTarget.Machine) { if ($Name -eq "path") { # if we need the path environment variable, we need it un-expanded, otherwise # when writing it back, we would loose all the variables like %systemroot% in it. # We use the Win32 API directly using DoNotExpandEnvironmentNames # It is unclear whether any code calling this function for %path% needs the expanded version of %path% # There are currently no tests for this code # Microsoft.PowerShell.Management\Get-ItemProperty is passed through to the PowerShell Registry provider # which currently doesn't seem to support anything like: DoNotExpandEnvironmentNames $hklmHive = [Microsoft.Win32.Registry]::LocalMachine $EnvRegKey = $hklmHive.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\Environment", $FALSE) $itemPropertyValue = $EnvRegKey.GetValue($Name, "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames) return $itemPropertyValue } else { $itemPropertyValue = Microsoft.PowerShell.Management\Get-ItemProperty -Path $script:SystemEnvironmentKey -Name $Name -ErrorAction SilentlyContinue if($itemPropertyValue) { return $itemPropertyValue.$Name } } } elseif ($Target -eq $script:EnvironmentVariableTarget.User) { $itemPropertyValue = Microsoft.PowerShell.Management\Get-ItemProperty -Path $script:UserEnvironmentKey -Name $Name -ErrorAction SilentlyContinue if($itemPropertyValue) { return $itemPropertyValue.$Name } } } function Get-EscapedString { [CmdletBinding()] [OutputType([String])] Param ( [Parameter()] [string] $ElementValue ) return [System.Security.SecurityElement]::Escape($ElementValue) } function Get-ExportedDscResources { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [PSModuleInfo] $PSModuleInfo ) $dscResources = @() if(-not $script:IsCoreCLR -and (Get-Command -Name Get-DscResource -Module PSDesiredStateConfiguration -ErrorAction Ignore)) { $OldPSModulePath = $env:PSModulePath try { $env:PSModulePath = Join-Path -Path $PSHOME -ChildPath "Modules" $env:PSModulePath = "$env:PSModulePath;$(Split-Path -Path $PSModuleInfo.ModuleBase -Parent)" $dscResources = PSDesiredStateConfiguration\Get-DscResource -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Microsoft.PowerShell.Core\ForEach-Object { if($_.Module -and ($_.Module.Name -eq $PSModuleInfo.Name)) { $_.Name } } } finally { $env:PSModulePath = $OldPSModulePath } } else { $dscResourcesDir = Join-PathUtility -Path $PSModuleInfo.ModuleBase -ChildPath "DscResources" -PathType Directory if(Microsoft.PowerShell.Management\Test-Path $dscResourcesDir) { $dscResources = Microsoft.PowerShell.Management\Get-ChildItem -Path $dscResourcesDir -Directory -Name } } return $dscResources } function Get-ExternalModuleDependencies { Param ( [Parameter(Mandatory=$true)] [PSModuleInfo] $PSModuleInfo ) if($PSModuleInfo.PrivateData -and ($PSModuleInfo.PrivateData.GetType().ToString() -eq "System.Collections.Hashtable") -and $PSModuleInfo.PrivateData["PSData"] -and ($PSModuleInfo.PrivateData["PSData"].GetType().ToString() -eq "System.Collections.Hashtable") -and $PSModuleInfo.PrivateData.PSData['ExternalModuleDependencies'] -and ($PSModuleInfo.PrivateData.PSData['ExternalModuleDependencies'].GetType().ToString() -eq "System.Object[]") ) { return $PSModuleInfo.PrivateData.PSData.ExternalModuleDependencies } } function Get-First { param ( [Parameter(Mandatory=$true)] $IEnumerator ) foreach($item in $IEnumerator) { return $item } return $null } function Get-Hash # Returns a SHA1 hash of the specified string { [CmdletBinding()] Param ( [string] $locationString ) if(-not $locationString) { return "" } $sha1Object = New-Object System.Security.Cryptography.SHA1Managed $stringHash = $sha1Object.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($locationString)); $stringHashInHex = [System.BitConverter]::ToString($stringHash) if ($stringHashInHex) { # Remove all dashes in the hex string return $stringHashInHex.Replace('-', '') } return "" } # Determine scope. We prefer CurrentUser scope even if the older module is installed for AllUsers, unless: # old module is installed for all users, we are elevated, AND using Windows PowerShell # This is to mirror newer behavior of Install-Module. function Get-InstallationScope() { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string]$PreviousInstallLocation, [Parameter(Mandatory=$true)] [string]$CurrentUserPath ) if ( -not $PreviousInstallLocation.ToString().StartsWith($currentUserPath, [System.StringComparison]::OrdinalIgnoreCase) -and -not $script:IsCoreCLR -and (Test-RunningAsElevated)) { $Scope = "AllUsers" } else { $Scope = "CurrentUser" } Write-Debug "Get-InstallationScope: $PreviousInstallLocation $($script:IsCoreCLR) $(Test-RunningAsElevated) : $Scope" return $Scope } function Get-InstalledModuleAuthenticodeSignature { [CmdletBinding()] Param( [Parameter(Mandatory=$true)] [PSModuleInfo] $InstalledModuleInfo, [Parameter(Mandatory=$true)] [string] $InstallLocation ) $ModuleName = $InstalledModuleInfo.Name # Priority order for getting the published details of the installed module: # 1. Latest version under the $InstallLocation # 2. Latest available version in $PSModulePath # 3. $InstalledModuleInfo $AvailableModules = Microsoft.PowerShell.Core\Get-Module -ListAvailable ` -Name $ModuleName ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue ` -Verbose:$false | Microsoft.PowerShell.Utility\Sort-Object -Property Version -Descending # Remove the version folder on 5.0 to get the actual module base folder without version if(Test-ModuleSxSVersionSupport) { $InstallLocation = Microsoft.PowerShell.Management\Split-Path -Path $InstallLocation } $SourceModule = $AvailableModules | Microsoft.PowerShell.Core\Where-Object { $_.ModuleBase.StartsWith($InstallLocation, [System.StringComparison]::OrdinalIgnoreCase) } | Microsoft.PowerShell.Utility\Select-Object -First 1 -ErrorAction Ignore if(-not $SourceModule) { $SourceModule = $AvailableModules | Microsoft.PowerShell.Utility\Select-Object -First 1 -ErrorAction Ignore } else { $SourceModule = $InstalledModuleInfo } $SignedFilePath = $SourceModule.Path $CatalogFileName = "$ModuleName.cat" $CatalogFilePath = Microsoft.PowerShell.Management\Join-Path -Path $SourceModule.ModuleBase -ChildPath $CatalogFileName if(Microsoft.PowerShell.Management\Test-Path -Path $CatalogFilePath -PathType Leaf) { $message = $LocalizedData.CatalogFileFound -f ($CatalogFileName, $ModuleName) Write-Debug -Message $message $SignedFilePath = $CatalogFilePath } else { Write-Debug -Message ($LocalizedData.CatalogFileNotFoundInAvailableModule -f ($CatalogFileName, $ModuleName)) } $message = "Using the previously-installed module '{0}' with version '{1}' under '{2}' for getting the publisher details." -f ($SourceModule.Name, $SourceModule.Version, $SourceModule.ModuleBase) Write-Debug -Message $message $message = "Using the '{0}' file for getting the authenticode signature." -f ($SignedFilePath) Write-Debug -Message $message $AuthenticodeSignature = Microsoft.PowerShell.Security\Get-AuthenticodeSignature -FilePath $SignedFilePath $ModuleDetails = $null if($AuthenticodeSignature) { $ModuleDetails = @{} $ModuleDetails['AuthenticodeSignature'] = $AuthenticodeSignature $ModuleDetails['Version'] = $SourceModule.Version $ModuleDetails['ModuleBase']=$SourceModule.ModuleBase $ModuleDetails['IsMicrosoftCertificate'] = Test-MicrosoftCertificate -AuthenticodeSignature $AuthenticodeSignature $PublisherDetails = Get-AuthenticodePublisher -AuthenticodeSignature $AuthenticodeSignature $ModuleDetails['Publisher'] = if($PublisherDetails) {$PublisherDetails.Publisher} $ModuleDetails['RootCertificateAuthority'] = if($PublisherDetails) {$PublisherDetails.PublisherRootCA} $message = $LocalizedData.SourceModuleDetailsForPublisherValidation -f ($ModuleName, $SourceModule.Version, $SourceModule.ModuleBase, $ModuleDetails.Publisher, $ModuleDetails.RootCertificateAuthority, $ModuleDetails.IsMicrosoftCertificate) Write-Debug $message } return $ModuleDetails } function Get-InstalledModuleDetails { [CmdletBinding()] param ( [Parameter()] [string] $Name, [Parameter()] [string] $RequiredVersion, [Parameter()] [string] $MinimumVersion, [Parameter()] [string] $MaximumVersion ) Set-InstalledModulesVariable # Keys in $script:PSGetInstalledModules are "<ModuleName><ModuleVersion>", # first filter the installed modules using "$Name*" wildcard search # then apply $Name wildcard search to get the module name which meets the specified name with wildcards. # $wildcardPattern = New-Object System.Management.Automation.WildcardPattern "$Name*",$script:wildcardOptions $nameWildcardPattern = New-Object System.Management.Automation.WildcardPattern $Name,$script:wildcardOptions $script:PSGetInstalledModules.GetEnumerator() | Microsoft.PowerShell.Core\ForEach-Object { if($wildcardPattern.IsMatch($_.Key)) { $InstalledModuleDetails = $_.Value if(-not $Name -or $nameWildcardPattern.IsMatch($InstalledModuleDetails.PSGetItemInfo.Name)) { if (Test-ItemPrereleaseVersionRequirements -Version $InstalledModuleDetails.PSGetItemInfo.Version ` -RequiredVersion $RequiredVersion ` -MinimumVersion $MinimumVersion ` -MaximumVersion $MaximumVersion) { $InstalledModuleDetails } } } } } function Get-InstalledScriptDetails { [CmdletBinding()] param ( [Parameter()] [string] $Name, [Parameter()] [string] $RequiredVersion, [Parameter()] [string] $MinimumVersion, [Parameter()] [string] $MaximumVersion ) Set-InstalledScriptsVariable # Keys in $script:PSGetInstalledScripts are "<ScriptName><ScriptVersion>", # first filter the installed scripts using "$Name*" wildcard search # then apply $Name wildcard search to get the script name which meets the specified name with wildcards. # $wildcardPattern = New-Object System.Management.Automation.WildcardPattern "$Name*",$script:wildcardOptions $nameWildcardPattern = New-Object System.Management.Automation.WildcardPattern $Name,$script:wildcardOptions $script:PSGetInstalledScripts.GetEnumerator() | Microsoft.PowerShell.Core\ForEach-Object { if($wildcardPattern.IsMatch($_.Key)) { $InstalledScriptDetails = $_.Value if(-not $Name -or $nameWildcardPattern.IsMatch($InstalledScriptDetails.PSGetItemInfo.Name)) { if (Test-ItemPrereleaseVersionRequirements -Version $InstalledScriptDetails.PSGetItemInfo.Version ` -RequiredVersion $RequiredVersion ` -MinimumVersion $MinimumVersion ` -MaximumVersion $MaximumVersion) { $InstalledScriptDetails } } } } } function Get-InstalledScriptFilePath { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter()] [string] $Name ) $installedScriptFilePaths = @() $scriptFilePaths = Get-AvailableScriptFilePath @PSBoundParameters foreach ($scriptFilePath in $scriptFilePaths) { $scriptInfo = Test-ScriptInstalled -Name ([System.IO.Path]::GetFileNameWithoutExtension($scriptFilePath)) if($scriptInfo) { $installedScriptInfoFilePath = $null $installedScriptInfoFileName = "$($scriptInfo.Name)_$script:InstalledScriptInfoFileName" if($scriptInfo.Path.StartsWith($script:ProgramFilesScriptsPath, [System.StringComparison]::OrdinalIgnoreCase)) { $installedScriptInfoFilePath = Microsoft.PowerShell.Management\Join-Path -Path $script:ProgramFilesInstalledScriptInfosPath ` -ChildPath $installedScriptInfoFileName } elseif($scriptInfo.Path.StartsWith($script:MyDocumentsScriptsPath, [System.StringComparison]::OrdinalIgnoreCase)) { $installedScriptInfoFilePath = Microsoft.PowerShell.Management\Join-Path -Path $script:MyDocumentsInstalledScriptInfosPath ` -ChildPath $installedScriptInfoFileName } if($installedScriptInfoFilePath -and (Microsoft.PowerShell.Management\Test-Path -Path $installedScriptInfoFilePath -PathType Leaf)) { $installedScriptFilePaths += $scriptInfo.Path } } } return $installedScriptFilePaths } function Get-LocationString { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter()] [Uri] $LocationUri ) $LocationString = $null if($LocationUri) { if($LocationUri.Scheme -eq 'file') { $LocationString = $LocationUri.OriginalString } elseif($LocationUri.AbsoluteUri) { $LocationString = $LocationUri.AbsoluteUri } else { $LocationString = $LocationUri.ToString() } } return $LocationString } function Get-ManifestHashTable { param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Path, [Parameter()] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCmdlet] $CallerPSCmdlet ) $Lines = $null try { $Lines = Get-Content -Path $Path -Force } catch { if($CallerPSCmdlet) { $CallerPSCmdlet.ThrowTerminatingError($_.Exception.ErrorRecord) } } if(-not $Lines) { return } $scriptBlock = [ScriptBlock]::Create( $Lines -join "`n" ) $allowedVariables = [System.Collections.Generic.List[String]] @('PSEdition', 'PSScriptRoot') $allowedCommands = [System.Collections.Generic.List[String]] @() $allowEnvironmentVariables = $false try { $scriptBlock.CheckRestrictedLanguage($allowedCommands, $allowedVariables, $allowEnvironmentVariables) } catch { if($CallerPSCmdlet) { $CallerPSCmdlet.ThrowTerminatingError($_.Exception.ErrorRecord) } return } return $scriptBlock.InvokeReturnAsIs() } function Get-ModuleDependencies { Param ( [Parameter(Mandatory=$true)] [PSModuleInfo] $PSModuleInfo, [Parameter(Mandatory=$true)] [string] $Repository, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCmdlet] $CallerPSCmdlet, [Parameter(Mandatory=$false)] [pscredential] $Credential ) $DependentModuleDetails = @() if($PSModuleInfo.RequiredModules -or $PSModuleInfo.NestedModules) { # PSModuleInfo.RequiredModules doesn't provide the RequiredVersion info from the ModuleSpecification # Reading the contents of module manifest file # to get the RequiredVersion details. $ModuleManifestHashTable = Get-ManifestHashTable -Path $PSModuleInfo.Path if($PSModuleInfo.RequiredModules) { $ModuleManifestRequiredModules = $null if($ModuleManifestHashTable) { $ModuleManifestRequiredModules = $ModuleManifestHashTable.RequiredModules } $ValidateAndGetRequiredModuleDetails_Params = @{ ModuleManifestRequiredModules=$ModuleManifestRequiredModules RequiredPSModuleInfos=$PSModuleInfo.RequiredModules Repository=$Repository DependentModuleInfo=$PSModuleInfo CallerPSCmdlet=$CallerPSCmdlet Verbose=$VerbosePreference Debug=$DebugPreference } if ($PSBoundParameters.ContainsKey('Credential')) { $ValidateAndGetRequiredModuleDetails_Params.Add('Credential',$Credential) } $DependentModuleDetails += ValidateAndGet-RequiredModuleDetails @ValidateAndGetRequiredModuleDetails_Params } if($PSModuleInfo.NestedModules) { $ModuleManifestRequiredModules = $null if($ModuleManifestHashTable) { $ModuleManifestRequiredModules = $ModuleManifestHashTable.NestedModules } # A nested module is be considered as a dependency # 1) whose module base is not under the specified module base OR # 2) whose module base is under the specified module base and it's path doesn't exists # $RequiredPSModuleInfos = $PSModuleInfo.NestedModules | Microsoft.PowerShell.Core\Where-Object { -not $_.ModuleBase.StartsWith($PSModuleInfo.ModuleBase, [System.StringComparison]::OrdinalIgnoreCase) -or -not $_.Path -or -not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $_.Path) } $ValidateAndGetRequiredModuleDetails_Params = @{ ModuleManifestRequiredModules=$ModuleManifestRequiredModules RequiredPSModuleInfos=$RequiredPSModuleInfos Repository=$Repository DependentModuleInfo=$PSModuleInfo CallerPSCmdlet=$CallerPSCmdlet Verbose=$VerbosePreference Debug=$DebugPreference } if ($PSBoundParameters.ContainsKey('Credential')) { $ValidateAndGetRequiredModuleDetails_Params.Add('Credential',$Credential) } $DependentModuleDetails += ValidateAndGet-RequiredModuleDetails @ValidateAndGetRequiredModuleDetails_Params } } return $DependentModuleDetails } function Get-NormalizedVersionString { <# .DESCRIPTION Latest versions of nuget.exe and dotnet command generate the .nupkg file name with semantic version format for the modules/scripts with two part version. For example: package 1.0 --> package.1.0.0.nupkg #> param ( [Parameter(Mandatory = $true)] [string] $Version ) [Version]$ParsedVersion = $null if ([System.Version]::TryParse($Version, [ref]$ParsedVersion)) { $Build = $ParsedVersion.Build if ($Build -eq -1) { $Build = 0 } return "$($ParsedVersion.Major).$($ParsedVersion.Minor).$Build" } return $Version } function Get-OrderedPSScriptInfoObject { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] [PSCustomObject] $PSScriptInfo ) $NewPSScriptInfo = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ $script:Name = $PSScriptInfo.$script:Name $script:Version = $PSScriptInfo.$script:Version $script:Guid = $PSScriptInfo.$script:Guid $script:Path = $PSScriptInfo.$script:Path $script:ScriptBase = $PSScriptInfo.$script:ScriptBase $script:Description = $PSScriptInfo.$script:Description $script:Author = $PSScriptInfo.$script:Author $script:CompanyName = $PSScriptInfo.$script:CompanyName $script:Copyright = $PSScriptInfo.$script:Copyright $script:Tags = $PSScriptInfo.$script:Tags $script:ReleaseNotes = $PSScriptInfo.$script:ReleaseNotes $script:RequiredModules = $PSScriptInfo.$script:RequiredModules $script:ExternalModuleDependencies = $PSScriptInfo.$script:ExternalModuleDependencies $script:RequiredScripts = $PSScriptInfo.$script:RequiredScripts $script:ExternalScriptDependencies = $PSScriptInfo.$script:ExternalScriptDependencies $script:LicenseUri = $PSScriptInfo.$script:LicenseUri $script:ProjectUri = $PSScriptInfo.$script:ProjectUri $script:IconUri = $PSScriptInfo.$script:IconUri $script:DefinedCommands = $PSScriptInfo.$script:DefinedCommands $script:DefinedFunctions = $PSScriptInfo.$script:DefinedFunctions $script:DefinedWorkflows = $PSScriptInfo.$script:DefinedWorkflows $script:PrivateData = $PSScriptInfo.$script:PrivateData }) $NewPSScriptInfo.PSTypeNames.Insert(0, "Microsoft.PowerShell.Commands.PSScriptInfo") return $NewPSScriptInfo } function Get-PackageManagementProviderName { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [Uri] $Location ) $PackageManagementProviderName = $null $loc = Get-LocationString -LocationUri $Location $providers = PackageManagement\Get-PackageProvider | Where-Object { $_.Features.ContainsKey($script:SupportsPSModulesFeatureName) } foreach($provider in $providers) { # Skip the PowerShellGet provider if($provider.ProviderName -eq $script:PSModuleProviderName) { continue } $packageSource = Get-PackageSource -Location $loc -Provider $provider.ProviderName -ErrorAction SilentlyContinue if($packageSource) { $PackageManagementProviderName = $provider.ProviderName break } } return $PackageManagementProviderName } function Get-ParametersHashtable { param( $Proxy, $ProxyCredential ) $ParametersHashtable = @{} if($Proxy) { $ParametersHashtable[$script:Proxy] = $Proxy } if($ProxyCredential) { $ParametersHashtable[$script:ProxyCredential] = $ProxyCredential } return $ParametersHashtable } function Get-PrivateData #Utility function to help form the content string for PrivateData { param ( [System.Collections.Hashtable] $PrivateData ) if($PrivateData.Keys.Count -eq 0) { $content = " PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. # Tags = @() # A URL to the license for this module. # LicenseUri = '' # A URL to the main website for this project. # ProjectUri = '' # A URL to an icon representing this module. # IconUri = '' # ReleaseNotes of this module # ReleaseNotes = '' # Prerelease string of this module # Prerelease = '' # Flag to indicate whether the module requires explicit user acceptance for install/update/save # RequireLicenseAcceptance = `$false # External dependent modules of this module # ExternalModuleDependencies = @() } # End of PSData hashtable } # End of PrivateData hashtable" return $content } #Validate each of the property of PSData is of the desired data type $Tags= $PrivateData["Tags"] -join "','" | Foreach-Object {"'$_'"} $LicenseUri = $PrivateData["LicenseUri"]| Foreach-Object {"'$_'"} $ProjectUri = $PrivateData["ProjectUri"] | Foreach-Object {"'$_'"} $IconUri = $PrivateData["IconUri"] | Foreach-Object {"'$_'"} $ReleaseNotesEscape = $PrivateData["ReleaseNotes"] -Replace "'","''" $ReleaseNotes = $ReleaseNotesEscape | Foreach-Object {"'$_'"} $Prerelease = $PrivateData[$script:Prerelease] | Foreach-Object {"'$_'"} $RequireLicenseAcceptance = $PrivateData["RequireLicenseAcceptance"] $ExternalModuleDependencies = $PrivateData["ExternalModuleDependencies"] -join "','" | Foreach-Object {"'$_'"} $DefaultProperties = @("Tags","LicenseUri","ProjectUri","IconUri","ReleaseNotes",$script:Prerelease,"ExternalModuleDependencies","RequireLicenseAcceptance") $ExtraProperties = @() foreach($key in $PrivateData.Keys) { if($DefaultProperties -notcontains $key) { $PropertyString = "#"+"$key"+ " of this module" $PropertyString += "`r`n " if(($PrivateData[$key]).GetType().IsArray) { $PropertyString += $key +" = " +" @(" $PrivateData[$key] | Foreach-Object { $PropertyString += "'" + $_ +"'" + "," } if($PrivateData[$key].Length -ge 1) { #Remove extra , $PropertyString = $PropertyString -Replace ".$" } $PropertyString += ")" } else { $PropertyString += $key +" = " + "'"+$PrivateData[$key]+"'" } $ExtraProperties += ,$PropertyString } } $ExtraPropertiesString = "" $firstProperty = $true foreach($property in $ExtraProperties) { if($firstProperty) { $firstProperty = $false } else { $ExtraPropertiesString += "`r`n`r`n " } $ExtraPropertiesString += $Property } $TagsLine ="# Tags = @()" if($Tags -ne "''") { $TagsLine = "Tags = "+$Tags } $LicenseUriLine = "# LicenseUri = ''" if($LicenseUri -ne "''") { $LicenseUriLine = "LicenseUri = "+$LicenseUri } $ProjectUriLine = "# ProjectUri = ''" if($ProjectUri -ne "''") { $ProjectUriLine = "ProjectUri = " +$ProjectUri } $IconUriLine = "# IconUri = ''" if($IconUri -ne "''") { $IconUriLine = "IconUri = " +$IconUri } $ReleaseNotesLine = "# ReleaseNotes = ''" if($ReleaseNotes -ne "''") { $ReleaseNotesLine = "ReleaseNotes = "+$ReleaseNotes } $PrereleaseLine = "# Prerelease = ''" if ($Prerelease -ne "''") { $PrereleaseLine = "Prerelease = " +$Prerelease } $RequireLicenseAcceptanceLine = "# RequireLicenseAcceptance = `$false" if($RequireLicenseAcceptance) { $RequireLicenseAcceptanceLine = "RequireLicenseAcceptance = `$true" } $ExternalModuleDependenciesLine ="# ExternalModuleDependencies = @()" if($ExternalModuleDependencies -ne "''") { $ExternalModuleDependenciesLine = "ExternalModuleDependencies = @($ExternalModuleDependencies)" } if(-not $ExtraPropertiesString -eq "") { $Content = " ExtraProperties PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. $TagsLine # A URL to the license for this module. $LicenseUriLine # A URL to the main website for this project. $ProjectUriLine # A URL to an icon representing this module. $IconUriLine # ReleaseNotes of this module $ReleaseNotesLine # Prerelease string of this module $PrereleaseLine # Flag to indicate whether the module requires explicit user acceptance for install/update/save $RequireLicenseAcceptanceLine # External dependent modules of this module $ExternalModuleDependenciesLine } # End of PSData hashtable } # End of PrivateData hashtable" #Replace the Extra PrivateData in the block $Content -replace "ExtraProperties", $ExtraPropertiesString } else { $content = " PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. $TagsLine # A URL to the license for this module. $LicenseUriLine # A URL to the main website for this project. $ProjectUriLine # A URL to an icon representing this module. $IconUriLine # ReleaseNotes of this module $ReleaseNotesLine # Prerelease string of this module $PrereleaseLine # Flag to indicate whether the module requires explicit user acceptance for install/update/save $RequireLicenseAcceptanceLine # External dependent modules of this module $ExternalModuleDependenciesLine } # End of PSData hashtable } # End of PrivateData hashtable" return $content } } function Get-ProviderName { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [PSCustomObject] $PSCustomObject ) $providerName = $script:NuGetProviderName if((Get-Member -InputObject $PSCustomObject -Name PackageManagementProvider)) { $providerName = $PSCustomObject.PackageManagementProvider } return $providerName } function Get-PSScriptInfoString { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Version, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [Guid] $Guid, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Author, [Parameter()] [String] $CompanyName, [Parameter()] [string] $Copyright, [Parameter()] [String[]] $ExternalModuleDependencies, [Parameter()] [string[]] $RequiredScripts, [Parameter()] [String[]] $ExternalScriptDependencies, [Parameter()] [string[]] $Tags, [Parameter()] [Uri] $ProjectUri, [Parameter()] [Uri] $LicenseUri, [Parameter()] [Uri] $IconUri, [Parameter()] [string[]] $ReleaseNotes, [Parameter()] [string] $PrivateData ) Process { $PSScriptInfoString = @" <#PSScriptInfo .VERSION$(if ($Version) {" $Version"}) .GUID$(if ($Guid) {" $Guid"}) .AUTHOR$(if ($Author) {" $Author"}) .COMPANYNAME$(if ($CompanyName) {" $CompanyName"}) .COPYRIGHT$(if ($Copyright) {" $Copyright"}) .TAGS$(if ($Tags) {" $Tags"}) .LICENSEURI$(if ($LicenseUri) {" $LicenseUri"}) .PROJECTURI$(if ($ProjectUri) {" $ProjectUri"}) .ICONURI$(if ($IconUri) {" $IconUri"}) .EXTERNALMODULEDEPENDENCIES$(if ($ExternalModuleDependencies) {" $($ExternalModuleDependencies -join ',')"}) .REQUIREDSCRIPTS$(if ($RequiredScripts) {" $($RequiredScripts -join ',')"}) .EXTERNALSCRIPTDEPENDENCIES$(if ($ExternalScriptDependencies) {" $($ExternalScriptDependencies -join ',')"}) .RELEASENOTES $($ReleaseNotes -join "`r`n") .PRIVATEDATA$(if ($PrivateData) {" $PrivateData"}) #> "@ return $PSScriptInfoString } } function Get-PublishLocation { [CmdletBinding()] Param ( [Parameter()] [String] $Location ) $PublishLocation = $null if($Location) { # For local dir or SMB-share locations, ScriptPublishLocation is PublishLocation. if(Microsoft.PowerShell.Management\Test-Path -Path $Location) { $PublishLocation = $Location } else { $tempPublishLocation = $null if($Location.EndsWith('/api/v2', [System.StringComparison]::OrdinalIgnoreCase)) { $tempPublishLocation = $Location + '/package/' } elseif($Location.EndsWith('/api/v2/', [System.StringComparison]::OrdinalIgnoreCase)) { $tempPublishLocation = $Location + 'package/' } if($tempPublishLocation) { $PublishLocation = $tempPublishLocation } } } return $PublishLocation } function Get-RequiresString { [CmdletBinding()] Param ( [Parameter()] [Object[]] $RequiredModules ) Process { if($RequiredModules) { $RequiredModuleStrings = @() foreach($requiredModuleObject in $RequiredModules) { if($requiredModuleObject.GetType().ToString() -eq 'System.Collections.Hashtable') { if(($requiredModuleObject.Keys.Count -eq 1) -and (Microsoft.PowerShell.Utility\Get-Member -InputObject $requiredModuleObject -Name 'ModuleName')) { $RequiredModuleStrings += $requiredModuleObject['ModuleName'].ToString() } else { $moduleSpec = New-Object Microsoft.PowerShell.Commands.ModuleSpecification -ArgumentList $requiredModuleObject if (-not (Microsoft.PowerShell.Utility\Get-Variable -Name moduleSpec -ErrorAction SilentlyContinue)) { return } $keyvalueStrings = $requiredModuleObject.Keys | Microsoft.PowerShell.Core\ForEach-Object {"$_ = '$( $requiredModuleObject[$_])'"} $RequiredModuleStrings += "@{$($keyvalueStrings -join '; ')}" } } elseif(($PSVersionTable.PSVersion -eq '3.0.0') -and ($requiredModuleObject.GetType().ToString() -eq 'Microsoft.PowerShell.Commands.ModuleSpecification')) { # ModuleSpecification.ToString() is not implemented on PowerShell 3.0. $optionalString = " " if($requiredModuleObject.Version) { $optionalString += "ModuleVersion = '$($requiredModuleObject.Version.ToString())'; " } if($requiredModuleObject.Guid) { $optionalString += "Guid = '$($requiredModuleObject.Guid.ToString())'; " } if($optionalString.Trim()) { $moduleSpecString = "@{ ModuleName = '$($requiredModuleObject.Name.ToString())';$optionalString}" } else { $moduleSpecString = $requiredModuleObject.Name.ToString() } $RequiredModuleStrings += $moduleSpecString } else { $RequiredModuleStrings += $requiredModuleObject.ToString() } } $hashRequiresStrings = $RequiredModuleStrings | Microsoft.PowerShell.Core\ForEach-Object { "#Requires -Module $_" } return $hashRequiresStrings } else { return "" } } } function Get-ScriptCommentHelpInfoString { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Description, [Parameter()] [string] $Synopsis, [Parameter()] [string[]] $Example, [Parameter()] [string[]] $Inputs, [Parameter()] [string[]] $Outputs, [Parameter()] [string[]] $Notes, [Parameter()] [string[]] $Link, [Parameter()] [string] $Component, [Parameter()] [string] $Role, [Parameter()] [string] $Functionality ) Process { $ScriptCommentHelpInfoString = "<# `r`n`r`n.DESCRIPTION `r`n $Description `r`n`r`n" if("$Synopsis".Trim()) { $ScriptCommentHelpInfoString += ".SYNOPSIS `r`n$Synopsis `r`n`r`n" } if("$Example".Trim()) { $Example | ForEach-Object { if($_) { $ScriptCommentHelpInfoString += ".EXAMPLE `r`n$_ `r`n`r`n" } } } if("$Inputs".Trim()) { $Inputs | ForEach-Object { if($_) { $ScriptCommentHelpInfoString += ".INPUTS `r`n$_ `r`n`r`n" } } } if("$Outputs".Trim()) { $Outputs | ForEach-Object { if($_) { $ScriptCommentHelpInfoString += ".OUTPUTS `r`n$_ `r`n`r`n" } } } if("$Notes".Trim()) { $ScriptCommentHelpInfoString += ".NOTES `r`n$($Notes -join "`r`n") `r`n`r`n" } if("$Link".Trim()) { $Link | ForEach-Object { if($_) { $ScriptCommentHelpInfoString += ".LINK `r`n$_ `r`n`r`n" } } } if("$Component".Trim()) { $ScriptCommentHelpInfoString += ".COMPONENT `r`n$($Component -join "`r`n") `r`n`r`n" } if("$Role".Trim()) { $ScriptCommentHelpInfoString += ".ROLE `r`n$($Role -join "`r`n") `r`n`r`n" } if("$Functionality".Trim()) { $ScriptCommentHelpInfoString += ".FUNCTIONALITY `r`n$($Functionality -join "`r`n") `r`n`r`n" } $ScriptCommentHelpInfoString += "#> `r`n" return $ScriptCommentHelpInfoString } } function Get-ScriptSourceLocation { [CmdletBinding()] Param ( [Parameter()] [String] $Location, [Parameter()] $Credential, [Parameter()] $Proxy, [Parameter()] $ProxyCredential ) $scriptLocation = $null if($Location) { # For local dir or SMB-share locations, ScriptSourceLocation is SourceLocation. if(Microsoft.PowerShell.Management\Test-Path -Path $Location) { $scriptLocation = $Location } else { $tempScriptLocation = $null if($Location.EndsWith('/api/v2', [System.StringComparison]::OrdinalIgnoreCase)) { $tempScriptLocation = $Location + '/items/psscript/' } elseif($Location.EndsWith('/api/v2/', [System.StringComparison]::OrdinalIgnoreCase)) { $tempScriptLocation = $Location + 'items/psscript/' } if($tempScriptLocation) { # Ping and resolve the specified location $scriptLocation = Resolve-Location -Location $tempScriptLocation ` -LocationParameterName 'ScriptSourceLocation' ` -Credential $Credential ` -Proxy $Proxy ` -ProxyCredential $ProxyCredential ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue } } } return $scriptLocation } function Get-SourceLocation { [CmdletBinding()] [OutputType("string")] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $SourceName ) Set-ModuleSourcesVariable if($script:PSGetModuleSources.Contains($SourceName)) { return $script:PSGetModuleSources[$SourceName].SourceLocation } else { return $SourceName } } function Get-SourceName { [CmdletBinding()] [OutputType("string")] Param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $Location ) Set-ModuleSourcesVariable foreach ($psModuleSource in $script:PSGetModuleSources.Values) { if (($psModuleSource.Name -eq $Location) -or (Test-EquivalentLocation -LocationA $psModuleSource.SourceLocation -LocationB $Location) -or ((Get-Member -InputObject $psModuleSource -Name $script:ScriptSourceLocation) -and (Test-EquivalentLocation -LocationA $psModuleSource.ScriptSourceLocation -LocationB $Location))) { return $psModuleSource.Name } } } function Get-UrlFromSwid { param ( [Parameter(Mandatory=$true)] $SoftwareIdentity, [Parameter(Mandatory=$true)] $UrlName ) foreach($link in $SoftwareIdentity.Links) { if( $link.Relationship -eq $UrlName) { return $link.HRef } } return $null } function Get-ValidModuleLocation { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $LocationString, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $ParameterName, [Parameter()] $Credential, [Parameter()] $Proxy, [Parameter()] $ProxyCredential ) # Get the actual Uri from the Location if(-not (Microsoft.PowerShell.Management\Test-Path $LocationString)) { # Append '/api/v2/' to the $LocationString, return if that URI works. if(($LocationString -notmatch 'LinkID') -and -not ($LocationString.EndsWith('/nuget/v2', [System.StringComparison]::OrdinalIgnoreCase)) -and -not ($LocationString.EndsWith('/nuget/v2/', [System.StringComparison]::OrdinalIgnoreCase)) -and -not ($LocationString.EndsWith('/nuget', [System.StringComparison]::OrdinalIgnoreCase)) -and -not ($LocationString.EndsWith('/nuget/', [System.StringComparison]::OrdinalIgnoreCase)) -and -not ($LocationString.EndsWith('index.json', [System.StringComparison]::OrdinalIgnoreCase)) -and -not ($LocationString.EndsWith('index.json/', [System.StringComparison]::OrdinalIgnoreCase)) -and -not ($LocationString.EndsWith('/api/v2', [System.StringComparison]::OrdinalIgnoreCase)) -and -not ($LocationString.EndsWith('/api/v2/', [System.StringComparison]::OrdinalIgnoreCase)) ) { $tempLocation = $null if($LocationString.EndsWith('/', [System.StringComparison]::OrdinalIgnoreCase)) { $tempLocation = $LocationString + 'api/v2/' } else { $tempLocation = $LocationString + '/api/v2/' } if($tempLocation) { # Ping and resolve the specified location $tempLocation = Resolve-Location -Location $tempLocation ` -LocationParameterName $ParameterName ` -Credential $Credential ` -Proxy $Proxy ` -ProxyCredential $ProxyCredential ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue if($tempLocation) { return $tempLocation } # No error if we can't resolve the URL appended with '/api/v2/' } } # Ping and resolve the specified location $LocationString = Resolve-Location -Location $LocationString ` -LocationParameterName $ParameterName ` -Credential $Credential ` -Proxy $Proxy ` -ProxyCredential $ProxyCredential ` -CallerPSCmdlet $PSCmdlet } return $LocationString } function HttpClientApisAvailable { $HttpClientApisAvailable = $false try { [System.Net.Http.HttpClient] $HttpClientApisAvailable = $true } catch { } return $HttpClientApisAvailable } function Install-NuGetClientBinaries { [CmdletBinding()] param ( [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCmdlet] $CallerPSCmdlet, [parameter()] [switch] $BootstrapNuGetExe, [Parameter()] $Proxy, [Parameter()] $ProxyCredential, [parameter()] [switch] $Force ) if ($script:NuGetProvider -and ($script:NuGetExeVersion -and ($script:NuGetExeVersion -ge $script:NuGetExeMinRequiredVersion)) -and (-not $BootstrapNuGetExe -or (($script:NuGetExePath -and (Microsoft.PowerShell.Management\Test-Path -Path $script:NuGetExePath)) -or ($script:DotnetCommandPath -and (Microsoft.PowerShell.Management\Test-Path -Path $script:DotnetCommandPath))))) { return } $bootstrapNuGetProvider = (-not $script:NuGetProvider) if($bootstrapNuGetProvider) { # Bootstrap the NuGet provider only if it is not available. # By default PackageManagement loads the latest version of the NuGet provider. $nugetProvider = PackageManagement\Get-PackageProvider -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Microsoft.PowerShell.Core\Where-Object { $_.Name -eq $script:NuGetProviderName -and $_.Version -ge $script:NuGetProviderVersion } if($nugetProvider) { $script:NuGetProvider = $nugetProvider $bootstrapNuGetProvider = $false } else { # User might have installed it in an another console or in the same process, check available NuGet providers and import the required provider. $availableNugetProviders = PackageManagement\Get-PackageProvider -Name $script:NuGetProviderName ` -ListAvailable ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue | Microsoft.PowerShell.Core\Where-Object { $_.Name -eq $script:NuGetProviderName -and $_.Version -ge $script:NuGetProviderVersion } if($availableNugetProviders) { # Force import ensures that nuget provider with minimum version got loaded. $null = PackageManagement\Import-PackageProvider -Name $script:NuGetProviderName ` -MinimumVersion $script:NuGetProviderVersion ` -Force $nugetProvider = PackageManagement\Get-PackageProvider -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Microsoft.PowerShell.Core\Where-Object { $_.Name -eq $script:NuGetProviderName -and $_.Version -ge $script:NuGetProviderVersion } if($nugetProvider) { $script:NuGetProvider = $nugetProvider $bootstrapNuGetProvider = $false } } } } if($script:IsWindows -and -not $script:IsNanoServer) { if($BootstrapNuGetExe -and (-not $script:NuGetExePath -or -not (Microsoft.PowerShell.Management\Test-Path -Path $script:NuGetExePath)) -or ($script:NuGetExeVersion -and ($script:NuGetExeVersion -lt $script:NuGetExeMinRequiredVersion)) ) { $programDataExePath = Microsoft.PowerShell.Management\Join-Path -Path $script:PSGetProgramDataPath -ChildPath $script:NuGetExeName $applocalDataExePath = Microsoft.PowerShell.Management\Join-Path -Path $script:PSGetAppLocalPath -ChildPath $script:NuGetExeName # Check if NuGet.exe is available under one of the predefined PowerShellGet locations under ProgramData or LocalAppData if(Microsoft.PowerShell.Management\Test-Path -Path $programDataExePath) { $NugetExePath = $programDataExePath } elseif(Microsoft.PowerShell.Management\Test-Path -Path $applocalDataExePath) { $NugetExePath = $applocalDataExePath } else { # Using Get-Command cmdlet, get the location of NuGet.exe if it is available under $env:PATH. # NuGet.exe does not work if it is under $env:WINDIR, so skip it from the Get-Command results. $nugetCmd = Microsoft.PowerShell.Core\Get-Command -Name $script:NuGetExeName ` -ErrorAction Ignore ` -WarningAction SilentlyContinue | Microsoft.PowerShell.Core\Where-Object { $_.Path -and ((Microsoft.PowerShell.Management\Split-Path -Path $_.Path -Leaf) -eq $script:NuGetExeName) -and (-not $_.Path.StartsWith($env:windir, [System.StringComparison]::OrdinalIgnoreCase)) } | Microsoft.PowerShell.Utility\Select-Object -First 1 -ErrorAction Ignore if($nugetCmd -and $nugetCmd.Path -and $nugetCmd.FileVersionInfo.FileVersion) { $NugetExePath = $nugetCmd.Path } } if ($NugetExePath -and (Microsoft.PowerShell.Management\Test-Path -Path $NugetExePath)) { $script:NuGetExePath = $NugetExePath $script:NuGetExeVersion = (Get-Command $script:NuGetExePath).FileVersionInfo.FileVersion # No need to bootstrap the NuGet.exe if there is a NuGet.exe file that is at least the minimum required version found if ($script:NuGetExeVersion -and ($script:NuGetExeVersion -ge $script:NuGetExeMinRequiredVersion)) { $BootstrapNuGetExe = $false } } } else { # No need to bootstrap the NuGet.exe when $BootstrapNuGetExe is false or NuGet.exe path is already assigned. $BootstrapNuGetExe = $false } } if($BootstrapNuGetExe) { $DotnetCmd = Microsoft.PowerShell.Core\Get-Command -Name $script:DotnetCommandName -ErrorAction Ignore -WarningAction SilentlyContinue | Microsoft.PowerShell.Utility\Select-Object -First 1 -ErrorAction Ignore if ($DotnetCmd -and $DotnetCmd.Path) { $script:DotnetCommandPath = $DotnetCmd.Path $BootstrapNuGetExe = $false } else { if($script:IsWindows) { $DotnetCommandPath = Microsoft.PowerShell.Management\Join-Path -Path $env:LocalAppData -ChildPath Microsoft | Microsoft.PowerShell.Management\Join-Path -ChildPath dotnet | Microsoft.PowerShell.Management\Join-Path -ChildPath dotnet.exe if($DotnetCommandPath -and -not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $DotnetCommandPath -PathType Leaf)) { $DotnetCommandPath = Microsoft.PowerShell.Management\Join-Path -Path $env:ProgramFiles -ChildPath dotnet | Microsoft.PowerShell.Management\Join-Path -ChildPath dotnet.exe } } else { $DotnetCommandPath = '/usr/local/bin/dotnet' } if($DotnetCommandPath -and (Microsoft.PowerShell.Management\Test-Path -LiteralPath $DotnetCommandPath -PathType Leaf)) { $DotnetCommandVersion,$null = (& $DotnetCommandPath '--version') -split '-',2 if($DotnetCommandVersion -and ($script:MinimumDotnetCommandVersion -le $DotnetCommandVersion)) { $script:DotnetCommandPath = $DotnetCommandPath $BootstrapNuGetExe = $false } } } } # On non-Windows, dotnet should be installed by the user, throw an error if dotnet is not found using above logic. if ($BootstrapNuGetExe -and (-not $script:IsWindows -or $script:IsNanoServer)) { $ThrowError_params = @{ ExceptionName = 'System.InvalidOperationException' ExceptionMessage = ($LocalizedData.CouldNotFindDotnetCommand -f $script:MinimumDotnetCommandVersion, $script:DotnetInstallUrl) ErrorId = 'CouldNotFindDotnetCommand' CallerPSCmdlet = $CallerPSCmdlet ErrorCategory = 'InvalidOperation' } ThrowError @ThrowError_params return } if(-not $bootstrapNuGetProvider -and -not $BootstrapNuGetExe) { return } # We should prompt only once for bootstrapping the NuGet provider and/or NuGet.exes if($BootstrapNuGetExe -and $script:NuGetExePath -and $bootstrapNuGetProvider) { # Should continue message for upgrading NuGet.exe and installing NuGet provider $shouldContinueQueryMessage = $LocalizedData.InstallNugetBinariesUpgradeShouldContinueQuery -f @($script:NuGetExeMinRequiredVersion,$script:NuGetProviderVersion,$script:NuGetBinaryProgramDataPath,$script:NuGetBinaryLocalAppDataPath,$script:PSGetProgramDataPath,$script:PSGetAppLocalPath) $shouldContinueCaption = $LocalizedData.InstallNuGetBinariesUpgradeShouldContinueCaption } elseif($BootstrapNuGetExe -and $bootstrapNuGetProvider) { # Should continue message for installing both NuGet.exe and NuGet provider $shouldContinueQueryMessage = $LocalizedData.InstallNuGetBinariesShouldContinueQuery -f @($script:NuGetExeMinRequiredVersion, $script:NuGetProviderVersion, $script:NuGetBinaryProgramDataPath, $script:NuGetBinaryLocalAppDataPath, $script:PSGetProgramDataPath,$script:PSGetAppLocalPath) $shouldContinueCaption = $LocalizedData.InstallNuGetBinariesShouldContinueCaption } elseif($BootstrapNuGetExe -and $script:NuGetExePath) { # Should continue message for upgrading NuGet.exe $shouldContinueQueryMessage = $LocalizedData.InstallNugetExeUpgradeShouldContinueQuery -f @($script:NuGetExeMinRequiredVersion, $script:PSGetProgramDataPath, $script:PSGetAppLocalPath) $shouldContinueCaption = $LocalizedData.InstallNuGetExeUpgradeShouldContinueCaption } elseif($BootstrapNuGetExe) { # Should continue message for installing NuGet.exe $shouldContinueQueryMessage = $LocalizedData.InstallNuGetExeShouldContinueQuery -f @($script:NuGetExeMinRequiredVersion, $script:PSGetProgramDataPath, $script:PSGetAppLocalPath) $shouldContinueCaption = $LocalizedData.InstallNuGetExeShouldContinueCaption } elseif($bootstrapNuGetProvider) { # Should continue message for installing NuGet Provider $shouldContinueQueryMessage = $LocalizedData.InstallNuGetProviderShouldContinueQuery -f @($script:NuGetProviderVersion,$script:NuGetBinaryProgramDataPath,$script:NuGetBinaryLocalAppDataPath) $shouldContinueCaption = $LocalizedData.InstallNuGetProviderShouldContinueCaption } $AdditionalParams = Get-ParametersHashtable -Proxy $Proxy -ProxyCredential $ProxyCredential if($Force -or $psCmdlet.ShouldContinue($shouldContinueQueryMessage, $shouldContinueCaption)) { if($bootstrapNuGetProvider) { Write-Verbose -Message $LocalizedData.DownloadingNugetProvider $scope = 'CurrentUser' if(Test-RunningAsElevated) { $scope = 'AllUsers' } # Bootstrap the NuGet provider $null = PackageManagement\Install-PackageProvider -Name $script:NuGetProviderName ` -MinimumVersion $script:NuGetProviderVersion ` -Scope $scope ` -Force @AdditionalParams # Force import ensures that nuget provider with minimum version got loaded. $null = PackageManagement\Import-PackageProvider -Name $script:NuGetProviderName ` -MinimumVersion $script:NuGetProviderVersion ` -Force $nugetProvider = PackageManagement\Get-PackageProvider -Name $script:NuGetProviderName if ($nugetProvider) { $script:NuGetProvider = $nugetProvider } } if($BootstrapNuGetExe -and $script:IsWindows) { Write-Verbose -Message $LocalizedData.DownloadingNugetExe $nugetExeBasePath = $script:PSGetAppLocalPath # if the current process is running with elevated privileges, # install NuGet.exe to $script:PSGetProgramDataPath if(Test-RunningAsElevated) { $nugetExeBasePath = $script:PSGetProgramDataPath } if(-not (Microsoft.PowerShell.Management\Test-Path -Path $nugetExeBasePath)) { $null = Microsoft.PowerShell.Management\New-Item -Path $nugetExeBasePath ` -ItemType Directory -Force ` -ErrorAction SilentlyContinue ` -WarningAction SilentlyContinue ` -Confirm:$false -WhatIf:$false } $nugetExeFilePath = Microsoft.PowerShell.Management\Join-Path -Path $nugetExeBasePath -ChildPath $script:NuGetExeName # Download the NuGet.exe from https://dist.nuget.org/win-x86-commandline/latest/nuget.exe $null = Microsoft.PowerShell.Utility\Invoke-WebRequest -Uri $script:NuGetClientSourceURL ` -OutFile $nugetExeFilePath ` @AdditionalParams if (Microsoft.PowerShell.Management\Test-Path -Path $nugetExeFilePath) { $script:NuGetExePath = $nugetExeFilePath $script:NuGetExeVersion = (Get-Command $nugetExeFilePath).FileVersionInfo.FileVersion } } } $message = $null $errorId = $null $failedToBootstrapNuGetProvider = $false $failedToBootstrapNuGetExe = $false if($bootstrapNuGetProvider -and -not $script:NuGetProvider) { $failedToBootstrapNuGetProvider = $true $message = $LocalizedData.CouldNotInstallNuGetProvider -f @($script:NuGetProviderVersion) $errorId = 'CouldNotInstallNuGetProvider' } if($BootstrapNuGetExe) { if(-not $script:NuGetExePath -or -not (Microsoft.PowerShell.Management\Test-Path -Path $script:NuGetExePath)) { $failedToBootstrapNuGetExe = $true $message = $LocalizedData.CouldNotInstallNuGetExe -f @($script:NuGetExeMinRequiredVersion, $script:MinimumDotnetCommandVersion) $errorId = 'CouldNotInstallNuGetExe' } elseif($script:NuGetExeVersion -and ($script:NuGetExeVersion -lt $script:NuGetExeMinRequiredVersion)) { $failedToBootstrapNuGetExe = $true $message = $LocalizedData.CouldNotUpgradeNuGetExe -f @($script:NuGetExeMinRequiredVersion, $script:MinimumDotnetCommandVersion) $errorId = 'CouldNotUpgradeNuGetExe' } } # Change the error id and message if both NuGet provider and NuGet.exe are not installed. if($failedToBootstrapNuGetProvider -and $failedToBootstrapNuGetExe) { $message = $LocalizedData.CouldNotInstallNuGetBinaries2 -f @($script:NuGetProviderVersion) $errorId = 'CouldNotInstallNuGetBinaries' } # Throw the error message if one of the above conditions are met if($message -and $errorId) { ThrowError -ExceptionName "System.InvalidOperationException" ` -ExceptionMessage $message ` -ErrorId $errorId ` -CallerPSCmdlet $CallerPSCmdlet ` -ErrorCategory InvalidOperation } } function Install-PackageUtility { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $FastPackageReference, [Parameter()] [ValidateNotNullOrEmpty()] [string] $Location, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $request ) Set-ModuleSourcesVariable Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Install-PackageUtility')) Write-Debug ($LocalizedData.FastPackageReference -f $fastPackageReference) $Force = $false $SkipPublisherCheck = $false $AllowClobber = $false $Debug = $false $MinimumVersion = "" $RequiredVersion = "" $IsSavePackage = $false $Scope = $null $NoPathUpdate = $false $AcceptLicense = $false # take the fastPackageReference and get the package object again. $parts = $fastPackageReference -Split '[|]' if( $parts.Length -eq 5 ) { $providerName = $parts[0] $packageName = $parts[1] $version = $parts[2] $sourceLocation= $parts[3] $artifactType = $parts[4] $result = ValidateAndGet-VersionPrereleaseStrings -Version $version -CallerPSCmdlet $PSCmdlet if (-not $result) { # ValidateAndGet-VersionPrereleaseStrings throws the error. # returning to avoid further execution when different values are specified for -ErrorAction parameter return } $galleryItemVersion = $result["Version"] $galleryItemPrerelease = $result["Prerelease"] $galleryItemFullVersion = $result["FullVersion"] # The default destination location for Modules and Scripts is ProgramFiles path $scriptDestination = $script:ProgramFilesScriptsPath $moduleDestination = $script:programFilesModulesPath $Scope = 'AllUsers' if($artifactType -eq $script:PSArtifactTypeScript) { $AdminPrivilegeErrorMessage = $LocalizedData.InstallScriptAdminPrivilegeRequiredForAllUsersScope -f @($script:ProgramFilesScriptsPath, $script:MyDocumentsScriptsPath) $AdminPrivilegeErrorId = 'InstallScriptAdminPrivilegeRequiredForAllUsersScope' } else { $AdminPrivilegeErrorMessage = $LocalizedData.InstallModuleAdminPrivilegeRequiredForAllUsersScope -f @($script:programFilesModulesPath, $script:MyDocumentsModulesPath) $AdminPrivilegeErrorId = 'InstallModuleAdminPrivilegeRequiredForAllUsersScope' } $installUpdate = $false $options = $request.Options if($options) { foreach( $o in $options.Keys ) { Write-Debug ("OPTION: {0} => {1}" -f ($o, $request.Options[$o]) ) } if($options.ContainsKey('Scope')) { $Scope = $options['Scope'] Write-Verbose ($LocalizedData.SpecifiedInstallationScope -f $Scope) if($Scope -eq "CurrentUser") { $scriptDestination = $script:MyDocumentsScriptsPath $moduleDestination = $script:MyDocumentsModulesPath } elseif($Scope -eq "AllUsers") { $scriptDestination = $script:ProgramFilesScriptsPath $moduleDestination = $script:programFilesModulesPath if(-not (Test-RunningAsElevated)) { # Throw an error when Install-Module/Script is used as a non-admin user and '-Scope AllUsers' ThrowError -ExceptionName "System.ArgumentException" ` -ExceptionMessage $AdminPrivilegeErrorMessage ` -ErrorId $AdminPrivilegeErrorId ` -CallerPSCmdlet $PSCmdlet ` -ErrorCategory InvalidArgument } } } elseif($Location) { $IsSavePackage = $true $Scope = $null $moduleDestination = $Location $scriptDestination = $Location } elseif(-not $script:IsCoreCLR -and (Test-RunningAsElevated)) { # If Windows and elevated default scope will be all users $scriptDestination = $script:ProgramFilesScriptsPath $moduleDestination = $script:ProgramFilesModulesPath } else { # If non-Windows or non-elevated default scope will be current user $scriptDestination = $script:MyDocumentsScriptsPath $moduleDestination = $script:MyDocumentsModulesPath } if($options.ContainsKey('SkipPublisherCheck')) { $SkipPublisherCheck = $options['SkipPublisherCheck'] if($SkipPublisherCheck.GetType().ToString() -eq 'System.String') { if($SkipPublisherCheck -eq 'true') { $SkipPublisherCheck = $true } else { $SkipPublisherCheck = $false } } } if($options.ContainsKey('AllowClobber')) { $AllowClobber = $options['AllowClobber'] if($AllowClobber.GetType().ToString() -eq 'System.String') { if($AllowClobber -eq 'false') { $AllowClobber = $false } elseif($AllowClobber -eq 'true') { $AllowClobber = $true } } } if($options.ContainsKey('Force')) { $Force = $options['Force'] if($Force.GetType().ToString() -eq 'System.String') { if($Force -eq 'false') { $Force = $false } elseif($Force -eq 'true') { $Force = $true } } } if($options.ContainsKey('AcceptLicense')) { $AcceptLicense = $options['AcceptLicense'] if($AcceptLicense.GetType().ToString() -eq 'System.String') { if($AcceptLicense -eq 'false') { $AcceptLicense = $false } elseif($AcceptLicense -eq 'true') { $AcceptLicense = $true } } } if($options.ContainsKey('Debug')) { $Debug = $options['Debug'] if($Debug.GetType().ToString() -eq 'System.String') { if($Debug -eq 'false') { $Debug = $false } elseif($Debug -eq 'true') { $Debug = $true } } } if($options.ContainsKey('NoPathUpdate')) { $NoPathUpdate = $options['NoPathUpdate'] if($NoPathUpdate.GetType().ToString() -eq 'System.String') { if($NoPathUpdate -eq 'false') { $NoPathUpdate = $false } elseif($NoPathUpdate -eq 'true') { $NoPathUpdate = $true } } } if($options.ContainsKey('MinimumVersion')) { $MinimumVersion = $options['MinimumVersion'] } if($options.ContainsKey('RequiredVersion')) { $RequiredVersion = $options['RequiredVersion'] } if($options.ContainsKey('InstallUpdate')) { $installUpdate = $options['InstallUpdate'] if($installUpdate.GetType().ToString() -eq 'System.String') { if($installUpdate -eq 'false') { $installUpdate = $false } elseif($installUpdate -eq 'true') { $installUpdate = $true } } } if($Scope -and ($artifactType -eq $script:PSArtifactTypeScript) -and (-not $installUpdate)) { ValidateAndSet-PATHVariableIfUserAccepts -Scope $Scope ` -ScopePath $scriptDestination ` -Request $request ` -NoPathUpdate:$NoPathUpdate ` -Force:$Force } if($artifactType -eq $script:PSArtifactTypeModule) { $message = $LocalizedData.ModuleDestination -f @($moduleDestination) } else { $message = $LocalizedData.ScriptDestination -f @($scriptDestination, $moduleDestination) } Write-Verbose $message } Write-Debug "ArtifactType is $artifactType" if($artifactType -eq $script:PSArtifactTypeModule) { # Test if module is already installed $InstalledModuleInfo = if(-not $IsSavePackage){ Test-ModuleInstalled -Name $packageName -RequiredVersion $RequiredVersion } if(-not $Force -and $InstalledModuleInfo) { $installedModPrerelease = $null if ((Get-Member -InputObject $InstalledModuleInfo -Name PrivateData -ErrorAction SilentlyContinue) -and ` $InstalledModuleInfo.PrivateData -and ` $InstalledModuleInfo.PrivateData.GetType().ToString() -eq "System.Collections.Hashtable" -and ` ($InstalledModuleInfo.PrivateData.ContainsKey('PSData')) -and ` $InstalledModuleInfo.PrivateData.PSData.GetType().ToString() -eq "System.Collections.Hashtable" -and ` ($InstalledModuleInfo.PrivateData.PSData.ContainsKey('Prerelease'))) { $installedModPrerelease = $InstalledModuleInfo.PrivateData.PSData.Prerelease } $result = ValidateAndGet-VersionPrereleaseStrings -Version $InstalledModuleInfo.Version -Prerelease $installedModPrerelease -CallerPSCmdlet $PSCmdlet if (-not $result) { # ValidateAndGet-VersionPrereleaseStrings throws the error. # returning to avoid further execution when different values are specified for -ErrorAction parameter return } $installedModuleVersion = $result["Version"] $installedModulePrerelease = $result["Prerelease"] $installedModuleFullVersion = $result["FullVersion"] if($RequiredVersion -and (Test-ModuleSxSVersionSupport)) { # Check if the module with the required version is already installed otherwise proceed to install/update. if($InstalledModuleInfo) { $message = $LocalizedData.ModuleWithRequiredVersionAlreadyInstalled -f ($InstalledModuleInfo.Version, $InstalledModuleInfo.Name, $InstalledModuleInfo.ModuleBase, $InstalledModuleInfo.Version) Write-Error -Message $message -ErrorId "ModuleWithRequiredVersionAlreadyInstalled" -Category InvalidOperation return } } else { if(-not $installUpdate) { if ($MinimumVersion) { $result = ValidateAndGet-VersionPrereleaseStrings -Version $MinimumVersion -CallerPSCmdlet $PSCmdlet if (-not $result) { # ValidateAndGet-VersionPrereleaseStrings throws the error. # returning to avoid further execution when different values are specified for -ErrorAction parameter return } $minVersion = $result["Version"] $minPrerelease = $result["Prerelease"] $minFullVersion = $result["FullVersion"] } else { $minVersion = $null $minPrerelease = $null $minFullVersion = $null } if( (-not $MinimumVersion -and ($galleryItemFullVersion -ne $InstalledModuleFullVersion)) -or ($MinimumVersion -and (Compare-PrereleaseVersions -FirstItemVersion $installedModuleVersion ` -FirstItemPrerelease $installedModulePrerelease ` -SecondItemVersion $minVersion ` -SecondItemPrerelease $minPrerelease))) { if($PSVersionTable.PSVersion -ge '5.0.0') { $message = $LocalizedData.ModuleAlreadyInstalledSxS -f ($InstalledModuleFullVersion, $InstalledModuleInfo.Name, $InstalledModuleInfo.ModuleBase, $galleryItemFullVersion, $InstalledModuleFullVersion, $galleryItemFullVersion) } else { $message = $LocalizedData.ModuleAlreadyInstalled -f ($InstalledModuleFullVersion, $InstalledModuleInfo.Name, $InstalledModuleInfo.ModuleBase, $InstalledModuleFullVersion, $galleryItemFullVersion) } Write-Error -Message $message -ErrorId "ModuleAlreadyInstalled" -Category InvalidOperation } else { $message = $LocalizedData.ModuleAlreadyInstalledVerbose -f ($InstalledModuleFullVersion, $InstalledModuleInfo.Name, $InstalledModuleInfo.ModuleBase) Write-Verbose $message } return } else { if (Compare-PrereleaseVersions -FirstItemVersion $installedModuleVersion ` -FirstItemPrerelease $installedModulePrerelease ` -SecondItemVersion $galleryItemVersion.ToString() ` -SecondItemPrerelease $galleryItemPrerelease) { $message = $LocalizedData.FoundModuleUpdate -f ($InstalledModuleInfo.Name, $galleryItemFullVersion) Write-Verbose $message } else { $message = $LocalizedData.NoUpdateAvailable -f ($InstalledModuleInfo.Name) Write-Verbose $message return } } } } } if($artifactType -eq $script:PSArtifactTypeScript) { # Test if script is already installed $InstalledScriptInfo = if(-not $IsSavePackage){ Test-ScriptInstalled -Name $packageName } Write-Debug "InstalledScriptInfo is $InstalledScriptInfo" if(-not $Force -and $InstalledScriptInfo) { $result = ValidateAndGet-VersionPrereleaseStrings -Version $InstalledScriptInfo.Version -CallerPSCmdlet $PSCmdlet if (-not $result) { # ValidateAndGet-VersionPrereleaseStrings throws the error. # returning to avoid further execution when different values are specified for -ErrorAction parameter return } $installedScriptInfoVersion = $result["Version"] $installedScriptInfoPrerelease = $result["Prerelease"] $installedScriptFullVersion = $result["FullVersion"] if(-not $installUpdate) { if ($MinimumVersion) { $result = ValidateAndGet-VersionPrereleaseStrings -Version $MinimumVersion -CallerPSCmdlet $PSCmdlet if (-not $result) { # ValidateAndGet-VersionPrereleaseStrings throws the error. # returning to avoid further execution when different values are specified for -ErrorAction parameter return } $minVersion = $result["Version"] $minPrerelease = $result["Prerelease"] $minFullVersion = $result["FullVersion"] } else { $minVersion = $null $minPrerelease = $null $minFullVersion = $null } if( (-not $MinimumVersion -and ($galleryItemFullVersion -ne $installedScriptFullVersion)) -or ($MinimumVersion -and (Compare-PrereleaseVersions -FirstItemVersion $installedScriptInfoVersion ` -FirstItemPrerelease $installedScriptInfoPrerelease ` -SecondItemVersion $minVersion ` -SecondItemPrerelease $minPrerelease) )) { $message = $LocalizedData.ScriptAlreadyInstalled -f ($installedScriptFullVersion, $InstalledScriptInfo.Name, $InstalledScriptInfo.ScriptBase, $installedScriptFullVersion, $galleryItemFullVersion) Write-Error -Message $message -ErrorId "ScriptAlreadyInstalled" -Category InvalidOperation } else { $message = $LocalizedData.ScriptAlreadyInstalledVerbose -f ($installedScriptFullVersion, $InstalledScriptInfo.Name, $InstalledScriptInfo.ScriptBase) Write-Verbose $message } return } else { if (Compare-PrereleaseVersions -FirstItemVersion $installedScriptInfoVersion.ToString() ` -FirstItemPrerelease $installedScriptInfoPrerelease ` -SecondItemVersion $galleryItemVersion.ToString() ` -SecondItemPrerelease $galleryItemPrerelease) { $message = $LocalizedData.FoundScriptUpdate -f ($InstalledScriptInfo.Name, $version) Write-Verbose $message } else { $message = $LocalizedData.NoScriptUpdateAvailable -f ($InstalledScriptInfo.Name) Write-Verbose $message return } } } # Throw an error if there is a command with the same name and -force is not specified. if(-not $installUpdate -and -not $IsSavePackage -and -not $Force) { $cmd = Microsoft.PowerShell.Core\Get-Command -Name $packageName ` -ErrorAction Ignore ` -WarningAction SilentlyContinue if($cmd) { $message = $LocalizedData.CommandAlreadyAvailable -f ($packageName) Write-Error -Message $message -ErrorId CommandAlreadyAvailableWitScriptName -Category InvalidOperation return } } } # create a temp folder and download the module $tempDestination = Microsoft.PowerShell.Management\Join-Path -Path $script:TempPath -ChildPath "$(Microsoft.PowerShell.Utility\Get-Random)" $null = Microsoft.PowerShell.Management\New-Item -Path $tempDestination -ItemType Directory -Force -Confirm:$false -WhatIf:$false try { $provider = $request.SelectProvider($providerName) if(-not $provider) { Write-Error -Message ($LocalizedData.PackageManagementProviderIsNotAvailable -f $providerName) return } if($request.IsCanceled) { return } Write-Verbose ($LocalizedData.SpecifiedLocationAndOGP -f ($provider.ProviderName, $providerName)) $InstalledItemsList = $null $pkg = $script:FastPackRefHashtable[$fastPackageReference] # If an item has dependencies, prepare the list of installed items and # pass it to the NuGet provider to not download the already installed items. if($pkg.Dependencies.count -and -not $IsSavePackage -and -not $Force) { $InstalledItemsList = Microsoft.PowerShell.Core\Get-Module -ListAvailable | Microsoft.PowerShell.Core\ForEach-Object {"$($_.Name)!#!$($_.Version)".ToLower()} if($artifactType -eq $script:PSArtifactTypeScript) { $InstalledItemsList += $script:PSGetInstalledScripts.GetEnumerator() | Microsoft.PowerShell.Core\ForEach-Object { "$($_.Value.PSGetItemInfo.Name)!#!$($_.Value.PSGetItemInfo.Version)".ToLower() } } $InstalledItemsList | Select-Object -Unique -ErrorAction Ignore if($Debug) { $InstalledItemsList | Microsoft.PowerShell.Core\ForEach-Object { Write-Debug -Message "Locally available Item: $_"} } } $ProviderOptions = @{ Destination=$tempDestination; } if($InstalledItemsList) { $ProviderOptions['InstalledPackages'] = $InstalledItemsList } $newRequest = $request.CloneRequest( $ProviderOptions, @($SourceLocation), $request.Credential ) if($artifactType -eq $script:PSArtifactTypeModule) { $message = $LocalizedData.DownloadingModuleFromGallery -f ($packageName, $galleryItemFullVersion, $sourceLocation) } else { $message = $LocalizedData.DownloadingScriptFromGallery -f ($packageName, $galleryItemFullVersion, $sourceLocation) } Write-Verbose $message $installedPkgs = $provider.InstallPackage($script:FastPackRefHashtable[$fastPackageReference], $newRequest) $YesToAll = $false $NoToAll = $false foreach($pkg in $installedPkgs) { if($request.IsCanceled) { return } $result = ValidateAndGet-VersionPrereleaseStrings -Version $pkg.Version -CallerPSCmdlet $PSCmdlet if (-not $result) { # ValidateAndGet-VersionPrereleaseStrings throws the error. # returning to avoid further execution when different values are specified for -ErrorAction parameter return } $pkgVersion = $result["Version"] $pkgPrerelease = $result["Prerelease"] $pkgFullVersion = $result["FullVersion"] $destinationModulePath = Microsoft.PowerShell.Management\Join-Path -Path $moduleDestination -ChildPath $pkg.Name # Side-by-Side module version is available on PowerShell 5.0 or later versions only # By default, PowerShell module versions will be installed/updated Side-by-Side. if(Test-ModuleSxSVersionSupport) { $destinationModulePath = Microsoft.PowerShell.Management\Join-Path -Path $destinationModulePath -ChildPath $pkgVersion } $destinationscriptPath = $scriptDestination # Get actual artifact type from the package $packageType = $script:PSArtifactTypeModule $installLocation = $destinationModulePath # Below logic handles the package folder name with version. $tempPackagePath = Microsoft.PowerShell.Management\Join-Path -Path $tempDestination -ChildPath "$($pkg.Name).$($pkg.Version)" if(-not (Microsoft.PowerShell.Management\Test-Path -Path $tempPackagePath -PathType Container)) { $message = $LocalizedData.UnableToDownloadThePackage -f ($provider.ProviderName, $pkg.Name, $pkg.Version, $tempPackagePath) Write-Error -Message $message -ErrorId 'UnableToDownloadThePackage' -Category InvalidOperation return } $packageFiles = Microsoft.PowerShell.Management\Get-ChildItem -Path $tempPackagePath -Recurse -Exclude "*.nupkg","*.nuspec" if($packageFiles -and $packageFiles.GetType().ToString() -eq 'System.IO.FileInfo' -and $packageFiles.Name -eq "$($pkg.Name).ps1") { $packageType = $script:PSArtifactTypeScript $installLocation = $destinationscriptPath } $AdditionalParams = @{} if(-not $IsSavePackage) { # During the install operation: # InstalledDate should be the current Get-Date value # UpdatedDate should be null # # During the update operation: # InstalledDate should be from the previous version's InstalledDate otherwise current Get-Date value # UpdatedDate should be the current Get-Date value # $InstalledDate = Microsoft.PowerShell.Utility\Get-Date if($installUpdate) { $AdditionalParams['UpdatedDate'] = Microsoft.PowerShell.Utility\Get-Date $InstalledItemDetails = $null if($packageType -eq $script:PSArtifactTypeModule) { $InstalledItemDetails = Get-InstalledModuleDetails -Name $pkg.Name | Select-Object -Last 1 -ErrorAction Ignore } elseif($packageType -eq $script:PSArtifactTypeScript) { $InstalledItemDetails = Get-InstalledScriptDetails -Name $pkg.Name | Select-Object -Last 1 -ErrorAction Ignore } if($InstalledItemDetails -and $InstalledItemDetails.PSGetItemInfo -and (Get-Member -InputObject $InstalledItemDetails.PSGetItemInfo -Name 'InstalledDate') -and $InstalledItemDetails.PSGetItemInfo.InstalledDate) { $InstalledDate = $InstalledItemDetails.PSGetItemInfo.InstalledDate } } $AdditionalParams['InstalledDate'] = $InstalledDate } # construct the PSGetItemInfo from SoftwareIdentity and persist it $psgItemInfo = New-PSGetItemInfo -SoftwareIdentity $pkg ` -PackageManagementProviderName $provider.ProviderName ` -SourceLocation $sourceLocation ` -Type $packageType ` -InstalledLocation $installLocation ` @AdditionalParams if($packageType -eq $script:PSArtifactTypeModule) { if ($psgItemInfo.PowerShellGetFormatVersion -and ($script:SupportedPSGetFormatVersionMajors -notcontains $psgItemInfo.PowerShellGetFormatVersion.Major)) { $message = $LocalizedData.NotSupportedPowerShellGetFormatVersion -f ($psgItemInfo.Name, $psgItemInfo.PowerShellGetFormatVersion, $psgItemInfo.Name) Write-Error -Message $message -ErrorId "NotSupportedPowerShellGetFormatVersion" -Category InvalidOperation continue } $sourceModulePath = $tempPackagePath if($psgItemInfo.PowerShellGetFormatVersion -eq "1.0") { $sourceModulePath = Microsoft.PowerShell.Management\Join-Path -Path $sourceModulePath -ChildPath 'Content' | Microsoft.PowerShell.Management\Join-Path -ChildPath '*' | Microsoft.PowerShell.Management\Join-Path -ChildPath $script:ModuleReferences | Microsoft.PowerShell.Management\Join-Path -ChildPath $pkg.Name } #Prompt if module requires license Acceptance $requireLicenseAcceptance = $false if($psgItemInfo.PowerShellGetFormatVersion -and $psgItemInfo.PowerShellGetFormatVersion -ge $script:PSGetRequireLicenseAcceptanceFormatVersion) { if($psgItemInfo.AdditionalMetadata -and $psgItemInfo.AdditionalMetadata.requireLicenseAcceptance) { $requireLicenseAcceptance = $psgItemInfo.AdditionalMetadata.requireLicenseAcceptance } } if($requireLicenseAcceptance -eq $true) { if($Force -and -not($AcceptLicense)) { $message = $LocalizedData.ForceAcceptLicense -f $pkg.Name ThrowError -ExceptionName "System.ArgumentException" ` -ExceptionMessage $message ` -ErrorId "ForceAcceptLicense" ` -CallerPSCmdlet $PSCmdlet ` -ErrorCategory InvalidArgument } If (-not ($YesToAll -or $NoToAll -or $AcceptLicense)) { $LicenseFilePath = Join-PathUtility -Path $sourceModulePath -ChildPath 'License.txt' -PathType File if(-not(Test-Path -Path $LicenseFilePath -PathType Leaf)) { $message = $LocalizedData.LicenseTxtNotFound ThrowError -ExceptionName "System.ArgumentException" ` -ExceptionMessage $message ` -ErrorId "LicenseTxtNotFound" ` -CallerPSCmdlet $PSCmdlet ` -ErrorCategory ObjectNotFound } $FormattedEula = (Get-Content -Path $LicenseFilePath) -Join "`r`n" $message = $FormattedEula + "`r`n" + ($LocalizedData.AcceptanceLicenseQuery -f $pkg.Name) $title = $LocalizedData.AcceptLicense $result = $request.ShouldContinue($message, $title, [ref]$yesToAll, [ref]$NoToAll) if(($result -eq $false) -or ($NoToAll -eq $true)) { Write-Warning -Message $LocalizedData.UserDeclinedLicenseAcceptance return } } } $CurrentModuleInfo = $null # Validate the module if(-not $IsSavePackage) { $CurrentModuleInfo = Test-ValidManifestModule -ModuleBasePath $sourceModulePath ` -ModuleName $pkg.Name ` -InstallLocation $InstallLocation ` -AllowClobber:$AllowClobber ` -SkipPublisherCheck:$SkipPublisherCheck ` -IsUpdateOperation:$installUpdate if(-not $CurrentModuleInfo) { Write-Verbose -Message ($LocalizedData.ModuleValidationFailed -f $ModuleName,$ModuleBasePath) # This Install-Package provider API gets called once per an item/package/SoftwareIdentity. # Return if there is an error instead of continuing further to install the dependencies or current module. # return } } # Test if module is already installed $InstalledModuleInfo2 = if(-not $IsSavePackage){ Test-ModuleInstalled -Name $pkg.Name -RequiredVersion $pkgFullVersion } if($pkg.Name -ne $packageName) &nb |