c748652c34
commit 8cec8f150da7583b7af5efbe2853efee0179750c
14471 lines
556 KiB
PowerShell
14471 lines
556 KiB
PowerShell
|
|
#########################################################################################
|
|
#
|
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
#
|
|
# PowerShellGet Module
|
|
#
|
|
#########################################################################################
|
|
|
|
Microsoft.PowerShell.Core\Set-StrictMode -Version Latest
|
|
|
|
#region script variables
|
|
|
|
# Check if this is nano server. [System.Runtime.Loader.AssemblyLoadContext] is only available on NanoServer
|
|
$script:isNanoServer = $null -ne ('System.Runtime.Loader.AssemblyLoadContext' -as [Type])
|
|
|
|
try
|
|
{
|
|
$script:MyDocumentsFolderPath = [Environment]::GetFolderPath("MyDocuments")
|
|
}
|
|
catch
|
|
{
|
|
$script:MyDocumentsFolderPath = $null
|
|
}
|
|
|
|
$script:ProgramFilesPSPath = Microsoft.PowerShell.Management\Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell"
|
|
|
|
$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"
|
|
}
|
|
|
|
$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:TempPath = ([System.IO.DirectoryInfo]$env:TEMP).FullName
|
|
$script:PSGetItemInfoFileName = "PSGetModuleInfo.xml"
|
|
$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\'
|
|
$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:InstalledScriptInfoFileName = 'InstalledScriptInfo.xml'
|
|
$script:PSGetInstalledScripts = $null
|
|
|
|
# Public PSGallery module source name and location
|
|
$Script:PSGalleryModuleSource="PSGallery"
|
|
$Script:PSGallerySourceUri = 'https://go.microsoft.com/fwlink/?LinkID=397631&clcid=0x409'
|
|
$Script:PSGalleryPublishUri = 'https://go.microsoft.com/fwlink/?LinkID=397527&clcid=0x409'
|
|
$Script:PSGalleryScriptSourceUri = 'https://go.microsoft.com/fwlink/?LinkID=622995&clcid=0x409'
|
|
|
|
# PSGallery V3 Source
|
|
$Script:PSGalleryV3SourceUri = 'https://go.microsoft.com/fwlink/?LinkId=528403&clcid=0x409'
|
|
|
|
$Script:PSGalleryV2ApiAvailable = $true
|
|
$Script:PSGalleryV3ApiAvailable = $false
|
|
$Script:PSGalleryApiChecked = $false
|
|
|
|
$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:NuGetProviderName = "NuGet"
|
|
$script:NuGetProviderVersion = [Version]'2.8.5.201'
|
|
|
|
$script:SupportsPSModulesFeatureName="supports-powershell-modules"
|
|
$script:FastPackRefHastable = @{}
|
|
$script:NuGetBinaryProgramDataPath="$env:ProgramFiles\PackageManagement\ProviderAssemblies"
|
|
$script:NuGetBinaryLocalAppDataPath="$env:LOCALAPPDATA\PackageManagement\ProviderAssemblies"
|
|
# go fwlink for 'https://nuget.org/nuget.exe'
|
|
$script:NuGetClientSourceURL = 'http://go.microsoft.com/fwlink/?LinkID=690216&clcid=0x409'
|
|
$script:NuGetExeName = 'NuGet.exe'
|
|
$script:NuGetExePath = $null
|
|
$script:NuGetProvider = $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:CurrentPSGetFormatVersion = "1.0"
|
|
$script:PSGetFormatVersion = "PowerShellGetFormatVersion"
|
|
$script:SupportedPSGetFormatVersionMajors = @("1")
|
|
$script:ModuleReferences = 'Module References'
|
|
$script:AllVersions = "AllVersions"
|
|
$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: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: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)
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
Microsoft.PowerShell.Utility\Import-LocalizedData LocalizedData -filename PSGet.Resource.psd1
|
|
|
|
#region Add .Net type for Telemetry APIs and WebProxy
|
|
|
|
# This code is required to add a .Net type and call the Telemetry APIs
|
|
# This is required since PowerShell does not support generation of .Net Anonymous types
|
|
#
|
|
$requiredAssembly = @( "system.management.automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
|
|
"$([System.Net.IWebProxy].AssemblyQualifiedName)".Substring('System.Net.IWebProxy'.Length+1).Trim(),
|
|
"$([System.Uri].AssemblyQualifiedName)".Substring('System.Uri'.Length+1).Trim()
|
|
)
|
|
|
|
$source = @"
|
|
using System;
|
|
using System.Net;
|
|
using System.Management.Automation;
|
|
using Microsoft.Win32.SafeHandles;
|
|
using System.Security.Cryptography;
|
|
using System.Runtime.InteropServices;
|
|
|
|
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 });
|
|
}
|
|
|
|
}
|
|
|
|
/// <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;
|
|
}
|
|
}
|
|
|
|
[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;
|
|
}
|
|
|
|
public class Win32Helpers
|
|
{
|
|
[DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
|
|
public extern static
|
|
bool CertVerifyCertificateChainPolicy(
|
|
[In] IntPtr pszPolicyOID,
|
|
[In] SafeX509ChainHandle 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
|
|
SafeX509ChainHandle CertDuplicateCertificateChain(
|
|
[In] IntPtr pChainContext);
|
|
|
|
public static bool IsMicrosoftCertificate([In] SafeX509ChainHandle 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;
|
|
|
|
if(!CertVerifyCertificateChainPolicy(new IntPtr(CERT_CHAIN_POLICY_MICROSOFT_ROOT),
|
|
pChainContext,
|
|
ref PolicyPara,
|
|
ref PolicyStatus))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return (PolicyStatus.dwError == 0);
|
|
}
|
|
}
|
|
}
|
|
"@
|
|
|
|
# Telemetry is turned off by default.
|
|
$script:TelemetryEnabled = $false
|
|
|
|
try
|
|
{
|
|
# If the telemetry namespace/methods are not found flow goes to the catch block where telemetry is disabled
|
|
$telemetryMethods = ([Microsoft.PowerShell.Get.Telemetry] | Get-Member -Static).Name
|
|
|
|
if ($telemetryMethods.Contains("TraceMessageArtifactsNotFound") -and $telemetryMethods.Contains("TraceMessageNonPSGalleryRegistration"))
|
|
{
|
|
# Turn ON Telemetry if the infrastructure is present on the machine
|
|
$script:TelemetryEnabled = $true
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
# Ignore the error and try adding the type below
|
|
}
|
|
|
|
if(-not $script:TelemetryEnabled)
|
|
{
|
|
try
|
|
{
|
|
Add-Type -ReferencedAssemblies $requiredAssembly -TypeDefinition $source -Language CSharp -ErrorAction SilentlyContinue
|
|
|
|
# If the telemetry namespace/methods are not found flow goes to the catch block where telemetry is disabled
|
|
$telemetryMethods = ([Microsoft.PowerShell.Get.Telemetry] | Get-Member -Static).Name
|
|
|
|
if ($telemetryMethods.Contains("TraceMessageArtifactsNotFound") -and $telemetryMethods.Contains("TraceMessageNonPSGalleryRegistration"))
|
|
{
|
|
# Turn ON Telemetry if the infrastructure is present on the machine
|
|
$script:TelemetryEnabled = $true
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
# Disable Telemetry if there are any issues finding/loading the Telemetry infrastructure
|
|
$script:TelemetryEnabled = $false
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region *-Module cmdlets
|
|
function Publish-Module
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(SupportsShouldProcess=$true,
|
|
PositionalBinding=$false,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkID=398575',
|
|
DefaultParameterSetName="ModuleNameParameterSet")]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
ParameterSetName="ModuleNameParameterSet",
|
|
ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Name,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ParameterSetName="ModulePathParameterSet",
|
|
ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Path,
|
|
|
|
[Parameter(ParameterSetName="ModuleNameParameterSet")]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$NuGetApiKey,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Repository = $Script:PSGalleryModuleSource,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
[ValidateSet("1.0")]
|
|
[Version]
|
|
$FormatVersion,
|
|
|
|
[Parameter()]
|
|
[string[]]
|
|
$ReleaseNotes,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Tags,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$LicenseUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$IconUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$ProjectUri,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
Begin
|
|
{
|
|
if($script:isNanoServer) {
|
|
$message = $LocalizedData.PublishPSArtifactUnsupportedOnNano -f "Module"
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PublishModuleIsNotSupportedOnNanoServer" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
|
|
Get-PSGalleryApiAvailability -Repository $Repository
|
|
|
|
if($LicenseUri -and -not (Test-WebUri -uri $LicenseUri))
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($LicenseUri, "LicenseUri")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $LicenseUri
|
|
}
|
|
|
|
if($IconUri -and -not (Test-WebUri -uri $IconUri))
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($IconUri, "IconUri")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $IconUri
|
|
}
|
|
|
|
if($ProjectUri -and -not (Test-WebUri -uri $ProjectUri))
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($ProjectUri, "ProjectUri")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $ProjectUri
|
|
}
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -BootstrapNuGetExe -Force:$Force
|
|
}
|
|
|
|
Process
|
|
{
|
|
if($Repository -eq $Script:PSGalleryModuleSource)
|
|
{
|
|
$moduleSource = Get-PSRepository -Name $Repository -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
|
|
if(-not $moduleSource)
|
|
{
|
|
$message = $LocalizedData.PSGalleryNotFound -f ($Repository)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'PSGalleryNotFound' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Repository
|
|
return
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$ev = $null
|
|
$moduleSource = Get-PSRepository -Name $Repository -ErrorVariable ev
|
|
if($ev) { return }
|
|
}
|
|
|
|
$DestinationLocation = $moduleSource.PublishLocation
|
|
|
|
if(-not $DestinationLocation -or
|
|
(-not (Microsoft.PowerShell.Management\Test-Path $DestinationLocation) -and
|
|
-not (Test-WebUri -uri $DestinationLocation)))
|
|
|
|
{
|
|
$message = $LocalizedData.PSGalleryPublishLocationIsMissing -f ($Repository, $Repository)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PSGalleryPublishLocationIsMissing" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Repository
|
|
}
|
|
|
|
$message = $LocalizedData.PublishLocation -f ($DestinationLocation)
|
|
Write-Verbose -Message $message
|
|
|
|
if(-not $NuGetApiKey.Trim())
|
|
{
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $DestinationLocation)
|
|
{
|
|
$NuGetApiKey = "$(Get-Random)"
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.NuGetApiKeyIsRequiredForNuGetBasedGalleryService -f ($Repository, $DestinationLocation)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "NuGetApiKeyIsRequiredForNuGetBasedGalleryService" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
|
|
$providerName = Get-ProviderName -PSCustomObject $moduleSource
|
|
if($providerName -ne $script:NuGetProviderName)
|
|
{
|
|
$message = $LocalizedData.PublishModuleSupportsOnlyNuGetBasedPublishLocations -f ($moduleSource.PublishLocation, $Repository, $Repository)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PublishModuleSupportsOnlyNuGetBasedPublishLocations" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Repository
|
|
}
|
|
|
|
$moduleName = $null
|
|
|
|
if($Name)
|
|
{
|
|
$module = Microsoft.PowerShell.Core\Get-Module -ListAvailable -Name $Name -Verbose:$false |
|
|
Microsoft.PowerShell.Core\Where-Object {-not $RequiredVersion -or ($RequiredVersion -eq $_.Version)}
|
|
|
|
if(-not $module)
|
|
{
|
|
if($RequiredVersion)
|
|
{
|
|
$message = $LocalizedData.ModuleWithRequiredVersionNotAvailableLocally -f ($Name, $RequiredVersion)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.ModuleNotAvailableLocally -f ($Name)
|
|
}
|
|
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "ModuleNotAvailableLocallyToPublish" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Name
|
|
|
|
}
|
|
elseif($module.GetType().ToString() -ne "System.Management.Automation.PSModuleInfo")
|
|
{
|
|
$message = $LocalizedData.AmbiguousModuleName -f ($Name)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "AmbiguousModuleNameToPublish" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Name
|
|
}
|
|
|
|
$moduleName = $module.Name
|
|
$Path = $module.ModuleBase
|
|
}
|
|
else
|
|
{
|
|
$resolvedPath = Resolve-PathHelper -Path $Path -CallerPSCmdlet $PSCmdlet | Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $resolvedPath -or
|
|
-not (Microsoft.PowerShell.Management\Test-Path -Path $resolvedPath -PathType Container))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage ($LocalizedData.PathIsNotADirectory -f ($Path)) `
|
|
-ErrorId "PathIsNotADirectory" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Path
|
|
return
|
|
}
|
|
|
|
$moduleName = Microsoft.PowerShell.Management\Split-Path -Path $resolvedPath -Leaf
|
|
$modulePathWithVersion = $false
|
|
|
|
# if the Leaf of the $resolvedPath is a version, use its parent folder name as the module name
|
|
$ModuleVersion = New-Object System.Version
|
|
if([System.Version]::TryParse($moduleName, ([ref]$ModuleVersion)))
|
|
{
|
|
$moduleName = Microsoft.PowerShell.Management\Split-Path -Path (Microsoft.PowerShell.Management\Split-Path $resolvedPath -Parent) -Leaf
|
|
$modulePathWithVersion = $true
|
|
}
|
|
|
|
$manifestPath = Join-Path -Path $resolvedPath -ChildPath "$moduleName.psd1"
|
|
$module = $null
|
|
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $manifestPath -PathType Leaf)
|
|
{
|
|
$ev = $null
|
|
$module = Microsoft.PowerShell.Core\Test-ModuleManifest -Path $manifestPath `
|
|
-ErrorVariable ev `
|
|
-Verbose:$VerbosePreference
|
|
if($ev)
|
|
{
|
|
# Above Test-ModuleManifest cmdlet should write an errors to the Errors stream and Console.
|
|
return
|
|
}
|
|
}
|
|
elseif(-not $modulePathWithVersion -and ($PSVersionTable.PSVersion -ge [Version]'5.0'))
|
|
{
|
|
$module = Microsoft.PowerShell.Core\Get-Module -Name $resolvedPath -ListAvailable -ErrorAction SilentlyContinue -Verbose:$false
|
|
}
|
|
|
|
if(-not $module)
|
|
{
|
|
$message = $LocalizedData.InvalidModulePathToPublish -f ($Path)
|
|
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'InvalidModulePathToPublish' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Path
|
|
}
|
|
elseif($module.GetType().ToString() -ne "System.Management.Automation.PSModuleInfo")
|
|
{
|
|
$message = $LocalizedData.AmbiguousModulePath -f ($Path)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'AmbiguousModulePathToPublish' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Path
|
|
}
|
|
|
|
if($module -and (-not $module.Path.EndsWith('.psd1', [System.StringComparison]::OrdinalIgnoreCase)))
|
|
{
|
|
$message = $LocalizedData.InvalidModuleToPublish -f ($module.Name)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidModuleToPublish" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $module.Name
|
|
}
|
|
|
|
$moduleName = $module.Name
|
|
$Path = $module.ModuleBase
|
|
}
|
|
|
|
$message = $LocalizedData.PublishModuleLocation -f ($moduleName, $Path)
|
|
Write-Verbose -Message $message
|
|
|
|
#If users are providing tags using -Tags while running PS 5.0, will show warning messages
|
|
if($Tags)
|
|
{
|
|
$message = $LocalizedData.TagsShouldBeIncludedInManifestFile -f ($moduleName, $Path)
|
|
Write-Warning $message
|
|
}
|
|
|
|
if($ReleaseNotes)
|
|
{
|
|
$message = $LocalizedData.ReleaseNotesShouldBeIncludedInManifestFile -f ($moduleName, $Path)
|
|
Write-Warning $message
|
|
}
|
|
|
|
if($LicenseUri)
|
|
{
|
|
$message = $LocalizedData.LicenseUriShouldBeIncludedInManifestFile -f ($moduleName, $Path)
|
|
Write-Warning $message
|
|
}
|
|
|
|
if($IconUri)
|
|
{
|
|
$message = $LocalizedData.IconUriShouldBeIncludedInManifestFile -f ($moduleName, $Path)
|
|
Write-Warning $message
|
|
}
|
|
|
|
if($ProjectUri)
|
|
{
|
|
$message = $LocalizedData.ProjectUriShouldBeIncludedInManifestFile -f ($moduleName, $Path)
|
|
Write-Warning $message
|
|
}
|
|
|
|
|
|
# Copy the source module to temp location to publish
|
|
$tempModulePath = Microsoft.PowerShell.Management\Join-Path -Path $script:TempPath `
|
|
-ChildPath "$(Microsoft.PowerShell.Utility\Get-Random)\$moduleName"
|
|
|
|
if(-not $FormatVersion)
|
|
{
|
|
$tempModulePathForFormatVersion = $tempModulePath
|
|
}
|
|
elseif ($FormatVersion -eq "1.0")
|
|
{
|
|
$tempModulePathForFormatVersion = Microsoft.PowerShell.Management\Join-Path $tempModulePath "Content\Deployment\$script:ModuleReferences\$moduleName"
|
|
}
|
|
|
|
$null = Microsoft.PowerShell.Management\New-Item -Path $tempModulePathForFormatVersion -ItemType Directory -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
Microsoft.PowerShell.Management\Copy-Item -Path "$Path\*" -Destination $tempModulePathForFormatVersion -Force -Recurse -Confirm:$false -WhatIf:$false
|
|
|
|
try
|
|
{
|
|
$manifestPath = Microsoft.PowerShell.Management\Join-Path $tempModulePathForFormatVersion "$moduleName.psd1"
|
|
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path $manifestPath))
|
|
{
|
|
$message = $LocalizedData.InvalidModuleToPublish -f ($moduleName)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidModuleToPublish" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $moduleName
|
|
}
|
|
|
|
$ev = $null
|
|
$moduleInfo = Microsoft.PowerShell.Core\Test-ModuleManifest -Path $manifestPath `
|
|
-ErrorVariable ev `
|
|
-Verbose:$VerbosePreference
|
|
if($ev)
|
|
{
|
|
# Above Test-ModuleManifest cmdlet should write an errors to the Errors stream and Console.
|
|
return
|
|
}
|
|
|
|
if(-not $moduleInfo -or
|
|
-not $moduleInfo.Author -or
|
|
-not $moduleInfo.Description)
|
|
{
|
|
$message = $LocalizedData.MissingRequiredManifestKeys -f ($moduleName)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "MissingRequiredModuleManifestKeys" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $moduleName
|
|
}
|
|
|
|
$FindParameters = @{
|
|
Name = $moduleName
|
|
Repository = $Repository
|
|
Tag = 'PSScript'
|
|
Verbose = $VerbosePreference
|
|
ErrorAction = 'SilentlyContinue'
|
|
WarningAction = 'SilentlyContinue'
|
|
Debug = $DebugPreference
|
|
}
|
|
|
|
if($Credential)
|
|
{
|
|
$FindParameters[$script:Credential] = $Credential
|
|
}
|
|
|
|
# Check if the specified module name is already used for a script on the specified repository
|
|
# Use Find-Script to check if that name is already used as scriptname
|
|
$scriptPSGetItemInfo = Find-Script @FindParameters |
|
|
Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $moduleName} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Last 1
|
|
if($scriptPSGetItemInfo)
|
|
{
|
|
$message = $LocalizedData.SpecifiedNameIsAlearyUsed -f ($moduleName, $Repository, 'Find-Script')
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "SpecifiedNameIsAlearyUsed" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $moduleName
|
|
}
|
|
|
|
$null = $FindParameters.Remove('Tag')
|
|
$currentPSGetItemInfo = Find-Module @FindParameters |
|
|
Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $moduleInfo.Name} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Last 1
|
|
|
|
if($currentPSGetItemInfo)
|
|
{
|
|
if($currentPSGetItemInfo.Version -eq $moduleInfo.Version)
|
|
{
|
|
$message = $LocalizedData.ModuleVersionIsAlreadyAvailableInTheGallery -f ($moduleInfo.Name, $moduleInfo.Version, $currentPSGetItemInfo.Version, $currentPSGetItemInfo.RepositorySourceLocation)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'ModuleVersionIsAlreadyAvailableInTheGallery' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
elseif(-not $Force -and ($currentPSGetItemInfo.Version -gt $moduleInfo.Version))
|
|
{
|
|
$message = $LocalizedData.ModuleVersionShouldBeGreaterThanGalleryVersion -f ($moduleInfo.Name, $moduleInfo.Version, $currentPSGetItemInfo.Version, $currentPSGetItemInfo.RepositorySourceLocation)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "ModuleVersionShouldBeGreaterThanGalleryVersion" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
}
|
|
|
|
$shouldProcessMessage = $LocalizedData.PublishModulewhatIfMessage -f ($moduleInfo.Version, $moduleInfo.Name)
|
|
if($Force -or $PSCmdlet.ShouldProcess($shouldProcessMessage, "Publish-Module"))
|
|
{
|
|
Publish-PSArtifactUtility -PSModuleInfo $moduleInfo `
|
|
-ManifestPath $manifestPath `
|
|
-NugetApiKey $NuGetApiKey `
|
|
-Destination $DestinationLocation `
|
|
-Repository $Repository `
|
|
-NugetPackageRoot $tempModulePath `
|
|
-FormatVersion $FormatVersion `
|
|
-ReleaseNotes $($ReleaseNotes -join "`r`n") `
|
|
-Tags $Tags `
|
|
-LicenseUri $LicenseUri `
|
|
-IconUri $IconUri `
|
|
-ProjectUri $ProjectUri `
|
|
-Verbose:$VerbosePreference `
|
|
-WarningAction $WarningPreference `
|
|
-ErrorAction $ErrorActionPreference `
|
|
-Debug:$DebugPreference
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item $tempModulePath -Force -Recurse -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
}
|
|
}
|
|
|
|
function Find-Module
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri='http://go.microsoft.com/fwlink/?LinkID=398574')]
|
|
[outputtype("PSCustomObject[]")]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Position=0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$AllVersions,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$IncludeDependencies,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string]
|
|
$Filter,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$Tag,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[ValidateSet('DscResource','Cmdlet','Function','RoleCapability')]
|
|
[string[]]
|
|
$Includes,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$DscResource,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$RoleCapability,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$Command,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Repository
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
}
|
|
|
|
Process
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion `
|
|
-AllVersions:$AllVersions
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeModule
|
|
|
|
if($PSBoundParameters.ContainsKey("Repository"))
|
|
{
|
|
$PSBoundParameters["Source"] = $Repository
|
|
$null = $PSBoundParameters.Remove("Repository")
|
|
|
|
$ev = $null
|
|
$null = Get-PSRepository -Name $Repository -ErrorVariable ev -verbose:$false
|
|
if($ev) { return }
|
|
}
|
|
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlock
|
|
|
|
$modulesFoundInPSGallery = @()
|
|
|
|
# No Telemetry must be performed if PSGallery is not in the supplied list of Repositories
|
|
$isRepositoryNullOrPSGallerySpecified = $false
|
|
if ($Repository -and ($Repository -Contains $Script:PSGalleryModuleSource))
|
|
{
|
|
$isRepositoryNullOrPSGallerySpecified = $true
|
|
}
|
|
elseif(-not $Repository)
|
|
{
|
|
$psgalleryRepo = Get-PSRepository -Name $Script:PSGalleryModuleSource `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
if($psgalleryRepo)
|
|
{
|
|
$isRepositoryNullOrPSGallerySpecified = $true
|
|
}
|
|
}
|
|
|
|
PackageManagement\Find-Package @PSBoundParameters | Microsoft.PowerShell.Core\ForEach-Object {
|
|
|
|
$psgetItemInfo = New-PSGetItemInfo -SoftwareIdentity $_ -Type $script:PSArtifactTypeModule
|
|
|
|
$psgetItemInfo
|
|
|
|
if ($psgetItemInfo -and
|
|
$isRepositoryNullOrPSGallerySpecified -and
|
|
$script:TelemetryEnabled -and
|
|
($psgetItemInfo.Repository -eq $Script:PSGalleryModuleSource))
|
|
{
|
|
$modulesFoundInPSGallery += $psgetItemInfo.Name
|
|
}
|
|
}
|
|
|
|
# Perform Telemetry if Repository is not supplied or Repository contains PSGallery
|
|
# We are only interested in finding modules not in PSGallery
|
|
if ($isRepositoryNullOrPSGallerySpecified)
|
|
{
|
|
Log-ArtifactNotFoundInPSGallery -SearchedName $Name -FoundName $modulesFoundInPSGallery -operationName 'PSGET_FIND_MODULE'
|
|
}
|
|
}
|
|
}
|
|
|
|
function Save-Module
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(DefaultParameterSetName='NameAndPathParameterSet',
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=531351',
|
|
SupportsShouldProcess=$true)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipeline=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='InputOjectAndPathParameterSet')]
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipeline=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='InputOjectAndLiteralPathParameterSet')]
|
|
[ValidateNotNull()]
|
|
[PSCustomObject[]]
|
|
$InputObject,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository,
|
|
|
|
[Parameter(Mandatory=$true, ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(Mandatory=$true, ParameterSetName='InputOjectAndPathParameterSet')]
|
|
[string]
|
|
$Path,
|
|
|
|
[Parameter(Mandatory=$true, ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[Parameter(Mandatory=$true, ParameterSetName='InputOjectAndLiteralPathParameterSet')]
|
|
[string]
|
|
$LiteralPath,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Repository
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
# Module names already tried in the current pipeline for InputObject parameterset
|
|
$moduleNamesInPipeline = @()
|
|
}
|
|
|
|
Process
|
|
{
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementSaveModuleMessageResolverScriptBlock
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeModule
|
|
|
|
# When -Force is specified, Path will be created if not available.
|
|
if(-not $Force)
|
|
{
|
|
if($Path)
|
|
{
|
|
$destinationPath = Resolve-PathHelper -Path $Path -CallerPSCmdlet $PSCmdlet | Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $destinationPath -or -not (Microsoft.PowerShell.Management\Test-path $destinationPath))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $Path)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $Path `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
$PSBoundParameters['Path'] = $destinationPath
|
|
}
|
|
else
|
|
{
|
|
$destinationPath = Resolve-PathHelper -Path $LiteralPath -IsLiteralPath -CallerPSCmdlet $PSCmdlet | Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $destinationPath -or -not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $destinationPath))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $LiteralPath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $LiteralPath `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
$PSBoundParameters['LiteralPath'] = $destinationPath
|
|
}
|
|
}
|
|
|
|
if($Name)
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-TestWildcardsInName `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
if($PSBoundParameters.ContainsKey("Repository"))
|
|
{
|
|
$PSBoundParameters["Source"] = $Repository
|
|
$null = $PSBoundParameters.Remove("Repository")
|
|
|
|
$ev = $null
|
|
$null = Get-PSRepository -Name $Repository -ErrorVariable ev -verbose:$false
|
|
if($ev) { return }
|
|
}
|
|
|
|
$null = PackageManagement\Save-Package @PSBoundParameters
|
|
}
|
|
elseif($InputObject)
|
|
{
|
|
$null = $PSBoundParameters.Remove("InputObject")
|
|
|
|
foreach($inputValue in $InputObject)
|
|
{
|
|
if (($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSRepositoryItemInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSRepositoryItemInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSGetCommandInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSGetCommandInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSGetDscResourceInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSGetDscResourceInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo"))
|
|
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.InvalidInputObjectValue `
|
|
-ErrorId "InvalidInputObjectValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $inputValue
|
|
}
|
|
|
|
if( ($inputValue.PSTypeNames -contains "Microsoft.PowerShell.Commands.PSGetDscResourceInfo") -or
|
|
($inputValue.PSTypeNames -contains "Deserialized.Microsoft.PowerShell.Commands.PSGetDscResourceInfo") -or
|
|
($inputValue.PSTypeNames -contains "Microsoft.PowerShell.Commands.PSGetCommandInfo") -or
|
|
($inputValue.PSTypeNames -contains "Deserialized.Microsoft.PowerShell.Commands.PSGetCommandInfo") -or
|
|
($inputValue.PSTypeNames -contains "Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo") -or
|
|
($inputValue.PSTypeNames -contains "Deserialized.Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo"))
|
|
{
|
|
$psgetModuleInfo = $inputValue.PSGetModuleInfo
|
|
}
|
|
else
|
|
{
|
|
$psgetModuleInfo = $inputValue
|
|
}
|
|
|
|
# Skip the module name if it is already tried in the current pipeline
|
|
if($moduleNamesInPipeline -contains $psgetModuleInfo.Name)
|
|
{
|
|
continue
|
|
}
|
|
|
|
$moduleNamesInPipeline += $psgetModuleInfo.Name
|
|
|
|
if ($psgetModuleInfo.PowerShellGetFormatVersion -and
|
|
($script:SupportedPSGetFormatVersionMajors -notcontains $psgetModuleInfo.PowerShellGetFormatVersion.Major))
|
|
{
|
|
$message = $LocalizedData.NotSupportedPowerShellGetFormatVersion -f ($psgetModuleInfo.Name, $psgetModuleInfo.PowerShellGetFormatVersion, $psgetModuleInfo.Name)
|
|
Write-Error -Message $message -ErrorId "NotSupportedPowerShellGetFormatVersion" -Category InvalidOperation
|
|
continue
|
|
}
|
|
|
|
$PSBoundParameters["Name"] = $psgetModuleInfo.Name
|
|
$PSBoundParameters["RequiredVersion"] = $psgetModuleInfo.Version
|
|
$PSBoundParameters['Source'] = $psgetModuleInfo.Repository
|
|
$PSBoundParameters["PackageManagementProvider"] = (Get-ProviderName -PSCustomObject $psgetModuleInfo)
|
|
|
|
$null = PackageManagement\Save-Package @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Install-Module
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(DefaultParameterSetName='NameParameterSet',
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkID=398573',
|
|
SupportsShouldProcess=$true)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipeline=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='InputObject')]
|
|
[ValidateNotNull()]
|
|
[PSCustomObject[]]
|
|
$InputObject,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
[ValidateSet("CurrentUser","AllUsers")]
|
|
[string]
|
|
$Scope = "AllUsers",
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$AllowClobber,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$SkipPublisherCheck,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Repository
|
|
|
|
if(-not (Test-RunningAsElevated) -and ($Scope -ne "CurrentUser"))
|
|
{
|
|
# Throw an error when Install-Module is used as a non-admin user and '-Scope CurrentUser' is not specified
|
|
$message = $LocalizedData.InstallModuleNeedsCurrentUserScopeParameterForNonAdminUser -f @($script:programFilesModulesPath, $script:MyDocumentsModulesPath)
|
|
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InstallModuleNeedsCurrentUserScopeParameterForNonAdminUser" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
# Module names already tried in the current pipeline for InputObject parameterset
|
|
$moduleNamesInPipeline = @()
|
|
$YesToAll = $false
|
|
$NoToAll = $false
|
|
$SourceSGrantedTrust = @()
|
|
$SourcesDeniedTrust = @()
|
|
}
|
|
|
|
Process
|
|
{
|
|
$RepositoryIsNotTrusted = $LocalizedData.RepositoryIsNotTrusted
|
|
$QueryInstallUntrustedPackage = $LocalizedData.QueryInstallUntrustedPackage
|
|
$PackageTarget = $LocalizedData.InstallModulewhatIfMessage
|
|
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementInstallModuleMessageResolverScriptBlock
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeModule
|
|
$PSBoundParameters['Scope'] = $Scope
|
|
|
|
if($PSCmdlet.ParameterSetName -eq "NameParameterSet")
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-TestWildcardsInName `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
if($PSBoundParameters.ContainsKey("Repository"))
|
|
{
|
|
$PSBoundParameters["Source"] = $Repository
|
|
$null = $PSBoundParameters.Remove("Repository")
|
|
|
|
$ev = $null
|
|
$null = Get-PSRepository -Name $Repository -ErrorVariable ev -verbose:$false
|
|
if($ev) { return }
|
|
}
|
|
|
|
$null = PackageManagement\Install-Package @PSBoundParameters
|
|
}
|
|
elseif($PSCmdlet.ParameterSetName -eq "InputObject")
|
|
{
|
|
$null = $PSBoundParameters.Remove("InputObject")
|
|
|
|
foreach($inputValue in $InputObject)
|
|
{
|
|
if (($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSRepositoryItemInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSRepositoryItemInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSGetCommandInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSGetCommandInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSGetDscResourceInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSGetDscResourceInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo"))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.InvalidInputObjectValue `
|
|
-ErrorId "InvalidInputObjectValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $inputValue
|
|
}
|
|
|
|
if( ($inputValue.PSTypeNames -contains "Microsoft.PowerShell.Commands.PSGetDscResourceInfo") -or
|
|
($inputValue.PSTypeNames -contains "Deserialized.Microsoft.PowerShell.Commands.PSGetDscResourceInfo") -or
|
|
($inputValue.PSTypeNames -contains "Microsoft.PowerShell.Commands.PSGetCommandInfo") -or
|
|
($inputValue.PSTypeNames -contains "Deserialized.Microsoft.PowerShell.Commands.PSGetCommandInfo") -or
|
|
($inputValue.PSTypeNames -contains "Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo") -or
|
|
($inputValue.PSTypeNames -contains "Deserialized.Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo"))
|
|
{
|
|
$psgetModuleInfo = $inputValue.PSGetModuleInfo
|
|
}
|
|
else
|
|
{
|
|
$psgetModuleInfo = $inputValue
|
|
}
|
|
|
|
# Skip the module name if it is already tried in the current pipeline
|
|
if($moduleNamesInPipeline -contains $psgetModuleInfo.Name)
|
|
{
|
|
continue
|
|
}
|
|
|
|
$moduleNamesInPipeline += $psgetModuleInfo.Name
|
|
|
|
if ($psgetModuleInfo.PowerShellGetFormatVersion -and
|
|
($script:SupportedPSGetFormatVersionMajors -notcontains $psgetModuleInfo.PowerShellGetFormatVersion.Major))
|
|
{
|
|
$message = $LocalizedData.NotSupportedPowerShellGetFormatVersion -f ($psgetModuleInfo.Name, $psgetModuleInfo.PowerShellGetFormatVersion, $psgetModuleInfo.Name)
|
|
Write-Error -Message $message -ErrorId "NotSupportedPowerShellGetFormatVersion" -Category InvalidOperation
|
|
continue
|
|
}
|
|
|
|
$PSBoundParameters["Name"] = $psgetModuleInfo.Name
|
|
$PSBoundParameters["RequiredVersion"] = $psgetModuleInfo.Version
|
|
$PSBoundParameters['Source'] = $psgetModuleInfo.Repository
|
|
$PSBoundParameters["PackageManagementProvider"] = (Get-ProviderName -PSCustomObject $psgetModuleInfo)
|
|
|
|
#Check if module is already installed
|
|
$InstalledModuleInfo = Test-ModuleInstalled -Name $psgetModuleInfo.Name -RequiredVersion $psgetModuleInfo.Version
|
|
if(-not $Force -and $InstalledModuleInfo -ne $null)
|
|
{
|
|
$message = $LocalizedData.ModuleAlreadyInstalledVerbose -f ($InstalledModuleInfo.Version, $InstalledModuleInfo.Name, $InstalledModuleInfo.ModuleBase)
|
|
Write-Verbose -Message $message
|
|
}
|
|
else
|
|
{
|
|
$source = $psgetModuleInfo.Repository
|
|
$installationPolicy = (Get-PSRepository -Name $source).InstallationPolicy
|
|
$ShouldProcessMessage = $PackageTarget -f ($psgetModuleInfo.Name, $psgetModuleInfo.Version)
|
|
|
|
if($psCmdlet.ShouldProcess($ShouldProcessMessage))
|
|
{
|
|
if($installationPolicy.Equals("Untrusted", [StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
if(-not($YesToAll -or $NoToAll -or $SourceSGrantedTrust.Contains($source) -or $sourcesDeniedTrust.Contains($source) -or $Force))
|
|
{
|
|
$message = $QueryInstallUntrustedPackage -f ($psgetModuleInfo.Name, $psgetModuleInfo.RepositorySourceLocation)
|
|
if($PSVersionTable.PSVersion -ge [Version]"5.0")
|
|
{
|
|
$sourceTrusted = $psCmdlet.ShouldContinue("$message", "$RepositoryIsNotTrusted",$true, [ref]$YesToAll, [ref]$NoToAll)
|
|
}
|
|
else
|
|
{
|
|
$sourceTrusted = $psCmdlet.ShouldContinue("$message", "$RepositoryIsNotTrusted", [ref]$YesToAll, [ref]$NoToAll)
|
|
}
|
|
|
|
if($sourceTrusted)
|
|
{
|
|
$SourceSGrantedTrust+=$source
|
|
}
|
|
else
|
|
{
|
|
$SourcesDeniedTrust+=$source
|
|
}
|
|
}
|
|
}
|
|
|
|
if($installationPolicy.Equals("trusted", [StringComparison]::OrdinalIgnoreCase) -or $SourceSGrantedTrust.Contains($source) -or $YesToAll -or $Force)
|
|
{
|
|
$PSBoundParameters["Force"] = $true
|
|
$null = PackageManagement\Install-Package @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Update-Module
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(SupportsShouldProcess=$true,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkID=398576')]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Position=0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$Name,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$Force
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
# Module names already tried in the current pipeline
|
|
$moduleNamesInPipeline = @()
|
|
}
|
|
|
|
Process
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
$GetPackageParameters = @{}
|
|
$GetPackageParameters[$script:PSArtifactType] = $script:PSArtifactTypeModule
|
|
$GetPackageParameters["Provider"] = $script:PSModuleProviderName
|
|
$GetPackageParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlock
|
|
$GetPackageParameters['ErrorAction'] = 'SilentlyContinue'
|
|
$GetPackageParameters['WarningAction'] = 'SilentlyContinue'
|
|
|
|
$PSGetItemInfos = @()
|
|
|
|
if($Name)
|
|
{
|
|
foreach($moduleName in $Name)
|
|
{
|
|
$GetPackageParameters['Name'] = $moduleName
|
|
$installedPackages = PackageManagement\Get-Package @GetPackageParameters
|
|
|
|
if(-not $installedPackages -and -not (Test-WildcardPattern -Name $moduleName))
|
|
{
|
|
$availableModules = Get-Module -ListAvailable $moduleName -Verbose:$false | Microsoft.PowerShell.Utility\Select-Object -Unique
|
|
|
|
if(-not $availableModules)
|
|
{
|
|
$message = $LocalizedData.ModuleNotInstalledOnThisMachine -f ($moduleName)
|
|
Write-Error -Message $message -ErrorId 'ModuleNotInstalledOnThisMachine' -Category InvalidOperation -TargetObject $moduleName
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.ModuleNotInstalledUsingPowerShellGet -f ($moduleName)
|
|
Write-Error -Message $message -ErrorId 'ModuleNotInstalledUsingInstallModuleCmdlet' -Category InvalidOperation -TargetObject $moduleName
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
$installedPackages |
|
|
Microsoft.PowerShell.Core\ForEach-Object {New-PSGetItemInfo -SoftwareIdentity $_ -Type $script:PSArtifactTypeModule} |
|
|
Microsoft.PowerShell.Core\ForEach-Object {
|
|
if(-not (Test-RunningAsElevated) -and $_.InstalledLocation.StartsWith($script:programFilesModulesPath, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
if(-not (Test-WildcardPattern -Name $moduleName))
|
|
{
|
|
$message = $LocalizedData.AdminPrivilegesRequiredForUpdate -f ($_.Name, $_.InstalledLocation)
|
|
Write-Error -Message $message -ErrorId "AdminPrivilegesAreRequiredForUpdate" -Category InvalidOperation -TargetObject $moduleName
|
|
}
|
|
continue
|
|
}
|
|
|
|
$PSGetItemInfos += $_
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
$PSGetItemInfos = PackageManagement\Get-Package @GetPackageParameters |
|
|
Microsoft.PowerShell.Core\ForEach-Object {New-PSGetItemInfo -SoftwareIdentity $_ -Type $script:PSArtifactTypeModule} |
|
|
Microsoft.PowerShell.Core\Where-Object {
|
|
(Test-RunningAsElevated) -or
|
|
$_.InstalledLocation.StartsWith($script:MyDocumentsModulesPath, [System.StringComparison]::OrdinalIgnoreCase)
|
|
}
|
|
}
|
|
|
|
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementUpdateModuleMessageResolverScriptBlock
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeModule
|
|
|
|
foreach($psgetItemInfo in $PSGetItemInfos)
|
|
{
|
|
# Skip the module name if it is already tried in the current pipeline
|
|
if($moduleNamesInPipeline -contains $psgetItemInfo.Name)
|
|
{
|
|
continue
|
|
}
|
|
|
|
$moduleNamesInPipeline += $psgetItemInfo.Name
|
|
|
|
$message = $LocalizedData.CheckingForModuleUpdate -f ($psgetItemInfo.Name)
|
|
Write-Verbose -Message $message
|
|
|
|
$providerName = Get-ProviderName -PSCustomObject $psgetItemInfo
|
|
if(-not $providerName)
|
|
{
|
|
$providerName = $script:NuGetProviderName
|
|
}
|
|
|
|
$PSBoundParameters["Name"] = $psgetItemInfo.Name
|
|
$PSBoundParameters['Source'] = $psgetItemInfo.Repository
|
|
|
|
Get-PSGalleryApiAvailability -Repository (Get-SourceName -Location $psgetItemInfo.RepositorySourceLocation)
|
|
|
|
$PSBoundParameters["PackageManagementProvider"] = $providerName
|
|
$PSBoundParameters["InstallUpdate"] = $true
|
|
|
|
if($psgetItemInfo.InstalledLocation.ToString().StartsWith($script:MyDocumentsModulesPath, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$PSBoundParameters["Scope"] = "CurrentUser"
|
|
}
|
|
else
|
|
{
|
|
$PSBoundParameters['Scope'] = 'AllUsers'
|
|
}
|
|
|
|
$sid = PackageManagement\Install-Package @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
|
|
function Uninstall-Module
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(DefaultParameterSetName='NameParameterSet',
|
|
SupportsShouldProcess=$true,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=526864')]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Mandatory=$true,
|
|
Position=0,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$Name,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipeline=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='InputObject')]
|
|
[ValidateNotNull()]
|
|
[PSCustomObject[]]
|
|
$InputObject,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ParameterSetName='NameParameterSet')]
|
|
[switch]
|
|
$AllVersions,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$Force
|
|
)
|
|
|
|
Process
|
|
{
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementUnInstallModuleMessageResolverScriptBlock
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeModule
|
|
|
|
if($PSCmdlet.ParameterSetName -eq "InputObject")
|
|
{
|
|
$null = $PSBoundParameters.Remove("InputObject")
|
|
|
|
foreach($inputValue in $InputObject)
|
|
{
|
|
if (($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSRepositoryItemInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSRepositoryItemInfo"))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.InvalidInputObjectValue `
|
|
-ErrorId "InvalidInputObjectValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $inputValue
|
|
}
|
|
|
|
$PSBoundParameters["Name"] = $inputValue.Name
|
|
$PSBoundParameters["RequiredVersion"] = $inputValue.Version
|
|
|
|
$null = PackageManagement\Uninstall-Package @PSBoundParameters
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-TestWildcardsInName `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion `
|
|
-AllVersions:$AllVersions
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
$null = PackageManagement\Uninstall-Package @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
|
|
function Get-InstalledModule
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri='http://go.microsoft.com/fwlink/?LinkId=526863')]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Position=0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$Name,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$AllVersions
|
|
)
|
|
|
|
Process
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion `
|
|
-AllVersions:$AllVersions
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlock
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeModule
|
|
|
|
PackageManagement\Get-Package @PSBoundParameters | Microsoft.PowerShell.Core\ForEach-Object {New-PSGetItemInfo -SoftwareIdentity $_ -Type $script:PSArtifactTypeModule}
|
|
}
|
|
}
|
|
|
|
#endregion *-Module cmdlets
|
|
|
|
#region Find-DscResouce cmdlet
|
|
|
|
function Find-DscResource
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri = 'http://go.microsoft.com/fwlink/?LinkId=517196')]
|
|
[outputtype('PSCustomObject[]')]
|
|
Param
|
|
(
|
|
[Parameter(Position = 0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$ModuleName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$AllVersions,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$Tag,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string]
|
|
$Filter,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository
|
|
)
|
|
|
|
|
|
Process
|
|
{
|
|
$PSBoundParameters['Includes'] = 'DscResource'
|
|
|
|
if($PSBoundParameters.ContainsKey('Name'))
|
|
{
|
|
$PSBoundParameters['DscResource'] = $Name
|
|
$null = $PSBoundParameters.Remove('Name')
|
|
}
|
|
|
|
if($PSBoundParameters.ContainsKey('ModuleName'))
|
|
{
|
|
$PSBoundParameters['Name'] = $ModuleName
|
|
$null = $PSBoundParameters.Remove('ModuleName')
|
|
}
|
|
|
|
PowerShellGet\Find-Module @PSBoundParameters |
|
|
Microsoft.PowerShell.Core\ForEach-Object {
|
|
$psgetModuleInfo = $_
|
|
$psgetModuleInfo.Includes.DscResource | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if($Name -and ($Name -notcontains $_))
|
|
{
|
|
return
|
|
}
|
|
|
|
$psgetDscResourceInfo = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
|
|
Name = $_
|
|
Version = $psgetModuleInfo.Version
|
|
ModuleName = $psgetModuleInfo.Name
|
|
Repository = $psgetModuleInfo.Repository
|
|
PSGetModuleInfo = $psgetModuleInfo
|
|
})
|
|
|
|
$psgetDscResourceInfo.PSTypeNames.Insert(0, 'Microsoft.PowerShell.Commands.PSGetDscResourceInfo')
|
|
$psgetDscResourceInfo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Find-DscResouce cmdlet
|
|
|
|
#region Find-Command cmdlet
|
|
|
|
function Find-Command
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri = 'http://go.microsoft.com/fwlink/?LinkId=733636')]
|
|
[outputtype('PSCustomObject[]')]
|
|
Param
|
|
(
|
|
[Parameter(Position = 0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$ModuleName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$AllVersions,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$Tag,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string]
|
|
$Filter,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository
|
|
)
|
|
|
|
|
|
Process
|
|
{
|
|
if($PSBoundParameters.ContainsKey('Name'))
|
|
{
|
|
$PSBoundParameters['Command'] = $Name
|
|
$null = $PSBoundParameters.Remove('Name')
|
|
}
|
|
else
|
|
{
|
|
$PSBoundParameters['Includes'] = @('Cmdlet','Function')
|
|
}
|
|
|
|
if($PSBoundParameters.ContainsKey('ModuleName'))
|
|
{
|
|
$PSBoundParameters['Name'] = $ModuleName
|
|
$null = $PSBoundParameters.Remove('ModuleName')
|
|
}
|
|
|
|
PowerShellGet\Find-Module @PSBoundParameters |
|
|
Microsoft.PowerShell.Core\ForEach-Object {
|
|
$psgetModuleInfo = $_
|
|
$psgetModuleInfo.Includes.Command | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if(($_ -eq "*") -or ($Name -and ($Name -notcontains $_)))
|
|
{
|
|
return
|
|
}
|
|
|
|
$psgetCommandInfo = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
|
|
Name = $_
|
|
Version = $psgetModuleInfo.Version
|
|
ModuleName = $psgetModuleInfo.Name
|
|
Repository = $psgetModuleInfo.Repository
|
|
PSGetModuleInfo = $psgetModuleInfo
|
|
})
|
|
|
|
$psgetCommandInfo.PSTypeNames.Insert(0, 'Microsoft.PowerShell.Commands.PSGetCommandInfo')
|
|
$psgetCommandInfo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Find-Command cmdlet
|
|
|
|
#region Find-RoleCapability cmdlet
|
|
|
|
function Find-RoleCapability
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri = 'http://go.microsoft.com/fwlink/?LinkId=718029')]
|
|
[outputtype('PSCustomObject[]')]
|
|
Param
|
|
(
|
|
[Parameter(Position = 0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$ModuleName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$AllVersions,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$Tag,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string]
|
|
$Filter,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository
|
|
)
|
|
|
|
|
|
Process
|
|
{
|
|
$PSBoundParameters['Includes'] = 'RoleCapability'
|
|
|
|
if($PSBoundParameters.ContainsKey('Name'))
|
|
{
|
|
$PSBoundParameters['RoleCapability'] = $Name
|
|
$null = $PSBoundParameters.Remove('Name')
|
|
}
|
|
|
|
if($PSBoundParameters.ContainsKey('ModuleName'))
|
|
{
|
|
$PSBoundParameters['Name'] = $ModuleName
|
|
$null = $PSBoundParameters.Remove('ModuleName')
|
|
}
|
|
|
|
PowerShellGet\Find-Module @PSBoundParameters |
|
|
Microsoft.PowerShell.Core\ForEach-Object {
|
|
$psgetModuleInfo = $_
|
|
$psgetModuleInfo.Includes.RoleCapability | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if($Name -and ($Name -notcontains $_))
|
|
{
|
|
return
|
|
}
|
|
|
|
$psgetRoleCapabilityInfo = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
|
|
Name = $_
|
|
Version = $psgetModuleInfo.Version
|
|
ModuleName = $psgetModuleInfo.Name
|
|
Repository = $psgetModuleInfo.Repository
|
|
PSGetModuleInfo = $psgetModuleInfo
|
|
})
|
|
|
|
$psgetRoleCapabilityInfo.PSTypeNames.Insert(0, 'Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo')
|
|
$psgetRoleCapabilityInfo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Find-RoleCapability cmdlet
|
|
|
|
#region *-Script cmdlets
|
|
function Publish-Script
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(SupportsShouldProcess=$true,
|
|
PositionalBinding=$false,
|
|
DefaultParameterSetName='PathParameterSet',
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619788')]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='PathParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Path,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='LiteralPathParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$LiteralPath,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$NuGetApiKey,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Repository = $Script:PSGalleryModuleSource,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
Begin
|
|
{
|
|
if($script:isNanoServer) {
|
|
$message = $LocalizedData.PublishPSArtifactUnsupportedOnNano -f "Script"
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PublishScriptIsNotSupportedOnNanoServer" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
|
|
Get-PSGalleryApiAvailability -Repository $Repository
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -BootstrapNuGetExe -Force:$Force
|
|
}
|
|
|
|
Process
|
|
{
|
|
$scriptFilePath = $null
|
|
if($Path)
|
|
{
|
|
$scriptFilePath = Resolve-PathHelper -Path $Path -CallerPSCmdlet $PSCmdlet |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $scriptFilePath -or
|
|
-not (Microsoft.PowerShell.Management\Test-Path -Path $scriptFilePath -PathType Leaf))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $Path)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $Path `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$scriptFilePath = Resolve-PathHelper -Path $LiteralPath -IsLiteralPath -CallerPSCmdlet $PSCmdlet |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $scriptFilePath -or
|
|
-not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $scriptFilePath -PathType Leaf))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $LiteralPath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $LiteralPath `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
|
|
if(-not $scriptFilePath.EndsWith('.ps1', [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$errorMessage = ($LocalizedData.InvalidScriptFilePath -f $scriptFilePath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "InvalidScriptFilePath" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $scriptFilePath `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
if($Repository -eq $Script:PSGalleryModuleSource)
|
|
{
|
|
$repo = Get-PSRepository -Name $Repository -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
|
|
if(-not $repo)
|
|
{
|
|
$message = $LocalizedData.PSGalleryNotFound -f ($Repository)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'PSGalleryNotFound' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Repository
|
|
return
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$ev = $null
|
|
$repo = Get-PSRepository -Name $Repository -ErrorVariable ev
|
|
if($ev) { return }
|
|
}
|
|
|
|
$DestinationLocation = $null
|
|
|
|
if(Get-Member -InputObject $repo -Name $script:ScriptPublishLocation)
|
|
{
|
|
$DestinationLocation = $repo.ScriptPublishLocation
|
|
}
|
|
|
|
if(-not $DestinationLocation -or
|
|
(-not (Microsoft.PowerShell.Management\Test-Path -Path $DestinationLocation) -and
|
|
-not (Test-WebUri -uri $DestinationLocation)))
|
|
|
|
{
|
|
$message = $LocalizedData.PSRepositoryScriptPublishLocationIsMissing -f ($Repository, $Repository)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PSRepositoryScriptPublishLocationIsMissing" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Repository
|
|
}
|
|
|
|
$message = $LocalizedData.PublishLocation -f ($DestinationLocation)
|
|
Write-Verbose -Message $message
|
|
|
|
if(-not $NuGetApiKey.Trim())
|
|
{
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $DestinationLocation)
|
|
{
|
|
$NuGetApiKey = "$(Get-Random)"
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.NuGetApiKeyIsRequiredForNuGetBasedGalleryService -f ($Repository, $DestinationLocation)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "NuGetApiKeyIsRequiredForNuGetBasedGalleryService" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
|
|
$providerName = Get-ProviderName -PSCustomObject $repo
|
|
if($providerName -ne $script:NuGetProviderName)
|
|
{
|
|
$message = $LocalizedData.PublishScriptSupportsOnlyNuGetBasedPublishLocations -f ($DestinationLocation, $Repository, $Repository)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PublishScriptSupportsOnlyNuGetBasedPublishLocations" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Repository
|
|
}
|
|
|
|
if($Path)
|
|
{
|
|
$PSScriptInfo = Test-ScriptFileInfo -Path $scriptFilePath
|
|
}
|
|
else
|
|
{
|
|
$PSScriptInfo = Test-ScriptFileInfo -LiteralPath $scriptFilePath
|
|
}
|
|
|
|
if(-not $PSScriptInfo)
|
|
{
|
|
# Test-ScriptFileInfo throws the actual error
|
|
return
|
|
}
|
|
|
|
$scriptName = $PSScriptInfo.Name
|
|
|
|
# Copy the source script file to temp location to publish
|
|
$tempScriptPath = Microsoft.PowerShell.Management\Join-Path -Path $script:TempPath `
|
|
-ChildPath "$(Microsoft.PowerShell.Utility\Get-Random)\$scriptName"
|
|
|
|
$null = Microsoft.PowerShell.Management\New-Item -Path $tempScriptPath -ItemType Directory -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
if($Path)
|
|
{
|
|
Microsoft.PowerShell.Management\Copy-Item -Path $scriptFilePath -Destination $tempScriptPath -Force -Recurse -Confirm:$false -WhatIf:$false
|
|
}
|
|
else
|
|
{
|
|
Microsoft.PowerShell.Management\Copy-Item -LiteralPath $scriptFilePath -Destination $tempScriptPath -Force -Recurse -Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
try
|
|
{
|
|
$FindParameters = @{
|
|
Name = $scriptName
|
|
Repository = $Repository
|
|
Tag = 'PSModule'
|
|
Verbose = $VerbosePreference
|
|
ErrorAction = 'SilentlyContinue'
|
|
WarningAction = 'SilentlyContinue'
|
|
Debug = $DebugPreference
|
|
}
|
|
|
|
if($Credential)
|
|
{
|
|
$FindParameters[$script:Credential] = $Credential
|
|
}
|
|
|
|
# Check if the specified script name is already used for a module on the specified repository
|
|
# Use Find-Module to check if that name is already used as module name
|
|
$modulePSGetItemInfo = Find-Module @FindParameters |
|
|
Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $scriptName} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Last 1
|
|
if($modulePSGetItemInfo)
|
|
{
|
|
$message = $LocalizedData.SpecifiedNameIsAlearyUsed -f ($scriptName, $Repository, 'Find-Module')
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "SpecifiedNameIsAlearyUsed" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $scriptName
|
|
}
|
|
|
|
$null = $FindParameters.Remove('Tag')
|
|
|
|
$currentPSGetItemInfo = $null
|
|
$currentPSGetItemInfo = Find-Script @FindParameters |
|
|
Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $scriptName} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Last 1
|
|
|
|
if($currentPSGetItemInfo)
|
|
{
|
|
if($currentPSGetItemInfo.Version -eq $PSScriptInfo.Version)
|
|
{
|
|
$message = $LocalizedData.ScriptVersionIsAlreadyAvailableInTheGallery -f ($scriptName,
|
|
$PSScriptInfo.Version,
|
|
$currentPSGetItemInfo.Version,
|
|
$currentPSGetItemInfo.RepositorySourceLocation)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'ScriptVersionIsAlreadyAvailableInTheGallery' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
elseif(-not $Force -and ($currentPSGetItemInfo.Version -gt $PSScriptInfo.Version))
|
|
{
|
|
$message = $LocalizedData.ScriptVersionShouldBeGreaterThanGalleryVersion -f ($scriptName,
|
|
$PSScriptInfo.Version,
|
|
$currentPSGetItemInfo.Version,
|
|
$currentPSGetItemInfo.RepositorySourceLocation)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "ScriptVersionShouldBeGreaterThanGalleryVersion" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
}
|
|
|
|
$shouldProcessMessage = $LocalizedData.PublishScriptwhatIfMessage -f ($PSScriptInfo.Version, $scriptName)
|
|
if($Force -or $PSCmdlet.ShouldProcess($shouldProcessMessage, "Publish-Script"))
|
|
{
|
|
Publish-PSArtifactUtility -PSScriptInfo $PSScriptInfo `
|
|
-NugetApiKey $NuGetApiKey `
|
|
-Destination $DestinationLocation `
|
|
-Repository $Repository `
|
|
-NugetPackageRoot $tempScriptPath `
|
|
-Verbose:$VerbosePreference `
|
|
-WarningAction $WarningPreference `
|
|
-ErrorAction $ErrorActionPreference `
|
|
-Debug:$DebugPreference
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item $tempScriptPath -Force -Recurse -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
}
|
|
}
|
|
|
|
function Find-Script
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri='http://go.microsoft.com/fwlink/?LinkId=619785')]
|
|
[outputtype("PSCustomObject[]")]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Position=0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$AllVersions,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$IncludeDependencies,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string]
|
|
$Filter,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$Tag,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[ValidateSet('Function','Workflow')]
|
|
[string[]]
|
|
$Includes,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNull()]
|
|
[string[]]
|
|
$Command,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Repository
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
}
|
|
|
|
Process
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion `
|
|
-AllVersions:$AllVersions
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
$PSBoundParameters['Provider'] = $script:PSModuleProviderName
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeScript
|
|
|
|
if($PSBoundParameters.ContainsKey("Repository"))
|
|
{
|
|
$PSBoundParameters["Source"] = $Repository
|
|
$null = $PSBoundParameters.Remove("Repository")
|
|
|
|
$ev = $null
|
|
$repositories = Get-PSRepository -Name $Repository -ErrorVariable ev -verbose:$false
|
|
if($ev) { return }
|
|
|
|
$RepositoriesWithoutScriptSourceLocation = $false
|
|
foreach($repo in $repositories)
|
|
{
|
|
if(-not $repo.ScriptSourceLocation)
|
|
{
|
|
$message = $LocalizedData.ScriptSourceLocationIsMissing -f ($repo.Name)
|
|
Write-Error -Message $message `
|
|
-ErrorId 'ScriptSourceLocationIsMissing' `
|
|
-Category InvalidArgument `
|
|
-TargetObject $repo.Name `
|
|
-Exception 'System.ArgumentException'
|
|
|
|
$RepositoriesWithoutScriptSourceLocation = $true
|
|
}
|
|
}
|
|
|
|
if($RepositoriesWithoutScriptSourceLocation)
|
|
{
|
|
return
|
|
}
|
|
}
|
|
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlockForScriptCmdlets
|
|
|
|
$scriptsFoundInPSGallery = @()
|
|
|
|
# No Telemetry must be performed if PSGallery is not in the supplied list of Repositories
|
|
$isRepositoryNullOrPSGallerySpecified = $false
|
|
if ($Repository -and ($Repository -Contains $Script:PSGalleryModuleSource))
|
|
{
|
|
$isRepositoryNullOrPSGallerySpecified = $true
|
|
}
|
|
elseif(-not $Repository)
|
|
{
|
|
$psgalleryRepo = Get-PSRepository -Name $Script:PSGalleryModuleSource `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
# And check for IsDeafult?
|
|
if($psgalleryRepo)
|
|
{
|
|
$isRepositoryNullOrPSGallerySpecified = $true
|
|
}
|
|
}
|
|
|
|
PackageManagement\Find-Package @PSBoundParameters | Microsoft.PowerShell.Core\ForEach-Object {
|
|
$psgetItemInfo = New-PSGetItemInfo -SoftwareIdentity $_ -Type $script:PSArtifactTypeScript
|
|
|
|
$psgetItemInfo
|
|
|
|
if ($psgetItemInfo -and
|
|
$isRepositoryNullOrPSGallerySpecified -and
|
|
$script:TelemetryEnabled -and
|
|
($psgetItemInfo.Repository -eq $Script:PSGalleryModuleSource))
|
|
{
|
|
$scriptsFoundInPSGallery += $psgetItemInfo.Name
|
|
}
|
|
}
|
|
|
|
# Perform Telemetry if Repository is not supplied or Repository contains PSGallery
|
|
# We are only interested in finding artifacts not in PSGallery
|
|
if ($isRepositoryNullOrPSGallerySpecified)
|
|
{
|
|
Log-ArtifactNotFoundInPSGallery -SearchedName $Name -FoundName $scriptsFoundInPSGallery -operationName PSGET_FIND_SCRIPT
|
|
}
|
|
}
|
|
}
|
|
|
|
function Save-Script
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(DefaultParameterSetName='NameAndPathParameterSet',
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619786',
|
|
SupportsShouldProcess=$true)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipeline=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='InputOjectAndPathParameterSet')]
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipeline=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='InputOjectAndLiteralPathParameterSet')]
|
|
[ValidateNotNull()]
|
|
[PSCustomObject[]]
|
|
$InputObject,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndPathParameterSet')]
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='InputOjectAndPathParameterSet')]
|
|
[string]
|
|
$Path,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameAndLiteralPathParameterSet')]
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='InputOjectAndLiteralPathParameterSet')]
|
|
[string]
|
|
$LiteralPath,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Repository
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
# Script names already tried in the current pipeline for InputObject parameterset
|
|
$scriptNamesInPipeline = @()
|
|
}
|
|
|
|
Process
|
|
{
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementSaveScriptMessageResolverScriptBlock
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeScript
|
|
|
|
# When -Force is specified, Path will be created if not available.
|
|
if(-not $Force)
|
|
{
|
|
if($Path)
|
|
{
|
|
$destinationPath = Resolve-PathHelper -Path $Path -CallerPSCmdlet $PSCmdlet |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $destinationPath -or -not (Microsoft.PowerShell.Management\Test-path $destinationPath))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $Path)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $Path `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
$PSBoundParameters['Path'] = $destinationPath
|
|
}
|
|
else
|
|
{
|
|
$destinationPath = Resolve-PathHelper -Path $LiteralPath -IsLiteralPath -CallerPSCmdlet $PSCmdlet |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $destinationPath -or -not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $destinationPath))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $LiteralPath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $LiteralPath `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
$PSBoundParameters['LiteralPath'] = $destinationPath
|
|
}
|
|
}
|
|
|
|
if($Name)
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-TestWildcardsInName `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
if($PSBoundParameters.ContainsKey("Repository"))
|
|
{
|
|
$PSBoundParameters["Source"] = $Repository
|
|
$null = $PSBoundParameters.Remove("Repository")
|
|
|
|
$ev = $null
|
|
$repositories = Get-PSRepository -Name $Repository -ErrorVariable ev -verbose:$false
|
|
if($ev) { return }
|
|
|
|
$RepositoriesWithoutScriptSourceLocation = $false
|
|
foreach($repo in $repositories)
|
|
{
|
|
if(-not $repo.ScriptSourceLocation)
|
|
{
|
|
$message = $LocalizedData.ScriptSourceLocationIsMissing -f ($repo.Name)
|
|
Write-Error -Message $message `
|
|
-ErrorId 'ScriptSourceLocationIsMissing' `
|
|
-Category InvalidArgument `
|
|
-TargetObject $repo.Name `
|
|
-Exception 'System.ArgumentException'
|
|
|
|
$RepositoriesWithoutScriptSourceLocation = $true
|
|
}
|
|
}
|
|
|
|
if($RepositoriesWithoutScriptSourceLocation)
|
|
{
|
|
return
|
|
}
|
|
}
|
|
|
|
$null = PackageManagement\Save-Package @PSBoundParameters
|
|
}
|
|
elseif($InputObject)
|
|
{
|
|
$null = $PSBoundParameters.Remove("InputObject")
|
|
|
|
foreach($inputValue in $InputObject)
|
|
{
|
|
if (($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSRepositoryItemInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSRepositoryItemInfo"))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.InvalidInputObjectValue `
|
|
-ErrorId "InvalidInputObjectValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $inputValue
|
|
}
|
|
|
|
$psRepositoryItemInfo = $inputValue
|
|
|
|
# Skip the script name if it is already tried in the current pipeline
|
|
if($scriptNamesInPipeline -contains $psRepositoryItemInfo.Name)
|
|
{
|
|
continue
|
|
}
|
|
|
|
$scriptNamesInPipeline += $psRepositoryItemInfo.Name
|
|
|
|
if ($psRepositoryItemInfo.PowerShellGetFormatVersion -and
|
|
($script:SupportedPSGetFormatVersionMajors -notcontains $psRepositoryItemInfo.PowerShellGetFormatVersion.Major))
|
|
{
|
|
$message = $LocalizedData.NotSupportedPowerShellGetFormatVersionScripts -f ($psRepositoryItemInfo.Name, $psRepositoryItemInfo.PowerShellGetFormatVersion, $psRepositoryItemInfo.Name)
|
|
Write-Error -Message $message -ErrorId "NotSupportedPowerShellGetFormatVersion" -Category InvalidOperation
|
|
continue
|
|
}
|
|
|
|
$PSBoundParameters["Name"] = $psRepositoryItemInfo.Name
|
|
$PSBoundParameters["RequiredVersion"] = $psRepositoryItemInfo.Version
|
|
$PSBoundParameters['Source'] = $psRepositoryItemInfo.Repository
|
|
$PSBoundParameters["PackageManagementProvider"] = (Get-ProviderName -PSCustomObject $psRepositoryItemInfo)
|
|
|
|
$null = PackageManagement\Save-Package @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Install-Script
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(DefaultParameterSetName='NameParameterSet',
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619784',
|
|
SupportsShouldProcess=$true)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipeline=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='InputObject')]
|
|
[ValidateNotNull()]
|
|
[PSCustomObject[]]
|
|
$InputObject,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Repository,
|
|
|
|
[Parameter()]
|
|
[ValidateSet("CurrentUser","AllUsers")]
|
|
[string]
|
|
$Scope = 'AllUsers',
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$NoPathUpdate,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Repository
|
|
|
|
if(-not (Test-RunningAsElevated) -and ($Scope -ne "CurrentUser"))
|
|
{
|
|
# Throw an error when Install-Script is used as a non-admin user and '-Scope CurrentUser' is not specified
|
|
$AdminPreviligeErrorMessage = $LocalizedData.InstallScriptNeedsCurrentUserScopeParameterForNonAdminUser -f @($script:ProgramFilesScriptsPath, $script:MyDocumentsScriptsPath)
|
|
$AdminPreviligeErrorId = 'InstallScriptNeedsCurrentUserScopeParameterForNonAdminUser'
|
|
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $AdminPreviligeErrorMessage `
|
|
-ErrorId $AdminPreviligeErrorId `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
# Check and add the scope path to PATH environment variable
|
|
if($Scope -eq 'AllUsers')
|
|
{
|
|
$scopePath = $script:ProgramFilesScriptsPath
|
|
}
|
|
else
|
|
{
|
|
$scopePath = $script:MyDocumentsScriptsPath
|
|
}
|
|
|
|
ValidateAndSet-PATHVariableIfUserAccepts -Scope $Scope `
|
|
-ScopePath $scopePath `
|
|
-NoPathUpdate:$NoPathUpdate `
|
|
-Force:$Force
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
# Script names already tried in the current pipeline for InputObject parameterset
|
|
$scriptNamesInPipeline = @()
|
|
|
|
$YesToAll = $false
|
|
$NoToAll = $false
|
|
$SourceSGrantedTrust = @()
|
|
$SourcesDeniedTrust = @()
|
|
}
|
|
|
|
Process
|
|
{
|
|
$RepositoryIsNotTrusted = $LocalizedData.RepositoryIsNotTrusted
|
|
$QueryInstallUntrustedPackage = $LocalizedData.QueryInstallUntrustedScriptPackage
|
|
$PackageTarget = $LocalizedData.InstallScriptwhatIfMessage
|
|
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementInstallScriptMessageResolverScriptBlock
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeScript
|
|
$PSBoundParameters['Scope'] = $Scope
|
|
|
|
if($PSCmdlet.ParameterSetName -eq "NameParameterSet")
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-TestWildcardsInName `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
if($PSBoundParameters.ContainsKey("Repository"))
|
|
{
|
|
$PSBoundParameters["Source"] = $Repository
|
|
$null = $PSBoundParameters.Remove("Repository")
|
|
|
|
$ev = $null
|
|
$repositories = Get-PSRepository -Name $Repository -ErrorVariable ev -verbose:$false
|
|
if($ev) { return }
|
|
|
|
$RepositoriesWithoutScriptSourceLocation = $false
|
|
foreach($repo in $repositories)
|
|
{
|
|
if(-not $repo.ScriptSourceLocation)
|
|
{
|
|
$message = $LocalizedData.ScriptSourceLocationIsMissing -f ($repo.Name)
|
|
Write-Error -Message $message `
|
|
-ErrorId 'ScriptSourceLocationIsMissing' `
|
|
-Category InvalidArgument `
|
|
-TargetObject $repo.Name `
|
|
-Exception 'System.ArgumentException'
|
|
|
|
$RepositoriesWithoutScriptSourceLocation = $true
|
|
}
|
|
}
|
|
|
|
if($RepositoriesWithoutScriptSourceLocation)
|
|
{
|
|
return
|
|
}
|
|
}
|
|
|
|
if(-not $Force)
|
|
{
|
|
foreach($scriptName in $Name)
|
|
{
|
|
# Throw an error if there is a command with the same name and -force is not specified.
|
|
$cmd = Microsoft.PowerShell.Core\Get-Command -Name $scriptName `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
if($cmd)
|
|
{
|
|
# Check if this script was already installed, may be with -Force
|
|
$InstalledScriptInfo = Test-ScriptInstalled -Name $scriptName `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
if(-not $InstalledScriptInfo)
|
|
{
|
|
$message = $LocalizedData.CommandAlreadyAvailable -f ($scriptName)
|
|
Write-Error -Message $message -ErrorId CommandAlreadyAvailableWitScriptName -Category InvalidOperation
|
|
|
|
# return if only single name is specified
|
|
if($scriptName -eq $Name)
|
|
{
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$null = PackageManagement\Install-Package @PSBoundParameters
|
|
}
|
|
elseif($PSCmdlet.ParameterSetName -eq "InputObject")
|
|
{
|
|
$null = $PSBoundParameters.Remove("InputObject")
|
|
|
|
foreach($inputValue in $InputObject)
|
|
{
|
|
|
|
if (($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSRepositoryItemInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSRepositoryItemInfo"))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.InvalidInputObjectValue `
|
|
-ErrorId "InvalidInputObjectValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $inputValue
|
|
}
|
|
|
|
$psRepositoryItemInfo = $inputValue
|
|
|
|
# Skip the script name if it is already tried in the current pipeline
|
|
if($scriptNamesInPipeline -contains $psRepositoryItemInfo.Name)
|
|
{
|
|
continue
|
|
}
|
|
|
|
$scriptNamesInPipeline += $psRepositoryItemInfo.Name
|
|
|
|
if ($psRepositoryItemInfo.PowerShellGetFormatVersion -and
|
|
($script:SupportedPSGetFormatVersionMajors -notcontains $psRepositoryItemInfo.PowerShellGetFormatVersion.Major))
|
|
{
|
|
$message = $LocalizedData.NotSupportedPowerShellGetFormatVersionScripts -f ($psRepositoryItemInfo.Name, $psRepositoryItemInfo.PowerShellGetFormatVersion, $psRepositoryItemInfo.Name)
|
|
Write-Error -Message $message -ErrorId "NotSupportedPowerShellGetFormatVersion" -Category InvalidOperation
|
|
continue
|
|
}
|
|
|
|
$PSBoundParameters["Name"] = $psRepositoryItemInfo.Name
|
|
$PSBoundParameters["RequiredVersion"] = $psRepositoryItemInfo.Version
|
|
$PSBoundParameters['Source'] = $psRepositoryItemInfo.Repository
|
|
$PSBoundParameters["PackageManagementProvider"] = (Get-ProviderName -PSCustomObject $psRepositoryItemInfo)
|
|
|
|
$InstalledScriptInfo = Test-ScriptInstalled -Name $psRepositoryItemInfo.Name
|
|
if(-not $Force -and $InstalledScriptInfo)
|
|
{
|
|
$message = $LocalizedData.ScriptAlreadyInstalledVerbose -f ($InstalledScriptInfo.Version, $InstalledScriptInfo.Name, $InstalledScriptInfo.ScriptBase)
|
|
Write-Verbose -Message $message
|
|
}
|
|
else
|
|
{
|
|
# Throw an error if there is a command with the same name and -force is not specified.
|
|
if(-not $Force)
|
|
{
|
|
$cmd = Microsoft.PowerShell.Core\Get-Command -Name $psRepositoryItemInfo.Name `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
if($cmd)
|
|
{
|
|
$message = $LocalizedData.CommandAlreadyAvailable -f ($psRepositoryItemInfo.Name)
|
|
Write-Error -Message $message -ErrorId CommandAlreadyAvailableWitScriptName -Category InvalidOperation
|
|
|
|
continue
|
|
}
|
|
}
|
|
|
|
$source = $psRepositoryItemInfo.Repository
|
|
$installationPolicy = (Get-PSRepository -Name $source).InstallationPolicy
|
|
$ShouldProcessMessage = $PackageTarget -f ($psRepositoryItemInfo.Name, $psRepositoryItemInfo.Version)
|
|
|
|
if($psCmdlet.ShouldProcess($ShouldProcessMessage))
|
|
{
|
|
if($installationPolicy.Equals("Untrusted", [StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
if(-not($YesToAll -or $NoToAll -or $SourceSGrantedTrust.Contains($source) -or $sourcesDeniedTrust.Contains($source) -or $Force))
|
|
{
|
|
$message = $QueryInstallUntrustedPackage -f ($psRepositoryItemInfo.Name, $psRepositoryItemInfo.RepositorySourceLocation)
|
|
|
|
if($PSVersionTable.PSVersion -ge [Version]"5.0")
|
|
{
|
|
$sourceTrusted = $psCmdlet.ShouldContinue("$message", "$RepositoryIsNotTrusted",$true, [ref]$YesToAll, [ref]$NoToAll)
|
|
}
|
|
else
|
|
{
|
|
$sourceTrusted = $psCmdlet.ShouldContinue("$message", "$RepositoryIsNotTrusted", [ref]$YesToAll, [ref]$NoToAll)
|
|
}
|
|
|
|
if($sourceTrusted)
|
|
{
|
|
$SourcesGrantedTrust+=$source
|
|
}
|
|
else
|
|
{
|
|
$SourcesDeniedTrust+=$source
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if($installationPolicy.Equals("trusted", [StringComparison]::OrdinalIgnoreCase) -or $SourcesGrantedTrust.Contains($source) -or $YesToAll -or $Force)
|
|
{
|
|
$PSBoundParameters["Force"] = $true
|
|
$null = PackageManagement\Install-Package @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Update-Script
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(SupportsShouldProcess=$true,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619787')]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Position=0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$Name,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$Force
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
# Script names already tried in the current pipeline
|
|
$scriptNamesInPipeline = @()
|
|
}
|
|
|
|
Process
|
|
{
|
|
$scriptFilePathsToUpdate = @()
|
|
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
if($Name)
|
|
{
|
|
foreach($scriptName in $Name)
|
|
{
|
|
$availableScriptPaths = Get-AvailableScriptFilePath -Name $scriptName -Verbose:$false
|
|
|
|
if(-not $availableScriptPaths -and -not (Test-WildcardPattern -Name $scriptName))
|
|
{
|
|
$message = $LocalizedData.ScriptNotInstalledOnThisMachine -f ($scriptName, $script:MyDocumentsScriptsPath, $script:ProgramFilesScriptsPath)
|
|
Write-Error -Message $message -ErrorId "ScriptNotInstalledOnThisMachine" -Category InvalidOperation -TargetObject $scriptName
|
|
continue
|
|
}
|
|
|
|
foreach($scriptFilePath in $availableScriptPaths)
|
|
{
|
|
$installedScriptFilePath = Get-InstalledScriptFilePath -Name ([System.IO.Path]::GetFileNameWithoutExtension($scriptFilePath)) |
|
|
Microsoft.PowerShell.Core\Where-Object {$_ -eq $scriptFilePath }
|
|
|
|
# Check if this script got installed with PowerShellGet and user has required permissions
|
|
if ($installedScriptFilePath)
|
|
{
|
|
if(-not (Test-RunningAsElevated) -and $installedScriptFilePath.StartsWith($script:ProgramFilesScriptsPath, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
if(-not (Test-WildcardPattern -Name $scriptName))
|
|
{
|
|
$message = $LocalizedData.AdminPrivilegesRequiredForScriptUpdate -f ($scriptName, $installedScriptFilePath)
|
|
Write-Error -Message $message -ErrorId "AdminPrivilegesAreRequiredForUpdate" -Category InvalidOperation -TargetObject $scriptName
|
|
}
|
|
continue
|
|
}
|
|
|
|
$scriptFilePathsToUpdate += $installedScriptFilePath
|
|
}
|
|
else
|
|
{
|
|
if(-not (Test-WildcardPattern -Name $scriptName))
|
|
{
|
|
$message = $LocalizedData.ScriptNotInstalledUsingPowerShellGet -f ($scriptName)
|
|
Write-Error -Message $message -ErrorId "ScriptNotInstalledUsingPowerShellGet" -Category InvalidOperation -TargetObject $scriptName
|
|
}
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$isRunningAsElevated = Test-RunningAsElevated
|
|
$installedScriptFilePaths = Get-InstalledScriptFilePath
|
|
|
|
if($isRunningAsElevated)
|
|
{
|
|
$scriptFilePathsToUpdate = $installedScriptFilePaths
|
|
}
|
|
else
|
|
{
|
|
# Update the scripts installed under
|
|
$scriptFilePathsToUpdate = $installedScriptFilePaths | Microsoft.PowerShell.Core\Where-Object {
|
|
$_.StartsWith($script:MyDocumentsScriptsPath, [System.StringComparison]::OrdinalIgnoreCase)}
|
|
}
|
|
}
|
|
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeScript
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementUpdateScriptMessageResolverScriptBlock
|
|
$PSBoundParameters["InstallUpdate"] = $true
|
|
|
|
foreach($scriptFilePath in $scriptFilePathsToUpdate)
|
|
{
|
|
$scriptName = [System.IO.Path]::GetFileNameWithoutExtension($scriptFilePath)
|
|
|
|
$installedScriptInfoFilePath = $null
|
|
$installedScriptInfoFileName = "$($scriptName)_$script:InstalledScriptInfoFileName"
|
|
|
|
if($scriptFilePath.ToString().StartsWith($script:MyDocumentsScriptsPath, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$PSBoundParameters["Scope"] = "CurrentUser"
|
|
$installedScriptInfoFilePath = Microsoft.PowerShell.Management\Join-Path -Path $script:MyDocumentsInstalledScriptInfosPath `
|
|
-ChildPath $installedScriptInfoFileName
|
|
}
|
|
elseif($scriptFilePath.ToString().StartsWith($script:ProgramFilesScriptsPath, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$PSBoundParameters["Scope"] = "AllUsers"
|
|
$installedScriptInfoFilePath = Microsoft.PowerShell.Management\Join-Path -Path $script:ProgramFilesInstalledScriptInfosPath `
|
|
-ChildPath $installedScriptInfoFileName
|
|
|
|
}
|
|
|
|
$psgetItemInfo = $null
|
|
if($installedScriptInfoFilePath -and (Microsoft.PowerShell.Management\Test-Path -Path $installedScriptInfoFilePath -PathType Leaf))
|
|
{
|
|
$psgetItemInfo = DeSerialize-PSObject -Path $installedScriptInfoFilePath
|
|
}
|
|
|
|
# Skip the script name if it is already tried in the current pipeline
|
|
if(-not $psgetItemInfo -or ($scriptNamesInPipeline -contains $psgetItemInfo.Name))
|
|
{
|
|
continue
|
|
}
|
|
|
|
|
|
$scriptFilePath = Microsoft.PowerShell.Management\Join-Path -Path $psgetItemInfo.InstalledLocation `
|
|
-ChildPath "$($psgetItemInfo.Name).ps1"
|
|
|
|
# Remove the InstalledScriptInfo.xml file if the actual script file was manually uninstalled by the user
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path -Path $scriptFilePath -PathType Leaf))
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $installedScriptInfoFilePath -Force -ErrorAction SilentlyContinue
|
|
|
|
continue
|
|
}
|
|
|
|
$scriptNamesInPipeline += $psgetItemInfo.Name
|
|
|
|
$message = $LocalizedData.CheckingForScriptUpdate -f ($psgetItemInfo.Name)
|
|
Write-Verbose -Message $message
|
|
|
|
$providerName = Get-ProviderName -PSCustomObject $psgetItemInfo
|
|
if(-not $providerName)
|
|
{
|
|
$providerName = $script:NuGetProviderName
|
|
}
|
|
|
|
$PSBoundParameters["PackageManagementProvider"] = $providerName
|
|
$PSBoundParameters["Name"] = $psgetItemInfo.Name
|
|
$PSBoundParameters['Source'] = $psgetItemInfo.Repository
|
|
|
|
Get-PSGalleryApiAvailability -Repository (Get-SourceName -Location $psgetItemInfo.RepositorySourceLocation)
|
|
|
|
$sid = PackageManagement\Install-Package @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
|
|
function Uninstall-Script
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(DefaultParameterSetName='NameParameterSet',
|
|
SupportsShouldProcess=$true,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619789')]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Mandatory=$true,
|
|
Position=0,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$Name,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipeline=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
Position=0,
|
|
ParameterSetName='InputObject')]
|
|
[ValidateNotNull()]
|
|
[PSCustomObject[]]
|
|
$InputObject,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$Force
|
|
)
|
|
|
|
Process
|
|
{
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementUnInstallScriptMessageResolverScriptBlock
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeScript
|
|
|
|
if($PSCmdlet.ParameterSetName -eq "InputObject")
|
|
{
|
|
$null = $PSBoundParameters.Remove("InputObject")
|
|
|
|
foreach($inputValue in $InputObject)
|
|
{
|
|
if (($inputValue.PSTypeNames -notcontains "Microsoft.PowerShell.Commands.PSRepositoryItemInfo") -and
|
|
($inputValue.PSTypeNames -notcontains "Deserialized.Microsoft.PowerShell.Commands.PSRepositoryItemInfo"))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.InvalidInputObjectValue `
|
|
-ErrorId "InvalidInputObjectValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $inputValue
|
|
}
|
|
|
|
$PSBoundParameters["Name"] = $inputValue.Name
|
|
$PSBoundParameters["RequiredVersion"] = $inputValue.Version
|
|
|
|
$null = PackageManagement\Uninstall-Package @PSBoundParameters
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-TestWildcardsInName `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
$null = PackageManagement\Uninstall-Package @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
|
|
function Get-InstalledScript
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri='http://go.microsoft.com/fwlink/?LinkId=619790')]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Position=0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$Name,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNull()]
|
|
[Version]
|
|
$MaximumVersion
|
|
)
|
|
|
|
Process
|
|
{
|
|
$ValidationResult = Validate-VersionParameters -CallerPSCmdlet $PSCmdlet `
|
|
-Name $Name `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion `
|
|
-RequiredVersion $RequiredVersion
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
# Validate-VersionParameters throws the error.
|
|
# returning to avoid further execution when different values are specified for -ErrorAction parameter
|
|
return
|
|
}
|
|
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlockForScriptCmdlets
|
|
$PSBoundParameters[$script:PSArtifactType] = $script:PSArtifactTypeScript
|
|
|
|
PackageManagement\Get-Package @PSBoundParameters | Microsoft.PowerShell.Core\ForEach-Object {New-PSGetItemInfo -SoftwareIdentity $_ -Type $script:PSArtifactTypeScript}
|
|
}
|
|
}
|
|
|
|
#endregion *-Script cmdlets
|
|
|
|
#region *-PSRepository cmdlets
|
|
|
|
function Register-PSRepository
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(DefaultParameterSetName='NameParameterSet',
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkID=517129')]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
Position=0,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Name,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
Position=1,
|
|
ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$SourceLocation,
|
|
|
|
[Parameter(ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$PublishLocation,
|
|
|
|
[Parameter(ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$ScriptSourceLocation,
|
|
|
|
[Parameter(ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$ScriptPublishLocation,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='NameParameterSet')]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ParameterSetName='PSGalleryParameterSet')]
|
|
[Switch]
|
|
$Default,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Trusted','Untrusted')]
|
|
[string]
|
|
$InstallationPolicy = 'Untrusted',
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter(ParameterSetName='NameParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$PackageManagementProvider
|
|
)
|
|
|
|
DynamicParam
|
|
{
|
|
if (Get-Variable -Name SourceLocation -ErrorAction SilentlyContinue)
|
|
{
|
|
Set-Variable -Name selctedProviderName -value $null -Scope 1
|
|
|
|
if(Get-Variable -Name PackageManagementProvider -ErrorAction SilentlyContinue)
|
|
{
|
|
$selctedProviderName = $PackageManagementProvider
|
|
$null = Get-DynamicParameters -Location $SourceLocation -PackageManagementProvider ([REF]$selctedProviderName)
|
|
}
|
|
else
|
|
{
|
|
$dynamicParameters = Get-DynamicParameters -Location $SourceLocation -PackageManagementProvider ([REF]$selctedProviderName)
|
|
Set-Variable -Name PackageManagementProvider -Value $selctedProviderName -Scope 1
|
|
$null = $dynamicParameters
|
|
}
|
|
}
|
|
}
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Name
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
if($PackageManagementProvider)
|
|
{
|
|
$providers = PackageManagement\Get-PackageProvider | Where-Object { $_.Name -ne $script:PSModuleProviderName -and $_.Features.ContainsKey($script:SupportsPSModulesFeatureName) }
|
|
|
|
if (-not $providers -or $providers.Name -notcontains $PackageManagementProvider)
|
|
{
|
|
$possibleProviderNames = $script:NuGetProviderName
|
|
|
|
if($providers)
|
|
{
|
|
$possibleProviderNames = ($providers.Name -join ',')
|
|
}
|
|
|
|
$message = $LocalizedData.InvalidPackageManagementProviderValue -f ($PackageManagementProvider, $possibleProviderNames, $script:NuGetProviderName)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidPackageManagementProviderValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $PackageManagementProvider
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
Process
|
|
{
|
|
if($PSCmdlet.ParameterSetName -eq 'PSGalleryParameterSet')
|
|
{
|
|
if(-not $Default)
|
|
{
|
|
return
|
|
}
|
|
|
|
$PSBoundParameters['Name'] = $Script:PSGalleryModuleSource
|
|
$null = $PSBoundParameters.Remove('Default')
|
|
}
|
|
else
|
|
{
|
|
if($Name -eq $Script:PSGalleryModuleSource)
|
|
{
|
|
$message = $LocalizedData.UseDefaultParameterSetOnRegisterPSRepository
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'UseDefaultParameterSetOnRegisterPSRepository' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Name
|
|
return
|
|
}
|
|
|
|
# Ping and resolve the specified location
|
|
$SourceLocation = Resolve-Location -Location (Get-LocationString -LocationUri $SourceLocation) `
|
|
-LocationParameterName 'SourceLocation' `
|
|
-Credential $Credential `
|
|
-Proxy $Proxy `
|
|
-ProxyCredential $ProxyCredential `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
if(-not $SourceLocation)
|
|
{
|
|
# Above Resolve-Location function throws an error when it is not able to resolve a location
|
|
return
|
|
}
|
|
|
|
$providerName = $null
|
|
|
|
if($PackageManagementProvider)
|
|
{
|
|
$providerName = $PackageManagementProvider
|
|
}
|
|
elseif($selctedProviderName)
|
|
{
|
|
$providerName = $selctedProviderName
|
|
}
|
|
else
|
|
{
|
|
$providerName = Get-PackageManagementProviderName -Location $SourceLocation
|
|
}
|
|
|
|
if($providerName)
|
|
{
|
|
$PSBoundParameters[$script:PackageManagementProviderParam] = $providerName
|
|
}
|
|
|
|
if($PublishLocation)
|
|
{
|
|
$PSBoundParameters[$script:PublishLocation] = Get-LocationString -LocationUri $PublishLocation
|
|
}
|
|
|
|
if($ScriptPublishLocation)
|
|
{
|
|
$PSBoundParameters[$script:ScriptPublishLocation] = Get-LocationString -LocationUri $ScriptPublishLocation
|
|
}
|
|
|
|
if($ScriptSourceLocation)
|
|
{
|
|
$PSBoundParameters[$script:ScriptSourceLocation] = Get-LocationString -LocationUri $ScriptSourceLocation
|
|
}
|
|
|
|
$PSBoundParameters["Location"] = Get-LocationString -LocationUri $SourceLocation
|
|
$null = $PSBoundParameters.Remove("SourceLocation")
|
|
}
|
|
|
|
if($InstallationPolicy -eq "Trusted")
|
|
{
|
|
$PSBoundParameters['Trusted'] = $true
|
|
}
|
|
$null = $PSBoundParameters.Remove("InstallationPolicy")
|
|
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlock
|
|
|
|
$null = PackageManagement\Register-PackageSource @PSBoundParameters
|
|
}
|
|
}
|
|
|
|
function Set-PSRepository
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(PositionalBinding=$false,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkID=517128')]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true, Position=0)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Name,
|
|
|
|
[Parameter(Position=1)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$SourceLocation,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$PublishLocation,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$ScriptSourceLocation,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$ScriptPublishLocation,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Trusted','Untrusted')]
|
|
[string]
|
|
$InstallationPolicy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$Proxy,
|
|
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[PSCredential]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$PackageManagementProvider
|
|
)
|
|
|
|
DynamicParam
|
|
{
|
|
if (Get-Variable -Name Name -ErrorAction SilentlyContinue)
|
|
{
|
|
$moduleSource = Get-PSRepository -Name $Name -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
|
|
|
|
if($moduleSource)
|
|
{
|
|
$providerName = (Get-ProviderName -PSCustomObject $moduleSource)
|
|
|
|
$loc = $moduleSource.SourceLocation
|
|
|
|
if(Get-Variable -Name SourceLocation -ErrorAction SilentlyContinue)
|
|
{
|
|
$loc = $SourceLocation
|
|
}
|
|
|
|
if(Get-Variable -Name PackageManagementProvider -ErrorAction SilentlyContinue)
|
|
{
|
|
$providerName = $PackageManagementProvider
|
|
}
|
|
|
|
$null = Get-DynamicParameters -Location $loc -PackageManagementProvider ([REF]$providerName)
|
|
}
|
|
}
|
|
}
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Name
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
if($PackageManagementProvider)
|
|
{
|
|
$providers = PackageManagement\Get-PackageProvider | Where-Object { $_.Name -ne $script:PSModuleProviderName -and $_.Features.ContainsKey($script:SupportsPSModulesFeatureName) }
|
|
|
|
if (-not $providers -or $providers.Name -notcontains $PackageManagementProvider)
|
|
{
|
|
$possibleProviderNames = $script:NuGetProviderName
|
|
|
|
if($providers)
|
|
{
|
|
$possibleProviderNames = ($providers.Name -join ',')
|
|
}
|
|
|
|
$message = $LocalizedData.InvalidPackageManagementProviderValue -f ($PackageManagementProvider, $possibleProviderNames, $script:NuGetProviderName)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidPackageManagementProviderValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $PackageManagementProvider
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
Process
|
|
{
|
|
# Ping and resolve the specified location
|
|
if($SourceLocation)
|
|
{
|
|
# Ping and resolve the specified location
|
|
$SourceLocation = Resolve-Location -Location (Get-LocationString -LocationUri $SourceLocation) `
|
|
-LocationParameterName 'SourceLocation' `
|
|
-Credential $Credential `
|
|
-Proxy $Proxy `
|
|
-ProxyCredential $ProxyCredential `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
if(-not $SourceLocation)
|
|
{
|
|
# Above Resolve-Location function throws an error when it is not able to resolve a location
|
|
return
|
|
}
|
|
}
|
|
|
|
$ModuleSource = Get-PSRepository -Name $Name -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
|
|
|
|
if(-not $ModuleSource)
|
|
{
|
|
$message = $LocalizedData.RepositoryNotFound -f ($Name)
|
|
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "RepositoryNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $Name
|
|
}
|
|
|
|
if (-not $PackageManagementProvider)
|
|
{
|
|
$PackageManagementProvider = (Get-ProviderName -PSCustomObject $ModuleSource)
|
|
}
|
|
|
|
$Trusted = $ModuleSource.Trusted
|
|
if($InstallationPolicy)
|
|
{
|
|
if($InstallationPolicy -eq "Trusted")
|
|
{
|
|
$Trusted = $true
|
|
}
|
|
else
|
|
{
|
|
$Trusted = $false
|
|
}
|
|
|
|
$null = $PSBoundParameters.Remove("InstallationPolicy")
|
|
}
|
|
|
|
if($PublishLocation)
|
|
{
|
|
$PSBoundParameters[$script:PublishLocation] = Get-LocationString -LocationUri $PublishLocation
|
|
}
|
|
|
|
if($ScriptPublishLocation)
|
|
{
|
|
$PSBoundParameters[$script:ScriptPublishLocation] = Get-LocationString -LocationUri $ScriptPublishLocation
|
|
}
|
|
|
|
if($ScriptSourceLocation)
|
|
{
|
|
$PSBoundParameters[$script:ScriptSourceLocation] = Get-LocationString -LocationUri $ScriptSourceLocation
|
|
}
|
|
|
|
if($SourceLocation)
|
|
{
|
|
$PSBoundParameters["NewLocation"] = Get-LocationString -LocationUri $SourceLocation
|
|
|
|
$null = $PSBoundParameters.Remove("SourceLocation")
|
|
}
|
|
|
|
$PSBoundParameters[$script:PackageManagementProviderParam] = $PackageManagementProvider
|
|
$PSBoundParameters.Add("Trusted", $Trusted)
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlock
|
|
|
|
$null = PackageManagement\Set-PackageSource @PSBoundParameters
|
|
}
|
|
}
|
|
|
|
function Unregister-PSRepository
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri='http://go.microsoft.com/fwlink/?LinkID=517130')]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true,
|
|
Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Name
|
|
}
|
|
|
|
Process
|
|
{
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlock
|
|
|
|
$null = $PSBoundParameters.Remove("Name")
|
|
|
|
foreach ($moduleSourceName in $Name)
|
|
{
|
|
# Check if $moduleSourceName contains any wildcards
|
|
if(Test-WildcardPattern $moduleSourceName)
|
|
{
|
|
$message = $LocalizedData.RepositoryNameContainsWildCards -f ($moduleSourceName)
|
|
Write-Error -Message $message -ErrorId "RepositoryNameContainsWildCards" -Category InvalidOperation
|
|
continue
|
|
}
|
|
|
|
$PSBoundParameters["Source"] = $moduleSourceName
|
|
|
|
$null = PackageManagement\Unregister-PackageSource @PSBoundParameters
|
|
}
|
|
}
|
|
}
|
|
|
|
function Get-PSRepository
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(HelpUri='http://go.microsoft.com/fwlink/?LinkID=517127')]
|
|
Param
|
|
(
|
|
[Parameter(ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Name
|
|
)
|
|
|
|
Begin
|
|
{
|
|
Get-PSGalleryApiAvailability -Repository $Name
|
|
}
|
|
|
|
Process
|
|
{
|
|
$PSBoundParameters["Provider"] = $script:PSModuleProviderName
|
|
$PSBoundParameters["MessageResolver"] = $script:PackageManagementMessageResolverScriptBlock
|
|
|
|
if($Name)
|
|
{
|
|
foreach($sourceName in $Name)
|
|
{
|
|
$PSBoundParameters["Name"] = $sourceName
|
|
|
|
$packageSources = PackageManagement\Get-PackageSource @PSBoundParameters
|
|
|
|
$packageSources | Microsoft.PowerShell.Core\ForEach-Object { New-ModuleSourceFromPackageSource -PackageSource $_ }
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$packageSources = PackageManagement\Get-PackageSource @PSBoundParameters
|
|
|
|
$packageSources | Microsoft.PowerShell.Core\ForEach-Object { New-ModuleSourceFromPackageSource -PackageSource $_ }
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion *-PSRepository cmdlets
|
|
|
|
#region *-ScriptFileInfo cmdlets
|
|
|
|
# Below is the sample PSScriptInfo in a script file.
|
|
<#PSScriptInfo
|
|
|
|
.VERSION 1.0
|
|
|
|
.GUID 544238e3-1751-4065-9227-be105ff11636
|
|
|
|
.AUTHOR manikb
|
|
|
|
.COMPANYNAME Microsoft Corporation
|
|
|
|
.COPYRIGHT (c) 2015 Microsoft Corporation. All rights reserved.
|
|
|
|
.TAGS Tag1 Tag2 Tag3
|
|
|
|
.LICENSEURI https://contoso.com/License
|
|
|
|
.PROJECTURI https://contoso.com/
|
|
|
|
.ICONURI https://contoso.com/Icon
|
|
|
|
.EXTERNALMODULEDEPENDENCIES ExternalModule1
|
|
|
|
.REQUIREDSCRIPTS Start-WFContosoServer,Stop-ContosoServerScript
|
|
|
|
.EXTERNALSCRIPTDEPENDENCIES Stop-ContosoServerScript
|
|
|
|
.RELEASENOTES
|
|
contoso script now supports following features
|
|
Feature 1
|
|
Feature 2
|
|
Feature 3
|
|
Feature 4
|
|
Feature 5
|
|
|
|
#>
|
|
|
|
<# #Requires -Module statements #>
|
|
|
|
<#
|
|
|
|
.DESCRIPTION
|
|
Description goes here.
|
|
|
|
#>
|
|
|
|
|
|
#
|
|
function Test-ScriptFileInfo
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(PositionalBinding=$false,
|
|
DefaultParameterSetName='PathParameterSet',
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619791')]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
Position=0,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='PathParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Path,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
ValueFromPipelineByPropertyName=$true,
|
|
ParameterSetName='LiteralPathParameterSet')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$LiteralPath
|
|
)
|
|
|
|
Process
|
|
{
|
|
$scriptFilePath = $null
|
|
if($Path)
|
|
{
|
|
$scriptFilePath = Resolve-PathHelper -Path $Path -CallerPSCmdlet $PSCmdlet | Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $scriptFilePath -or -not (Microsoft.PowerShell.Management\Test-Path -Path $scriptFilePath -PathType Leaf))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $Path)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $Path `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$scriptFilePath = Resolve-PathHelper -Path $LiteralPath -IsLiteralPath -CallerPSCmdlet $PSCmdlet | Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $scriptFilePath -or -not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $scriptFilePath -PathType Leaf))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $LiteralPath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $LiteralPath `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
}
|
|
|
|
if(-not $scriptFilePath.EndsWith('.ps1', [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$errorMessage = ($LocalizedData.InvalidScriptFilePath -f $scriptFilePath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "InvalidScriptFilePath" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $scriptFilePath `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
$PSScriptInfo = New-PSScriptInfoObject -Path $scriptFilePath
|
|
|
|
[System.Management.Automation.Language.Token[]]$tokens = $null;
|
|
[System.Management.Automation.Language.ParseError[]]$errors = $null;
|
|
$ast = [System.Management.Automation.Language.Parser]::ParseFile($scriptFilePath, ([ref]$tokens), ([ref]$errors))
|
|
|
|
|
|
$notSupportedOnNanoErrorIds = @('WorkflowNotSupportedInPowerShellCore',
|
|
'ConfigurationNotSupportedInPowerShellCore')
|
|
$errosAfterSkippingOneCoreErrors = $errors | Microsoft.PowerShell.Core\Where-Object { $notSupportedOnNanoErrorIds -notcontains $_.ErrorId}
|
|
|
|
if($errosAfterSkippingOneCoreErrors)
|
|
{
|
|
$errorMessage = ($LocalizedData.ScriptParseError -f $scriptFilePath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "ScriptParseError" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $errosAfterSkippingOneCoreErrors `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
if($ast)
|
|
{
|
|
# Get the block/group comment begining with <#PSScriptInfo
|
|
$CommentTokens = $tokens | Microsoft.PowerShell.Core\Where-Object {$_.Kind -eq 'Comment'}
|
|
|
|
$psscriptInfoComments = $CommentTokens |
|
|
Microsoft.PowerShell.Core\Where-Object { $_.Extent.Text -match "<#PSScriptInfo" } |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $psscriptInfoComments)
|
|
{
|
|
$errorMessage = ($LocalizedData.MissingPSScriptInfo -f $scriptFilePath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "MissingPSScriptInfo" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $scriptFilePath `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
# $psscriptInfoComments.Text will have the multiline PSScriptInfo comment,
|
|
# split them into multiple lines to parse for the PSScriptInfo metadata properties.
|
|
$commentLines = $psscriptInfoComments.Text -split "`r`n"
|
|
|
|
$KeyName = $null
|
|
$Value = ""
|
|
|
|
# PSScriptInfo comment will be in following format:
|
|
<#PSScriptInfo
|
|
|
|
.VERSION 1.0
|
|
|
|
.GUID 544238e3-1751-4065-9227-be105ff11636
|
|
|
|
.AUTHOR manikb
|
|
|
|
.COMPANYNAME Microsoft Corporation
|
|
|
|
.COPYRIGHT (c) 2015 Microsoft Corporation. All rights reserved.
|
|
|
|
.TAGS Tag1 Tag2 Tag3
|
|
|
|
.LICENSEURI https://contoso.com/License
|
|
|
|
.PROJECTURI https://contoso.com/
|
|
|
|
.ICONURI https://contoso.com/Icon
|
|
|
|
.EXTERNALMODULEDEPENDENCIES ExternalModule1
|
|
|
|
.REQUIREDSCRIPTS Start-WFContosoServer,Stop-ContosoServerScript
|
|
|
|
.EXTERNALSCRIPTDEPENDENCIES Stop-ContosoServerScript
|
|
|
|
.RELEASENOTES
|
|
contoso script now supports following features
|
|
Feature 1
|
|
Feature 2
|
|
Feature 3
|
|
Feature 4
|
|
Feature 5
|
|
|
|
#>
|
|
# If comment line count is not more than two, it doesn't have the any metadata property
|
|
# First line is <#PSScriptInfo
|
|
# Last line #>
|
|
#
|
|
if($commentLines.Count -gt 2)
|
|
{
|
|
for($i = 1; $i -lt ($commentLines.count - 1); $i++)
|
|
{
|
|
$line = $commentLines[$i]
|
|
|
|
if(-not $line)
|
|
{
|
|
continue
|
|
}
|
|
|
|
# A line is starting with . conveys a new metadata property
|
|
# __NEWLINE__ is used for replacing the value lines while adding the value to $PSScriptInfo object
|
|
#
|
|
if($line.trim().StartsWith('.'))
|
|
{
|
|
$parts = $line.trim() -split '[.\s+]',3 | Microsoft.PowerShell.Core\Where-Object {$_}
|
|
|
|
if($KeyName -and $Value)
|
|
{
|
|
if($keyName -eq $script:ReleaseNotes)
|
|
{
|
|
$Value = $Value.Trim() -split '__NEWLINE__'
|
|
}
|
|
elseif($keyName -eq $script:DESCRIPTION)
|
|
{
|
|
$Value = $Value -split '__NEWLINE__'
|
|
$Value = ($Value -join "`r`n").Trim()
|
|
}
|
|
else
|
|
{
|
|
$Value = $Value -split '__NEWLINE__' | Microsoft.PowerShell.Core\Where-Object { $_ }
|
|
|
|
if($Value -and $Value.GetType().ToString() -eq "System.String")
|
|
{
|
|
$Value = $Value.Trim()
|
|
}
|
|
}
|
|
|
|
ValidateAndAdd-PSScriptInfoEntry -PSScriptInfo $PSScriptInfo `
|
|
-PropertyName $KeyName `
|
|
-PropertyValue $Value `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
}
|
|
|
|
$KeyName = $null
|
|
$Value = ""
|
|
|
|
if($parts.GetType().ToString() -eq "System.String")
|
|
{
|
|
$KeyName = $parts
|
|
}
|
|
else
|
|
{
|
|
$KeyName = $parts[0];
|
|
$Value = $parts[1]
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if($Value)
|
|
{
|
|
# __NEWLINE__ is used for replacing the value lines while adding the value to $PSScriptInfo object
|
|
$Value += '__NEWLINE__'
|
|
}
|
|
|
|
$Value += $line
|
|
}
|
|
}
|
|
|
|
if($KeyName -and $Value)
|
|
{
|
|
if($keyName -eq $script:ReleaseNotes)
|
|
{
|
|
$Value = $Value.Trim() -split '__NEWLINE__'
|
|
}
|
|
elseif($keyName -eq $script:DESCRIPTION)
|
|
{
|
|
$Value = $Value -split '__NEWLINE__'
|
|
$Value = ($Value -join "`r`n").Trim()
|
|
}
|
|
else
|
|
{
|
|
$Value = $Value -split '__NEWLINE__' | Microsoft.PowerShell.Core\Where-Object { $_ }
|
|
|
|
if($Value -and $Value.GetType().ToString() -eq "System.String")
|
|
{
|
|
$Value = $Value.Trim()
|
|
}
|
|
}
|
|
|
|
ValidateAndAdd-PSScriptInfoEntry -PSScriptInfo $PSScriptInfo `
|
|
-PropertyName $KeyName `
|
|
-PropertyValue $Value `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
|
|
$KeyName = $null
|
|
$Value = ""
|
|
}
|
|
}
|
|
|
|
$helpContent = $ast.GetHelpContent()
|
|
if($helpContent -and $helpContent.Description)
|
|
{
|
|
ValidateAndAdd-PSScriptInfoEntry -PSScriptInfo $PSScriptInfo `
|
|
-PropertyName $script:DESCRIPTION `
|
|
-PropertyValue $helpContent.Description.Trim() `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
|
|
}
|
|
|
|
# Handle RequiredModules
|
|
if((Microsoft.PowerShell.Utility\Get-Member -InputObject $ast -Name 'ScriptRequirements') -and
|
|
$ast.ScriptRequirements -and
|
|
(Microsoft.PowerShell.Utility\Get-Member -InputObject $ast.ScriptRequirements -Name 'RequiredModules') -and
|
|
$ast.ScriptRequirements.RequiredModules)
|
|
{
|
|
ValidateAndAdd-PSScriptInfoEntry -PSScriptInfo $PSScriptInfo `
|
|
-PropertyName $script:RequiredModules `
|
|
-PropertyValue $ast.ScriptRequirements.RequiredModules `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
}
|
|
|
|
# Get all defined functions and populate DefinedCommands, DefinedFunctions and DefinedWorkflows
|
|
$allCommands = $ast.FindAll({param($i) return ($i.GetType().Name -eq 'FunctionDefinitionAst')}, $true)
|
|
|
|
if($allCommands)
|
|
{
|
|
$allCommandNames = $allCommands | ForEach-Object {$_.Name} | Select-Object -Unique
|
|
ValidateAndAdd-PSScriptInfoEntry -PSScriptInfo $PSScriptInfo `
|
|
-PropertyName $script:DefinedCommands `
|
|
-PropertyValue $allCommandNames `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
|
|
$allFunctionNames = $allCommands | Where-Object {-not $_.IsWorkflow} | ForEach-Object {$_.Name} | Select-Object -Unique
|
|
ValidateAndAdd-PSScriptInfoEntry -PSScriptInfo $PSScriptInfo `
|
|
-PropertyName $script:DefinedFunctions `
|
|
-PropertyValue $allFunctionNames `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
|
|
|
|
$allWorkflowNames = $allCommands | Where-Object {$_.IsWorkflow} | ForEach-Object {$_.Name} | Select-Object -Unique
|
|
ValidateAndAdd-PSScriptInfoEntry -PSScriptInfo $PSScriptInfo `
|
|
-PropertyName $script:DefinedWorkflows `
|
|
-PropertyValue $allWorkflowNames `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
}
|
|
}
|
|
|
|
# Ensure that the script file has the required metadata properties.
|
|
if(-not $PSScriptInfo.Version -or -not $PSScriptInfo.Guid -or -not $PSScriptInfo.Author -or -not $PSScriptInfo.Description)
|
|
{
|
|
$errorMessage = ($LocalizedData.MissingRequiredPSScriptInfoProperties -f $scriptFilePath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "MissingRequiredPSScriptInfoProperties" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $Path `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
$PSScriptInfo = Get-OrderedPSScriptInfoObject -PSScriptInfo $PSScriptInfo
|
|
|
|
return $PSScriptInfo
|
|
}
|
|
}
|
|
|
|
function New-ScriptFileInfo
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(PositionalBinding=$false,
|
|
SupportsShouldProcess=$true,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619792')]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$false,
|
|
Position=0,
|
|
ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Path,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$Version,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Author,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Guid]
|
|
$Guid,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$CompanyName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Copyright,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Object[]]
|
|
$RequiredModules,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$ExternalModuleDependencies,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$RequiredScripts,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$ExternalScriptDependencies,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Tags,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$ProjectUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$LicenseUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$IconUri,
|
|
|
|
[Parameter()]
|
|
[string[]]
|
|
$ReleaseNotes,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$PassThru,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
Process
|
|
{
|
|
if($Path)
|
|
{
|
|
if(-not $Path.EndsWith('.ps1', [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$errorMessage = ($LocalizedData.InvalidScriptFilePath -f $Path)
|
|
ThrowError -ExceptionName 'System.ArgumentException' `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId 'InvalidScriptFilePath' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $Path `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
if(-not $Force -and (Microsoft.PowerShell.Management\Test-Path -Path $Path))
|
|
{
|
|
$errorMessage = ($LocalizedData.ScriptFileExist -f $Path)
|
|
ThrowError -ExceptionName 'System.ArgumentException' `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId 'ScriptFileExist' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $Path `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
}
|
|
elseif(-not $PassThru)
|
|
{
|
|
ThrowError -ExceptionName 'System.ArgumentException' `
|
|
-ExceptionMessage $LocalizedData.MissingTheRequiredPathOrPassThruParameter `
|
|
-ErrorId 'MissingTheRequiredPathOrPassThruParameter' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
if(-not $Version)
|
|
{
|
|
$Version = [Version]'1.0'
|
|
}
|
|
|
|
if(-not $Author)
|
|
{
|
|
$Author = (Get-EnvironmentVariable -Name 'USERNAME' -Target $script:EnvironmentVariableTarget.Process -ErrorAction SilentlyContinue)
|
|
}
|
|
|
|
if(-not $Guid)
|
|
{
|
|
$Guid = [System.Guid]::NewGuid()
|
|
}
|
|
|
|
$params = @{
|
|
Version = $Version
|
|
Author = $Author
|
|
Guid = $Guid
|
|
CompanyName = $CompanyName
|
|
Copyright = $Copyright
|
|
ExternalModuleDependencies = $ExternalModuleDependencies
|
|
RequiredScripts = $RequiredScripts
|
|
ExternalScriptDependencies = $ExternalScriptDependencies
|
|
Tags = $Tags
|
|
ProjectUri = $ProjectUri
|
|
LicenseUri = $LicenseUri
|
|
IconUri = $IconUri
|
|
ReleaseNotes = $ReleaseNotes
|
|
}
|
|
|
|
if(-not (Validate-ScriptFileInfoParameters -parameters $params))
|
|
{
|
|
return
|
|
}
|
|
|
|
if("$Description" -match '<#' -or "$Description" -match '#>')
|
|
{
|
|
$message = $LocalizedData.InvalidParameterValue -f ($Description, 'Description')
|
|
Write-Error -Message $message -ErrorId 'InvalidParameterValue' -Category InvalidArgument
|
|
|
|
return
|
|
}
|
|
|
|
$PSScriptInfoString = Get-PSScriptInfoString @params
|
|
|
|
$requiresStrings = Get-RequiresString -RequiredModules $RequiredModules
|
|
|
|
$ScriptCommentHelpInfoString = Get-ScriptCommentHelpInfoString -Description $Description
|
|
|
|
$ScriptMetadataString = $PSScriptInfoString
|
|
$ScriptMetadataString += "`r`n"
|
|
|
|
if("$requiresStrings".Trim())
|
|
{
|
|
$ScriptMetadataString += "`r`n"
|
|
$ScriptMetadataString += $requiresStrings -join "`r`n"
|
|
$ScriptMetadataString += "`r`n"
|
|
}
|
|
|
|
$ScriptMetadataString += "`r`n"
|
|
$ScriptMetadataString += $ScriptCommentHelpInfoString
|
|
$ScriptMetadataString += "Param()`r`n`r`n"
|
|
|
|
$tempScriptFilePath = Microsoft.PowerShell.Management\Join-Path -Path $env:TEMP -ChildPath "$(Get-Random).ps1"
|
|
|
|
try
|
|
{
|
|
Microsoft.PowerShell.Management\Set-Content -Value $ScriptMetadataString -Path $tempScriptFilePath -Force -WhatIf:$false -Confirm:$false
|
|
|
|
$scriptInfo = Test-ScriptFileInfo -Path $tempScriptFilePath
|
|
|
|
if(-not $scriptInfo)
|
|
{
|
|
# Above Test-ScriptFileInfo cmdlet writes the errors
|
|
return
|
|
}
|
|
|
|
if($Path -and ($Force -or $PSCmdlet.ShouldProcess($Path, ($LocalizedData.NewScriptFileInfowhatIfMessage -f $Path) )))
|
|
{
|
|
Microsoft.PowerShell.Management\Copy-Item -Path $tempScriptFilePath -Destination $Path -Force -WhatIf:$false -Confirm:$false
|
|
}
|
|
|
|
if($PassThru)
|
|
{
|
|
Write-Output -InputObject $ScriptMetadataString
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $tempScriptFilePath -Force -WhatIf:$false -Confirm:$false -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
|
|
}
|
|
}
|
|
}
|
|
|
|
function Update-ScriptFileInfo
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(PositionalBinding=$false,
|
|
DefaultParameterSetName='PathParameterSet',
|
|
SupportsShouldProcess=$true,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619793')]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
Position=0,
|
|
ParameterSetName='PathParameterSet',
|
|
ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Path,
|
|
|
|
[Parameter(Mandatory=$true,
|
|
Position=0,
|
|
ParameterSetName='LiteralPathParameterSet',
|
|
ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$LiteralPath,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$Version,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Author,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Guid]
|
|
$Guid,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$CompanyName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Copyright,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Object[]]
|
|
$RequiredModules,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$ExternalModuleDependencies,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$RequiredScripts,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$ExternalScriptDependencies,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Tags,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$ProjectUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$LicenseUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$IconUri,
|
|
|
|
[Parameter()]
|
|
[string[]]
|
|
$ReleaseNotes,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$PassThru,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$Force
|
|
)
|
|
|
|
Process
|
|
{
|
|
$scriptFilePath = $null
|
|
if($Path)
|
|
{
|
|
$scriptFilePath = Resolve-PathHelper -Path $Path -CallerPSCmdlet $PSCmdlet |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $scriptFilePath -or
|
|
-not (Microsoft.PowerShell.Management\Test-Path -Path $scriptFilePath -PathType Leaf))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $Path)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $Path `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$scriptFilePath = Resolve-PathHelper -Path $LiteralPath -IsLiteralPath -CallerPSCmdlet $PSCmdlet |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $scriptFilePath -or
|
|
-not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $scriptFilePath -PathType Leaf))
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $LiteralPath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $LiteralPath `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
|
|
if(-not $scriptFilePath.EndsWith('.ps1', [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$errorMessage = ($LocalizedData.InvalidScriptFilePath -f $scriptFilePath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "InvalidScriptFilePath" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $scriptFilePath `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
$psscriptInfo = $null
|
|
try
|
|
{
|
|
$psscriptInfo = Test-ScriptFileInfo -LiteralPath $scriptFilePath
|
|
}
|
|
catch
|
|
{
|
|
if(-not $Force)
|
|
{
|
|
throw $_
|
|
return
|
|
}
|
|
}
|
|
|
|
if(-not $psscriptInfo)
|
|
{
|
|
if(-not $Description)
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.DescriptionParameterIsMissingForAddingTheScriptFileInfo `
|
|
-ErrorId 'DescriptionParameterIsMissingForAddingTheScriptFileInfo' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
if(-not $Version)
|
|
{
|
|
$Version = [Version]'1.0'
|
|
}
|
|
|
|
if(-not $Author)
|
|
{
|
|
$Author = (Get-EnvironmentVariable -Name 'USERNAME' -Target $script:EnvironmentVariableTarget.Process -ErrorAction SilentlyContinue)
|
|
}
|
|
|
|
if(-not $Guid)
|
|
{
|
|
$Guid = [System.Guid]::NewGuid()
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Use existing values if any of the parameters are not specified during Update-ScriptFileInfo
|
|
if(-not $Version -and $psscriptInfo.Version)
|
|
{
|
|
$Version = $psscriptInfo.Version
|
|
}
|
|
|
|
if(-not $Guid -and $psscriptInfo.Guid)
|
|
{
|
|
$Guid = $psscriptInfo.Guid
|
|
}
|
|
|
|
if(-not $Author -and $psscriptInfo.Author)
|
|
{
|
|
$Author = $psscriptInfo.Author
|
|
}
|
|
|
|
if(-not $CompanyName -and $psscriptInfo.CompanyName)
|
|
{
|
|
$CompanyName = $psscriptInfo.CompanyName
|
|
}
|
|
|
|
if(-not $Copyright -and $psscriptInfo.Copyright)
|
|
{
|
|
$Copyright = $psscriptInfo.Copyright
|
|
}
|
|
|
|
if(-not $RequiredModules -and $psscriptInfo.RequiredModules)
|
|
{
|
|
$RequiredModules = $psscriptInfo.RequiredModules
|
|
}
|
|
|
|
if(-not $ExternalModuleDependencies -and $psscriptInfo.ExternalModuleDependencies)
|
|
{
|
|
$ExternalModuleDependencies = $psscriptInfo.ExternalModuleDependencies
|
|
}
|
|
|
|
if(-not $RequiredScripts -and $psscriptInfo.RequiredScripts)
|
|
{
|
|
$RequiredScripts = $psscriptInfo.RequiredScripts
|
|
}
|
|
|
|
if(-not $ExternalScriptDependencies -and $psscriptInfo.ExternalScriptDependencies)
|
|
{
|
|
$ExternalScriptDependencies = $psscriptInfo.ExternalScriptDependencies
|
|
}
|
|
|
|
if(-not $Tags -and $psscriptInfo.Tags)
|
|
{
|
|
$Tags = $psscriptInfo.Tags
|
|
}
|
|
|
|
if(-not $ProjectUri -and $psscriptInfo.ProjectUri)
|
|
{
|
|
$ProjectUri = $psscriptInfo.ProjectUri
|
|
}
|
|
|
|
if(-not $LicenseUri -and $psscriptInfo.LicenseUri)
|
|
{
|
|
$LicenseUri = $psscriptInfo.LicenseUri
|
|
}
|
|
|
|
if(-not $IconUri -and $psscriptInfo.IconUri)
|
|
{
|
|
$IconUri = $psscriptInfo.IconUri
|
|
}
|
|
|
|
if(-not $ReleaseNotes -and $psscriptInfo.ReleaseNotes)
|
|
{
|
|
$ReleaseNotes = $psscriptInfo.ReleaseNotes
|
|
}
|
|
}
|
|
|
|
$params = @{
|
|
Version = $Version
|
|
Author = $Author
|
|
Guid = $Guid
|
|
CompanyName = $CompanyName
|
|
Copyright = $Copyright
|
|
ExternalModuleDependencies = $ExternalModuleDependencies
|
|
RequiredScripts = $RequiredScripts
|
|
ExternalScriptDependencies = $ExternalScriptDependencies
|
|
Tags = $Tags
|
|
ProjectUri = $ProjectUri
|
|
LicenseUri = $LicenseUri
|
|
IconUri = $IconUri
|
|
ReleaseNotes = $ReleaseNotes
|
|
}
|
|
|
|
if(-not (Validate-ScriptFileInfoParameters -parameters $params))
|
|
{
|
|
return
|
|
}
|
|
|
|
if("$Description" -match '<#' -or "$Description" -match '#>')
|
|
{
|
|
$message = $LocalizedData.InvalidParameterValue -f ($Description, 'Description')
|
|
Write-Error -Message $message -ErrorId 'InvalidParameterValue' -Category InvalidArgument
|
|
|
|
return
|
|
}
|
|
|
|
$PSScriptInfoString = Get-PSScriptInfoString @params
|
|
|
|
$requiresStrings = ""
|
|
$requiresStrings = Get-RequiresString -RequiredModules $RequiredModules
|
|
|
|
$DescriptionValue = if($Description) {$Description} else {$psscriptInfo.Description}
|
|
$ScriptCommentHelpInfoString = Get-ScriptCommentHelpInfoString -Description $DescriptionValue
|
|
|
|
$ScriptMetadataString = $PSScriptInfoString
|
|
$ScriptMetadataString += "`r`n"
|
|
|
|
if("$requiresStrings".Trim())
|
|
{
|
|
$ScriptMetadataString += "`r`n"
|
|
$ScriptMetadataString += $requiresStrings -join "`r`n"
|
|
$ScriptMetadataString += "`r`n"
|
|
}
|
|
|
|
$ScriptMetadataString += "`r`n"
|
|
$ScriptMetadataString += $ScriptCommentHelpInfoString
|
|
$ScriptMetadataString += "`r`nParam()`r`n`r`n"
|
|
if(-not $ScriptMetadataString)
|
|
{
|
|
return
|
|
}
|
|
|
|
$tempScriptFilePath = Microsoft.PowerShell.Management\Join-Path -Path $env:TEMP -ChildPath "$(Get-Random).ps1"
|
|
|
|
try
|
|
{
|
|
# First create a new script file with new script metadata to ensure that updated values are valid.
|
|
Microsoft.PowerShell.Management\Set-Content -Value $ScriptMetadataString -Path $tempScriptFilePath -Force -WhatIf:$false -Confirm:$false
|
|
|
|
$scriptInfo = Test-ScriptFileInfo -Path $tempScriptFilePath
|
|
|
|
if(-not $scriptInfo)
|
|
{
|
|
# Above Test-ScriptFileInfo cmdlet writes the error
|
|
return
|
|
}
|
|
|
|
$scriptFileContents = Microsoft.PowerShell.Management\Get-Content -LiteralPath $scriptFilePath
|
|
|
|
# If -Force is specified and script file doesnt have a valid PSScriptInfo
|
|
# Prepend the PSScriptInfo and Check if the Test-ScriptFileInfo returns a valid script info without any errors
|
|
if($Force -and -not $psscriptInfo)
|
|
{
|
|
# Add the script file contents to the temp file with script metadata
|
|
Microsoft.PowerShell.Management\Set-Content -LiteralPath $tempScriptFilePath `
|
|
-Value $ScriptMetadataString,$scriptFileContents `
|
|
-Force `
|
|
-WhatIf:$false `
|
|
-Confirm:$false
|
|
|
|
$tempScriptInfo = $null
|
|
try
|
|
{
|
|
$tempScriptInfo = Test-ScriptFileInfo -LiteralPath $tempScriptFilePath
|
|
}
|
|
catch
|
|
{
|
|
$errorMessage = ($LocalizedData.UnableToAddPSScriptInfo -f $scriptFilePath)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId 'UnableToAddPSScriptInfo' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $scriptFilePath `
|
|
-ErrorCategory InvalidOperation
|
|
return
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[System.Management.Automation.Language.Token[]]$tokens = $null;
|
|
[System.Management.Automation.Language.ParseError[]]$errors = $null;
|
|
$ast = [System.Management.Automation.Language.Parser]::ParseFile($scriptFilePath, ([ref]$tokens), ([ref]$errors))
|
|
|
|
# Update PSScriptInfo and #Requires
|
|
$CommentTokens = $tokens | Microsoft.PowerShell.Core\Where-Object {$_.Kind -eq 'Comment'}
|
|
|
|
$psscriptInfoComments = $CommentTokens |
|
|
Microsoft.PowerShell.Core\Where-Object { $_.Extent.Text -match "<#PSScriptInfo" } |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
if(-not $psscriptInfoComments)
|
|
{
|
|
$errorMessage = ($LocalizedData.MissingPSScriptInfo -f $scriptFilePath)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "MissingPSScriptInfo" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ExceptionObject $scriptFilePath `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
# Ensure that metadata is replaced at the correct location and should not corrupt the existing script file.
|
|
|
|
# Remove the lines between below lines and add the new PSScriptInfo and new #Requires statements
|
|
# ($psscriptInfoComments.Extent.StartLineNumber - 1)
|
|
# ($psscriptInfoComments.Extent.EndLineNumber - 1)
|
|
$tempContents = @()
|
|
$IsNewPScriptInfoAdded = $false
|
|
|
|
for($i = 0; $i -lt $scriptFileContents.Count; $i++)
|
|
{
|
|
$line = $scriptFileContents[$i]
|
|
if(($i -ge ($psscriptInfoComments.Extent.StartLineNumber - 1)) -and
|
|
($i -le ($psscriptInfoComments.Extent.EndLineNumber - 1)))
|
|
{
|
|
if(-not $IsNewPScriptInfoAdded)
|
|
{
|
|
$PSScriptInfoString = $PSScriptInfoString.TrimStart()
|
|
$requiresStrings = $requiresStrings.TrimEnd()
|
|
|
|
$tempContents += "$PSScriptInfoString `r`n`r`n$($requiresStrings -join "`r`n")"
|
|
$IsNewPScriptInfoAdded = $true
|
|
}
|
|
}
|
|
elseif($line -notmatch "\s*#Requires\s+-Module")
|
|
{
|
|
# Add the existing lines if they are not part of PSScriptInfo comment or not containing #Requires -Module statements.
|
|
$tempContents += $line
|
|
}
|
|
}
|
|
|
|
Microsoft.PowerShell.Management\Set-Content -Value $tempContents -Path $tempScriptFilePath -Force -WhatIf:$false -Confirm:$false
|
|
|
|
$scriptInfo = Test-ScriptFileInfo -Path $tempScriptFilePath
|
|
|
|
if(-not $scriptInfo)
|
|
{
|
|
# Above Test-ScriptFileInfo cmdlet writes the error
|
|
return
|
|
}
|
|
|
|
# Now update the Description value if a new is specified.
|
|
if($Description)
|
|
{
|
|
$tempContents = @()
|
|
$IsDescriptionAdded = $false
|
|
|
|
$IsDescriptionBeginFound = $false
|
|
$scriptFileContents = Microsoft.PowerShell.Management\Get-Content -Path $tempScriptFilePath
|
|
|
|
for($i = 0; $i -lt $scriptFileContents.Count; $i++)
|
|
{
|
|
$line = $scriptFileContents[$i]
|
|
|
|
if(-not $IsDescriptionAdded)
|
|
{
|
|
if(-not $IsDescriptionBeginFound)
|
|
{
|
|
if($line.Trim().StartsWith(".DESCRIPTION", [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$IsDescriptionBeginFound = $true
|
|
}
|
|
else
|
|
{
|
|
$tempContents += $line
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Description begin has found
|
|
# Skip the old description lines until description end is found
|
|
|
|
if($line.Trim().StartsWith("#>", [System.StringComparison]::OrdinalIgnoreCase) -or
|
|
$line.Trim().StartsWith(".", [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$tempContents += ".DESCRIPTION `r`n$($Description -join "`r`n")`r`n"
|
|
$IsDescriptionAdded = $true
|
|
$tempContents += $line
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$tempContents += $line
|
|
}
|
|
}
|
|
|
|
Microsoft.PowerShell.Management\Set-Content -Value $tempContents -Path $tempScriptFilePath -Force -WhatIf:$false -Confirm:$false
|
|
|
|
$scriptInfo = Test-ScriptFileInfo -Path $tempScriptFilePath
|
|
|
|
if(-not $scriptInfo)
|
|
{
|
|
# Above Test-ScriptFileInfo cmdlet writes the error
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if($Force -or $PSCmdlet.ShouldProcess($scriptFilePath, ($LocalizedData.UpdateScriptFileInfowhatIfMessage -f $Path) ))
|
|
{
|
|
Microsoft.PowerShell.Management\Copy-Item -Path $tempScriptFilePath -Destination $scriptFilePath -Force -WhatIf:$false -Confirm:$false
|
|
|
|
if($PassThru)
|
|
{
|
|
$ScriptMetadataString
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $tempScriptFilePath -Force -WhatIf:$false -Confirm:$false -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
|
|
}
|
|
}
|
|
}
|
|
|
|
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 [Version]'3.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-PSScriptInfoString
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$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
|
|
)
|
|
|
|
Process
|
|
{
|
|
$PSScriptInfoString = @"
|
|
|
|
<#PSScriptInfo
|
|
|
|
.VERSION $Version
|
|
|
|
.GUID $Guid
|
|
|
|
.AUTHOR $Author
|
|
|
|
.COMPANYNAME $CompanyName
|
|
|
|
.COPYRIGHT $Copyright
|
|
|
|
.TAGS $Tags
|
|
|
|
.LICENSEURI $LicenseUri
|
|
|
|
.PROJECTURI $ProjectUri
|
|
|
|
.ICONURI $IconUri
|
|
|
|
.EXTERNALMODULEDEPENDENCIES $($ExternalModuleDependencies -join ',')
|
|
|
|
.REQUIREDSCRIPTS $($RequiredScripts -join ',')
|
|
|
|
.EXTERNALSCRIPTDEPENDENCIES $($ExternalScriptDependencies -join ',')
|
|
|
|
.RELEASENOTES
|
|
$($ReleaseNotes -join "`r`n")
|
|
|
|
#>
|
|
"@
|
|
return $PSScriptInfoString
|
|
}
|
|
}
|
|
|
|
function Validate-ScriptFileInfoParameters
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[PSCustomObject]
|
|
$Parameters
|
|
)
|
|
|
|
$hasErrors = $false
|
|
|
|
$Parameters.Keys | ForEach-Object {
|
|
|
|
$parameterName = $_
|
|
|
|
$parameterValue = $($Parameters[$parameterName])
|
|
|
|
if("$parameterValue" -match '<#' -or "$parameterValue" -match '#>')
|
|
{
|
|
$message = $LocalizedData.InvalidParameterValue -f ($parameterValue, $parameterName)
|
|
Write-Error -Message $message -ErrorId 'InvalidParameterValue' -Category InvalidArgument
|
|
|
|
$hasErrors = $true
|
|
}
|
|
}
|
|
|
|
return (-not $hasErrors)
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
#endregion *-ScriptFileInfo cmdlets
|
|
|
|
#region Utility functions
|
|
|
|
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-ParametersHashtable
|
|
{
|
|
param(
|
|
$Proxy,
|
|
$ProxyCredential
|
|
)
|
|
|
|
$ParametersHashtable = @{}
|
|
if($Proxy)
|
|
{
|
|
$ParametersHashtable[$script:Proxy] = $Proxy
|
|
}
|
|
|
|
if($ProxyCredential)
|
|
{
|
|
$ParametersHashtable[$script:ProxyCredential] = $ProxyCredential
|
|
}
|
|
|
|
return $ParametersHashtable
|
|
}
|
|
|
|
function ToUpper
|
|
{
|
|
param([string]$str)
|
|
return $script:TextInfo.ToUpper($str)
|
|
}
|
|
|
|
function Resolve-PathHelper
|
|
{
|
|
param
|
|
(
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$path,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$isLiteralPath,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCmdlet]
|
|
$callerPSCmdlet
|
|
)
|
|
|
|
$resolvedPaths =@()
|
|
|
|
foreach($currentPath in $path)
|
|
{
|
|
try
|
|
{
|
|
if($isLiteralPath)
|
|
{
|
|
$currentResolvedPaths = Microsoft.PowerShell.Management\Resolve-Path -LiteralPath $currentPath -ErrorAction Stop
|
|
}
|
|
else
|
|
{
|
|
$currentResolvedPaths = Microsoft.PowerShell.Management\Resolve-Path -Path $currentPath -ErrorAction Stop
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
$errorMessage = ($LocalizedData.PathNotFound -f $currentPath)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $errorMessage `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $callerPSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
|
|
foreach($currentResolvedPath in $currentResolvedPaths)
|
|
{
|
|
$resolvedPaths += $currentResolvedPath.ProviderPath
|
|
}
|
|
}
|
|
|
|
$resolvedPaths
|
|
}
|
|
|
|
function Check-PSGalleryApiAvailability
|
|
{
|
|
param
|
|
(
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$PSGalleryV2ApiUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$PSGalleryV3ApiUri
|
|
)
|
|
|
|
# check internet availability first
|
|
$connected = $false
|
|
$microsoftDomain = 'www.microsoft.com'
|
|
if(Get-Command Microsoft.PowerShell.Management\Test-Connection -ErrorAction SilentlyContinue)
|
|
{
|
|
$connected = Microsoft.PowerShell.Management\Test-Connection -ComputerName $microsoftDomain -Count 1 -Quiet
|
|
}
|
|
else
|
|
{
|
|
$connected = NetTCPIP\Test-NetConnection -ComputerName $microsoftDomain -InformationLevel Quiet
|
|
}
|
|
if ( -not $connected)
|
|
{
|
|
return
|
|
}
|
|
|
|
$statusCode_v2 = $null
|
|
$resolvedUri_v2 = $null
|
|
$statusCode_v3 = $null
|
|
$resolvedUri_v3 = $null
|
|
|
|
# ping V2
|
|
$res_v2 = Ping-Endpoint -Endpoint $PSGalleryV2ApiUri
|
|
if ($res_v2.ContainsKey($Script:ResponseUri))
|
|
{
|
|
$resolvedUri_v2 = $res_v2[$Script:ResponseUri]
|
|
}
|
|
if ($res_v2.ContainsKey($Script:StatusCode))
|
|
{
|
|
$statusCode_v2 = $res_v2[$Script:StatusCode]
|
|
}
|
|
|
|
|
|
# ping V3
|
|
$res_v3 = Ping-Endpoint -Endpoint $PSGalleryV3ApiUri
|
|
if ($res_v3.ContainsKey($Script:ResponseUri))
|
|
{
|
|
$resolvedUri_v3 = $res_v3[$Script:ResponseUri]
|
|
}
|
|
if ($res_v3.ContainsKey($Script:StatusCode))
|
|
{
|
|
$statusCode_v3 = $res_v3[$Script:StatusCode]
|
|
}
|
|
|
|
|
|
$Script:PSGalleryV2ApiAvailable = (($statusCode_v2 -eq 200) -and ($resolvedUri_v2))
|
|
$Script:PSGalleryV3ApiAvailable = (($statusCode_v3 -eq 200) -and ($resolvedUri_v3))
|
|
$Script:PSGalleryApiChecked = $true
|
|
}
|
|
|
|
function Get-PSGalleryApiAvailability
|
|
{
|
|
param
|
|
(
|
|
[Parameter()]
|
|
[string[]]
|
|
$Repository
|
|
)
|
|
|
|
# skip if repository is null or not PSGallery
|
|
if ( -not $Repository)
|
|
{
|
|
return
|
|
}
|
|
|
|
if ($Repository -notcontains $Script:PSGalleryModuleSource )
|
|
{
|
|
return
|
|
}
|
|
|
|
# run check only once
|
|
if( -not $Script:PSGalleryApiChecked)
|
|
{
|
|
$null = Check-PSGalleryApiAvailability -PSGalleryV2ApiUri $Script:PSGallerySourceUri -PSGalleryV3ApiUri $Script:PSGalleryV3SourceUri
|
|
}
|
|
|
|
if ( -not $Script:PSGalleryV2ApiAvailable )
|
|
{
|
|
if ($Script:PSGalleryV3ApiAvailable)
|
|
{
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $LocalizedData.PSGalleryApiV2Discontinued `
|
|
-ErrorId "PSGalleryApiV2Discontinued" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
else
|
|
{
|
|
# both APIs are down, throw error
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $LocalizedData.PowerShellGalleryUnavailable `
|
|
-ErrorId "PowerShellGalleryUnavailable" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if ($Script:PSGalleryV3ApiAvailable)
|
|
{
|
|
Write-Warning -Message $LocalizedData.PSGalleryApiV2Deprecated
|
|
return
|
|
}
|
|
}
|
|
|
|
# if V2 is available and V3 is not available, do nothing
|
|
}
|
|
|
|
function HttpClientApisAvailable
|
|
{
|
|
$HttpClientApisAvailable = $false
|
|
try
|
|
{
|
|
[System.Net.Http.HttpClient]
|
|
$HttpClientApisAvailable = $true
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return $HttpClientApisAvailable
|
|
}
|
|
|
|
function Ping-Endpoint
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Endpoint,
|
|
|
|
[Parameter()]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
$Proxy,
|
|
|
|
[Parameter()]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$AllowAutoRedirect = $true
|
|
)
|
|
|
|
$results = @{}
|
|
|
|
$WebProxy = $null
|
|
if($Proxy)
|
|
{
|
|
$ProxyNetworkCredential = $null
|
|
if($ProxyCredential)
|
|
{
|
|
$ProxyNetworkCredential = $ProxyCredential.GetNetworkCredential()
|
|
}
|
|
|
|
$WebProxy = New-Object Microsoft.PowerShell.Get.InternalWebProxy -ArgumentList $Proxy,$ProxyNetworkCredential
|
|
}
|
|
|
|
if(HttpClientApisAvailable)
|
|
{
|
|
$response = $null
|
|
try
|
|
{
|
|
$handler = New-Object System.Net.Http.HttpClientHandler
|
|
|
|
if($Credential)
|
|
{
|
|
$handler.Credentials = $Credential.GetNetworkCredential()
|
|
}
|
|
else
|
|
{
|
|
$handler.UseDefaultCredentials = $true
|
|
}
|
|
|
|
if($WebProxy)
|
|
{
|
|
$handler.Proxy = $WebProxy
|
|
}
|
|
|
|
$httpClient = New-Object System.Net.Http.HttpClient -ArgumentList $handler
|
|
$response = $httpclient.GetAsync($endpoint)
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
if ($response -ne $null -and $response.result -ne $null)
|
|
{
|
|
$results.Add($Script:ResponseUri,$response.Result.RequestMessage.RequestUri.AbsoluteUri.ToString())
|
|
$results.Add($Script:StatusCode,$response.result.StatusCode.value__)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$iss = [System.Management.Automation.Runspaces.InitialSessionState]::Create()
|
|
$iss.types.clear()
|
|
$iss.formats.clear()
|
|
$iss.LanguageMode = "FullLanguage"
|
|
|
|
$WebRequestcmd = @'
|
|
param($Credential, $WebProxy)
|
|
|
|
try
|
|
{{
|
|
$request = [System.Net.WebRequest]::Create("{0}")
|
|
$request.Method = 'GET'
|
|
$request.Timeout = 30000
|
|
if($Credential)
|
|
{{
|
|
$request.Credentials = $Credential.GetNetworkCredential()
|
|
}}
|
|
else
|
|
{{
|
|
$request.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
|
|
}}
|
|
|
|
$request.AllowAutoRedirect = ${1}
|
|
|
|
if($WebProxy)
|
|
{{
|
|
$request.Proxy = $WebProxy
|
|
}}
|
|
|
|
$response = [System.Net.HttpWebResponse]$request.GetResponse()
|
|
if($response.StatusCode.value__ -eq 302)
|
|
{{
|
|
$response.Headers["Location"].ToString()
|
|
}}
|
|
else
|
|
{{
|
|
$response
|
|
}}
|
|
$response.Close()
|
|
}}
|
|
catch [System.Net.WebException]
|
|
{{
|
|
"Error:System.Net.WebException"
|
|
}}
|
|
'@ -f $EndPoint, $AllowAutoRedirect
|
|
|
|
$ps = [powershell]::Create($iss).AddScript($WebRequestcmd)
|
|
|
|
if($WebProxy)
|
|
{
|
|
$null = $ps.AddParameter('WebProxy', $WebProxy)
|
|
}
|
|
|
|
if($Credential)
|
|
{
|
|
$null = $ps.AddParameter('Credential', $Credential)
|
|
}
|
|
|
|
$response = $ps.Invoke()
|
|
$ps.dispose()
|
|
if ($response -ne "Error:System.Net.WebException")
|
|
{
|
|
if($AllowAutoRedirect)
|
|
{
|
|
$results.Add($Script:ResponseUri,$response.ResponseUri.ToString())
|
|
$results.Add($Script:StatusCode,$response.StatusCode.value__)
|
|
}
|
|
else
|
|
{
|
|
$results.Add($Script:ResponseUri,[String]$response)
|
|
}
|
|
}
|
|
}
|
|
return $results
|
|
}
|
|
|
|
function Validate-VersionParameters
|
|
{
|
|
Param(
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCmdlet]
|
|
$CallerPSCmdlet,
|
|
|
|
[Parameter()]
|
|
[String[]]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$MaximumVersion,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$AllVersions,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$TestWildcardsInName
|
|
)
|
|
|
|
if($TestWildcardsInName -and $Name -and (Test-WildcardPattern -Name "$Name"))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage ($LocalizedData.NameShouldNotContainWildcardCharacters -f "$($Name -join ',')") `
|
|
-ErrorId 'NameShouldNotContainWildcardCharacters' `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Name
|
|
}
|
|
elseif($AllVersions -and ($RequiredVersion -or $MinimumVersion -or $MaximumVersion))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.AllVersionsCannotBeUsedWithOtherVersionParameters `
|
|
-ErrorId 'AllVersionsCannotBeUsedWithOtherVersionParameters' `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
elseif($RequiredVersion -and ($MinimumVersion -or $MaximumVersion))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.VersionRangeAndRequiredVersionCannotBeSpecifiedTogether `
|
|
-ErrorId "VersionRangeAndRequiredVersionCannotBeSpecifiedTogether" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
elseif($MinimumVersion -and $MaximumVersion -and ($MinimumVersion -gt $MaximumVersion))
|
|
{
|
|
$Message = $LocalizedData.MinimumVersionIsGreaterThanMaximumVersion -f ($MinimumVersion, $MaximumVersion)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $Message `
|
|
-ErrorId "MinimumVersionIsGreaterThanMaximumVersion" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
elseif($AllVersions -or $RequiredVersion -or $MinimumVersion -or $MaximumVersion)
|
|
{
|
|
if(-not $Name -or $Name.Count -ne 1 -or (Test-WildcardPattern -Name $Name[0]))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.VersionParametersAreAllowedOnlyWithSingleName `
|
|
-ErrorId "VersionParametersAreAllowedOnlyWithSingleName" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
|
|
return $true
|
|
}
|
|
|
|
function ValidateAndSet-PATHVariableIfUserAccepts
|
|
{
|
|
[CmdletBinding()]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Scope,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$ScopePath,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$NoPathUpdate,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$Force,
|
|
|
|
[Parameter()]
|
|
$Request
|
|
)
|
|
|
|
Set-PSGetSettingsVariable
|
|
|
|
# Check and add the scope path to PATH environment variable if USER accepts the prompt.
|
|
if($Scope -eq 'AllUsers')
|
|
{
|
|
$envVariableTarget = $script:EnvironmentVariableTarget.Machine
|
|
$scriptPATHPromptQuery=$LocalizedData.ScriptPATHPromptQuery -f $ScopePath
|
|
$scopeSpecificKey = 'AllUsersScope_AllowPATHChangeForScripts'
|
|
}
|
|
else
|
|
{
|
|
$envVariableTarget = $script:EnvironmentVariableTarget.User
|
|
$scriptPATHPromptQuery=$LocalizedData.ScriptPATHPromptQuery -f $ScopePath
|
|
$scopeSpecificKey = 'CurrentUserScope_AllowPATHChangeForScripts'
|
|
}
|
|
|
|
$AlreadyPromptedForScope = $script:PSGetSettings.Contains($scopeSpecificKey)
|
|
Write-Debug "Already prompted for the current scope:$AlreadyPromptedForScope"
|
|
|
|
if(-not $AlreadyPromptedForScope)
|
|
{
|
|
# Read the file contents once again to ensure that it was not set in another PowerShell Session
|
|
Set-PSGetSettingsVariable -Force
|
|
|
|
$AlreadyPromptedForScope = $script:PSGetSettings.Contains($scopeSpecificKey)
|
|
Write-Debug "After reading contents of PowerShellGetSettings.xml file, the Already prompted for the current scope:$AlreadyPromptedForScope"
|
|
|
|
if($AlreadyPromptedForScope)
|
|
{
|
|
return
|
|
}
|
|
|
|
$userResponse = $false
|
|
|
|
if(-not $NoPathUpdate)
|
|
{
|
|
$scopePathEndingWithBackSlash = "$scopePath\"
|
|
|
|
# Check and add the $scopePath to $env:Path value
|
|
if( (($env:PATH -split ';') -notcontains $scopePath) -and
|
|
(($env:PATH -split ';') -notcontains $scopePathEndingWithBackSlash))
|
|
{
|
|
if($Force)
|
|
{
|
|
$userResponse = $true
|
|
}
|
|
else
|
|
{
|
|
$scriptPATHPromptCaption = $LocalizedData.ScriptPATHPromptCaption
|
|
|
|
if($Request)
|
|
{
|
|
$userResponse = $Request.ShouldContinue($scriptPATHPromptQuery, $scriptPATHPromptCaption)
|
|
}
|
|
else
|
|
{
|
|
$userResponse = $PSCmdlet.ShouldContinue($scriptPATHPromptQuery, $scriptPATHPromptCaption)
|
|
}
|
|
}
|
|
|
|
if($userResponse)
|
|
{
|
|
$currentPATHValue = Get-EnvironmentVariable -Name 'PATH' -Target $envVariableTarget
|
|
|
|
if((($currentPATHValue -split ';') -notcontains $scopePath) -and
|
|
(($currentPATHValue -split ';') -notcontains $scopePathEndingWithBackSlash))
|
|
{
|
|
# To ensure that the installed script is immediately usable,
|
|
# we need to add the scope path to the PATH enviroment variable.
|
|
Set-EnvironmentVariable -Name 'PATH' `
|
|
-Value "$currentPATHValue;$scopePath" `
|
|
-Target $envVariableTarget
|
|
|
|
Write-Verbose ($LocalizedData.AddedScopePathToPATHVariable -f ($scopePath,$Scope))
|
|
}
|
|
|
|
# Process specific PATH
|
|
# Check and add the $scopePath to $env:Path value of current process
|
|
# so that installed scripts can be used in the current process.
|
|
$target = $script:EnvironmentVariableTarget.Process
|
|
$currentPATHValue = Get-EnvironmentVariable -Name 'PATH' -Target $target
|
|
|
|
if((($currentPATHValue -split ';') -notcontains $scopePath) -and
|
|
(($currentPATHValue -split ';') -notcontains $scopePathEndingWithBackSlash))
|
|
{
|
|
# To ensure that the installed script is immediately usable,
|
|
# we need to add the scope path to the PATH enviroment variable.
|
|
Set-EnvironmentVariable -Name 'PATH' `
|
|
-Value "$currentPATHValue;$scopePath" `
|
|
-Target $target
|
|
|
|
Write-Verbose ($LocalizedData.AddedScopePathToProcessSpecificPATHVariable -f ($scopePath,$Scope))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Add user's response to the PowerShellGet.settings file
|
|
$script:PSGetSettings[$scopeSpecificKey] = $userResponse
|
|
|
|
Save-PSGetSettings
|
|
}
|
|
}
|
|
|
|
function Save-PSGetSettings
|
|
{
|
|
if($script:PSGetSettings)
|
|
{
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path -Path $script:PSGetAppLocalPath))
|
|
{
|
|
$null = Microsoft.PowerShell.Management\New-Item -Path $script:PSGetAppLocalPath `
|
|
-ItemType Directory `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue `
|
|
-Confirm:$false `
|
|
-WhatIf:$false
|
|
}
|
|
|
|
Microsoft.PowerShell.Utility\Out-File -FilePath $script:PSGetSettingsFilePath -Force `
|
|
-InputObject ([System.Management.Automation.PSSerializer]::Serialize($script:PSGetSettings))
|
|
|
|
Write-Debug "In Save-PSGetSettings, persisted the $script:PSGetSettingsFilePath file"
|
|
}
|
|
}
|
|
|
|
function Set-PSGetSettingsVariable
|
|
{
|
|
[CmdletBinding()]
|
|
param([switch]$Force)
|
|
|
|
if(-not $script:PSGetSettings -or $Force)
|
|
{
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $script:PSGetSettingsFilePath)
|
|
{
|
|
$script:PSGetSettings = DeSerialize-PSObject -Path $script:PSGetSettingsFilePath
|
|
}
|
|
else
|
|
{
|
|
$script:PSGetSettings = [ordered]@{}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Set-PSGalleryRepository
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter()]
|
|
[switch]
|
|
$Trusted,
|
|
|
|
[Parameter()]
|
|
$Proxy,
|
|
|
|
[Parameter()]
|
|
$ProxyCredential
|
|
)
|
|
|
|
$psgalleryLocation = Resolve-Location -Location $Script:PSGallerySourceUri `
|
|
-LocationParameterName 'SourceLocation' `
|
|
-Proxy $Proxy `
|
|
-ProxyCredential $ProxyCredential `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
|
|
$scriptSourceLocation = Resolve-Location -Location $Script:PSGalleryScriptSourceUri `
|
|
-LocationParameterName 'ScriptSourceLocation' `
|
|
-Proxy $Proxy `
|
|
-ProxyCredential $ProxyCredential `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
if($psgalleryLocation)
|
|
{
|
|
$result = Ping-Endpoint -Endpoint $Script:PSGalleryPublishUri -AllowAutoRedirect:$false -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
if ($result.ContainsKey($Script:ResponseUri) -and $result[$Script:ResponseUri])
|
|
{
|
|
$script:PSGalleryPublishUri = $result[$Script:ResponseUri]
|
|
}
|
|
|
|
$repository = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
|
|
Name = $Script:PSGalleryModuleSource
|
|
SourceLocation = $psgalleryLocation
|
|
PublishLocation = $Script:PSGalleryPublishUri
|
|
ScriptSourceLocation = $scriptSourceLocation
|
|
ScriptPublishLocation = $Script:PSGalleryPublishUri
|
|
Trusted=$Trusted
|
|
Registered=$true
|
|
InstallationPolicy = if($Trusted) {'Trusted'} else {'Untrusted'}
|
|
PackageManagementProvider=$script:NuGetProviderName
|
|
ProviderOptions = @{}
|
|
})
|
|
|
|
$repository.PSTypeNames.Insert(0, "Microsoft.PowerShell.Commands.PSRepository")
|
|
$script:PSGetModuleSources[$Script:PSGalleryModuleSource] = $repository
|
|
|
|
Save-ModuleSources
|
|
|
|
return $repository
|
|
}
|
|
}
|
|
|
|
function Set-ModuleSourcesVariable
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[switch]
|
|
$Force,
|
|
|
|
$Proxy,
|
|
|
|
$ProxyCredential
|
|
)
|
|
|
|
if(-not $script:PSGetModuleSources -or $Force)
|
|
{
|
|
$isPersistRequired = $false
|
|
if(Microsoft.PowerShell.Management\Test-Path $script:PSGetModuleSourcesFilePath)
|
|
{
|
|
$script:PSGetModuleSources = DeSerialize-PSObject -Path $script:PSGetModuleSourcesFilePath
|
|
}
|
|
else
|
|
{
|
|
$script:PSGetModuleSources = [ordered]@{}
|
|
|
|
if(-not $script:PSGetModuleSources.Contains($Script:PSGalleryModuleSource))
|
|
{
|
|
$null = Set-PSGalleryRepository -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
}
|
|
}
|
|
|
|
# Already registed repositories may not have the ScriptSourceLocation property, try to populate it from the existing SourceLocation
|
|
# Also populate the PublishLocation and ScriptPublishLocation from the SourceLocation if PublishLocation is empty/null.
|
|
#
|
|
$script:PSGetModuleSources.Keys | Microsoft.PowerShell.Core\ForEach-Object {
|
|
$moduleSource = $script:PSGetModuleSources[$_]
|
|
|
|
if(-not (Get-Member -InputObject $moduleSource -Name $script:ScriptSourceLocation))
|
|
{
|
|
$scriptSourceLocation = Get-ScriptSourceLocation -Location $moduleSource.SourceLocation -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
Microsoft.PowerShell.Utility\Add-Member -InputObject $script:PSGetModuleSources[$_] `
|
|
-MemberType NoteProperty `
|
|
-Name $script:ScriptSourceLocation `
|
|
-Value $scriptSourceLocation
|
|
|
|
if(Get-Member -InputObject $moduleSource -Name $script:PublishLocation)
|
|
{
|
|
if(-not $moduleSource.PublishLocation)
|
|
{
|
|
$script:PSGetModuleSources[$_].PublishLocation = Get-PublishLocation -Location $moduleSource.SourceLocation
|
|
}
|
|
|
|
Microsoft.PowerShell.Utility\Add-Member -InputObject $script:PSGetModuleSources[$_] `
|
|
-MemberType NoteProperty `
|
|
-Name $script:ScriptPublishLocation `
|
|
-Value $moduleSource.PublishLocation
|
|
}
|
|
|
|
$isPersistRequired = $true
|
|
}
|
|
}
|
|
|
|
if($isPersistRequired)
|
|
{
|
|
Save-ModuleSources
|
|
}
|
|
}
|
|
}
|
|
|
|
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-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-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 New-PSGetItemInfo
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
$SoftwareIdentity,
|
|
|
|
[Parameter()]
|
|
$PackageManagementProviderName,
|
|
|
|
[Parameter()]
|
|
[string]
|
|
$SourceLocation,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Type,
|
|
|
|
[Parameter()]
|
|
[string]
|
|
$InstalledLocation,
|
|
|
|
[Parameter()]
|
|
[System.DateTime]
|
|
$InstalledDate,
|
|
|
|
[Parameter()]
|
|
[System.DateTime]
|
|
$UpdatedDate
|
|
)
|
|
|
|
foreach($swid in $SoftwareIdentity)
|
|
{
|
|
|
|
if($SourceLocation)
|
|
{
|
|
$sourceName = (Get-SourceName -Location $SourceLocation)
|
|
}
|
|
else
|
|
{
|
|
# First get the source name from the Metadata
|
|
# if not exists, get the source name from $swid.Source
|
|
# otherwise default to $swid.Source
|
|
$sourceName = (Get-First $swid.Metadata["SourceName"])
|
|
|
|
if(-not $sourceName)
|
|
{
|
|
$sourceName = (Get-SourceName -Location $swid.Source)
|
|
}
|
|
|
|
if(-not $sourceName)
|
|
{
|
|
$sourceName = $swid.Source
|
|
}
|
|
|
|
$SourceLocation = Get-SourceLocation -SourceName $sourceName
|
|
}
|
|
|
|
$published = (Get-First $swid.Metadata["published"])
|
|
$PublishedDate = New-Object System.DateTime
|
|
|
|
$InstalledDateString = (Get-First $swid.Metadata['installeddate'])
|
|
if(-not $InstalledDate -and $InstalledDateString)
|
|
{
|
|
$InstalledDate = New-Object System.DateTime
|
|
if(-not ([System.DateTime]::TryParse($InstalledDateString, ([ref]$InstalledDate))))
|
|
{
|
|
$InstalledDate = $null
|
|
}
|
|
}
|
|
|
|
$UpdatedDateString = (Get-First $swid.Metadata['updateddate'])
|
|
if(-not $UpdatedDate -and $UpdatedDateString)
|
|
{
|
|
$UpdatedDate = New-Object System.DateTime
|
|
if(-not ([System.DateTime]::TryParse($UpdatedDateString, ([ref]$UpdatedDate))))
|
|
{
|
|
$UpdatedDate = $null
|
|
}
|
|
}
|
|
|
|
$tags = (Get-First $swid.Metadata["tags"]) -split " "
|
|
$userTags = @()
|
|
|
|
$exportedDscResources = @()
|
|
$exportedRoleCapabilities = @()
|
|
$exportedCmdlets = @()
|
|
$exportedFunctions = @()
|
|
$exportedWorkflows = @()
|
|
$exportedCommands = @()
|
|
|
|
$exportedRoleCapabilities += (Get-First $swid.Metadata['RoleCapabilities']) -split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
$exportedDscResources += (Get-First $swid.Metadata["DscResources"]) -split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
$exportedCmdlets += (Get-First $swid.Metadata["Cmdlets"]) -split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
$exportedFunctions += (Get-First $swid.Metadata["Functions"]) -split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
$exportedWorkflows += (Get-First $swid.Metadata["Workflows"]) -split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
$exportedCommands += $exportedCmdlets + $exportedFunctions + $exportedWorkflows
|
|
$PSGetFormatVersion = $null
|
|
|
|
ForEach($tag in $tags)
|
|
{
|
|
if(-not $tag.Trim())
|
|
{
|
|
continue
|
|
}
|
|
|
|
$parts = $tag -split "_",2
|
|
if($parts.Count -ne 2)
|
|
{
|
|
$userTags += $tag
|
|
continue
|
|
}
|
|
|
|
Switch($parts[0])
|
|
{
|
|
$script:Command { $exportedCommands += $parts[1]; break }
|
|
$script:DscResource { $exportedDscResources += $parts[1]; break }
|
|
$script:Cmdlet { $exportedCmdlets += $parts[1]; break }
|
|
$script:Function { $exportedFunctions += $parts[1]; break }
|
|
$script:Workflow { $exportedWorkflows += $parts[1]; break }
|
|
$script:RoleCapability { $exportedRoleCapabilities += $parts[1]; break }
|
|
$script:PSGetFormatVersion { $PSGetFormatVersion = $parts[1]; break }
|
|
$script:Includes { break }
|
|
Default { $userTags += $tag; break }
|
|
}
|
|
}
|
|
|
|
$ArtifactDependencies = @()
|
|
Foreach ($dependencyString in $swid.Dependencies)
|
|
{
|
|
[Uri]$packageId = $null
|
|
if([Uri]::TryCreate($dependencyString, [System.UriKind]::Absolute, ([ref]$packageId)))
|
|
{
|
|
$segments = $packageId.Segments
|
|
$Version = $null
|
|
$DependencyName = $null
|
|
if ($segments)
|
|
{
|
|
$DependencyName = [Uri]::UnescapeDataString($segments[0].Trim('/', '\'))
|
|
$Version = if($segments.Count -gt 1){[Uri]::UnescapeDataString($segments[1])}
|
|
}
|
|
|
|
$dep = [ordered]@{
|
|
Name=$DependencyName
|
|
}
|
|
|
|
if($Version)
|
|
{
|
|
# Required/exact version is represented in NuGet as "[2.0]"
|
|
if ($Version -match "\[+[0-9.]+\]")
|
|
{
|
|
$dep["RequiredVersion"] = $Version.Trim('[', ']')
|
|
}
|
|
elseif ($Version -match "\[+[0-9., ]+\]")
|
|
{
|
|
# Minimum and Maximum version range is represented in NuGet as "[1.0, 2.0]"
|
|
$versionRange = $Version.Trim('[', ']') -split ',' | Microsoft.PowerShell.Core\Where-Object {$_}
|
|
if($versionRange -and $versionRange.count -eq 2)
|
|
{
|
|
$dep["MinimumVersion"] = $versionRange[0].Trim()
|
|
$dep["MaximumVersion"] = $versionRange[1].Trim()
|
|
}
|
|
}
|
|
elseif ($Version -match "\(+[0-9., ]+\]")
|
|
{
|
|
# Maximum version is represented in NuGet as "(, 2.0]"
|
|
$maximumVersion = $Version.Trim('(', ']') -split ',' | Microsoft.PowerShell.Core\Where-Object {$_}
|
|
|
|
if($maximumVersion)
|
|
{
|
|
$dep["MaximumVersion"] = $maximumVersion.Trim()
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$dep['MinimumVersion'] = $Version
|
|
}
|
|
}
|
|
|
|
$dep["CanonicalId"]=$dependencyString
|
|
|
|
$ArtifactDependencies += $dep
|
|
}
|
|
}
|
|
|
|
$additionalMetadata = New-Object -TypeName System.Collections.Hashtable
|
|
foreach ( $key in $swid.Metadata.Keys.LocalName)
|
|
{
|
|
if (!$additionalMetadata.ContainsKey($key))
|
|
{
|
|
$additionalMetadata.Add($key, (Get-First $swid.Metadata[$key]) )
|
|
}
|
|
}
|
|
|
|
if($additionalMetadata.ContainsKey('ItemType'))
|
|
{
|
|
$Type = $additionalMetadata['ItemType']
|
|
}
|
|
elseif($userTags -contains 'PSModule')
|
|
{
|
|
$Type = $script:PSArtifactTypeModule
|
|
}
|
|
elseif($userTags -contains 'PSScript')
|
|
{
|
|
$Type = $script:PSArtifactTypeScript
|
|
}
|
|
|
|
$PSGetItemInfo = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
|
|
Name = $swid.Name
|
|
Version = [Version]$swid.Version
|
|
Type = $Type
|
|
Description = (Get-First $swid.Metadata["description"])
|
|
Author = (Get-EntityName -SoftwareIdentity $swid -Role "author")
|
|
CompanyName = (Get-EntityName -SoftwareIdentity $swid -Role "owner")
|
|
Copyright = (Get-First $swid.Metadata["copyright"])
|
|
PublishedDate = if([System.DateTime]::TryParse($published, ([ref]$PublishedDate))){$PublishedDate};
|
|
InstalledDate = $InstalledDate;
|
|
UpdatedDate = $UpdatedDate;
|
|
LicenseUri = (Get-UrlFromSwid -SoftwareIdentity $swid -UrlName "license")
|
|
ProjectUri = (Get-UrlFromSwid -SoftwareIdentity $swid -UrlName "project")
|
|
IconUri = (Get-UrlFromSwid -SoftwareIdentity $swid -UrlName "icon")
|
|
Tags = $userTags
|
|
|
|
Includes = @{
|
|
DscResource = $exportedDscResources
|
|
Command = $exportedCommands
|
|
Cmdlet = $exportedCmdlets
|
|
Function = $exportedFunctions
|
|
Workflow = $exportedWorkflows
|
|
RoleCapability = $exportedRoleCapabilities
|
|
}
|
|
|
|
PowerShellGetFormatVersion=[Version]$PSGetFormatVersion
|
|
|
|
ReleaseNotes = (Get-First $swid.Metadata["releaseNotes"])
|
|
|
|
Dependencies = $ArtifactDependencies
|
|
|
|
RepositorySourceLocation = $SourceLocation
|
|
Repository = $sourceName
|
|
PackageManagementProvider = if($PackageManagementProviderName) { $PackageManagementProviderName } else { (Get-First $swid.Metadata["PackageManagementProvider"]) }
|
|
|
|
AdditionalMetadata = $additionalMetadata
|
|
})
|
|
|
|
if(-not $InstalledLocation)
|
|
{
|
|
$InstalledLocation = (Get-First $swid.Metadata[$script:InstalledLocation])
|
|
}
|
|
|
|
if($InstalledLocation)
|
|
{
|
|
Microsoft.PowerShell.Utility\Add-Member -InputObject $PSGetItemInfo -MemberType NoteProperty -Name $script:InstalledLocation -Value $InstalledLocation
|
|
}
|
|
|
|
$PSGetItemInfo.PSTypeNames.Insert(0, "Microsoft.PowerShell.Commands.PSRepositoryItemInfo")
|
|
$PSGetItemInfo
|
|
}
|
|
}
|
|
|
|
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
|
|
($psModuleSource.SourceLocation -eq $Location) -or
|
|
((Get-Member -InputObject $psModuleSource -Name $script:ScriptSourceLocation) -and
|
|
($psModuleSource.ScriptSourceLocation -eq $Location)))
|
|
{
|
|
return $psModuleSource.Name
|
|
}
|
|
}
|
|
}
|
|
|
|
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-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-EntityName
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
$SoftwareIdentity,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
$Role
|
|
)
|
|
|
|
foreach( $entity in $SoftwareIdentity.Entities )
|
|
{
|
|
if( $entity.Role -eq $Role)
|
|
{
|
|
$entity.Name
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
(-not $BootstrapNuGetExe -or
|
|
($script:NuGetExePath -and (Microsoft.PowerShell.Management\Test-Path -Path $script:NuGetExePath))))
|
|
{
|
|
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($BootstrapNuGetExe -and
|
|
(-not $script:NuGetExePath -or
|
|
-not (Microsoft.PowerShell.Management\Test-Path -Path $script:NuGetExePath)))
|
|
{
|
|
$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)
|
|
{
|
|
$script:NuGetExePath = $programDataExePath
|
|
$BootstrapNuGetExe = $false
|
|
}
|
|
elseif(Microsoft.PowerShell.Management\Test-Path -Path $applocalDataExePath)
|
|
{
|
|
$script:NuGetExePath = $applocalDataExePath
|
|
$BootstrapNuGetExe = $false
|
|
}
|
|
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 SilentlyContinue `
|
|
-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
|
|
|
|
if($nugetCmd -and $nugetCmd.Path)
|
|
{
|
|
$script:NuGetExePath = $nugetCmd.Path
|
|
$BootstrapNuGetExe = $false
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# No need to bootstrap the NuGet.exe when $BootstrapNuGetExe is false or NuGet.exe path is already assigned.
|
|
$BootstrapNuGetExe = $false
|
|
}
|
|
|
|
# On Nano server we don't need NuGet.exe
|
|
if(-not $bootstrapNuGetProvider -and ($script:isNanoServer -or -not $BootstrapNuGetExe))
|
|
{
|
|
return
|
|
}
|
|
|
|
# We should prompt only once for bootstrapping the NuGet provider and/or NuGet.exe
|
|
|
|
# Should continue message for bootstrapping only NuGet provider
|
|
$shouldContinueQueryMessage = $LocalizedData.InstallNuGetProviderShouldContinueQuery -f @($script:NuGetProviderVersion,$script:NuGetBinaryProgramDataPath,$script:NuGetBinaryLocalAppDataPath)
|
|
$shouldContinueCaption = $LocalizedData.InstallNuGetProviderShouldContinueCaption
|
|
|
|
# Should continue message for bootstrapping both NuGet provider and NuGet.exe
|
|
if($bootstrapNuGetProvider -and $BootstrapNuGetExe)
|
|
{
|
|
$shouldContinueQueryMessage = $LocalizedData.InstallNuGetBinariesShouldContinueQuery2 -f @($script:NuGetProviderVersion,$script:NuGetBinaryProgramDataPath,$script:NuGetBinaryLocalAppDataPath, $script:PSGetProgramDataPath, $script:PSGetAppLocalPath)
|
|
$shouldContinueCaption = $LocalizedData.InstallNuGetBinariesShouldContinueCaption2
|
|
}
|
|
elseif($BootstrapNuGetExe)
|
|
{
|
|
# Should continue message for bootstrapping only NuGet.exe
|
|
$shouldContinueQueryMessage = $LocalizedData.InstallNuGetExeShouldContinueQuery -f ($script:PSGetProgramDataPath, $script:PSGetAppLocalPath)
|
|
$shouldContinueCaption = $LocalizedData.InstallNuGetExeShouldContinueCaption
|
|
}
|
|
|
|
$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 -not $script:isNanoServer)
|
|
{
|
|
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 http://nuget.org/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
|
|
}
|
|
}
|
|
}
|
|
|
|
$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 -and
|
|
(-not $script:NuGetExePath -or
|
|
-not (Microsoft.PowerShell.Management\Test-Path -Path $script:NuGetExePath)))
|
|
{
|
|
$failedToBootstrapNuGetExe = $true
|
|
|
|
$message = $LocalizedData.CouldNotInstallNuGetExe -f @($script:NuGetProviderVersion)
|
|
$errorId = 'CouldNotInstallNuGetExe'
|
|
}
|
|
|
|
# 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
|
|
}
|
|
}
|
|
|
|
# Check if current user is running with elevated privileges
|
|
function Test-RunningAsElevated
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
Param()
|
|
|
|
$wid=[System.Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$prp=new-object System.Security.Principal.WindowsPrincipal($wid)
|
|
$adm=[System.Security.Principal.WindowsBuiltInRole]::Administrator
|
|
return $prp.IsInRole($adm)
|
|
}
|
|
|
|
function Get-EscapedString
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([String])]
|
|
Param
|
|
(
|
|
[Parameter()]
|
|
[string]
|
|
$ElementValue
|
|
)
|
|
|
|
return [System.Security.SecurityElement]::Escape($ElementValue)
|
|
}
|
|
|
|
function ValidateAndGet-ScriptDependencies
|
|
{
|
|
param(
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Repository,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[PSCustomObject]
|
|
$DependentScriptInfo,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCmdlet]
|
|
$CallerPSCmdlet
|
|
)
|
|
|
|
$DependenciesDetails = @()
|
|
|
|
# Validate dependent modules
|
|
$RequiredModuleSpecification = $DependentScriptInfo.RequiredModules
|
|
if($RequiredModuleSpecification)
|
|
{
|
|
ForEach($moduleSpecification in $RequiredModuleSpecification)
|
|
{
|
|
$ModuleName = $moduleSpecification.Name
|
|
|
|
$FindModuleArguments = @{
|
|
Repository = $Repository
|
|
Verbose = $VerbosePreference
|
|
ErrorAction = 'SilentlyContinue'
|
|
WarningAction = 'SilentlyContinue'
|
|
Debug = $DebugPreference
|
|
}
|
|
|
|
if($DependentScriptInfo.ExternalModuleDependencies -contains $ModuleName)
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.SkippedModuleDependency -f $ModuleName)
|
|
|
|
continue
|
|
}
|
|
|
|
$FindModuleArguments['Name'] = $ModuleName
|
|
$ReqModuleInfo = @{}
|
|
$ReqModuleInfo['Name'] = $ModuleName
|
|
|
|
if($moduleSpecification.Version)
|
|
{
|
|
$FindModuleArguments['MinimumVersion'] = $moduleSpecification.Version
|
|
$ReqModuleInfo['MinimumVersion'] = $moduleSpecification.Version
|
|
}
|
|
elseif((Get-Member -InputObject $moduleSpecification -Name RequiredVersion) -and $moduleSpecification.RequiredVersion)
|
|
{
|
|
$FindModuleArguments['RequiredVersion'] = $moduleSpecification.RequiredVersion
|
|
$ReqModuleInfo['RequiredVersion'] = $moduleSpecification.RequiredVersion
|
|
}
|
|
|
|
if((Get-Member -InputObject $moduleSpecification -Name MaximumVersion) -and $moduleSpecification.MaximumVersion)
|
|
{
|
|
# * can be specified in the MaximumVersion of a ModuleSpecification to convey that maximum possible value of that version part.
|
|
# like 1.0.0.* --> 1.0.0.99999999
|
|
# replace * with 99999999, PowerShell core takes care validating the * to be the last character in the version string.
|
|
$maximumVersion = $moduleSpecification.MaximumVersion -replace '\*','99999999'
|
|
$FindModuleArguments['MaximumVersion'] = $maximumVersion
|
|
$ReqModuleInfo['MaximumVersion'] = $maximumVersion
|
|
}
|
|
|
|
$psgetItemInfo = Find-Module @FindModuleArguments |
|
|
Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $ModuleName} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Last 1
|
|
|
|
if(-not $psgetItemInfo)
|
|
{
|
|
$message = $LocalizedData.UnableToResolveScriptDependency -f ('module', $ModuleName, $DependentScriptInfo.Name, $Repository, 'ExternalModuleDependencies')
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "UnableToResolveScriptDependency" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
|
|
$DependenciesDetails += $ReqModuleInfo
|
|
}
|
|
}
|
|
|
|
# Validate dependent scrips
|
|
$RequiredScripts = $DependentScriptInfo.RequiredScripts
|
|
if($RequiredScripts)
|
|
{
|
|
ForEach($requiredScript in $RequiredScripts)
|
|
{
|
|
$FindScriptArguments = @{
|
|
Repository = $Repository
|
|
Verbose = $VerbosePreference
|
|
ErrorAction = 'SilentlyContinue'
|
|
WarningAction = 'SilentlyContinue'
|
|
Debug = $DebugPreference
|
|
}
|
|
|
|
if($DependentScriptInfo.ExternalScriptDependencies -contains $requiredScript)
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.SkippedScriptDependency -f $requiredScript)
|
|
|
|
continue
|
|
}
|
|
|
|
$FindScriptArguments['Name'] = $requiredScript
|
|
$ReqScriptInfo = @{}
|
|
$ReqScriptInfo['Name'] = $requiredScript
|
|
|
|
$psgetItemInfo = Find-Script @FindScriptArguments |
|
|
Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $requiredScript} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Last 1
|
|
|
|
if(-not $psgetItemInfo)
|
|
{
|
|
$message = $LocalizedData.UnableToResolveScriptDependency -f ('script', $requiredScript, $DependentScriptInfo.Name, $Repository, 'ExternalScriptDependencies')
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "UnableToResolveScriptDependency" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
|
|
$DependenciesDetails += $ReqScriptInfo
|
|
}
|
|
}
|
|
|
|
return $DependenciesDetails
|
|
}
|
|
|
|
function ValidateAndGet-RequiredModuleDetails
|
|
{
|
|
param(
|
|
[Parameter()]
|
|
$ModuleManifestRequiredModules,
|
|
|
|
[Parameter()]
|
|
[PSModuleInfo[]]
|
|
$RequiredPSModuleInfos,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Repository,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[PSModuleInfo]
|
|
$DependentModuleInfo,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCmdlet]
|
|
$CallerPSCmdlet
|
|
)
|
|
|
|
$RequiredModuleDetails = @()
|
|
|
|
if(-not $RequiredPSModuleInfos)
|
|
{
|
|
return $RequiredModuleDetails
|
|
}
|
|
|
|
if($ModuleManifestRequiredModules)
|
|
{
|
|
ForEach($RequiredModule in $ModuleManifestRequiredModules)
|
|
{
|
|
$ModuleName = $null
|
|
$VersionString = $null
|
|
|
|
$ReqModuleInfo = @{}
|
|
|
|
$FindModuleArguments = @{
|
|
Repository = $Repository
|
|
Verbose = $VerbosePreference
|
|
ErrorAction = 'SilentlyContinue'
|
|
WarningAction = 'SilentlyContinue'
|
|
Debug = $DebugPreference
|
|
}
|
|
|
|
# ModuleSpecification case
|
|
if($RequiredModule.GetType().ToString() -eq 'System.Collections.Hashtable')
|
|
{
|
|
$ModuleName = $RequiredModule.ModuleName
|
|
|
|
# Version format in NuSpec:
|
|
# "[2.0]" --> (== 2.0) Required Version
|
|
# "2.0" --> (>= 2.0) Minimum Version
|
|
if($RequiredModule.Keys -Contains "RequiredVersion")
|
|
{
|
|
$FindModuleArguments['RequiredVersion'] = $RequiredModule.RequiredVersion
|
|
$ReqModuleInfo['RequiredVersion'] = $RequiredModule.RequiredVersion
|
|
}
|
|
elseif($RequiredModule.Keys -Contains "ModuleVersion")
|
|
{
|
|
$FindModuleArguments['MinimumVersion'] = $RequiredModule.ModuleVersion
|
|
$ReqModuleInfo['MinimumVersion'] = $RequiredModule.ModuleVersion
|
|
}
|
|
|
|
if($RequiredModule.Keys -Contains 'MaximumVersion' -and $RequiredModule.MaximumVersion)
|
|
{
|
|
# * can be specified in the MaximumVersion of a ModuleSpecification to convey that maximum possible value of that version part.
|
|
# like 1.0.0.* --> 1.0.0.99999999
|
|
# replace * with 99999999, PowerShell core takes care validating the * to be the last character in the version string.
|
|
$maximumVersion = $RequiredModule.MaximumVersion -replace '\*','99999999'
|
|
|
|
$FindModuleArguments['MaximumVersion'] = $maximumVersion
|
|
$ReqModuleInfo['MaximumVersion'] = $maximumVersion
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Just module name was specified
|
|
$ModuleName = $RequiredModule.ToString()
|
|
}
|
|
|
|
if((Get-ExternalModuleDependencies -PSModuleInfo $DependentModuleInfo) -contains $ModuleName)
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.SkippedModuleDependency -f $ModuleName)
|
|
|
|
continue
|
|
}
|
|
|
|
# Skip this module name if it's name is not in $RequiredPSModuleInfos.
|
|
# This is required when a ModuleName is part of the NestedModules list of the actual module.
|
|
# $ModuleName is packaged as part of the actual module When $RequiredPSModuleInfos doesn't contain it's name.
|
|
if($RequiredPSModuleInfos.Name -notcontains $ModuleName)
|
|
{
|
|
continue
|
|
}
|
|
|
|
$ReqModuleInfo['Name'] = $ModuleName
|
|
|
|
# Add the dependency only if the module is available on the gallery
|
|
# Otherwise Module installation will fail as all required modules need to be available on
|
|
# the same Repository
|
|
$FindModuleArguments['Name'] = $ModuleName
|
|
|
|
$psgetItemInfo = Find-Module @FindModuleArguments |
|
|
Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $ModuleName} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Last 1
|
|
|
|
if(-not $psgetItemInfo)
|
|
{
|
|
$message = $LocalizedData.UnableToResolveModuleDependency -f ($ModuleName, $DependentModuleInfo.Name, $Repository, $ModuleName, $Repository, $ModuleName, $ModuleName)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "UnableToResolveModuleDependency" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
|
|
$RequiredModuleDetails += $ReqModuleInfo
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# If Import-LocalizedData cmdlet was failed to read the .psd1 contents
|
|
# use provided $RequiredPSModuleInfos (PSModuleInfo.RequiredModules or PSModuleInfo.NestedModules of the actual dependent module)
|
|
|
|
$FindModuleArguments = @{
|
|
Repository = $Repository
|
|
Verbose = $VerbosePreference
|
|
ErrorAction = 'SilentlyContinue'
|
|
WarningAction = 'SilentlyContinue'
|
|
Debug = $DebugPreference
|
|
}
|
|
|
|
ForEach($RequiredModuleInfo in $RequiredPSModuleInfos)
|
|
{
|
|
$ModuleName = $requiredModuleInfo.Name
|
|
|
|
if((Get-ExternalModuleDependencies -PSModuleInfo $DependentModuleInfo) -contains $ModuleName)
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.SkippedModuleDependency -f $ModuleName)
|
|
|
|
continue
|
|
}
|
|
|
|
$FindModuleArguments['Name'] = $ModuleName
|
|
$FindModuleArguments['MinimumVersion'] = $requiredModuleInfo.Version
|
|
|
|
$psgetItemInfo = Find-Module @FindModuleArguments |
|
|
Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $ModuleName} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Last 1
|
|
|
|
if(-not $psgetItemInfo)
|
|
{
|
|
$message = $LocalizedData.UnableToResolveModuleDependency -f ($ModuleName, $DependentModuleInfo.Name, $Repository, $ModuleName, $Repository, $ModuleName, $ModuleName)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "UnableToResolveModuleDependency" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
|
|
$RequiredModuleDetails += @{
|
|
Name=$_.Name
|
|
MinimumVersion=$_.Version
|
|
}
|
|
}
|
|
}
|
|
|
|
return $RequiredModuleDetails
|
|
}
|
|
|
|
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-ModuleDependencies
|
|
{
|
|
Param (
|
|
[Parameter(Mandatory=$true)]
|
|
[PSModuleInfo]
|
|
$PSModuleInfo,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Repository,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCmdlet]
|
|
$CallerPSCmdlet
|
|
)
|
|
|
|
$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
|
|
}
|
|
|
|
|
|
$DependentModuleDetails += ValidateAndGet-RequiredModuleDetails -ModuleManifestRequiredModules $ModuleManifestRequiredModules `
|
|
-RequiredPSModuleInfos $PSModuleInfo.RequiredModules `
|
|
-Repository $Repository `
|
|
-DependentModuleInfo $PSModuleInfo `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-Verbose:$VerbosePreference `
|
|
-Debug:$DebugPreference
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
$DependentModuleDetails += ValidateAndGet-RequiredModuleDetails -ModuleManifestRequiredModules $ModuleManifestRequiredModules `
|
|
-RequiredPSModuleInfos $RequiredPSModuleInfos `
|
|
-Repository $Repository `
|
|
-DependentModuleInfo $PSModuleInfo `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-Verbose:$VerbosePreference `
|
|
-Debug:$DebugPreference
|
|
}
|
|
}
|
|
|
|
return $DependentModuleDetails
|
|
}
|
|
|
|
function Publish-PSArtifactUtility
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true, ParameterSetName='PublishModule')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[PSModuleInfo]
|
|
$PSModuleInfo,
|
|
|
|
[Parameter(Mandatory=$true, ParameterSetName='PublishScript')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[PSCustomObject]
|
|
$PSScriptInfo,
|
|
|
|
[Parameter(Mandatory=$true, ParameterSetName='PublishModule')]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$ManifestPath,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Destination,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Repository,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$NugetApiKey,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$NugetPackageRoot,
|
|
|
|
[Parameter(ParameterSetName='PublishModule')]
|
|
[Version]
|
|
$FormatVersion,
|
|
|
|
[Parameter(ParameterSetName='PublishModule')]
|
|
[string]
|
|
$ReleaseNotes,
|
|
|
|
[Parameter(ParameterSetName='PublishModule')]
|
|
[string[]]
|
|
$Tags,
|
|
|
|
[Parameter(ParameterSetName='PublishModule')]
|
|
[Uri]
|
|
$LicenseUri,
|
|
|
|
[Parameter(ParameterSetName='PublishModule')]
|
|
[Uri]
|
|
$IconUri,
|
|
|
|
[Parameter(ParameterSetName='PublishModule')]
|
|
[Uri]
|
|
$ProjectUri
|
|
)
|
|
|
|
Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet -BootstrapNuGetExe
|
|
|
|
$PSArtifactType = $script:PSArtifactTypeModule
|
|
$Name = $null
|
|
$Description = $null
|
|
$Version = $null
|
|
$Author = $null
|
|
$CompanyName = $null
|
|
$Copyright = $null
|
|
|
|
if($PSModuleInfo)
|
|
{
|
|
$Name = $PSModuleInfo.Name
|
|
$Description = $PSModuleInfo.Description
|
|
$Version = $PSModuleInfo.Version
|
|
$Author = $PSModuleInfo.Author
|
|
$CompanyName = $PSModuleInfo.CompanyName
|
|
$Copyright = $PSModuleInfo.Copyright
|
|
|
|
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")
|
|
)
|
|
{
|
|
if( -not $Tags -and $PSModuleInfo.PrivateData.PSData["Tags"])
|
|
{
|
|
$Tags = $PSModuleInfo.PrivateData.PSData.Tags
|
|
}
|
|
|
|
if( -not $ReleaseNotes -and $PSModuleInfo.PrivateData.PSData["ReleaseNotes"])
|
|
{
|
|
$ReleaseNotes = $PSModuleInfo.PrivateData.PSData.ReleaseNotes
|
|
}
|
|
|
|
if( -not $LicenseUri -and $PSModuleInfo.PrivateData.PSData["LicenseUri"])
|
|
{
|
|
$LicenseUri = $PSModuleInfo.PrivateData.PSData.LicenseUri
|
|
}
|
|
|
|
if( -not $IconUri -and $PSModuleInfo.PrivateData.PSData["IconUri"])
|
|
{
|
|
$IconUri = $PSModuleInfo.PrivateData.PSData.IconUri
|
|
}
|
|
|
|
if( -not $ProjectUri -and $PSModuleInfo.PrivateData.PSData["ProjectUri"])
|
|
{
|
|
$ProjectUri = $PSModuleInfo.PrivateData.PSData.ProjectUri
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$PSArtifactType = $script:PSArtifactTypeScript
|
|
|
|
$Name = $PSScriptInfo.Name
|
|
$Description = $PSScriptInfo.Description
|
|
$Version = $PSScriptInfo.Version
|
|
$Author = $PSScriptInfo.Author
|
|
$CompanyName = $PSScriptInfo.CompanyName
|
|
$Copyright = $PSScriptInfo.Copyright
|
|
|
|
if($PSScriptInfo.'Tags')
|
|
{
|
|
$Tags = $PSScriptInfo.Tags
|
|
}
|
|
|
|
if($PSScriptInfo.'ReleaseNotes')
|
|
{
|
|
$ReleaseNotes = $PSScriptInfo.ReleaseNotes
|
|
}
|
|
|
|
if($PSScriptInfo.'LicenseUri')
|
|
{
|
|
$LicenseUri = $PSScriptInfo.LicenseUri
|
|
}
|
|
|
|
if($PSScriptInfo.'IconUri')
|
|
{
|
|
$IconUri = $PSScriptInfo.IconUri
|
|
}
|
|
|
|
if($PSScriptInfo.'ProjectUri')
|
|
{
|
|
$ProjectUri = $PSScriptInfo.ProjectUri
|
|
}
|
|
}
|
|
|
|
|
|
# Add PSModule and PSGet format version tags
|
|
if(-not $Tags)
|
|
{
|
|
$Tags = @()
|
|
}
|
|
|
|
if($FormatVersion)
|
|
{
|
|
$Tags += "$($script:PSGetFormatVersion)_$FormatVersion"
|
|
}
|
|
|
|
$DependentModuleDetails = @()
|
|
|
|
if($PSScriptInfo)
|
|
{
|
|
$Tags += "PSScript"
|
|
|
|
if($PSScriptInfo.DefinedCommands)
|
|
{
|
|
if($PSScriptInfo.DefinedFunctions)
|
|
{
|
|
$Tags += "$($script:Includes)_Function"
|
|
$Tags += $PSScriptInfo.DefinedFunctions | Microsoft.PowerShell.Core\ForEach-Object { "$($script:Function)_$_" }
|
|
}
|
|
|
|
if($PSScriptInfo.DefinedWorkflows)
|
|
{
|
|
$Tags += "$($script:Includes)_Workflow"
|
|
$Tags += $PSScriptInfo.DefinedWorkflows | Microsoft.PowerShell.Core\ForEach-Object { "$($script:Workflow)_$_" }
|
|
}
|
|
|
|
$Tags += $PSScriptInfo.DefinedCommands | Microsoft.PowerShell.Core\ForEach-Object { "$($script:Command)_$_" }
|
|
}
|
|
|
|
# Populate the dependencies elements from RequiredModules and RequiredScripts
|
|
#
|
|
$DependentModuleDetails += ValidateAndGet-ScriptDependencies -Repository $Repository `
|
|
-DependentScriptInfo $PSScriptInfo `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-Verbose:$VerbosePreference `
|
|
-Debug:$DebugPreference
|
|
}
|
|
else
|
|
{
|
|
$Tags += "PSModule"
|
|
|
|
$ModuleManifestHashTable = Get-ManifestHashTable -Path $ManifestPath
|
|
|
|
if($PSModuleInfo.ExportedCommands.Count)
|
|
{
|
|
if($PSModuleInfo.ExportedCmdlets.Count)
|
|
{
|
|
$Tags += "$($script:Includes)_Cmdlet"
|
|
$Tags += $PSModuleInfo.ExportedCmdlets.Keys | Microsoft.PowerShell.Core\ForEach-Object { "$($script:Cmdlet)_$_" }
|
|
|
|
#if CmdletsToExport field in manifest file is "*", we suggest the user to include all those cmdlets for best practice
|
|
if($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey('CmdletsToExport') -and ($ModuleManifestHashTable.CmdletsToExport -eq "*"))
|
|
{
|
|
$WarningMessage = $LocalizedData.ShouldIncludeCmdletsToExport -f ($ManifestPath)
|
|
Write-Warning -Message $WarningMessage
|
|
}
|
|
}
|
|
|
|
if($PSModuleInfo.ExportedFunctions.Count)
|
|
{
|
|
$Tags += "$($script:Includes)_Function"
|
|
$Tags += $PSModuleInfo.ExportedFunctions.Keys | Microsoft.PowerShell.Core\ForEach-Object { "$($script:Function)_$_" }
|
|
|
|
if($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey('FunctionsToExport') -and ($ModuleManifestHashTable.FunctionsToExport -eq "*"))
|
|
{
|
|
$WarningMessage = $LocalizedData.ShouldIncludeFunctionsToExport -f ($ManifestPath)
|
|
Write-Warning -Message $WarningMessage
|
|
}
|
|
}
|
|
|
|
$Tags += $PSModuleInfo.ExportedCommands.Keys | Microsoft.PowerShell.Core\ForEach-Object { "$($script:Command)_$_" }
|
|
}
|
|
|
|
$dscResourceNames = Get-ExportedDscResources -PSModuleInfo $PSModuleInfo
|
|
if($dscResourceNames)
|
|
{
|
|
$Tags += "$($script:Includes)_DscResource"
|
|
|
|
$Tags += $dscResourceNames | Microsoft.PowerShell.Core\ForEach-Object { "$($script:DscResource)_$_" }
|
|
|
|
#If DscResourcesToExport is commented out or "*" is used, we will write-warning
|
|
if($ModuleManifestHashTable -and
|
|
($ModuleManifestHashTable.ContainsKey("DscResourcesToExport") -and
|
|
$ModuleManifestHashTable.DscResourcesToExport -eq "*") -or
|
|
-not $ModuleManifestHashTable.ContainsKey("DscResourcesToExport"))
|
|
{
|
|
$WarningMessage = $LocalizedData.ShouldIncludeDscResourcesToExport -f ($ManifestPath)
|
|
Write-Warning -Message $WarningMessage
|
|
}
|
|
}
|
|
|
|
$RoleCapabilityNames = Get-AvailableRoleCapabilityName -PSModuleInfo $PSModuleInfo
|
|
if($RoleCapabilityNames)
|
|
{
|
|
$Tags += "$($script:Includes)_RoleCapability"
|
|
|
|
$Tags += $RoleCapabilityNames | Microsoft.PowerShell.Core\ForEach-Object { "$($script:RoleCapability)_$_" }
|
|
}
|
|
|
|
# Populate the module dependencies elements from RequiredModules and
|
|
# NestedModules properties of the current PSModuleInfo
|
|
$DependentModuleDetails = Get-ModuleDependencies -PSModuleInfo $PSModuleInfo `
|
|
-Repository $Repository `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-Verbose:$VerbosePreference `
|
|
-Debug:$DebugPreference
|
|
}
|
|
|
|
$dependencies = @()
|
|
ForEach($Dependency in $DependentModuleDetails)
|
|
{
|
|
$ModuleName = $Dependency.Name
|
|
$VersionString = $null
|
|
|
|
# Version format in NuSpec:
|
|
# "[2.0]" --> (== 2.0) Required Version
|
|
# "2.0" --> (>= 2.0) Minimum Version
|
|
#
|
|
# When only MaximumVersion is specified in the ModuleSpecification
|
|
# (,1.0] = x <= 1.0
|
|
#
|
|
# When both Minimum and Maximum versions are specified in the ModuleSpecification
|
|
# [1.0,2.0] = 1.0 <= x <= 2.0
|
|
|
|
if($Dependency.Keys -Contains "RequiredVersion")
|
|
{
|
|
$VersionString = "[$($Dependency.RequiredVersion)]"
|
|
}
|
|
elseif($Dependency.Keys -Contains 'MinimumVersion' -and $Dependency.Keys -Contains 'MaximumVersion')
|
|
{
|
|
$VersionString = "[$($Dependency.MinimumVersion),$($Dependency.MaximumVersion)]"
|
|
}
|
|
elseif($Dependency.Keys -Contains 'MaximumVersion')
|
|
{
|
|
$VersionString = "(,$($Dependency.MaximumVersion)]"
|
|
}
|
|
elseif($Dependency.Keys -Contains 'MinimumVersion')
|
|
{
|
|
$VersionString = "$($Dependency.MinimumVersion)"
|
|
}
|
|
|
|
$dependencies += "<dependency id='$($ModuleName)' version='$($VersionString)' />"
|
|
}
|
|
|
|
# Populate the nuspec elements
|
|
$nuspec = @"
|
|
<?xml version="1.0"?>
|
|
<package >
|
|
<metadata>
|
|
<id>$(Get-EscapedString -ElementValue "$Name")</id>
|
|
<version>$($Version)</version>
|
|
<authors>$(Get-EscapedString -ElementValue "$Author")</authors>
|
|
<owners>$(Get-EscapedString -ElementValue "$CompanyName")</owners>
|
|
<description>$(Get-EscapedString -ElementValue "$Description")</description>
|
|
<releaseNotes>$(Get-EscapedString -ElementValue "$ReleaseNotes")</releaseNotes>
|
|
<copyright>$(Get-EscapedString -ElementValue "$Copyright")</copyright>
|
|
<tags>$(if($Tags){ Get-EscapedString -ElementValue ($Tags -join ' ')})</tags>
|
|
$(if($LicenseUri){
|
|
"<licenseUrl>$(Get-EscapedString -ElementValue "$LicenseUri")</licenseUrl>
|
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>"
|
|
})
|
|
$(if($ProjectUri){
|
|
"<projectUrl>$(Get-EscapedString -ElementValue "$ProjectUri")</projectUrl>"
|
|
})
|
|
$(if($IconUri){
|
|
"<iconUrl>$(Get-EscapedString -ElementValue "$IconUri")</iconUrl>"
|
|
})
|
|
<dependencies>
|
|
$dependencies
|
|
</dependencies>
|
|
</metadata>
|
|
</package>
|
|
"@
|
|
|
|
$NupkgPath = "$NugetPackageRoot\$Name.$($Version.ToString()).nupkg"
|
|
$NuspecPath = "$NugetPackageRoot\$Name.nuspec"
|
|
$tempErrorFile = $null
|
|
$tempOutputFile = $null
|
|
|
|
try
|
|
{
|
|
# Remove existing nuspec and nupkg files
|
|
Microsoft.PowerShell.Management\Remove-Item $NupkgPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
Microsoft.PowerShell.Management\Remove-Item $NuspecPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
|
|
Microsoft.PowerShell.Management\Set-Content -Value $nuspec -Path $NuspecPath -Force -Confirm:$false -WhatIf:$false
|
|
|
|
# Create .nupkg file
|
|
$output = & $script:NuGetExePath pack $NuspecPath -OutputDirectory $NugetPackageRoot
|
|
if($LASTEXITCODE)
|
|
{
|
|
if($PSArtifactType -eq $script:PSArtifactTypeModule)
|
|
{
|
|
$message = $LocalizedData.FailedToCreateCompressedModule -f ($output)
|
|
$errorId = "FailedToCreateCompressedModule"
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.FailedToCreateCompressedScript -f ($output)
|
|
$errorId = "FailedToCreateCompressedScript"
|
|
}
|
|
|
|
Write-Error -Message $message -ErrorId $errorId -Category InvalidOperation
|
|
return
|
|
}
|
|
|
|
# Publish the .nupkg to gallery
|
|
$tempErrorFile = Microsoft.PowerShell.Management\Join-Path -Path $nugetPackageRoot -ChildPath "TempPublishError.txt"
|
|
$tempOutputFile = Microsoft.PowerShell.Management\Join-Path -Path $nugetPackageRoot -ChildPath "TempPublishOutput.txt"
|
|
|
|
Microsoft.PowerShell.Management\Start-Process -FilePath "$script:NuGetExePath" `
|
|
-ArgumentList @('push', "`"$NupkgPath`"", '-source', "`"$($Destination.TrimEnd('\'))`"", '-NonInteractive', '-ApiKey', "`"$NugetApiKey`"") `
|
|
-RedirectStandardError $tempErrorFile `
|
|
-RedirectStandardOutput $tempOutputFile `
|
|
-NoNewWindow `
|
|
-Wait
|
|
|
|
$errorMsg = Microsoft.PowerShell.Management\Get-Content -Path $tempErrorFile -Raw
|
|
|
|
if($errorMsg)
|
|
{
|
|
if(($NugetApiKey -eq 'VSTS') -and
|
|
($errorMsg -match 'Cannot prompt for input in non-interactive mode.') )
|
|
{
|
|
$errorMsg = $LocalizedData.RegisterVSTSFeedAsNuGetPackageSource -f ($Destination, $script:VSTSAuthenticatedFeedsDocUrl)
|
|
}
|
|
|
|
if($PSArtifactType -eq $script:PSArtifactTypeModule)
|
|
{
|
|
$message = $LocalizedData.FailedToPublish -f ($Name,$errorMsg)
|
|
$errorId = "FailedToPublishTheModule"
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.FailedToPublishScript -f ($Name,$errorMsg)
|
|
$errorId = "FailedToPublishTheScript"
|
|
}
|
|
|
|
Write-Error -Message $message -ErrorId $errorId -Category InvalidOperation
|
|
}
|
|
else
|
|
{
|
|
if($PSArtifactType -eq $script:PSArtifactTypeModule)
|
|
{
|
|
$message = $LocalizedData.PublishedSuccessfully -f ($Name, $Destination, $Name)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.PublishedScriptSuccessfully -f ($Name, $Destination, $Name)
|
|
}
|
|
|
|
Write-Verbose -Message $message
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if($NupkgPath -and (Test-Path -Path $NupkgPath -PathType Leaf))
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item $NupkgPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
if($NuspecPath -and (Test-Path -Path $NuspecPath -PathType Leaf))
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item $NuspecPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
if($tempErrorFile -and (Test-Path -Path $tempErrorFile -PathType Leaf))
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item $tempErrorFile -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
if($tempOutputFile -and (Test-Path -Path $tempOutputFile -PathType Leaf))
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item $tempOutputFile -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
}
|
|
}
|
|
|
|
function ValidateAndAdd-PSScriptInfoEntry
|
|
{
|
|
[CmdletBinding()]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[PSCustomObject]
|
|
$PSScriptInfo,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$PropertyName,
|
|
|
|
[Parameter()]
|
|
$PropertyValue,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCmdlet]
|
|
$CallerPSCmdlet
|
|
)
|
|
|
|
$Value = $PropertyValue
|
|
$KeyName = $PropertyName
|
|
|
|
# return if $KeyName value is not null in $PSScriptInfo
|
|
if(-not $value -or -not $KeyName -or (Get-Member -InputObject $PSScriptInfo -Name $KeyName) -and $PSScriptInfo."$KeyName")
|
|
{
|
|
return
|
|
}
|
|
|
|
switch($PropertyName)
|
|
{
|
|
# Validate the property value and also use proper key name as users can specify the property name in any case.
|
|
$script:Version {
|
|
$KeyName = $script:Version
|
|
|
|
[Version]$Version = $null
|
|
|
|
if([System.Version]::TryParse($Value, ([ref]$Version)))
|
|
{
|
|
$Value = $Version
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.InvalidVersion -f ($Value)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidVersion" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Value
|
|
return
|
|
}
|
|
break
|
|
}
|
|
|
|
$script:Author { $KeyName = $script:Author }
|
|
|
|
$script:Guid {
|
|
$KeyName = $script:Guid
|
|
|
|
[Guid]$guid = [System.Guid]::Empty
|
|
if([System.Guid]::TryParse($Value, ([ref]$guid)))
|
|
{
|
|
$Value = $guid
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.InvalidGuid -f ($Value)
|
|
ThrowError -ExceptionName 'System.ArgumentException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'InvalidGuid' `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Value
|
|
return
|
|
}
|
|
|
|
break
|
|
}
|
|
|
|
$script:Description { $KeyName = $script:Description }
|
|
|
|
$script:CompanyName { $KeyName = $script:CompanyName }
|
|
|
|
$script:Copyright { $KeyName = $script:Copyright }
|
|
|
|
$script:Tags {
|
|
$KeyName = $script:Tags
|
|
$Value = $Value -split '[,\s+]' | Microsoft.PowerShell.Core\Where-Object {$_}
|
|
break
|
|
}
|
|
|
|
$script:LicenseUri {
|
|
$KeyName = $script:LicenseUri
|
|
if(-not (Test-WebUri -Uri $Value))
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($LicenseUri, "LicenseUri")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Value
|
|
return
|
|
}
|
|
|
|
$Value = [Uri]$Value
|
|
}
|
|
|
|
$script:ProjectUri {
|
|
$KeyName = $script:ProjectUri
|
|
if(-not (Test-WebUri -Uri $Value))
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($ProjectUri, "ProjectUri")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Value
|
|
return
|
|
}
|
|
|
|
$Value = [Uri]$Value
|
|
}
|
|
|
|
$script:IconUri {
|
|
$KeyName = $script:IconUri
|
|
if(-not (Test-WebUri -Uri $Value))
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($IconUri, "IconUri")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Value
|
|
return
|
|
}
|
|
|
|
$Value = [Uri]$Value
|
|
}
|
|
|
|
$script:ExternalModuleDependencies {
|
|
$KeyName = $script:ExternalModuleDependencies
|
|
$Value = $Value -split '[,\s+]' | Microsoft.PowerShell.Core\Where-Object {$_}
|
|
}
|
|
|
|
$script:ReleaseNotes { $KeyName = $script:ReleaseNotes }
|
|
|
|
$script:RequiredModules { $KeyName = $script:RequiredModules }
|
|
|
|
$script:RequiredScripts {
|
|
$KeyName = $script:RequiredScripts
|
|
$Value = $Value -split '[,\s+]' | Microsoft.PowerShell.Core\Where-Object {$_}
|
|
}
|
|
|
|
$script:ExternalScriptDependencies {
|
|
$KeyName = $script:ExternalScriptDependencies
|
|
$Value = $Value -split '[,\s+]' | Microsoft.PowerShell.Core\Where-Object {$_}
|
|
}
|
|
|
|
$script:DefinedCommands { $KeyName = $script:DefinedCommands }
|
|
|
|
$script:DefinedFunctions { $KeyName = $script:DefinedFunctions }
|
|
|
|
$script:DefinedWorkflows { $KeyName = $script:DefinedWorkflows }
|
|
}
|
|
|
|
Microsoft.PowerShell.Utility\Add-Member -InputObject $PSScriptInfo `
|
|
-MemberType NoteProperty `
|
|
-Name $KeyName `
|
|
-Value $Value `
|
|
-Force
|
|
}
|
|
|
|
function Get-ExportedDscResources
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[PSModuleInfo]
|
|
$PSModuleInfo
|
|
)
|
|
|
|
$dscResources = @()
|
|
|
|
if(Get-Command -Name Get-DscResource -Module PSDesiredStateConfiguration -ErrorAction SilentlyContinue)
|
|
{
|
|
$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 = Microsoft.PowerShell.Management\Join-Path -Path $PSModuleInfo.ModuleBase -ChildPath "DscResources"
|
|
if(Microsoft.PowerShell.Management\Test-Path $dscResourcesDir)
|
|
{
|
|
$dscResources = Microsoft.PowerShell.Management\Get-ChildItem -Path $dscResourcesDir -Directory -Name
|
|
}
|
|
}
|
|
|
|
return $dscResources
|
|
}
|
|
|
|
function Get-AvailableRoleCapabilityName
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[PSModuleInfo]
|
|
$PSModuleInfo
|
|
)
|
|
|
|
$RoleCapabilityNames = @()
|
|
|
|
$RoleCapabilitiesDir = Microsoft.PowerShell.Management\Join-Path -Path $PSModuleInfo.ModuleBase -ChildPath 'RoleCapabilities'
|
|
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-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
|
|
}
|
|
|
|
#endregion Utility functions
|
|
|
|
#region PowerShellGet Provider APIs Implementation
|
|
function Get-PackageProviderName
|
|
{
|
|
return $script:PSModuleProviderName
|
|
}
|
|
|
|
function Get-Feature
|
|
{
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Get-Feature'))
|
|
Write-Output -InputObject (New-Feature $script:SupportsPSModulesFeatureName )
|
|
}
|
|
|
|
function Initialize-Provider
|
|
{
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Initialize-Provider'))
|
|
}
|
|
|
|
function Get-DynamicOptions
|
|
{
|
|
param
|
|
(
|
|
[Microsoft.PackageManagement.MetaProvider.PowerShell.OptionCategory]
|
|
$category
|
|
)
|
|
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Get-DynamicOptions'))
|
|
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name $script:PackageManagementProviderParam -ExpectedType String -IsRequired $false)
|
|
|
|
switch($category)
|
|
{
|
|
Package {
|
|
Write-Output -InputObject (New-DynamicOption -Category $category `
|
|
-Name $script:PSArtifactType `
|
|
-ExpectedType String `
|
|
-IsRequired $false `
|
|
-PermittedValues @($script:PSArtifactTypeModule,$script:PSArtifactTypeScript, $script:All))
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name $script:Filter -ExpectedType String -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name $script:Tag -ExpectedType StringArray -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name Includes -ExpectedType StringArray -IsRequired $false -PermittedValues $script:IncludeValidSet)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name DscResource -ExpectedType StringArray -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name RoleCapability -ExpectedType StringArray -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name Command -ExpectedType StringArray -IsRequired $false)
|
|
}
|
|
|
|
Source {
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name $script:PublishLocation -ExpectedType String -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name $script:ScriptSourceLocation -ExpectedType String -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name $script:ScriptPublishLocation -ExpectedType String -IsRequired $false)
|
|
}
|
|
|
|
Install
|
|
{
|
|
Write-Output -InputObject (New-DynamicOption -Category $category `
|
|
-Name $script:PSArtifactType `
|
|
-ExpectedType String `
|
|
-IsRequired $false `
|
|
-PermittedValues @($script:PSArtifactTypeModule,$script:PSArtifactTypeScript, $script:All))
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name "Scope" -ExpectedType String -IsRequired $false -PermittedValues @("CurrentUser","AllUsers"))
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name 'AllowClobber' -ExpectedType Switch -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name 'SkipPublisherCheck' -ExpectedType Switch -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name "InstallUpdate" -ExpectedType Switch -IsRequired $false)
|
|
Write-Output -InputObject (New-DynamicOption -Category $category -Name 'NoPathUpdate' -ExpectedType Switch -IsRequired $false)
|
|
}
|
|
}
|
|
}
|
|
|
|
function Add-PackageSource
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[string]
|
|
$Name,
|
|
|
|
[string]
|
|
$Location,
|
|
|
|
[bool]
|
|
$Trusted
|
|
)
|
|
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Add-PackageSource'))
|
|
|
|
if(-not $Name)
|
|
{
|
|
return
|
|
}
|
|
|
|
$Credential = $request.Credential
|
|
|
|
$IsNewModuleSource = $false
|
|
$Options = $request.Options
|
|
|
|
foreach( $o in $Options.Keys )
|
|
{
|
|
Write-Debug ( "OPTION: {0} => {1}" -f ($o, $Options[$o]) )
|
|
}
|
|
|
|
$Proxy = $null
|
|
if($Options.ContainsKey($script:Proxy))
|
|
{
|
|
$Proxy = $Options[$script:Proxy]
|
|
|
|
if(-not (Test-WebUri -Uri $Proxy))
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($Proxy, $script:Proxy)
|
|
ThrowError -ExceptionName 'System.ArgumentException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'InvalidWebUri' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Proxy
|
|
}
|
|
}
|
|
|
|
$ProxyCredential = $null
|
|
if($Options.ContainsKey($script:ProxyCredential))
|
|
{
|
|
$ProxyCredential = $Options[$script:ProxyCredential]
|
|
}
|
|
|
|
Set-ModuleSourcesVariable -Force -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
|
|
if($Options.ContainsKey('IsNewModuleSource'))
|
|
{
|
|
$IsNewModuleSource = $Options['IsNewModuleSource']
|
|
|
|
if($IsNewModuleSource.GetType().ToString() -eq 'System.String')
|
|
{
|
|
if($IsNewModuleSource -eq 'false')
|
|
{
|
|
$IsNewModuleSource = $false
|
|
}
|
|
elseif($IsNewModuleSource -eq 'true')
|
|
{
|
|
$IsNewModuleSource = $true
|
|
}
|
|
}
|
|
}
|
|
|
|
$IsUpdatePackageSource = $false
|
|
if($Options.ContainsKey('IsUpdatePackageSource'))
|
|
{
|
|
$IsUpdatePackageSource = $Options['IsUpdatePackageSource']
|
|
|
|
if($IsUpdatePackageSource.GetType().ToString() -eq 'System.String')
|
|
{
|
|
if($IsUpdatePackageSource -eq 'false')
|
|
{
|
|
$IsUpdatePackageSource = $false
|
|
}
|
|
elseif($IsUpdatePackageSource -eq 'true')
|
|
{
|
|
$IsUpdatePackageSource = $true
|
|
}
|
|
}
|
|
}
|
|
|
|
$PublishLocation = $null
|
|
if($Options.ContainsKey($script:PublishLocation))
|
|
{
|
|
if($Name -eq $Script:PSGalleryModuleSource)
|
|
{
|
|
$message = $LocalizedData.ParameterIsNotAllowedWithPSGallery -f ('PublishLocation')
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'ParameterIsNotAllowedWithPSGallery' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $PublishLocation
|
|
}
|
|
|
|
$PublishLocation = $Options[$script:PublishLocation]
|
|
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path $PublishLocation) -and
|
|
-not (Test-WebUri -uri $PublishLocation))
|
|
{
|
|
$PublishLocationUri = [Uri]$PublishLocation
|
|
if($PublishLocationUri.Scheme -eq 'file')
|
|
{
|
|
$message = $LocalizedData.PathNotFound -f ($PublishLocation)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $PublishLocation
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($PublishLocation, "PublishLocation")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $PublishLocation
|
|
}
|
|
}
|
|
}
|
|
|
|
$ScriptSourceLocation = $null
|
|
if($Options.ContainsKey($script:ScriptSourceLocation))
|
|
{
|
|
if($Name -eq $Script:PSGalleryModuleSource)
|
|
{
|
|
$message = $LocalizedData.ParameterIsNotAllowedWithPSGallery -f ('ScriptSourceLocation')
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'ParameterIsNotAllowedWithPSGallery' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $ScriptSourceLocation
|
|
}
|
|
|
|
$ScriptSourceLocation = $Options[$script:ScriptSourceLocation]
|
|
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path $ScriptSourceLocation) -and
|
|
-not (Test-WebUri -uri $ScriptSourceLocation))
|
|
{
|
|
$ScriptSourceLocationUri = [Uri]$ScriptSourceLocation
|
|
if($ScriptSourceLocationUri.Scheme -eq 'file')
|
|
{
|
|
$message = $LocalizedData.PathNotFound -f ($ScriptSourceLocation)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $ScriptSourceLocation
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($ScriptSourceLocation, "ScriptSourceLocation")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $ScriptSourceLocation
|
|
}
|
|
}
|
|
}
|
|
|
|
$ScriptPublishLocation = $null
|
|
if($Options.ContainsKey($script:ScriptPublishLocation))
|
|
{
|
|
if($Name -eq $Script:PSGalleryModuleSource)
|
|
{
|
|
$message = $LocalizedData.ParameterIsNotAllowedWithPSGallery -f ('ScriptPublishLocation')
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'ParameterIsNotAllowedWithPSGallery' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $ScriptPublishLocation
|
|
}
|
|
|
|
$ScriptPublishLocation = $Options[$script:ScriptPublishLocation]
|
|
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path $ScriptPublishLocation) -and
|
|
-not (Test-WebUri -uri $ScriptPublishLocation))
|
|
{
|
|
$ScriptPublishLocationUri = [Uri]$ScriptPublishLocation
|
|
if($ScriptPublishLocationUri.Scheme -eq 'file')
|
|
{
|
|
$message = $LocalizedData.PathNotFound -f ($ScriptPublishLocation)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $ScriptPublishLocation
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($ScriptPublishLocation, "ScriptPublishLocation")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $ScriptPublishLocation
|
|
}
|
|
}
|
|
}
|
|
|
|
$currentSourceObject = $null
|
|
|
|
# Check if Name is already registered
|
|
if($script:PSGetModuleSources.Contains($Name))
|
|
{
|
|
$currentSourceObject = $script:PSGetModuleSources[$Name]
|
|
}
|
|
|
|
# Location is not allowed for PSGallery source
|
|
# However OneGet passes Location value during Set-PackageSource cmdlet,
|
|
# that's why ensuring that Location value is same as the current SourceLocation
|
|
#
|
|
if(($Name -eq $Script:PSGalleryModuleSource) -and
|
|
$Location -and
|
|
((-not $IsUpdatePackageSource) -or ($currentSourceObject -and $currentSourceObject.SourceLocation -ne $Location)))
|
|
{
|
|
$message = $LocalizedData.ParameterIsNotAllowedWithPSGallery -f ('Location, NewLocation or SourceLocation')
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'ParameterIsNotAllowedWithPSGallery' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Location
|
|
}
|
|
|
|
if($Name -eq $Script:PSGalleryModuleSource)
|
|
{
|
|
# Add or update the PSGallery repostory
|
|
$repository = Set-PSGalleryRepository -Trusted:$Trusted
|
|
|
|
if($repository)
|
|
{
|
|
# return the package source object.
|
|
Write-Output -InputObject (New-PackageSourceFromModuleSource -ModuleSource $repository)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
if($Location)
|
|
{
|
|
# Ping and resolve the specified location
|
|
$Location = Resolve-Location -Location $Location `
|
|
-LocationParameterName 'Location' `
|
|
-Credential $Credential `
|
|
-Proxy $Proxy `
|
|
-ProxyCredential $ProxyCredential `
|
|
-CallerPSCmdlet $PSCmdlet
|
|
}
|
|
|
|
if(-not $Location)
|
|
{
|
|
# Above Resolve-Location function throws an error when it is not able to resolve a location
|
|
return
|
|
}
|
|
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path -Path $Location) -and
|
|
-not (Test-WebUri -uri $Location) )
|
|
{
|
|
$LocationUri = [Uri]$Location
|
|
if($LocationUri.Scheme -eq 'file')
|
|
{
|
|
$message = $LocalizedData.PathNotFound -f ($Location)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Location
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($Location, "Location")
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Location
|
|
}
|
|
}
|
|
|
|
if(Test-WildcardPattern $Name)
|
|
{
|
|
$message = $LocalizedData.RepositoryNameContainsWildCards -f ($Name)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "RepositoryNameContainsWildCards" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Name
|
|
}
|
|
|
|
$LocationString = Get-ValidModuleLocation -LocationString $Location -ParameterName "Location" -Proxy $Proxy -ProxyCredential $ProxyCredential -Credential $Credential
|
|
|
|
# Check if Location is already registered with another Name
|
|
$existingSourceName = Get-SourceName -Location $LocationString
|
|
|
|
if($existingSourceName -and
|
|
($Name -ne $existingSourceName) -and
|
|
-not $IsNewModuleSource)
|
|
{
|
|
$message = $LocalizedData.RepositoryAlreadyRegistered -f ($existingSourceName, $Location, $Name)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "RepositoryAlreadyRegistered" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
if(-not $PublishLocation -and $currentSourceObject -and $currentSourceObject.PublishLocation)
|
|
{
|
|
$PublishLocation = $currentSourceObject.PublishLocation
|
|
}
|
|
|
|
if((-not $ScriptPublishLocation) -and
|
|
$currentSourceObject -and
|
|
(Get-Member -InputObject $currentSourceObject -Name $script:ScriptPublishLocation) -and
|
|
$currentSourceObject.ScriptPublishLocation)
|
|
{
|
|
$ScriptPublishLocation = $currentSourceObject.ScriptPublishLocation
|
|
}
|
|
|
|
if((-not $ScriptSourceLocation) -and
|
|
$currentSourceObject -and
|
|
(Get-Member -InputObject $currentSourceObject -Name $script:ScriptSourceLocation) -and
|
|
$currentSourceObject.ScriptSourceLocation)
|
|
{
|
|
$ScriptSourceLocation = $currentSourceObject.ScriptSourceLocation
|
|
}
|
|
|
|
$IsProviderSpecified = $false;
|
|
if ($Options.ContainsKey($script:PackageManagementProviderParam))
|
|
{
|
|
$SpecifiedProviderName = $Options[$script:PackageManagementProviderParam]
|
|
|
|
$IsProviderSpecified = $true
|
|
|
|
Write-Verbose ($LocalizedData.SpecifiedProviderName -f $SpecifiedProviderName)
|
|
if ($SpecifiedProviderName -eq $script:PSModuleProviderName)
|
|
{
|
|
$message = $LocalizedData.InvalidPackageManagementProviderValue -f ($SpecifiedProviderName, $script:NuGetProviderName, $script:NuGetProviderName)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidPackageManagementProviderValue" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $SpecifiedProviderName
|
|
return
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$SpecifiedProviderName = $script:NuGetProviderName
|
|
Write-Verbose ($LocalizedData.ProviderNameNotSpecified -f $SpecifiedProviderName)
|
|
}
|
|
|
|
$packageSource = $null
|
|
|
|
$selProviders = $request.SelectProvider($SpecifiedProviderName)
|
|
|
|
if(-not $selProviders -and $IsProviderSpecified)
|
|
{
|
|
$message = $LocalizedData.SpecifiedProviderNotAvailable -f $SpecifiedProviderName
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "SpecifiedProviderNotAvailable" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $SpecifiedProviderName
|
|
}
|
|
|
|
# Try with user specified provider or NuGet provider
|
|
foreach($SelectedProvider in $selProviders)
|
|
{
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
if($SelectedProvider -and $SelectedProvider.Features.ContainsKey($script:SupportsPSModulesFeatureName))
|
|
{
|
|
$NewRequest = $request.CloneRequest( $null, @($LocationString), $request.Credential )
|
|
$packageSource = $SelectedProvider.ResolvePackageSources( $NewRequest )
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.SpecifiedProviderDoesnotSupportPSModules -f $SelectedProvider.ProviderName
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "SpecifiedProviderDoesnotSupportPSModules" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $SelectedProvider.ProviderName
|
|
}
|
|
|
|
if($packageSource)
|
|
{
|
|
break
|
|
}
|
|
}
|
|
|
|
# Poll other package provider when NuGet provider doesn't resolves the specified location
|
|
if(-not $packageSource -and -not $IsProviderSpecified)
|
|
{
|
|
Write-Verbose ($LocalizedData.PollingPackageManagementProvidersForLocation -f $LocationString)
|
|
|
|
$moduleProviders = $request.SelectProvidersWithFeature($script:SupportsPSModulesFeatureName)
|
|
|
|
foreach($provider in $moduleProviders)
|
|
{
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
# Skip already tried $SpecifiedProviderName and PowerShellGet provider
|
|
if($provider.ProviderName -eq $SpecifiedProviderName -or
|
|
$provider.ProviderName -eq $script:PSModuleProviderName)
|
|
{
|
|
continue
|
|
}
|
|
|
|
Write-Verbose ($LocalizedData.PollingSingleProviderForLocation -f ($LocationString, $provider.ProviderName))
|
|
$NewRequest = $request.CloneRequest( @{}, @($LocationString), $request.Credential )
|
|
$packageSource = $provider.ResolvePackageSources($NewRequest)
|
|
|
|
if($packageSource)
|
|
{
|
|
Write-Verbose ($LocalizedData.FoundProviderForLocation -f ($provider.ProviderName, $Location))
|
|
$SelectedProvider = $provider
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if(-not $packageSource)
|
|
{
|
|
$message = $LocalizedData.SpecifiedLocationCannotBeRegistered -f $Location
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "SpecifiedLocationCannotBeRegistered" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $Location
|
|
}
|
|
|
|
$ProviderOptions = @{}
|
|
|
|
$SelectedProvider.DynamicOptions | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if($options.ContainsKey($_.Name) )
|
|
{
|
|
$ProviderOptions[$_.Name] = $options[$_.Name]
|
|
}
|
|
}
|
|
|
|
# Keep the existing provider options if not specified in Set-PSRepository
|
|
if($currentSourceObject)
|
|
{
|
|
$currentSourceObject.ProviderOptions.GetEnumerator() | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if (-not $ProviderOptions.ContainsKey($_.Key) )
|
|
{
|
|
$ProviderOptions[$_.Key] = $_.Value
|
|
}
|
|
}
|
|
}
|
|
|
|
if(-not $PublishLocation)
|
|
{
|
|
$PublishLocation = Get-PublishLocation -Location $LocationString
|
|
}
|
|
|
|
# Use the PublishLocation for the scripts when ScriptPublishLocation is not specified by the user
|
|
if(-not $ScriptPublishLocation)
|
|
{
|
|
$ScriptPublishLocation = $PublishLocation
|
|
|
|
# ScriptPublishLocation and PublishLocation should be equal in case of SMB Share or Local directory paths
|
|
if($Options.ContainsKey($script:ScriptPublishLocation) -and
|
|
(Microsoft.PowerShell.Management\Test-Path -Path $ScriptPublishLocation))
|
|
{
|
|
if($ScriptPublishLocation -ne $PublishLocation)
|
|
{
|
|
$message = $LocalizedData.PublishLocationPathsForModulesAndScriptsShouldBeEqual -f ($LocationString, $ScriptSourceLocation)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PublishLocationPathsForModulesAndScriptsShouldBeEqual" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $Location
|
|
}
|
|
}
|
|
}
|
|
|
|
if(-not $ScriptSourceLocation)
|
|
{
|
|
$ScriptSourceLocation = Get-ScriptSourceLocation -Location $LocationString -Proxy $Proxy -ProxyCredential $ProxyCredential -Credential $Credential
|
|
}
|
|
elseif($Options.ContainsKey($script:ScriptSourceLocation))
|
|
{
|
|
# ScriptSourceLocation and SourceLocation cannot be same for they are URLs
|
|
# Both should be equal in case of SMB Share or Local directory paths
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $ScriptSourceLocation)
|
|
{
|
|
if($ScriptSourceLocation -ne $LocationString)
|
|
{
|
|
$message = $LocalizedData.SourceLocationPathsForModulesAndScriptsShouldBeEqual -f ($LocationString, $ScriptSourceLocation)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "SourceLocationPathsForModulesAndScriptsShouldBeEqual" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $Location
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if($ScriptSourceLocation -eq $LocationString -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))
|
|
)
|
|
{
|
|
$message = $LocalizedData.SourceLocationUrisForModulesAndScriptsShouldBeDifferent -f ($LocationString, $ScriptSourceLocation)
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "SourceLocationUrisForModulesAndScriptsShouldBeDifferent" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation `
|
|
-ExceptionObject $Location
|
|
}
|
|
}
|
|
}
|
|
|
|
# no error so we can safely remove the source
|
|
if($script:PSGetModuleSources.Contains($Name))
|
|
{
|
|
$null = $script:PSGetModuleSources.Remove($Name)
|
|
}
|
|
|
|
# Add new module source
|
|
$moduleSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
|
|
Name = $Name
|
|
SourceLocation = $LocationString
|
|
PublishLocation = $PublishLocation
|
|
ScriptSourceLocation = $ScriptSourceLocation
|
|
ScriptPublishLocation = $ScriptPublishLocation
|
|
Trusted=$Trusted
|
|
Registered= (-not $IsNewModuleSource)
|
|
InstallationPolicy = if($Trusted) {'Trusted'} else {'Untrusted'}
|
|
PackageManagementProvider = $SelectedProvider.ProviderName
|
|
ProviderOptions = $ProviderOptions
|
|
})
|
|
|
|
#region telemetry - Capture non-PSGallery registrations as telemetry events
|
|
if ($script:TelemetryEnabled)
|
|
{
|
|
|
|
Log-NonPSGalleryRegistration -sourceLocation $moduleSource.SourceLocation `
|
|
-installationPolicy $moduleSource.InstallationPolicy `
|
|
-packageManagementProvider $moduleSource.PackageManagementProvider `
|
|
-publishLocation $moduleSource.PublishLocation `
|
|
-scriptSourceLocation $moduleSource.ScriptSourceLocation `
|
|
-scriptPublishLocation $moduleSource.ScriptPublishLocation `
|
|
-operationName PSGET_NONPSGALLERY_REGISTRATION `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
|
|
}
|
|
#endregion
|
|
|
|
$moduleSource.PSTypeNames.Insert(0, "Microsoft.PowerShell.Commands.PSRepository")
|
|
|
|
# Persist the repositories only when Register-PSRepository cmdlet is used
|
|
if(-not $IsNewModuleSource)
|
|
{
|
|
$script:PSGetModuleSources.Add($Name, $moduleSource)
|
|
|
|
$message = $LocalizedData.RepositoryRegistered -f ($Name, $LocationString)
|
|
Write-Verbose $message
|
|
|
|
# Persist the module sources
|
|
Save-ModuleSources
|
|
}
|
|
|
|
# return the package source object.
|
|
Write-Output -InputObject (New-PackageSourceFromModuleSource -ModuleSource $moduleSource)
|
|
}
|
|
|
|
function Resolve-PackageSource
|
|
{
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Resolve-PackageSource'))
|
|
|
|
Set-ModuleSourcesVariable
|
|
|
|
$SourceName = $request.PackageSources
|
|
|
|
if(-not $SourceName)
|
|
{
|
|
$SourceName = "*"
|
|
}
|
|
|
|
foreach($moduleSourceName in $SourceName)
|
|
{
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $moduleSourceName,$script:wildcardOptions
|
|
$moduleSourceFound = $false
|
|
|
|
$script:PSGetModuleSources.GetEnumerator() |
|
|
Microsoft.PowerShell.Core\Where-Object {$wildcardPattern.IsMatch($_.Key)} |
|
|
Microsoft.PowerShell.Core\ForEach-Object {
|
|
|
|
$moduleSource = $script:PSGetModuleSources[$_.Key]
|
|
|
|
$packageSource = New-PackageSourceFromModuleSource -ModuleSource $moduleSource
|
|
|
|
Write-Output -InputObject $packageSource
|
|
|
|
$moduleSourceFound = $true
|
|
}
|
|
|
|
if(-not $moduleSourceFound)
|
|
{
|
|
$sourceName = Get-SourceName -Location $moduleSourceName
|
|
|
|
if($sourceName)
|
|
{
|
|
$moduleSource = $script:PSGetModuleSources[$sourceName]
|
|
|
|
$packageSource = New-PackageSourceFromModuleSource -ModuleSource $moduleSource
|
|
|
|
Write-Output -InputObject $packageSource
|
|
}
|
|
elseif( -not (Test-WildcardPattern $moduleSourceName))
|
|
{
|
|
$message = $LocalizedData.RepositoryNotFound -f ($moduleSourceName)
|
|
|
|
Write-Error -Message $message -ErrorId "RepositoryNotFound" -Category InvalidOperation -TargetObject $moduleSourceName
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Remove-PackageSource
|
|
{
|
|
param
|
|
(
|
|
[string]
|
|
$Name
|
|
)
|
|
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Remove-PackageSource'))
|
|
|
|
Set-ModuleSourcesVariable -Force
|
|
|
|
$ModuleSourcesToBeRemoved = @()
|
|
|
|
foreach ($moduleSourceName in $Name)
|
|
{
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
# Check if $Name contains any wildcards
|
|
if(Test-WildcardPattern $moduleSourceName)
|
|
{
|
|
$message = $LocalizedData.RepositoryNameContainsWildCards -f ($moduleSourceName)
|
|
Write-Error -Message $message -ErrorId "RepositoryNameContainsWildCards" -Category InvalidOperation -TargetObject $moduleSourceName
|
|
continue
|
|
}
|
|
|
|
# Check if the specified module source name is in the registered module sources
|
|
if(-not $script:PSGetModuleSources.Contains($moduleSourceName))
|
|
{
|
|
$message = $LocalizedData.RepositoryNotFound -f ($moduleSourceName)
|
|
Write-Error -Message $message -ErrorId "RepositoryNotFound" -Category InvalidOperation -TargetObject $moduleSourceName
|
|
continue
|
|
}
|
|
|
|
$ModuleSourcesToBeRemoved += $moduleSourceName
|
|
$message = $LocalizedData.RepositoryUnregistered -f ($moduleSourceName)
|
|
Write-Verbose $message
|
|
}
|
|
|
|
# Remove the module source
|
|
$ModuleSourcesToBeRemoved | Microsoft.PowerShell.Core\ForEach-Object { $null = $script:PSGetModuleSources.Remove($_) }
|
|
|
|
# Persist the module sources
|
|
Save-ModuleSources
|
|
}
|
|
|
|
function Find-Package
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[string[]]
|
|
$names,
|
|
|
|
[string]
|
|
$requiredVersion,
|
|
|
|
[string]
|
|
$minimumVersion,
|
|
|
|
[string]
|
|
$maximumVersion
|
|
)
|
|
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Find-Package'))
|
|
|
|
Set-ModuleSourcesVariable
|
|
|
|
if($RequiredVersion -and $MinimumVersion)
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.VersionRangeAndRequiredVersionCannotBeSpecifiedTogether `
|
|
-ErrorId "VersionRangeAndRequiredVersionCannotBeSpecifiedTogether" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
if($RequiredVersion -or $MinimumVersion)
|
|
{
|
|
if(-not $names -or $names.Count -ne 1 -or (Test-WildcardPattern -Name $names[0]))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.VersionParametersAreAllowedOnlyWithSingleName `
|
|
-ErrorId "VersionParametersAreAllowedOnlyWithSingleName" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
|
|
$options = $request.Options
|
|
|
|
foreach( $o in $options.Keys )
|
|
{
|
|
Write-Debug ( "OPTION: {0} => {1}" -f ($o, $options[$o]) )
|
|
}
|
|
|
|
# When using -Name, we don't send PSGet-specific properties to the server - we will filter it ourselves
|
|
$postFilter = New-Object -TypeName System.Collections.Hashtable
|
|
if($options.ContainsKey("Name"))
|
|
{
|
|
if($options.ContainsKey("Includes"))
|
|
{
|
|
$postFilter["Includes"] = $options["Includes"]
|
|
$null = $options.Remove("Includes")
|
|
}
|
|
|
|
if($options.ContainsKey("DscResource"))
|
|
{
|
|
$postFilter["DscResource"] = $options["DscResource"]
|
|
$null = $options.Remove("DscResource")
|
|
}
|
|
|
|
if($options.ContainsKey('RoleCapability'))
|
|
{
|
|
$postFilter['RoleCapability'] = $options['RoleCapability']
|
|
$null = $options.Remove('RoleCapability')
|
|
}
|
|
|
|
if($options.ContainsKey("Command"))
|
|
{
|
|
$postFilter["Command"] = $options["Command"]
|
|
$null = $options.Remove("Command")
|
|
}
|
|
}
|
|
|
|
$LocationOGPHashtable = [ordered]@{}
|
|
if($options -and $options.ContainsKey('Source'))
|
|
{
|
|
$SourceNames = $($options['Source'])
|
|
|
|
Write-Verbose ($LocalizedData.SpecifiedSourceName -f ($SourceNames))
|
|
|
|
foreach($sourceName in $SourceNames)
|
|
{
|
|
if($script:PSGetModuleSources.Contains($sourceName))
|
|
{
|
|
$ModuleSource = $script:PSGetModuleSources[$sourceName]
|
|
$LocationOGPHashtable[$ModuleSource.SourceLocation] = (Get-ProviderName -PSCustomObject $ModuleSource)
|
|
}
|
|
else
|
|
{
|
|
$sourceByLocation = Get-SourceName -Location $sourceName
|
|
|
|
if ($sourceByLocation)
|
|
{
|
|
$ModuleSource = $script:PSGetModuleSources[$sourceByLocation]
|
|
$LocationOGPHashtable[$ModuleSource.SourceLocation] = (Get-ProviderName -PSCustomObject $ModuleSource)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.RepositoryNotFound -f ($sourceName)
|
|
Write-Error -Message $message `
|
|
-ErrorId 'RepositoryNotFound' `
|
|
-Category InvalidArgument `
|
|
-TargetObject $sourceName
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elseif($options -and
|
|
$options.ContainsKey($script:PackageManagementProviderParam) -and
|
|
$options.ContainsKey('Location'))
|
|
{
|
|
$Location = $options['Location']
|
|
$PackageManagementProvider = $options['PackageManagementProvider']
|
|
|
|
Write-Verbose ($LocalizedData.SpecifiedLocationAndOGP -f ($Location, $PackageManagementProvider))
|
|
|
|
$LocationOGPHashtable[$Location] = $PackageManagementProvider
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose $LocalizedData.NoSourceNameIsSpecified
|
|
|
|
$script:PSGetModuleSources.Values | Microsoft.PowerShell.Core\ForEach-Object { $LocationOGPHashtable[$_.SourceLocation] = (Get-ProviderName -PSCustomObject $_) }
|
|
}
|
|
|
|
$artifactTypes = $script:PSArtifactTypeModule
|
|
if($options.ContainsKey($script:PSArtifactType))
|
|
{
|
|
$artifactTypes = $options[$script:PSArtifactType]
|
|
}
|
|
|
|
if($artifactTypes -eq $script:All)
|
|
{
|
|
$artifactTypes = @($script:PSArtifactTypeModule,$script:PSArtifactTypeScript)
|
|
}
|
|
|
|
$providerOptions = @{}
|
|
|
|
if($options.ContainsKey($script:AllVersions))
|
|
{
|
|
$providerOptions[$script:AllVersions] = $options[$script:AllVersions]
|
|
}
|
|
|
|
if($options.ContainsKey($script:Filter))
|
|
{
|
|
$Filter = $options[$script:Filter]
|
|
$providerOptions['Contains'] = $Filter
|
|
}
|
|
|
|
if($options.ContainsKey($script:Tag))
|
|
{
|
|
$userSpecifiedTags = $options[$script:Tag] | Microsoft.PowerShell.Utility\Select-Object -Unique
|
|
}
|
|
else
|
|
{
|
|
$userSpecifiedTags = @($script:NotSpecified)
|
|
}
|
|
|
|
$specifiedDscResources = @()
|
|
if($options.ContainsKey('DscResource'))
|
|
{
|
|
$specifiedDscResources = $options['DscResource'] |
|
|
Microsoft.PowerShell.Utility\Select-Object -Unique |
|
|
Microsoft.PowerShell.Core\ForEach-Object {"$($script:DscResource)_$_"}
|
|
}
|
|
|
|
$specifiedRoleCapabilities = @()
|
|
if($options.ContainsKey('RoleCapability'))
|
|
{
|
|
$specifiedRoleCapabilities = $options['RoleCapability'] |
|
|
Microsoft.PowerShell.Utility\Select-Object -Unique |
|
|
Microsoft.PowerShell.Core\ForEach-Object {"$($script:RoleCapability)_$_"}
|
|
}
|
|
|
|
$specifiedCommands = @()
|
|
if($options.ContainsKey('Command'))
|
|
{
|
|
$specifiedCommands = $options['Command'] |
|
|
Microsoft.PowerShell.Utility\Select-Object -Unique |
|
|
Microsoft.PowerShell.Core\ForEach-Object {"$($script:Command)_$_"}
|
|
}
|
|
|
|
$specifiedIncludes = @()
|
|
if($options.ContainsKey('Includes'))
|
|
{
|
|
$includes = $options['Includes'] |
|
|
Microsoft.PowerShell.Utility\Select-Object -Unique |
|
|
Microsoft.PowerShell.Core\ForEach-Object {"$($script:Includes)_$_"}
|
|
|
|
# Add PSIncludes_DscResource to $specifiedIncludes iff -DscResource names are not specified
|
|
# Add PSIncludes_RoleCapability to $specifiedIncludes iff -RoleCapability names are not specified
|
|
# Add PSIncludes_Cmdlet or PSIncludes_Function to $specifiedIncludes iff -Command names are not specified
|
|
# otherwise $script:NotSpecified will be added to $specifiedIncludes
|
|
if($includes)
|
|
{
|
|
if(-not $specifiedDscResources -and ($includes -contains "$($script:Includes)_DscResource") )
|
|
{
|
|
$specifiedIncludes += "$($script:Includes)_DscResource"
|
|
}
|
|
|
|
if(-not $specifiedRoleCapabilities -and ($includes -contains "$($script:Includes)_RoleCapability") )
|
|
{
|
|
$specifiedIncludes += "$($script:Includes)_RoleCapability"
|
|
}
|
|
|
|
if(-not $specifiedCommands)
|
|
{
|
|
if($includes -contains "$($script:Includes)_Cmdlet")
|
|
{
|
|
$specifiedIncludes += "$($script:Includes)_Cmdlet"
|
|
}
|
|
|
|
if($includes -contains "$($script:Includes)_Function")
|
|
{
|
|
$specifiedIncludes += "$($script:Includes)_Function"
|
|
}
|
|
|
|
if($includes -contains "$($script:Includes)_Workflow")
|
|
{
|
|
$specifiedIncludes += "$($script:Includes)_Workflow"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(-not $specifiedDscResources)
|
|
{
|
|
$specifiedDscResources += $script:NotSpecified
|
|
}
|
|
|
|
if(-not $specifiedRoleCapabilities)
|
|
{
|
|
$specifiedRoleCapabilities += $script:NotSpecified
|
|
}
|
|
|
|
if(-not $specifiedCommands)
|
|
{
|
|
$specifiedCommands += $script:NotSpecified
|
|
}
|
|
|
|
if(-not $specifiedIncludes)
|
|
{
|
|
$specifiedIncludes += $script:NotSpecified
|
|
}
|
|
|
|
$providerSearchTags = @{}
|
|
|
|
foreach($tag in $userSpecifiedTags)
|
|
{
|
|
foreach($include in $specifiedIncludes)
|
|
{
|
|
foreach($command in $specifiedCommands)
|
|
{
|
|
foreach($resource in $specifiedDscResources)
|
|
{
|
|
foreach($roleCapability in $specifiedRoleCapabilities)
|
|
{
|
|
$providerTags = @()
|
|
if($resource -ne $script:NotSpecified)
|
|
{
|
|
$providerTags += $resource
|
|
}
|
|
|
|
if($roleCapability -ne $script:NotSpecified)
|
|
{
|
|
$providerTags += $roleCapability
|
|
}
|
|
|
|
if($command -ne $script:NotSpecified)
|
|
{
|
|
$providerTags += $command
|
|
}
|
|
|
|
if($include -ne $script:NotSpecified)
|
|
{
|
|
$providerTags += $include
|
|
}
|
|
|
|
if($tag -ne $script:NotSpecified)
|
|
{
|
|
$providerTags += $tag
|
|
}
|
|
|
|
if($providerTags)
|
|
{
|
|
$providerSearchTags["$tag $resource $roleCapability $command $include"] = $providerTags
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$InstallationPolicy = "Untrusted"
|
|
if($options.ContainsKey('InstallationPolicy'))
|
|
{
|
|
$InstallationPolicy = $options['InstallationPolicy']
|
|
}
|
|
|
|
$streamedResults = @()
|
|
|
|
foreach($artifactType in $artifactTypes)
|
|
{
|
|
foreach($kvPair in $LocationOGPHashtable.GetEnumerator())
|
|
{
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
$Location = $kvPair.Key
|
|
if($artifactType -eq $script:PSArtifactTypeScript)
|
|
{
|
|
$sourceName = Get-SourceName -Location $Location
|
|
|
|
if($SourceName)
|
|
{
|
|
$ModuleSource = $script:PSGetModuleSources[$SourceName]
|
|
|
|
# Skip source if no ScriptSourceLocation is available.
|
|
if(-not $ModuleSource.ScriptSourceLocation)
|
|
{
|
|
if($options.ContainsKey('Source'))
|
|
{
|
|
$message = $LocalizedData.ScriptSourceLocationIsMissing -f ($ModuleSource.Name)
|
|
Write-Error -Message $message `
|
|
-ErrorId 'ScriptSourceLocationIsMissing' `
|
|
-Category InvalidArgument `
|
|
-TargetObject $ModuleSource.Name
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
$Location = $ModuleSource.ScriptSourceLocation
|
|
}
|
|
}
|
|
|
|
$ProviderName = $kvPair.Value
|
|
|
|
Write-Verbose ($LocalizedData.GettingPackageManagementProviderObject -f ($ProviderName))
|
|
|
|
$provider = $request.SelectProvider($ProviderName)
|
|
|
|
if(-not $provider)
|
|
{
|
|
Write-Error -Message ($LocalizedData.PackageManagementProviderIsNotAvailable -f $ProviderName)
|
|
|
|
Continue
|
|
}
|
|
|
|
Write-Verbose ($LocalizedData.SpecifiedLocationAndOGP -f ($Location, $provider.ProviderName))
|
|
|
|
if($providerSearchTags.Values.Count)
|
|
{
|
|
$tagList = $providerSearchTags.Values
|
|
}
|
|
else
|
|
{
|
|
$tagList = @($script:NotSpecified)
|
|
}
|
|
|
|
$namesParameterEmpty = ($names.Count -eq 1) -and ($names[0] -eq '')
|
|
|
|
foreach($providerTag in $tagList)
|
|
{
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
$FilterOnTag = @()
|
|
|
|
if($providerTag -ne $script:NotSpecified)
|
|
{
|
|
$FilterOnTag = $providerTag
|
|
}
|
|
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $Location)
|
|
{
|
|
if($artifactType -eq $script:PSArtifactTypeScript)
|
|
{
|
|
$FilterOnTag += 'PSScript'
|
|
}
|
|
elseif($artifactType -eq $script:PSArtifactTypeModule)
|
|
{
|
|
$FilterOnTag += 'PSModule'
|
|
}
|
|
}
|
|
|
|
if($FilterOnTag)
|
|
{
|
|
$providerOptions["FilterOnTag"] = $FilterOnTag
|
|
}
|
|
elseif($providerOptions.ContainsKey('FilterOnTag'))
|
|
{
|
|
$null = $providerOptions.Remove('FilterOnTag')
|
|
}
|
|
|
|
if($request.Options.ContainsKey($script:FindByCanonicalId))
|
|
{
|
|
$providerOptions[$script:FindByCanonicalId] = $request.Options[$script:FindByCanonicalId]
|
|
}
|
|
|
|
$providerOptions["Headers"] = 'PSGalleryClientVersion=1.1'
|
|
|
|
$NewRequest = $request.CloneRequest( $providerOptions, @($Location), $request.Credential )
|
|
|
|
$pkgs = $provider.FindPackages($names,
|
|
$requiredVersion,
|
|
$minimumVersion,
|
|
$maximumVersion,
|
|
$NewRequest )
|
|
|
|
foreach($pkg in $pkgs)
|
|
{
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
# $pkg.Name has to match any of the supplied names, using PowerShell wildcards
|
|
if ($namesParameterEmpty -or ($names | % { if ($pkg.Name -like $_){return $true; break} } -End {return $false}))
|
|
{
|
|
$includePackage = $true
|
|
|
|
# If -Name was provided, we need to post-filter
|
|
# Filtering has AND semantics between different parameters and OR within a parameter (each parameter is potentially an array)
|
|
if($options.ContainsKey("Name") -and $postFilter.Count -gt 0)
|
|
{
|
|
if ($pkg.Metadata["DscResources"].Count -gt 0)
|
|
{
|
|
$pkgDscResources = $pkg.Metadata["DscResources"] -Split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
}
|
|
else
|
|
{
|
|
$pkgDscResources = $pkg.Metadata["tags"] -Split " " `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.Trim() } `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.StartsWith($script:DscResource, [System.StringComparison]::OrdinalIgnoreCase) } `
|
|
| Microsoft.PowerShell.Core\ForEach-Object { $_.Substring($script:DscResource.Length + 1) }
|
|
}
|
|
|
|
if ($pkg.Metadata['RoleCapabilities'].Count -gt 0)
|
|
{
|
|
$pkgRoleCapabilities = $pkg.Metadata['RoleCapabilities'] -Split ' ' | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
}
|
|
else
|
|
{
|
|
$pkgRoleCapabilities = $pkg.Metadata["tags"] -Split ' ' `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.Trim() } `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.StartsWith($script:RoleCapability, [System.StringComparison]::OrdinalIgnoreCase) } `
|
|
| Microsoft.PowerShell.Core\ForEach-Object { $_.Substring($script:RoleCapability.Length + 1) }
|
|
}
|
|
|
|
if ($pkg.Metadata["Functions"].Count -gt 0)
|
|
{
|
|
$pkgFunctions = $pkg.Metadata["Functions"] -Split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
}
|
|
else
|
|
{
|
|
$pkgFunctions = $pkg.Metadata["tags"] -Split " " `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.Trim() } `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.StartsWith($script:Function, [System.StringComparison]::OrdinalIgnoreCase) } `
|
|
| Microsoft.PowerShell.Core\ForEach-Object { $_.Substring($script:Function.Length + 1) }
|
|
}
|
|
|
|
if ($pkg.Metadata["Cmdlets"].Count -gt 0)
|
|
{
|
|
$pkgCmdlets = $pkg.Metadata["Cmdlets"] -Split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
}
|
|
else
|
|
{
|
|
$pkgCmdlets = $pkg.Metadata["tags"] -Split " " `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.Trim() } `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.StartsWith($script:Cmdlet, [System.StringComparison]::OrdinalIgnoreCase) } `
|
|
| Microsoft.PowerShell.Core\ForEach-Object { $_.Substring($script:Cmdlet.Length + 1) }
|
|
}
|
|
|
|
if ($pkg.Metadata["Workflows"].Count -gt 0)
|
|
{
|
|
$pkgWorkflows = $pkg.Metadata["Workflows"] -Split " " | Microsoft.PowerShell.Core\Where-Object { $_.Trim() }
|
|
}
|
|
else
|
|
{
|
|
$pkgWorkflows = $pkg.Metadata["tags"] -Split " " `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.Trim() } `
|
|
| Microsoft.PowerShell.Core\Where-Object { $_.StartsWith($script:Workflow, [System.StringComparison]::OrdinalIgnoreCase) } `
|
|
| Microsoft.PowerShell.Core\ForEach-Object { $_.Substring($script:Workflow.Length + 1) }
|
|
}
|
|
|
|
foreach ($key in $postFilter.Keys)
|
|
{
|
|
switch ($key)
|
|
{
|
|
"DscResource" {
|
|
$values = $postFilter[$key]
|
|
|
|
$includePackage = $false
|
|
|
|
foreach ($value in $values)
|
|
{
|
|
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $value,$script:wildcardOptions
|
|
|
|
$pkgDscResources | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if ($wildcardPattern.IsMatch($_))
|
|
{
|
|
$includePackage = $true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not $includePackage)
|
|
{
|
|
break
|
|
}
|
|
}
|
|
|
|
'RoleCapability' {
|
|
$values = $postFilter[$key]
|
|
|
|
$includePackage = $false
|
|
|
|
foreach ($value in $values)
|
|
{
|
|
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $value,$script:wildcardOptions
|
|
|
|
$pkgRoleCapabilities | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if ($wildcardPattern.IsMatch($_))
|
|
{
|
|
$includePackage = $true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not $includePackage)
|
|
{
|
|
break
|
|
}
|
|
}
|
|
|
|
"Command" {
|
|
$values = $postFilter[$key]
|
|
|
|
$includePackage = $false
|
|
|
|
foreach ($value in $values)
|
|
{
|
|
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $value,$script:wildcardOptions
|
|
|
|
$pkgFunctions | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if ($wildcardPattern.IsMatch($_))
|
|
{
|
|
$includePackage = $true
|
|
break
|
|
}
|
|
}
|
|
|
|
$pkgCmdlets | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if ($wildcardPattern.IsMatch($_))
|
|
{
|
|
$includePackage = $true
|
|
break
|
|
}
|
|
}
|
|
|
|
$pkgWorkflows | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if ($wildcardPattern.IsMatch($_))
|
|
{
|
|
$includePackage = $true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not $includePackage)
|
|
{
|
|
break
|
|
}
|
|
}
|
|
|
|
"Includes" {
|
|
$values = $postFilter[$key]
|
|
|
|
$includePackage = $false
|
|
|
|
foreach ($value in $values)
|
|
{
|
|
switch ($value)
|
|
{
|
|
"Cmdlet" { if ($pkgCmdlets ) { $includePackage = $true } }
|
|
"Function" { if ($pkgFunctions ) { $includePackage = $true } }
|
|
"DscResource" { if ($pkgDscResources ) { $includePackage = $true } }
|
|
"RoleCapability" { if ($pkgRoleCapabilities ) { $includePackage = $true } }
|
|
"Workflow" { if ($pkgWorkflows ) { $includePackage = $true } }
|
|
}
|
|
}
|
|
|
|
if (-not $includePackage)
|
|
{
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($includePackage)
|
|
{
|
|
$fastPackageReference = New-FastPackageReference -ProviderName $provider.ProviderName `
|
|
-PackageName $pkg.Name `
|
|
-Version $pkg.Version `
|
|
-Source $Location `
|
|
-ArtifactType $artifactType
|
|
|
|
if($streamedResults -notcontains $fastPackageReference)
|
|
{
|
|
$streamedResults += $fastPackageReference
|
|
|
|
$FromTrustedSource = $false
|
|
|
|
$ModuleSourceName = Get-SourceName -Location $Location
|
|
|
|
if($ModuleSourceName)
|
|
{
|
|
$FromTrustedSource = $script:PSGetModuleSources[$ModuleSourceName].Trusted
|
|
}
|
|
elseif($InstallationPolicy -eq "Trusted")
|
|
{
|
|
$FromTrustedSource = $true
|
|
}
|
|
|
|
$sid = New-SoftwareIdentityFromPackage -Package $pkg `
|
|
-PackageManagementProviderName $provider.ProviderName `
|
|
-SourceLocation $Location `
|
|
-IsFromTrustedSource:$FromTrustedSource `
|
|
-Type $artifactType `
|
|
-request $request
|
|
|
|
$script:FastPackRefHastable[$fastPackageReference] = $pkg
|
|
|
|
Write-Output -InputObject $sid
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Download-Package
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$FastPackageReference,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Location
|
|
)
|
|
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Download-Package'))
|
|
|
|
Install-PackageUtility -FastPackageReference $FastPackageReference -Request $Request -Location $Location
|
|
}
|
|
|
|
function Install-Package
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$FastPackageReference
|
|
)
|
|
|
|
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Install-Package'))
|
|
|
|
Install-PackageUtility -FastPackageReference $FastPackageReference -Request $Request
|
|
}
|
|
|
|
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 = $null
|
|
$RequiredVersion = $null
|
|
$IsSavePackage = $false
|
|
$Scope = $null
|
|
$NoPathUpdate = $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]
|
|
$artfactType = $parts[4]
|
|
|
|
# The default destination location for Modules and Scripts is ProgramFiles path
|
|
$scriptDestination = $script:ProgramFilesScriptsPath
|
|
$moduleDestination = $script:programFilesModulesPath
|
|
$Scope = 'AllUsers'
|
|
|
|
if($artfactType -eq $script:PSArtifactTypeScript)
|
|
{
|
|
$AdminPreviligeErrorMessage = $LocalizedData.InstallScriptNeedsCurrentUserScopeParameterForNonAdminUser -f @($script:ProgramFilesScriptsPath, $script:MyDocumentsScriptsPath)
|
|
$AdminPreviligeErrorId = 'InstallScriptNeedsCurrentUserScopeParameterForNonAdminUser'
|
|
}
|
|
else
|
|
{
|
|
$AdminPreviligeErrorMessage = $LocalizedData.InstallModuleNeedsCurrentUserScopeParameterForNonAdminUser -f @($script:programFilesModulesPath, $script:MyDocumentsModulesPath)
|
|
$AdminPreviligeErrorId = 'InstallModuleNeedsCurrentUserScopeParameterForNonAdminUser'
|
|
}
|
|
|
|
$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 CurrentUser' is not specified
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $AdminPreviligeErrorMessage `
|
|
-ErrorId $AdminPreviligeErrorId `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
}
|
|
elseif($Location)
|
|
{
|
|
$IsSavePackage = $true
|
|
$Scope = $null
|
|
|
|
$moduleDestination = $Location
|
|
$scriptDestination = $Location
|
|
}
|
|
# if no scope and no destination path and not elevated, then raise an error
|
|
elseif(-not (Test-RunningAsElevated))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $AdminPreviligeErrorMessage `
|
|
-ErrorId $AdminPreviligeErrorId `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
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('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 ($artfactType -eq $script:PSArtifactTypeScript) -and (-not $installUpdate))
|
|
{
|
|
ValidateAndSet-PATHVariableIfUserAccepts -Scope $Scope `
|
|
-ScopePath $scriptDestination `
|
|
-Request $request `
|
|
-NoPathUpdate:$NoPathUpdate `
|
|
-Force:$Force
|
|
}
|
|
|
|
if($artfactType -eq $script:PSArtifactTypeModule)
|
|
{
|
|
$message = $LocalizedData.ModuleDestination -f @($moduleDestination)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.ScriptDestination -f @($scriptDestination, $moduleDestination)
|
|
}
|
|
Write-Verbose $message
|
|
}
|
|
|
|
Write-Debug "ArtfactType is $artfactType"
|
|
|
|
if($artfactType -eq $script:PSArtifactTypeModule)
|
|
{
|
|
# Test if module is already installed
|
|
$InstalledModuleInfo = if(-not $IsSavePackage){ Test-ModuleInstalled -Name $packageName -RequiredVersion $RequiredVersion }
|
|
|
|
if(-not $Force -and $InstalledModuleInfo)
|
|
{
|
|
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( (-not $MinimumVersion -and ($version -ne $InstalledModuleInfo.Version)) -or
|
|
($MinimumVersion -and ($MinimumVersion -gt $InstalledModuleInfo.Version)))
|
|
{
|
|
if($PSVersionTable.PSVersion -ge [Version]"5.0")
|
|
{
|
|
$message = $LocalizedData.ModuleAlreadyInstalledSxS -f ($InstalledModuleInfo.Version, $InstalledModuleInfo.Name, $InstalledModuleInfo.ModuleBase, $version, $InstalledModuleInfo.Version, $version)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.ModuleAlreadyInstalled -f ($InstalledModuleInfo.Version, $InstalledModuleInfo.Name, $InstalledModuleInfo.ModuleBase, $InstalledModuleInfo.Version, $version)
|
|
}
|
|
Write-Error -Message $message -ErrorId "ModuleAlreadyInstalled" -Category InvalidOperation
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.ModuleAlreadyInstalledVerbose -f ($InstalledModuleInfo.Version, $InstalledModuleInfo.Name, $InstalledModuleInfo.ModuleBase)
|
|
Write-Verbose $message
|
|
}
|
|
|
|
return
|
|
}
|
|
else
|
|
{
|
|
if($InstalledModuleInfo.Version -lt $version)
|
|
{
|
|
$message = $LocalizedData.FoundModuleUpdate -f ($InstalledModuleInfo.Name, $version)
|
|
Write-Verbose $message
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.NoUpdateAvailable -f ($InstalledModuleInfo.Name)
|
|
Write-Verbose $message
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if($artfactType -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)
|
|
{
|
|
if(-not $installUpdate)
|
|
{
|
|
if( (-not $MinimumVersion -and ($version -ne $InstalledScriptInfo.Version)) -or
|
|
($MinimumVersion -and ($MinimumVersion -gt $InstalledScriptInfo.Version)))
|
|
{
|
|
$message = $LocalizedData.ScriptAlreadyInstalled -f ($InstalledScriptInfo.Version, $InstalledScriptInfo.Name, $InstalledScriptInfo.ScriptBase, $InstalledScriptInfo.Version, $version)
|
|
Write-Error -Message $message -ErrorId "ScriptAlreadyInstalled" -Category InvalidOperation
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.ScriptAlreadyInstalledVerbose -f ($InstalledScriptInfo.Version, $InstalledScriptInfo.Name, $InstalledScriptInfo.ScriptBase)
|
|
Write-Verbose $message
|
|
}
|
|
|
|
return
|
|
}
|
|
else
|
|
{
|
|
if($InstalledScriptInfo.Version -lt $version)
|
|
{
|
|
$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 SilentlyContinue `
|
|
-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:FastPackRefHastable[$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($artfactType -eq $script:PSArtifactTypeScript)
|
|
{
|
|
$InstalledItemsList += $script:PSGetInstalledScripts.GetEnumerator() |
|
|
Microsoft.PowerShell.Core\ForEach-Object {
|
|
"$($_.Value.PSGetItemInfo.Name)!#!$($_.Value.PSGetItemInfo.Version)".ToLower()
|
|
}
|
|
}
|
|
|
|
$InstalledItemsList | Select-Object -Unique
|
|
|
|
if($Debug)
|
|
{
|
|
$InstalledItemsList | Microsoft.PowerShell.Core\ForEach-Object { Write-Debug -Message "Locally available Item: $_"}
|
|
}
|
|
}
|
|
|
|
$ProviderOptions = @{
|
|
Destination=$tempDestination;
|
|
ExcludeVersion=$true
|
|
}
|
|
|
|
if($InstalledItemsList)
|
|
{
|
|
$ProviderOptions['InstalledPackages'] = $InstalledItemsList
|
|
}
|
|
|
|
$newRequest = $request.CloneRequest( $ProviderOptions, @($SourceLocation), $request.Credential )
|
|
|
|
if($artfactType -eq $script:PSArtifactTypeModule)
|
|
{
|
|
$message = $LocalizedData.DownloadingModuleFromGallery -f ($packageName, $version, $sourceLocation)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.DownloadingScriptFromGallery -f ($packageName, $version, $sourceLocation)
|
|
}
|
|
Write-Verbose $message
|
|
|
|
$installedPkgs = $provider.InstallPackage($script:FastPackRefHastable[$fastPackageReference], $newRequest)
|
|
|
|
foreach($pkg in $installedPkgs)
|
|
{
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
$destinationModulePath = Microsoft.PowerShell.Management\Join-Path -Path $moduleDestination -ChildPath $pkg.Name
|
|
|
|
# Side-by-Side module version is avialable 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 $pkg.Version
|
|
}
|
|
|
|
$destinationscriptPath = $scriptDestination
|
|
|
|
# Get actual artifact type from the package
|
|
$packageType = $script:PSArtifactTypeModule
|
|
$installLocation = $destinationModulePath
|
|
$tempPackagePath = Microsoft.PowerShell.Management\Join-Path -Path $tempDestination -ChildPath $pkg.Name
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $tempPackagePath)
|
|
{
|
|
$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
|
|
}
|
|
elseif($packageType -eq $script:PSArtifactTypeScript)
|
|
{
|
|
$InstalledItemDetails = Get-InstalledScriptDetails -Name $pkg.Name | Select-Object -Last 1
|
|
}
|
|
|
|
if($InstalledItemDetails -and
|
|
$InstalledItemDetails.PSGetItemInfo -and
|
|
(Get-Member -InputObject $InstalledItemDetails.PSGetItemInfo -Name 'InstalledDate') -and
|
|
$InstalledItemDetails.PSGetItemInfo.InstalledDate)
|
|
{
|
|
$InstalledDate = $InstalledItemDetails.PSGetItemInfo.InstalledDate
|
|
}
|
|
}
|
|
|
|
$AdditionalParams['InstalledDate'] = $InstalledDate
|
|
}
|
|
|
|
$sid = New-SoftwareIdentityFromPackage -Package $pkg `
|
|
-SourceLocation $sourceLocation `
|
|
-PackageManagementProviderName $provider.ProviderName `
|
|
-Request $request `
|
|
-Type $packageType `
|
|
-InstalledLocation $installLocation `
|
|
@AdditionalParams
|
|
|
|
# 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
|
|
}
|
|
|
|
if(-not $psgItemInfo.PowerShellGetFormatVersion)
|
|
{
|
|
$sourceModulePath = Microsoft.PowerShell.Management\Join-Path $tempDestination $pkg.Name
|
|
}
|
|
else
|
|
{
|
|
$sourceModulePath = Microsoft.PowerShell.Management\Join-Path $tempDestination "$($pkg.Name)\Content\*\$script:ModuleReferences\$($pkg.Name)"
|
|
}
|
|
|
|
$CurrentModuleInfo = $null
|
|
|
|
# Validate the module
|
|
if(-not $IsSavePackage)
|
|
{
|
|
$CurrentModuleInfo = Test-ValidManifestModule -ModuleBasePath $sourceModulePath `
|
|
-InstallLocation $InstallLocation `
|
|
-AllowClobber:$AllowClobber `
|
|
-SkipPublisherCheck:$SkipPublisherCheck `
|
|
-IsUpdateOperation:$installUpdate
|
|
|
|
if(-not $CurrentModuleInfo)
|
|
{
|
|
# 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 $pkg.Version }
|
|
|
|
if($pkg.Name -ne $packageName)
|
|
{
|
|
if(-not $Force -and $InstalledModuleInfo2)
|
|
{
|
|
if(Test-ModuleSxSVersionSupport)
|
|
{
|
|
if($pkg.version -eq $InstalledModuleInfo2.Version)
|
|
{
|
|
if(-not $installUpdate)
|
|
{
|
|
$message = $LocalizedData.ModuleWithRequiredVersionAlreadyInstalled -f ($InstalledModuleInfo2.Version, $InstalledModuleInfo2.Name, $InstalledModuleInfo2.ModuleBase, $InstalledModuleInfo2.Version)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.NoUpdateAvailable -f ($pkg.Name)
|
|
}
|
|
|
|
Write-Verbose $message
|
|
Continue
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(-not $installUpdate)
|
|
{
|
|
$message = $LocalizedData.ModuleAlreadyInstalledVerbose -f ($InstalledModuleInfo2.Version, $InstalledModuleInfo2.Name, $InstalledModuleInfo2.ModuleBase)
|
|
Write-Verbose $message
|
|
Continue
|
|
}
|
|
else
|
|
{
|
|
if($pkg.version -gt $InstalledModuleInfo2.Version)
|
|
{
|
|
$message = $LocalizedData.FoundModuleUpdate -f ($pkg.Name, $pkg.Version)
|
|
Write-Verbose $message
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.NoUpdateAvailable -f ($pkg.Name)
|
|
Write-Verbose $message
|
|
Continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if($IsSavePackage)
|
|
{
|
|
$DependencyInstallMessage = $LocalizedData.SavingDependencyModule -f ($pkg.Name, $pkg.Version, $packageName)
|
|
}
|
|
else
|
|
{
|
|
$DependencyInstallMessage = $LocalizedData.InstallingDependencyModule -f ($pkg.Name, $pkg.Version, $packageName)
|
|
}
|
|
|
|
Write-Verbose $DependencyInstallMessage
|
|
}
|
|
|
|
# check if module is in use
|
|
if($InstalledModuleInfo2)
|
|
{
|
|
$moduleInUse = Test-ModuleInUse -ModuleBasePath $InstalledModuleInfo2.ModuleBase `
|
|
-ModuleName $InstalledModuleInfo2.Name `
|
|
-ModuleVersion $InstalledModuleInfo2.Version `
|
|
-Verbose:$VerbosePreference `
|
|
-WarningAction $WarningPreference `
|
|
-ErrorAction $ErrorActionPreference `
|
|
-Debug:$DebugPreference
|
|
|
|
if($moduleInUse)
|
|
{
|
|
$message = $LocalizedData.ModuleIsInUse -f ($psgItemInfo.Name)
|
|
Write-Verbose $message
|
|
continue
|
|
}
|
|
}
|
|
|
|
Copy-Module -SourcePath $sourceModulePath -DestinationPath $destinationModulePath -PSGetItemInfo $psgItemInfo
|
|
|
|
if(-not $IsSavePackage)
|
|
{
|
|
# Write warning messages if externally managed module dependencies are not installed.
|
|
$ExternalModuleDependencies = Get-ExternalModuleDependencies -PSModuleInfo $CurrentModuleInfo
|
|
foreach($ExternalDependency in $ExternalModuleDependencies)
|
|
{
|
|
$depModuleInfo = Test-ModuleInstalled -Name $ExternalDependency
|
|
|
|
if(-not $depModuleInfo)
|
|
{
|
|
Write-Warning -Message ($LocalizedData.MissingExternallyManagedModuleDependency -f $ExternalDependency,$pkg.Name,$ExternalDependency)
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.ExternallyManagedModuleDependencyIsInstalled -f $ExternalDependency)
|
|
}
|
|
}
|
|
}
|
|
|
|
if($IsSavePackage)
|
|
{
|
|
$message = $LocalizedData.ModuleSavedSuccessfully -f ($psgItemInfo.Name, $installLocation)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.ModuleInstalledSuccessfully -f ($psgItemInfo.Name, $installLocation)
|
|
}
|
|
Write-Verbose $message
|
|
}
|
|
|
|
|
|
if($packageType -eq $script:PSArtifactTypeScript)
|
|
{
|
|
if ($psgItemInfo.PowerShellGetFormatVersion -and
|
|
($script:SupportedPSGetFormatVersionMajors -notcontains $psgItemInfo.PowerShellGetFormatVersion.Major))
|
|
{
|
|
$message = $LocalizedData.NotSupportedPowerShellGetFormatVersionScripts -f ($psgItemInfo.Name, $psgItemInfo.PowerShellGetFormatVersion, $psgItemInfo.Name)
|
|
Write-Error -Message $message -ErrorId "NotSupportedPowerShellGetFormatVersion" -Category InvalidOperation
|
|
continue
|
|
}
|
|
|
|
$sourceScriptPath = Microsoft.PowerShell.Management\Join-Path -Path $tempPackagePath -ChildPath "$($pkg.Name).ps1"
|
|
|
|
$currentScriptInfo = $null
|
|
if(-not $IsSavePackage)
|
|
{
|
|
# Validate the script
|
|
$currentScriptInfo = Test-ScriptFileInfo -Path $sourceScriptPath -ErrorAction SilentlyContinue
|
|
|
|
if(-not $currentScriptInfo)
|
|
{
|
|
$message = $LocalizedData.InvalidPowerShellScriptFile -f ($pkg.Name)
|
|
Write-Error -Message $message -ErrorId "InvalidPowerShellScriptFile" -Category InvalidOperation -TargetObject $pkg.Name
|
|
continue
|
|
}
|
|
}
|
|
|
|
# Test if script is already installed
|
|
$InstalledScriptInfo2 = if(-not $IsSavePackage){ Test-ScriptInstalled -Name $pkg.Name }
|
|
|
|
if($pkg.Name -ne $packageName)
|
|
{
|
|
if(-not $Force -and $InstalledScriptInfo2)
|
|
{
|
|
if(-not $installUpdate)
|
|
{
|
|
$message = $LocalizedData.ScriptAlreadyInstalledVerbose -f ($InstalledScriptInfo2.Version, $InstalledScriptInfo2.Name, $InstalledScriptInfo2.ScriptBase)
|
|
Write-Verbose $message
|
|
Continue
|
|
}
|
|
else
|
|
{
|
|
if($pkg.version -gt $InstalledScriptInfo2.Version)
|
|
{
|
|
$message = $LocalizedData.FoundScriptUpdate -f ($pkg.Name, $pkg.Version)
|
|
Write-Verbose $message
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.NoScriptUpdateAvailable -f ($pkg.Name)
|
|
Write-Verbose $message
|
|
Continue
|
|
}
|
|
}
|
|
}
|
|
|
|
if($IsSavePackage)
|
|
{
|
|
$DependencyInstallMessage = $LocalizedData.SavingDependencyScript -f ($pkg.Name, $pkg.Version, $packageName)
|
|
}
|
|
else
|
|
{
|
|
$DependencyInstallMessage = $LocalizedData.InstallingDependencyScript -f ($pkg.Name, $pkg.Version, $packageName)
|
|
}
|
|
|
|
Write-Verbose $DependencyInstallMessage
|
|
}
|
|
|
|
Write-Debug "SourceScriptPath is $sourceScriptPath and DestinationscriptPath is $destinationscriptPath"
|
|
Copy-ScriptFile -SourcePath $sourceScriptPath -DestinationPath $destinationscriptPath -PSGetItemInfo $psgItemInfo -Scope $Scope
|
|
|
|
if(-not $IsSavePackage)
|
|
{
|
|
# Write warning messages if externally managed module dependencies are not installed.
|
|
foreach($ExternalDependency in $currentScriptInfo.ExternalModuleDependencies)
|
|
{
|
|
$depModuleInfo = Test-ModuleInstalled -Name $ExternalDependency
|
|
|
|
if(-not $depModuleInfo)
|
|
{
|
|
Write-Warning -Message ($LocalizedData.ScriptMissingExternallyManagedModuleDependency -f $ExternalDependency,$pkg.Name,$ExternalDependency)
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.ExternallyManagedModuleDependencyIsInstalled -f $ExternalDependency)
|
|
}
|
|
}
|
|
|
|
# Write warning messages if externally managed script dependencies are not installed.
|
|
foreach($ExternalDependency in $currentScriptInfo.ExternalScriptDependencies)
|
|
{
|
|
$depScriptInfo = Test-ScriptInstalled -Name $ExternalDependency
|
|
|
|
if(-not $depScriptInfo)
|
|
{
|
|
Write-Warning -Message ($LocalizedData.ScriptMissingExternallyManagedScriptDependency -f $ExternalDependency,$pkg.Name,$ExternalDependency)
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.ScriptExternallyManagedScriptDependencyIsInstalled -f $ExternalDependency)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Remove the old scriptfile if it's path different from the required destination script path when -Force is specified
|
|
if($Force -and
|
|
$InstalledScriptInfo2 -and
|
|
-not $destinationscriptPath.StartsWith($InstalledScriptInfo2.ScriptBase, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $InstalledScriptInfo2.Path `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue `
|
|
-Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
if($IsSavePackage)
|
|
{
|
|
$message = $LocalizedData.ScriptSavedSuccessfully -f ($psgItemInfo.Name, $installLocation)
|
|
}
|
|
else
|
|
{
|
|
$message = $LocalizedData.ScriptInstalledSuccessfully -f ($psgItemInfo.Name, $installLocation)
|
|
}
|
|
Write-Verbose $message
|
|
}
|
|
|
|
Write-Output -InputObject $sid
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item $tempDestination -Force -Recurse -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
}
|
|
}
|
|
|
|
function Uninstall-Package
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$fastPackageReference
|
|
)
|
|
|
|
Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Uninstall-Package'))
|
|
|
|
Write-Debug -Message ($LocalizedData.FastPackageReference -f $fastPackageReference)
|
|
|
|
# take the fastPackageReference and get the package object again.
|
|
$parts = $fastPackageReference -Split '[|]'
|
|
$Force = $false
|
|
|
|
$options = $request.Options
|
|
if($options)
|
|
{
|
|
foreach( $o in $options.Keys )
|
|
{
|
|
Write-Debug -Message ("OPTION: {0} => {1}" -f ($o, $request.Options[$o]) )
|
|
}
|
|
}
|
|
|
|
if($parts.Length -eq 5)
|
|
{
|
|
$providerName = $parts[0]
|
|
$packageName = $parts[1]
|
|
$version = $parts[2]
|
|
$sourceLocation= $parts[3]
|
|
$artfactType = $parts[4]
|
|
|
|
if($request.IsCanceled)
|
|
{
|
|
return
|
|
}
|
|
|
|
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($artfactType -eq $script:PSArtifactTypeModule)
|
|
{
|
|
$moduleName = $packageName
|
|
$InstalledModuleInfo = $script:PSGetInstalledModules["$($moduleName)$($version)"]
|
|
|
|
if(-not $InstalledModuleInfo)
|
|
{
|
|
$message = $LocalizedData.ModuleUninstallationNotPossibleAsItIsNotInstalledUsingPowerShellGet -f $moduleName
|
|
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "ModuleUninstallationNotPossibleAsItIsNotInstalledUsingPowerShellGet" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
|
|
return
|
|
}
|
|
|
|
$moduleBase = $InstalledModuleInfo.PSGetItemInfo.InstalledLocation
|
|
|
|
if(-not (Test-RunningAsElevated) -and $moduleBase.StartsWith($script:programFilesModulesPath, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$message = $LocalizedData.AdminPrivilegesRequiredForUninstall -f ($moduleName, $moduleBase)
|
|
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "AdminPrivilegesRequiredForUninstall" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
|
|
return
|
|
}
|
|
|
|
$dependentModuleScript = {
|
|
param ([string] $moduleName)
|
|
Microsoft.PowerShell.Core\Get-Module -ListAvailable |
|
|
Microsoft.PowerShell.Core\Where-Object {
|
|
($moduleName -ne $_.Name) -and (
|
|
($_.RequiredModules -and $_.RequiredModules.Name -contains $moduleName) -or
|
|
($_.NestedModules -and $_.NestedModules.Name -contains $moduleName))
|
|
}
|
|
}
|
|
$dependentModulesJob = Microsoft.PowerShell.Core\Start-Job -ScriptBlock $dependentModuleScript -ArgumentList $moduleName
|
|
Microsoft.PowerShell.Core\Wait-Job -job $dependentModulesJob
|
|
$dependentModules = Microsoft.PowerShell.Core\Receive-Job -job $dependentModulesJob
|
|
|
|
if(-not $Force -and $dependentModules)
|
|
{
|
|
$message = $LocalizedData.UnableToUninstallAsOtherModulesNeedThisModule -f ($moduleName, $version, $moduleBase, $(($dependentModules.Name | Select-Object -Unique) -join ','), $moduleName)
|
|
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "UnableToUninstallAsOtherModulesNeedThisModule" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
|
|
return
|
|
}
|
|
|
|
$moduleInUse = Test-ModuleInUse -ModuleBasePath $moduleBase `
|
|
-ModuleName $InstalledModuleInfo.PSGetItemInfo.Name`
|
|
-ModuleVersion $InstalledModuleInfo.PSGetItemInfo.Version `
|
|
-Verbose:$VerbosePreference `
|
|
-WarningAction $WarningPreference `
|
|
-ErrorAction $ErrorActionPreference `
|
|
-Debug:$DebugPreference
|
|
|
|
if($moduleInUse)
|
|
{
|
|
$message = $LocalizedData.ModuleIsInUse -f ($moduleName)
|
|
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "ModuleIsInUse" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
|
|
return
|
|
}
|
|
|
|
$ModuleBaseFolderToBeRemoved = $moduleBase
|
|
|
|
# With SxS version support, more than one version of the module can be installed.
|
|
# - Remove the parent directory of the module version base when only one version is installed
|
|
# - Don't remove the modulebase when it was installed before SxS version support and
|
|
# other versions are installed under the module base folder
|
|
#
|
|
if(Test-ModuleSxSVersionSupport)
|
|
{
|
|
$ModuleBaseWithoutVersion = $moduleBase
|
|
$IsModuleInstalledAsSxSVersion = $false
|
|
|
|
if($moduleBase.EndsWith("$version", [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$IsModuleInstalledAsSxSVersion = $true
|
|
$ModuleBaseWithoutVersion = Microsoft.PowerShell.Management\Split-Path -Path $moduleBase -Parent
|
|
}
|
|
|
|
$InstalledVersionsWithSameModuleBase = @()
|
|
Get-Module -Name $moduleName -ListAvailable |
|
|
Microsoft.PowerShell.Core\ForEach-Object {
|
|
if($_.ModuleBase.StartsWith($ModuleBaseWithoutVersion, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
$InstalledVersionsWithSameModuleBase += $_.ModuleBase
|
|
}
|
|
}
|
|
|
|
# Remove ..\ModuleName directory when only one module is installed with the same ..\ModuleName path
|
|
# like ..\ModuleName\1.0 or ..\ModuleName
|
|
if($InstalledVersionsWithSameModuleBase.Count -eq 1)
|
|
{
|
|
$ModuleBaseFolderToBeRemoved = $ModuleBaseWithoutVersion
|
|
}
|
|
elseif($ModuleBaseWithoutVersion -eq $moduleBase)
|
|
{
|
|
# There are version specific folders under the same module base dir
|
|
# Throw an error saying uninstall other versions then uninstall this current version
|
|
$message = $LocalizedData.UnableToUninstallModuleVersion -f ($moduleName, $version, $moduleBase)
|
|
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "UnableToUninstallModuleVersion" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
|
|
return
|
|
}
|
|
# Otherwise specified version folder will be removed as current module base is assigned to $ModuleBaseFolderToBeRemoved
|
|
}
|
|
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $ModuleBaseFolderToBeRemoved `
|
|
-Force -Recurse `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue `
|
|
-Confirm:$false -WhatIf:$false
|
|
|
|
$message = $LocalizedData.ModuleUninstallationSucceeded -f $moduleName, $moduleBase
|
|
Write-Verbose $message
|
|
|
|
Write-Output -InputObject $InstalledModuleInfo.SoftwareIdentity
|
|
}
|
|
elseif($artfactType -eq $script:PSArtifactTypeScript)
|
|
{
|
|
$scriptName = $packageName
|
|
$InstalledScriptInfo = $script:PSGetInstalledScripts["$($scriptName)$($version)"]
|
|
|
|
if(-not $InstalledScriptInfo)
|
|
{
|
|
$message = $LocalizedData.ScriptUninstallationNotPossibleAsItIsNotInstalledUsingPowerShellGet -f $scriptName
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "ScriptUninstallationNotPossibleAsItIsNotInstalledUsingPowerShellGet" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
|
|
return
|
|
}
|
|
|
|
$scriptBase = $InstalledScriptInfo.PSGetItemInfo.InstalledLocation
|
|
$installedScriptInfoPath = $script:MyDocumentsInstalledScriptInfosPath
|
|
|
|
if($scriptBase.StartsWith($script:ProgramFilesScriptsPath, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
if(-not (Test-RunningAsElevated))
|
|
{
|
|
$message = $LocalizedData.AdminPrivilegesRequiredForScriptUninstall -f ($scriptName, $scriptBase)
|
|
|
|
ThrowError -ExceptionName "System.InvalidOperationException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "AdminPrivilegesRequiredForUninstall" `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
|
|
return
|
|
}
|
|
|
|
$installedScriptInfoPath = $script:ProgramFilesInstalledScriptInfosPath
|
|
}
|
|
|
|
# Check if there are any dependent scripts
|
|
$dependentScriptDetails = $script:PSGetInstalledScripts.Values |
|
|
Microsoft.PowerShell.Core\Where-Object {
|
|
$_.PSGetItemInfo.Dependencies -contains $scriptName
|
|
}
|
|
|
|
$dependentScriptNames = $dependentScriptDetails |
|
|
Microsoft.PowerShell.Core\ForEach-Object { $_.PSGetItemInfo.Name }
|
|
|
|
if(-not $Force -and $dependentScriptNames)
|
|
{
|
|
$message = $LocalizedData.UnableToUninstallAsOtherScriptsNeedThisScript -f
|
|
($scriptName,
|
|
$version,
|
|
$scriptBase,
|
|
$(($dependentScriptNames | Select-Object -Unique) -join ','),
|
|
$scriptName)
|
|
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'UnableToUninstallAsOtherScriptsNeedThisScript' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
return
|
|
}
|
|
|
|
$scriptFilePath = Microsoft.PowerShell.Management\Join-Path -Path $scriptBase `
|
|
-ChildPath "$($scriptName).ps1"
|
|
|
|
$installledScriptInfoFilePath = Microsoft.PowerShell.Management\Join-Path -Path $installedScriptInfoPath `
|
|
-ChildPath "$($scriptName)_$($script:InstalledScriptInfoFileName)"
|
|
|
|
# Remove the script file and it's corresponding InstalledScriptInfo.xml
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $scriptFilePath -PathType Leaf)
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $scriptFilePath `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue `
|
|
-Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $installledScriptInfoFilePath -PathType Leaf)
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $installledScriptInfoFilePath `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue `
|
|
-Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
$message = $LocalizedData.ScriptUninstallationSucceeded -f $scriptName, $scriptBase
|
|
Write-Verbose $message
|
|
|
|
Write-Output -InputObject $InstalledScriptInfo.SoftwareIdentity
|
|
}
|
|
}
|
|
}
|
|
|
|
function Get-InstalledPackage
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter()]
|
|
[string]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$MaximumVersion
|
|
)
|
|
|
|
Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Get-InstalledPackage'))
|
|
|
|
$options = $request.Options
|
|
|
|
foreach( $o in $options.Keys )
|
|
{
|
|
Write-Debug ( "OPTION: {0} => {1}" -f ($o, $options[$o]) )
|
|
}
|
|
|
|
$artifactTypes = $script:PSArtifactTypeModule
|
|
if($options.ContainsKey($script:PSArtifactType))
|
|
{
|
|
$artifactTypes = $options[$script:PSArtifactType]
|
|
}
|
|
|
|
if($artifactTypes -eq $script:All)
|
|
{
|
|
$artifactTypes = @($script:PSArtifactTypeModule,$script:PSArtifactTypeScript)
|
|
}
|
|
|
|
if($artifactTypes -contains $script:PSArtifactTypeModule)
|
|
{
|
|
Get-InstalledModuleDetails -Name $Name `
|
|
-RequiredVersion $RequiredVersion `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion | Microsoft.PowerShell.Core\ForEach-Object {$_.SoftwareIdentity}
|
|
}
|
|
|
|
if($artifactTypes -contains $script:PSArtifactTypeScript)
|
|
{
|
|
Get-InstalledScriptDetails -Name $Name `
|
|
-RequiredVersion $RequiredVersion `
|
|
-MinimumVersion $MinimumVersion `
|
|
-MaximumVersion $MaximumVersion | Microsoft.PowerShell.Core\ForEach-Object {$_.SoftwareIdentity}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Internal Utility functions for the PackageManagement Provider Implementation
|
|
|
|
function Set-InstalledScriptsVariable
|
|
{
|
|
# Initialize list of scripts installed by the PowerShellGet provider
|
|
$script:PSGetInstalledScripts = [ordered]@{}
|
|
$scriptPaths = @($script:ProgramFilesInstalledScriptInfosPath, $script:MyDocumentsInstalledScriptInfosPath)
|
|
|
|
foreach ($location in $scriptPaths)
|
|
{
|
|
# find all scripts installed using PowerShellGet
|
|
$scriptInfoFiles = Get-ChildItem -Path $location `
|
|
-Filter "*$script:InstalledScriptInfoFileName" `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
|
|
if($scriptInfoFiles)
|
|
{
|
|
foreach ($scriptInfoFile in $scriptInfoFiles)
|
|
{
|
|
$psgetItemInfo = DeSerialize-PSObject -Path $scriptInfoFile.FullName
|
|
|
|
$scriptFilePath = Microsoft.PowerShell.Management\Join-Path -Path $psgetItemInfo.InstalledLocation `
|
|
-ChildPath "$($psgetItemInfo.Name).ps1"
|
|
|
|
# Remove the InstalledScriptInfo.xml file if the actual script file was manually uninstalled by the user
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path -Path $scriptFilePath -PathType Leaf))
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $scriptInfoFile.FullName -Force -ErrorAction SilentlyContinue
|
|
|
|
continue
|
|
}
|
|
|
|
$package = New-SoftwareIdentityFromPSGetItemInfo -PSGetItemInfo $psgetItemInfo
|
|
|
|
if($package)
|
|
{
|
|
$script:PSGetInstalledScripts["$($psgetItemInfo.Name)$($psgetItemInfo.Version)"] = @{
|
|
SoftwareIdentity = $package
|
|
PSGetItemInfo = $psgetItemInfo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Get-InstalledScriptDetails
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter()]
|
|
[string]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$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($RequiredVersion)
|
|
{
|
|
if($RequiredVersion -eq $InstalledScriptDetails.PSGetItemInfo.Version)
|
|
{
|
|
$InstalledScriptDetails
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( (-not $MinimumVersion -or ($MinimumVersion -le $InstalledScriptDetails.PSGetItemInfo.Version)) -and
|
|
(-not $MaximumVersion -or ($MaximumVersion -ge $InstalledScriptDetails.PSGetItemInfo.Version)))
|
|
{
|
|
$InstalledScriptDetails
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Get-InstalledModuleDetails
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter()]
|
|
[string]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$RequiredVersion,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$MinimumVersion,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$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($RequiredVersion)
|
|
{
|
|
if($RequiredVersion -eq $InstalledModuleDetails.PSGetItemInfo.Version)
|
|
{
|
|
$InstalledModuleDetails
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( (-not $MinimumVersion -or ($MinimumVersion -le $InstalledModuleDetails.PSGetItemInfo.Version)) -and
|
|
(-not $MaximumVersion -or ($MaximumVersion -ge $InstalledModuleDetails.PSGetItemInfo.Version)))
|
|
{
|
|
$InstalledModuleDetails
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function New-SoftwareIdentityFromPackage
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
$Package,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$PackageManagementProviderName,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$SourceLocation,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$IsFromTrustedSource,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
$request,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Type,
|
|
|
|
[Parameter()]
|
|
[string]
|
|
$InstalledLocation,
|
|
|
|
[Parameter()]
|
|
[System.DateTime]
|
|
$InstalledDate,
|
|
|
|
[Parameter()]
|
|
[System.DateTime]
|
|
$UpdatedDate
|
|
)
|
|
|
|
$fastPackageReference = New-FastPackageReference -ProviderName $PackageManagementProviderName `
|
|
-PackageName $Package.Name `
|
|
-Version $Package.Version `
|
|
-Source $SourceLocation `
|
|
-ArtifactType $Type
|
|
|
|
$links = New-Object -TypeName System.Collections.ArrayList
|
|
foreach($lnk in $Package.Links)
|
|
{
|
|
if( $lnk.Relationship -eq "icon" -or $lnk.Relationship -eq "license" -or $lnk.Relationship -eq "project" )
|
|
{
|
|
$links.Add( (New-Link -Href $lnk.HRef -RelationShip $lnk.Relationship ) )
|
|
}
|
|
}
|
|
|
|
$entities = New-Object -TypeName System.Collections.ArrayList
|
|
foreach( $entity in $Package.Entities )
|
|
{
|
|
if( $entity.Role -eq "author" -or $entity.Role -eq "owner" )
|
|
{
|
|
$entities.Add( (New-Entity -Name $entity.Name -Role $entity.Role -RegId $entity.RegId -Thumbprint $entity.Thumbprint) )
|
|
}
|
|
}
|
|
|
|
$deps = (new-Object -TypeName System.Collections.ArrayList)
|
|
foreach( $dep in $pkg.Dependencies )
|
|
{
|
|
# Add each dependency and say it's from this provider.
|
|
$newDep = New-Dependency -ProviderName $script:PSModuleProviderName `
|
|
-PackageName $request.Services.ParsePackageName($dep) `
|
|
-Version $request.Services.ParsePackageVersion($dep) `
|
|
-Source $SourceLocation
|
|
|
|
$deps.Add( $newDep )
|
|
}
|
|
|
|
|
|
$details = New-Object -TypeName System.Collections.Hashtable
|
|
|
|
foreach ( $key in $Package.Metadata.Keys.LocalName)
|
|
{
|
|
if (!$details.ContainsKey($key))
|
|
{
|
|
$details.Add($key, (Get-First $Package.Metadata[$key]) )
|
|
}
|
|
}
|
|
|
|
$details.Add( "PackageManagementProvider" , $PackageManagementProviderName )
|
|
|
|
if($InstalledLocation)
|
|
{
|
|
$details.Add( $script:InstalledLocation , $InstalledLocation )
|
|
}
|
|
|
|
if($InstalledDate)
|
|
{
|
|
$details.Add( 'installeddate' , $InstalledDate.ToString() )
|
|
}
|
|
|
|
if($UpdatedDate)
|
|
{
|
|
$details.Add( 'updateddate' , $UpdatedDate.ToString() )
|
|
}
|
|
|
|
# Initialize package source name to the source location
|
|
$sourceNameForSoftwareIdentity = $SourceLocation
|
|
|
|
$sourceName = (Get-SourceName -Location $SourceLocation)
|
|
|
|
if($sourceName)
|
|
{
|
|
$details.Add( "SourceName" , $sourceName )
|
|
|
|
# Override the source name only if we are able to map source location to source name
|
|
$sourceNameForSoftwareIdentity = $sourceName
|
|
}
|
|
|
|
$params = @{FastPackageReference = $fastPackageReference;
|
|
Name = $Package.Name;
|
|
Version = $Package.Version;
|
|
versionScheme = "MultiPartNumeric";
|
|
Source = $sourceNameForSoftwareIdentity;
|
|
Summary = $Package.Summary;
|
|
SearchKey = $Package.Name;
|
|
FullPath = $Package.FullPath;
|
|
FileName = $Package.Name;
|
|
Details = $details;
|
|
Entities = $entities;
|
|
Links = $links;
|
|
Dependencies = $deps;
|
|
}
|
|
|
|
if($IsFromTrustedSource)
|
|
{
|
|
$params["FromTrustedSource"] = $true
|
|
}
|
|
|
|
$sid = New-SoftwareIdentity @params
|
|
|
|
return $sid
|
|
}
|
|
|
|
function New-PackageSourceFromModuleSource
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
$ModuleSource
|
|
)
|
|
|
|
$ScriptSourceLocation = $null
|
|
if(Get-Member -InputObject $ModuleSource -Name $script:ScriptSourceLocation)
|
|
{
|
|
$ScriptSourceLocation = $ModuleSource.ScriptSourceLocation
|
|
}
|
|
|
|
$ScriptPublishLocation = $ModuleSource.PublishLocation
|
|
if(Get-Member -InputObject $ModuleSource -Name $script:ScriptPublishLocation)
|
|
{
|
|
$ScriptPublishLocation = $ModuleSource.ScriptPublishLocation
|
|
}
|
|
|
|
$packageSourceDetails = @{}
|
|
$packageSourceDetails["InstallationPolicy"] = $ModuleSource.InstallationPolicy
|
|
$packageSourceDetails["PackageManagementProvider"] = (Get-ProviderName -PSCustomObject $ModuleSource)
|
|
$packageSourceDetails[$script:PublishLocation] = $ModuleSource.PublishLocation
|
|
$packageSourceDetails[$script:ScriptSourceLocation] = $ScriptSourceLocation
|
|
$packageSourceDetails[$script:ScriptPublishLocation] = $ScriptPublishLocation
|
|
|
|
$ModuleSource.ProviderOptions.GetEnumerator() | Microsoft.PowerShell.Core\ForEach-Object {
|
|
$packageSourceDetails[$_.Key] = $_.Value
|
|
}
|
|
|
|
# create a new package source
|
|
$src = New-PackageSource -Name $ModuleSource.Name `
|
|
-Location $ModuleSource.SourceLocation `
|
|
-Trusted $ModuleSource.Trusted `
|
|
-Registered $ModuleSource.Registered `
|
|
-Details $packageSourceDetails
|
|
|
|
Write-Verbose ( $LocalizedData.RepositoryDetails -f ($src.Name, $src.Location, $src.IsTrusted, $src.IsRegistered) )
|
|
|
|
# return the package source object.
|
|
Write-Output -InputObject $src
|
|
}
|
|
|
|
function New-ModuleSourceFromPackageSource
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
$PackageSource
|
|
)
|
|
|
|
$moduleSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
|
|
Name = $PackageSource.Name
|
|
SourceLocation = $PackageSource.Location
|
|
Trusted=$PackageSource.IsTrusted
|
|
Registered=$PackageSource.IsRegistered
|
|
InstallationPolicy = $PackageSource.Details['InstallationPolicy']
|
|
PackageManagementProvider=$PackageSource.Details['PackageManagementProvider']
|
|
PublishLocation=$PackageSource.Details[$script:PublishLocation]
|
|
ScriptSourceLocation=$PackageSource.Details[$script:ScriptSourceLocation]
|
|
ScriptPublishLocation=$PackageSource.Details[$script:ScriptPublishLocation]
|
|
ProviderOptions = @{}
|
|
})
|
|
|
|
$PackageSource.Details.GetEnumerator() | Microsoft.PowerShell.Core\ForEach-Object {
|
|
if($_.Key -ne 'PackageManagementProvider' -and
|
|
$_.Key -ne $script:PublishLocation -and
|
|
$_.Key -ne $script:ScriptPublishLocation -and
|
|
$_.Key -ne $script:ScriptSourceLocation -and
|
|
$_.Key -ne 'InstallationPolicy')
|
|
{
|
|
$moduleSource.ProviderOptions[$_.Key] = $_.Value
|
|
}
|
|
}
|
|
|
|
$moduleSource.PSTypeNames.Insert(0, "Microsoft.PowerShell.Commands.PSRepository")
|
|
|
|
# return the module source object.
|
|
Write-Output -InputObject $moduleSource
|
|
}
|
|
|
|
function New-FastPackageReference
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$ProviderName,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$PackageName,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Version,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Source,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$ArtifactType
|
|
)
|
|
|
|
return "$ProviderName|$PackageName|$Version|$Source|$ArtifactType"
|
|
}
|
|
|
|
function Get-First
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
$IEnumerator
|
|
)
|
|
|
|
foreach($item in $IEnumerator)
|
|
{
|
|
return $item
|
|
}
|
|
|
|
return $null
|
|
}
|
|
|
|
function Set-InstalledModulesVariable
|
|
{
|
|
# Initialize list of modules installed by the PowerShellGet provider
|
|
$script:PSGetInstalledModules = [ordered]@{}
|
|
|
|
$modulePaths = @($script:ProgramFilesModulesPath, $script:MyDocumentsModulesPath)
|
|
|
|
foreach ($location in $modulePaths)
|
|
{
|
|
# find all modules installed using PowerShellGet
|
|
$moduleBases = Get-ChildItem $location -Recurse `
|
|
-Attributes Hidden -Filter $script:PSGetItemInfoFileName `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue `
|
|
| Foreach-Object { $_.Directory }
|
|
|
|
|
|
foreach ($moduleBase in $moduleBases)
|
|
{
|
|
$PSGetItemInfoPath = Microsoft.PowerShell.Management\Join-Path $moduleBase.FullName $script:PSGetItemInfoFileName
|
|
|
|
# Check if this module got installed using PSGet, read its contents to create a SoftwareIdentity object
|
|
if (Microsoft.PowerShell.Management\Test-Path $PSGetItemInfoPath)
|
|
{
|
|
$psgetItemInfo = DeSerialize-PSObject -Path $PSGetItemInfoPath
|
|
|
|
# Add InstalledLocation if this module was installed with older version of PowerShellGet
|
|
if(-not (Get-Member -InputObject $psgetItemInfo -Name $script:InstalledLocation))
|
|
{
|
|
Microsoft.PowerShell.Utility\Add-Member -InputObject $psgetItemInfo `
|
|
-MemberType NoteProperty `
|
|
-Name $script:InstalledLocation `
|
|
-Value $moduleBase.FullName
|
|
}
|
|
|
|
$package = New-SoftwareIdentityFromPSGetItemInfo -PSGetItemInfo $psgetItemInfo
|
|
|
|
if($package)
|
|
{
|
|
$script:PSGetInstalledModules["$($psgetItemInfo.Name)$($psgetItemInfo.Version)"] = @{
|
|
SoftwareIdentity = $package
|
|
PSGetItemInfo = $psgetItemInfo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function New-SoftwareIdentityFromPSGetItemInfo
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
$PSGetItemInfo
|
|
)
|
|
|
|
$SourceLocation = $psgetItemInfo.RepositorySourceLocation
|
|
|
|
if(Get-Member -InputObject $PSGetItemInfo -Name $script:PSArtifactType)
|
|
{
|
|
$artifactType = $psgetItemInfo.Type
|
|
}
|
|
else
|
|
{
|
|
$artifactType = $script:PSArtifactTypeModule
|
|
}
|
|
|
|
$fastPackageReference = New-FastPackageReference -ProviderName (Get-ProviderName -PSCustomObject $psgetItemInfo) `
|
|
-PackageName $psgetItemInfo.Name `
|
|
-Version $psgetItemInfo.Version `
|
|
-Source $SourceLocation `
|
|
-ArtifactType $artifactType
|
|
|
|
$links = New-Object -TypeName System.Collections.ArrayList
|
|
if($psgetItemInfo.IconUri)
|
|
{
|
|
$links.Add( (New-Link -Href $psgetItemInfo.IconUri -RelationShip "icon") )
|
|
}
|
|
|
|
if($psgetItemInfo.LicenseUri)
|
|
{
|
|
$links.Add( (New-Link -Href $psgetItemInfo.LicenseUri -RelationShip "license") )
|
|
}
|
|
|
|
if($psgetItemInfo.ProjectUri)
|
|
{
|
|
$links.Add( (New-Link -Href $psgetItemInfo.ProjectUri -RelationShip "project") )
|
|
}
|
|
|
|
$entities = New-Object -TypeName System.Collections.ArrayList
|
|
if($psgetItemInfo.Author -and $psgetItemInfo.Author.ToString())
|
|
{
|
|
$entities.Add( (New-Entity -Name $psgetItemInfo.Author -Role 'author') )
|
|
}
|
|
|
|
if($psgetItemInfo.CompanyName -and $psgetItemInfo.CompanyName.ToString())
|
|
{
|
|
$entities.Add( (New-Entity -Name $psgetItemInfo.CompanyName -Role 'owner') )
|
|
}
|
|
|
|
$details = @{
|
|
description = $psgetItemInfo.Description
|
|
copyright = $psgetItemInfo.Copyright
|
|
published = $psgetItemInfo.PublishedDate.ToString()
|
|
installeddate = $null
|
|
updateddate = $null
|
|
tags = $psgetItemInfo.Tags
|
|
releaseNotes = $psgetItemInfo.ReleaseNotes
|
|
PackageManagementProvider = (Get-ProviderName -PSCustomObject $psgetItemInfo)
|
|
}
|
|
|
|
if((Get-Member -InputObject $psgetItemInfo -Name 'InstalledDate') -and $psgetItemInfo.InstalledDate)
|
|
{
|
|
$details['installeddate'] = $psgetItemInfo.InstalledDate.ToString()
|
|
}
|
|
|
|
if((Get-Member -InputObject $psgetItemInfo -Name 'UpdatedDate') -and $psgetItemInfo.UpdatedDate)
|
|
{
|
|
$details['updateddate'] = $psgetItemInfo.UpdatedDate.ToString()
|
|
}
|
|
|
|
if(Get-Member -InputObject $psgetItemInfo -Name $script:InstalledLocation)
|
|
{
|
|
$details[$script:InstalledLocation] = $psgetItemInfo.InstalledLocation
|
|
}
|
|
|
|
$details[$script:PSArtifactType] = $artifactType
|
|
|
|
$sourceName = Get-SourceName -Location $SourceLocation
|
|
if($sourceName)
|
|
{
|
|
$details["SourceName"] = $sourceName
|
|
}
|
|
|
|
$params = @{
|
|
FastPackageReference = $fastPackageReference;
|
|
Name = $psgetItemInfo.Name;
|
|
Version = $psgetItemInfo.Version;
|
|
versionScheme = "MultiPartNumeric";
|
|
Source = $SourceLocation;
|
|
Summary = $psgetItemInfo.Description;
|
|
Details = $details;
|
|
Entities = $entities;
|
|
Links = $links
|
|
}
|
|
|
|
if($sourceName -and $script:PSGetModuleSources[$sourceName].Trusted)
|
|
{
|
|
$params["FromTrustedSource"] = $true
|
|
}
|
|
|
|
$sid = New-SoftwareIdentity @params
|
|
|
|
return $sid
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Common functions
|
|
|
|
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)
|
|
{
|
|
$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 Set-EnvironmentVariable
|
|
{
|
|
param
|
|
(
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$Name,
|
|
|
|
[parameter()]
|
|
[String]
|
|
$Value,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[int]
|
|
$Target
|
|
)
|
|
|
|
if ($Target -eq $script:EnvironmentVariableTarget.Process)
|
|
{
|
|
[System.Environment]::SetEnvironmentVariable($Name, $Value)
|
|
|
|
return
|
|
}
|
|
elseif ($Target -eq $script:EnvironmentVariableTarget.Machine)
|
|
{
|
|
if ($Name.Length -ge $script:SystemEnvironmentVariableMaximumLength)
|
|
{
|
|
$message = $LocalizedData.InvalidEnvironmentVariableName -f ($Name, $script:SystemEnvironmentVariableMaximumLength)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'InvalidEnvironmentVariableName' `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Name
|
|
return
|
|
}
|
|
|
|
$Path = $script:SystemEnvironmentKey
|
|
}
|
|
elseif ($Target -eq $script:EnvironmentVariableTarget.User)
|
|
{
|
|
if ($Name.Length -ge $script:UserEnvironmentVariableMaximumLength)
|
|
{
|
|
$message = $LocalizedData.InvalidEnvironmentVariableName -f ($Name, $script:UserEnvironmentVariableMaximumLength)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'InvalidEnvironmentVariableName' `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Name
|
|
return
|
|
}
|
|
|
|
$Path = $script:UserEnvironmentKey
|
|
}
|
|
|
|
if (!$Value)
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-ItemProperty $Path -Name $Name -ErrorAction SilentlyContinue
|
|
}
|
|
else
|
|
{
|
|
Microsoft.PowerShell.Management\Set-ItemProperty $Path -Name $Name -Value $Value
|
|
}
|
|
}
|
|
|
|
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 Log-ArtifactNotFoundInPSGallery
|
|
{
|
|
[CmdletBinding()]
|
|
Param
|
|
(
|
|
[Parameter()]
|
|
[string[]]
|
|
$SearchedName,
|
|
|
|
[Parameter()]
|
|
[string[]]
|
|
$FoundName,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$operationName
|
|
)
|
|
|
|
if (-not $script:TelemetryEnabled)
|
|
{
|
|
return
|
|
}
|
|
|
|
if(-not $SearchedName)
|
|
{
|
|
return
|
|
}
|
|
|
|
$SearchedNameNoWildCards = @()
|
|
|
|
# Ignore wild cards
|
|
foreach ($artifactName in $SearchedName)
|
|
{
|
|
if (-not (Test-WildcardPattern $artifactName))
|
|
{
|
|
$SearchedNameNoWildCards += $artifactName
|
|
}
|
|
}
|
|
|
|
# Find artifacts searched, but not found in the specified gallery
|
|
$notFoundArtifacts = @()
|
|
foreach ($element in $SearchedNameNoWildCards)
|
|
{
|
|
if (-not ($FoundName -contains $element))
|
|
{
|
|
$notFoundArtifacts += $element
|
|
}
|
|
}
|
|
|
|
# Perform Telemetry only if searched artifacts are not available in specified Gallery
|
|
if ($notFoundArtifacts)
|
|
{
|
|
[Microsoft.PowerShell.Get.Telemetry]::TraceMessageArtifactsNotFound($notFoundArtifacts, $operationName)
|
|
}
|
|
}
|
|
|
|
# Function to record non-PSGallery registration for telemetry
|
|
# Function consumes the type of registration (i.e hosted (http(s)), non-hosted (file/unc)), locations, installation policy, provider and event name
|
|
function Log-NonPSGalleryRegistration
|
|
{
|
|
[CmdletBinding()]
|
|
Param
|
|
(
|
|
[Parameter()]
|
|
[string]
|
|
$sourceLocation,
|
|
|
|
[Parameter()]
|
|
[string]
|
|
$installationPolicy,
|
|
|
|
[Parameter()]
|
|
[string]
|
|
$packageManagementProvider,
|
|
|
|
[Parameter()]
|
|
[string]
|
|
$publishLocation,
|
|
|
|
[Parameter()]
|
|
[string]
|
|
$scriptSourceLocation,
|
|
|
|
[Parameter()]
|
|
[string]
|
|
$scriptPublishLocation,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$operationName
|
|
)
|
|
|
|
if (-not $script:TelemetryEnabled)
|
|
{
|
|
return
|
|
}
|
|
|
|
# Initialize source location type - this can be hosted (http(s)) or not hosted (unc/file)
|
|
$sourceLocationType = "NON_WEB_HOSTED"
|
|
if (Test-WebUri -uri $sourceLocation)
|
|
{
|
|
$sourceLocationType = "WEB_HOSTED"
|
|
}
|
|
|
|
# Create a hash of the source location
|
|
# We cannot log the actual source location, since this might contain PII (Personally identifiable information) data
|
|
$sourceLocationHash = Get-Hash -locationString $sourceLocation
|
|
$publishLocationHash = Get-Hash -locationString $publishLocation
|
|
$scriptSourceLocationHash = Get-Hash -locationString $scriptSourceLocation
|
|
$scriptPublishLocationHash = Get-Hash -locationString $scriptPublishLocation
|
|
|
|
# Log the telemetry event
|
|
[Microsoft.PowerShell.Get.Telemetry]::TraceMessageNonPSGalleryRegistration($sourceLocationType, $sourceLocationHash, $installationPolicy, $packageManagementProvider, $publishLocationHash, $scriptSourceLocationHash, $scriptPublishLocationHash, $operationName)
|
|
}
|
|
|
|
# Returns a SHA1 hash of the specified string
|
|
function Get-Hash
|
|
{
|
|
[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 ""
|
|
}
|
|
|
|
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 Save-ModuleSources
|
|
{
|
|
if($script:PSGetModuleSources)
|
|
{
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path $script:PSGetAppLocalPath))
|
|
{
|
|
$null = Microsoft.PowerShell.Management\New-Item -Path $script:PSGetAppLocalPath `
|
|
-ItemType Directory -Force `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue `
|
|
-Confirm:$false -WhatIf:$false
|
|
}
|
|
Microsoft.PowerShell.Utility\Out-File -FilePath $script:PSGetModuleSourcesFilePath -Force -InputObject ([System.Management.Automation.PSSerializer]::Serialize($script:PSGetModuleSources))
|
|
}
|
|
}
|
|
|
|
function Test-ModuleSxSVersionSupport
|
|
{
|
|
# Side-by-Side module version is avialable on PowerShell 5.0 or later versions only
|
|
# By default, PowerShell module versions will be installed/updated Side-by-Side.
|
|
$PSVersionTable.PSVersion -ge [Version]"5.0"
|
|
}
|
|
|
|
function Test-ModuleInstalled
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
[OutputType("PSModuleInfo")]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$RequiredVersion
|
|
)
|
|
|
|
# Check if module is already installed
|
|
$availableModule = Microsoft.PowerShell.Core\Get-Module -ListAvailable -Name $Name -Verbose:$false |
|
|
Microsoft.PowerShell.Core\Where-Object {-not (Test-ModuleSxSVersionSupport) -or -not $RequiredVersion -or ($RequiredVersion -eq $_.Version)} |
|
|
Microsoft.PowerShell.Utility\Select-Object -Unique
|
|
|
|
return $availableModule
|
|
}
|
|
|
|
function Test-ScriptInstalled
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Name,
|
|
|
|
[Parameter()]
|
|
[Version]
|
|
$RequiredVersion
|
|
)
|
|
|
|
$scriptInfo = $null
|
|
$scriptFileName = "$Name.ps1"
|
|
$scriptPaths = @($script:ProgramFilesScriptsPath, $script:MyDocumentsScriptsPath)
|
|
$scriptInfos = @()
|
|
|
|
foreach ($location in $scriptPaths)
|
|
{
|
|
$scriptFilePath = Microsoft.PowerShell.Management\Join-Path -Path $location -ChildPath $scriptFileName
|
|
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $scriptFilePath -PathType Leaf)
|
|
{
|
|
$scriptInfo = $null
|
|
try
|
|
{
|
|
$scriptInfo = Test-ScriptFileInfo -Path $scriptFilePath -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
|
|
}
|
|
catch
|
|
{
|
|
# Ignore any terminating error from the Test-ScriptFileInfo cmdlet,
|
|
# if it does not contain valid Script metadata
|
|
Write-Verbose -Message "$_"
|
|
}
|
|
|
|
if($scriptInfo)
|
|
{
|
|
$scriptInfos += $scriptInfo
|
|
}
|
|
else
|
|
{
|
|
# Since the script file doesn't contain the valid script metadata,
|
|
# create dummy PSScriptInfo object with 0.0 version
|
|
$scriptInfo = New-PSScriptInfoObject -Path $scriptFilePath
|
|
$scriptInfo.$script:Version = [Version]'0.0'
|
|
|
|
$scriptInfos += $scriptInfo
|
|
}
|
|
}
|
|
}
|
|
|
|
$scriptInfo = $scriptInfos | Microsoft.PowerShell.Core\Where-Object {
|
|
(-not $RequiredVersion) -or ($RequiredVersion -eq $_.Version)
|
|
} | Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
|
|
return $scriptInfo
|
|
}
|
|
|
|
function New-PSScriptInfoObject
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Path
|
|
)
|
|
|
|
$PSScriptInfo = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{})
|
|
$script:PSScriptInfoProperties | Microsoft.PowerShell.Core\ForEach-Object {
|
|
Microsoft.PowerShell.Utility\Add-Member -InputObject $PSScriptInfo `
|
|
-MemberType NoteProperty `
|
|
-Name $_ `
|
|
-Value $null
|
|
}
|
|
|
|
$PSScriptInfo.$script:Name = [System.IO.Path]::GetFileNameWithoutExtension($Path)
|
|
$PSScriptInfo.$script:Path = $Path
|
|
$PSScriptInfo.$script:ScriptBase = (Microsoft.PowerShell.Management\Split-Path -Path $Path -Parent)
|
|
|
|
return $PSScriptInfo
|
|
}
|
|
|
|
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
|
|
})
|
|
|
|
$NewPSScriptInfo.PSTypeNames.Insert(0, "Microsoft.PowerShell.Commands.PSScriptInfo")
|
|
|
|
return $NewPSScriptInfo
|
|
}
|
|
|
|
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-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 Update-ModuleManifest
|
|
{
|
|
<#
|
|
.ExternalHelp PSGet.psm1-help.xml
|
|
#>
|
|
[CmdletBinding(SupportsShouldProcess=$true,
|
|
PositionalBinding=$false,
|
|
HelpUri='http://go.microsoft.com/fwlink/?LinkId=619311')]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true,
|
|
Position=0,
|
|
ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Path,
|
|
|
|
[ValidateNotNullOrEmpty()]
|
|
[Object[]]
|
|
$NestedModules,
|
|
|
|
[ValidateNotNullOrEmpty()]
|
|
[Guid]
|
|
$Guid,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Author,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$CompanyName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Copyright,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$RootModule,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$ModuleVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Reflection.ProcessorArchitecture]
|
|
$ProcessorArchitecture,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Desktop','Core')]
|
|
[string[]]
|
|
$CompatiblePSEditions,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$PowerShellVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$ClrVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$DotNetFrameworkVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$PowerShellHostName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$PowerShellHostVersion,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Object[]]
|
|
$RequiredModules,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$TypesToProcess,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$FormatsToProcess,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$ScriptsToProcess,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$RequiredAssemblies,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$FileList,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[object[]]
|
|
$ModuleList,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$FunctionsToExport,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$AliasesToExport,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$VariablesToExport,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$CmdletsToExport,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$DscResourcesToExport,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Collections.Hashtable]
|
|
$PrivateData,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string[]]
|
|
$Tags,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$ProjectUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$LicenseUri,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$IconUri,
|
|
|
|
[Parameter()]
|
|
[string[]]
|
|
$ReleaseNotes,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$HelpInfoUri,
|
|
|
|
[Parameter()]
|
|
[switch]
|
|
$PassThru,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$DefaultCommandPrefix,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$ExternalModuleDependencies,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String[]]
|
|
$PackageManagementProviders
|
|
)
|
|
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path -Path $Path -PathType Leaf))
|
|
{
|
|
$message = $LocalizedData.UpdateModuleManifestPathCannotFound -f ($Path)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidModuleManifestFilePath" `
|
|
-ExceptionObject $Path `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
|
|
$ModuleManifestHashTable = $null
|
|
|
|
try
|
|
{
|
|
$ModuleManifestHashTable = Get-ManifestHashTable -Path $Path -CallerPSCmdlet $PSCmdlet
|
|
}
|
|
catch
|
|
{
|
|
$message = $LocalizedData.TestModuleManifestFail -f ($_.Exception.Message)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidModuleManifestFile" `
|
|
-ExceptionObject $Path `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
#Get the original module manifest and migrate all the fields to the new module manifest, including the specified parameter values
|
|
$moduleInfo = $null
|
|
|
|
try
|
|
{
|
|
$moduleInfo = Microsoft.PowerShell.Core\Test-ModuleManifest -Path $Path -ErrorAction Stop
|
|
}
|
|
catch
|
|
{
|
|
# Throw an error only if Test-ModuleManifest did not return the PSModuleInfo object.
|
|
# This enables the users to use Update-ModuleManifest cmdlet to update the metadata.
|
|
if(-not $moduleInfo)
|
|
{
|
|
$message = $LocalizedData.TestModuleManifestFail -f ($_.Exception.Message)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidModuleManifestFile" `
|
|
-ExceptionObject $Path `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
}
|
|
|
|
#Params to pass to New-ModuleManifest module
|
|
$params = @{}
|
|
|
|
#NestedModules is read-only property
|
|
if($NestedModules)
|
|
{
|
|
$params.Add("NestedModules",$NestedModules)
|
|
}
|
|
elseif($moduleInfo.NestedModules)
|
|
{
|
|
#Get the original module info from ManifestHashTab
|
|
if($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("NestedModules"))
|
|
{
|
|
$params.Add("NestedModules",$ModuleManifestHashtable.NestedModules)
|
|
}
|
|
}
|
|
|
|
#Guid is read-only property
|
|
if($Guid)
|
|
{
|
|
$params.Add("Guid",$Guid)
|
|
}
|
|
elseif($moduleInfo.Guid)
|
|
{
|
|
$params.Add("Guid",$moduleInfo.Guid)
|
|
}
|
|
|
|
if($Author)
|
|
{
|
|
$params.Add("Author",$Author)
|
|
}
|
|
elseif($moduleInfo.Author)
|
|
{
|
|
$params.Add("Author",$moduleInfo.Author)
|
|
}
|
|
|
|
if($CompanyName)
|
|
{
|
|
$params.Add("CompanyName",$CompanyName)
|
|
}
|
|
elseif($moduleInfo.CompanyName)
|
|
{
|
|
$params.Add("CompanyName",$moduleInfo.CompanyName)
|
|
}
|
|
|
|
if($Copyright)
|
|
{
|
|
$params.Add("CopyRight",$Copyright)
|
|
}
|
|
elseif($moduleInfo.Copyright)
|
|
{
|
|
$params.Add("Copyright",$moduleInfo.Copyright)
|
|
}
|
|
|
|
if($RootModule)
|
|
{
|
|
$params.Add("RootModule",$RootModule)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("RootModule") -and $moduleInfo.RootModule)
|
|
{
|
|
$params.Add("RootModule",$ModuleManifestHashTable.RootModule)
|
|
}
|
|
|
|
if($ModuleVersion)
|
|
{
|
|
$params.Add("ModuleVersion",$ModuleVersion)
|
|
}
|
|
elseif($moduleInfo.Version)
|
|
{
|
|
$params.Add("ModuleVersion",$moduleInfo.Version)
|
|
}
|
|
|
|
if($Description)
|
|
{
|
|
$params.Add("Description",$Description)
|
|
}
|
|
elseif($moduleInfo.Description)
|
|
{
|
|
$params.Add("Description",$moduleInfo.Description)
|
|
}
|
|
|
|
if($ProcessorArchitecture)
|
|
{
|
|
$params.Add("ProcessorArchitecture",$ProcessorArchitecture)
|
|
}
|
|
#Check if ProcessorArchitecture has a value and is not 'None' on lower verison PS
|
|
elseif($moduleInfo.ProcessorArchitecture -and $moduleInfo.ProcessorArchitecture -ne 'None')
|
|
{
|
|
$params.Add("ProcessorArchitecture",$moduleInfo.ProcessorArchitecture)
|
|
}
|
|
|
|
if($PowerShellVersion)
|
|
{
|
|
$params.Add("PowerShellVersion",$PowerShellVersion)
|
|
}
|
|
elseif($moduleinfo.PowerShellVersion)
|
|
{
|
|
$params.Add("PowerShellVersion",$moduleinfo.PowerShellVersion)
|
|
}
|
|
|
|
if($ClrVersion)
|
|
{
|
|
$params.Add("ClrVersion",$ClrVersion)
|
|
}
|
|
elseif($moduleInfo.ClrVersion)
|
|
{
|
|
$params.Add("ClrVersion",$moduleInfo.ClrVersion)
|
|
}
|
|
|
|
if($DotNetFrameworkVersion)
|
|
{
|
|
$params.Add("DotNetFrameworkVersion",$DotNetFrameworkVersion)
|
|
}
|
|
elseif($moduleInfo.DotNetFrameworkVersion)
|
|
{
|
|
$params.Add("DotNetFrameworkVersion",$moduleInfo.DotNetFrameworkVersion)
|
|
}
|
|
|
|
if($PowerShellHostName)
|
|
{
|
|
$params.Add("PowerShellHostName",$PowerShellHostName)
|
|
}
|
|
elseif($moduleInfo.PowerShellHostName)
|
|
{
|
|
$params.Add("PowerShellHostName",$moduleInfo.PowerShellHostName)
|
|
}
|
|
|
|
if($PowerShellHostVersion)
|
|
{
|
|
$params.Add("PowerShellHostVersion",$PowerShellHostVersion)
|
|
}
|
|
elseif($moduleInfo.PowerShellHostVersion)
|
|
{
|
|
$params.Add("PowerShellHostVersion",$moduleInfo.PowerShellHostVersion)
|
|
}
|
|
|
|
if($RequiredModules)
|
|
{
|
|
$params.Add("RequiredModules",$RequiredModules)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("RequiredModules") -and $moduleInfo.RequiredModules)
|
|
{
|
|
$params.Add("RequiredModules",$ModuleManifestHashtable.RequiredModules)
|
|
}
|
|
|
|
if($TypesToProcess)
|
|
{
|
|
$params.Add("TypesToProcess",$TypesToProcess)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("TypesToProcess") -and $moduleInfo.ExportedTypeFiles)
|
|
{
|
|
$params.Add("TypesToProcess",$ModuleManifestHashTable.TypesToProcess)
|
|
}
|
|
|
|
if($FormatsToProcess)
|
|
{
|
|
$params.Add("FormatsToProcess",$FormatsToProcess)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("FormatsToProcess") -and $moduleInfo.ExportedFormatFiles)
|
|
{
|
|
$params.Add("FormatsToProcess",$ModuleManifestHashTable.FormatsToProcess)
|
|
}
|
|
|
|
if($ScriptsToProcess)
|
|
{
|
|
$params.Add("ScriptsToProcess",$ScriptstoProcess)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("ScriptsToProcess") -and $moduleInfo.Scripts)
|
|
{
|
|
$params.Add("ScriptsToProcess",$ModuleManifestHashTable.ScriptsToProcess)
|
|
}
|
|
|
|
if($RequiredAssemblies)
|
|
{
|
|
$params.Add("RequiredAssemblies",$RequiredAssemblies)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("RequiredAssemblies") -and $moduleInfo.RequiredAssemblies)
|
|
{
|
|
$params.Add("RequiredAssemblies",$moduleInfo.RequiredAssemblies)
|
|
}
|
|
|
|
if($FileList)
|
|
{
|
|
$params.Add("FileList",$FileList)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("FileList") -and $moduleInfo.FileList)
|
|
{
|
|
$params.Add("FileList",$ModuleManifestHashTable.FileList)
|
|
}
|
|
|
|
#Make sure every path defined under FileList is within module base
|
|
$moduleBase = $moduleInfo.ModuleBase
|
|
foreach($file in $params["FileList"])
|
|
{
|
|
#If path is not root path, append the module base to it and check if the file exists
|
|
if(-not [System.IO.Path]::IsPathRooted($file))
|
|
{
|
|
$combinedPath = Join-Path $moduleBase -ChildPath $file
|
|
}
|
|
else
|
|
{
|
|
$combinedPath = $file
|
|
}
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path -Type Leaf -LiteralPath $combinedPath))
|
|
{
|
|
$message = $LocalizedData.FilePathInFileListNotWithinModuleBase -f ($file,$moduleBase)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "FilePathInFileListNotWithinModuleBase" `
|
|
-ExceptionObject $file `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
if($ModuleList)
|
|
{
|
|
$params.Add("ModuleList",$ModuleList)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("ModuleList") -and $moduleInfo.ModuleList)
|
|
{
|
|
$params.Add("ModuleList",$ModuleManifestHashtable.ModuleList)
|
|
}
|
|
|
|
if($FunctionsToExport)
|
|
{
|
|
$params.Add("FunctionsToExport",$FunctionsToExport)
|
|
}
|
|
|
|
elseif($moduleInfo.ExportedFunctions)
|
|
{
|
|
#Since $moduleInfo.ExportedFunctions is a hashtable, we need to take the name of the
|
|
#functions and make them into a list
|
|
$params.Add("FunctionsToExport",($moduleInfo.ExportedFunctions.Keys -split ' '))
|
|
}
|
|
|
|
|
|
if($AliasesToExport)
|
|
{
|
|
$params.Add("AliasesToExport",$AliasesToExport)
|
|
}
|
|
elseif($moduleInfo.ExportedAliases)
|
|
{
|
|
$params.Add("AliasesToExport",($moduleInfo.ExportedAliases.Keys -split ' '))
|
|
}
|
|
if($VariablesToExport)
|
|
{
|
|
$params.Add("VariablesToExport",$VariablesToExport)
|
|
}
|
|
elseif($moduleInfo.ExportedVariables)
|
|
{
|
|
$params.Add("VariablesToExport",($moduleInfo.ExportedVariables.Keys -split ' '))
|
|
}
|
|
if($CmdletsToExport)
|
|
{
|
|
$params.Add("CmdletsToExport", $CmdletsToExport)
|
|
}
|
|
elseif($moduleInfo.ExportedCmdlets)
|
|
{
|
|
$params.Add("CmdletsToExport",($moduleInfo.ExportedCmdlets.Keys -split ' '))
|
|
}
|
|
if($DscResourcesToExport)
|
|
{
|
|
#DscResourcesToExport field is not available in PowerShell version lower than 5.0
|
|
|
|
if (($PSVersionTable.PSVersion -lt [Version]"5.0") -or ($PowerShellVersion -and $PowerShellVersion -lt [Version]"5.0") `
|
|
-or (-not $PowerShellVersion -and $moduleInfo.PowerShellVersion -and $moduleInfo.PowerShellVersion -lt [Version]"5.0") `
|
|
-or (-not $PowerShellVersion -and -not $moduleInfo.PowerShellVersion))
|
|
{
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $LocalizedData.ExportedDscResourcesNotSupportedOnLowerPowerShellVersion `
|
|
-ErrorId "ExportedDscResourcesNotSupported" `
|
|
-ExceptionObject $DscResourcesToExport `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
$params.Add("DscResourcesToExport",$DscResourcesToExport)
|
|
}
|
|
elseif(Microsoft.PowerShell.Utility\Get-Member -InputObject $moduleInfo -name "ExportedDscResources")
|
|
{
|
|
if($moduleInfo.ExportedDscResources)
|
|
{
|
|
$params.Add("DscResourcesToExport",$moduleInfo.ExportedDscResources)
|
|
}
|
|
}
|
|
|
|
if($CompatiblePSEditions)
|
|
{
|
|
# CompatiblePSEditions field is not available in PowerShell version lower than 5.1
|
|
#
|
|
if (($PSVersionTable.PSVersion -lt [Version]'5.1') -or ($PowerShellVersion -and $PowerShellVersion -lt [Version]'5.1') `
|
|
-or (-not $PowerShellVersion -and $moduleInfo.PowerShellVersion -and $moduleInfo.PowerShellVersion -lt [Version]'5.1') `
|
|
-or (-not $PowerShellVersion -and -not $moduleInfo.PowerShellVersion))
|
|
{
|
|
ThrowError -ExceptionName 'System.ArgumentException' `
|
|
-ExceptionMessage $LocalizedData.CompatiblePSEditionsNotSupportedOnLowerPowerShellVersion `
|
|
-ErrorId 'CompatiblePSEditionsNotSupported' `
|
|
-ExceptionObject $CompatiblePSEditions `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
$params.Add('CompatiblePSEditions', $CompatiblePSEditions)
|
|
}
|
|
elseif( (Microsoft.PowerShell.Utility\Get-Member -InputObject $moduleInfo -name 'CompatiblePSEditions') -and
|
|
$moduleInfo.CompatiblePSEditions)
|
|
{
|
|
$params.Add('CompatiblePSEditions', $moduleInfo.CompatiblePSEditions)
|
|
}
|
|
|
|
if($HelpInfoUri)
|
|
{
|
|
$params.Add("HelpInfoUri",$HelpInfoUri)
|
|
}
|
|
elseif($moduleInfo.HelpInfoUri)
|
|
{
|
|
$params.Add("HelpInfoUri",$moduleInfo.HelpInfoUri)
|
|
}
|
|
|
|
if($DefaultCommandPrefix)
|
|
{
|
|
$params.Add("DefaultCommandPrefix",$DefaultCommandPrefix)
|
|
}
|
|
elseif($ModuleManifestHashTable -and $ModuleManifestHashTable.ContainsKey("DefaultCommandPrefix") -and $ModuleManifestHashTable.DefaultCommandPrefix)
|
|
{
|
|
$params.Add("DefaultCommandPrefix",$ModuleManifestHashTable.DefaultCommandPrefix)
|
|
}
|
|
|
|
#Create a temp file within the directory and generate a new temporary manifest with the input
|
|
$tempPath = Microsoft.PowerShell.Management\Join-Path -Path $moduleInfo.ModuleBase -ChildPath "PSGet_$($moduleInfo.Name).psd1"
|
|
$params.Add("Path",$tempPath)
|
|
|
|
try
|
|
{
|
|
#Terminates if there is error creating new module manifest
|
|
try{
|
|
Microsoft.PowerShell.Core\New-ModuleManifest @params -Confirm:$false -WhatIf:$false
|
|
}
|
|
catch
|
|
{
|
|
$ErrorMessage = $LocalizedData.UpdatedModuleManifestNotValid -f ($Path, $_.Exception.Message)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $ErrorMessage `
|
|
-ErrorId "NewModuleManifestFailure" `
|
|
-ExceptionObject $params `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
#Manually update the section in PrivateData since New-ModuleManifest works differently on different PS version
|
|
$PrivateDataInput = ""
|
|
$ExistingData = $moduleInfo.PrivateData
|
|
$Data = @{}
|
|
if($ExistingData)
|
|
{
|
|
foreach($key in $ExistingData.Keys)
|
|
{
|
|
if($key -ne "PSData"){
|
|
$Data.Add($key,$ExistingData[$key])
|
|
}
|
|
else
|
|
{
|
|
$PSData = $ExistingData["PSData"]
|
|
foreach($entry in $PSData.Keys)
|
|
{
|
|
$Data.Add($entry,$PSData[$Entry])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if($PrivateData)
|
|
{
|
|
foreach($key in $PrivateData.Keys)
|
|
{
|
|
#if user provides PSData within PrivateData, we will parse through the PSData
|
|
if($key -ne "PSData")
|
|
{
|
|
$Data[$key] = $PrivateData[$Key]
|
|
}
|
|
|
|
else
|
|
{
|
|
$PSData = $ExistingData["PSData"]
|
|
foreach($entry in $PSData.Keys)
|
|
{
|
|
$Data[$entry] = $PSData[$entry]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#Tags is a read-only property
|
|
if($Tags)
|
|
{
|
|
$Data["Tags"] = $Tags
|
|
}
|
|
|
|
|
|
#The following Uris and ReleaseNotes cannot be empty
|
|
if($ProjectUri)
|
|
{
|
|
$Data["ProjectUri"] = $ProjectUri
|
|
}
|
|
|
|
if($LicenseUri)
|
|
{
|
|
$Data["LicenseUri"] = $LicenseUri
|
|
}
|
|
if($IconUri)
|
|
{
|
|
$Data["IconUri"] = $IconUri
|
|
}
|
|
|
|
if($ReleaseNotes)
|
|
{
|
|
#If value is provided as an array, we append the string.
|
|
$Data["ReleaseNotes"] = $($ReleaseNotes -join "`r`n")
|
|
}
|
|
|
|
if($ExternalModuleDependencies)
|
|
{
|
|
#ExternalModuleDependencies have to be specified either under $RequiredModules or $NestedModules
|
|
#Extract all the module names specified in the moduleInfo of NestedModules and RequiredModules
|
|
$DependentModuleNames = @()
|
|
foreach($moduleInfo in $params["NestedModules"])
|
|
{
|
|
if($moduleInfo.GetType() -eq [System.Collections.Hashtable])
|
|
{
|
|
$DependentModuleNames += $moduleInfo.ModuleName
|
|
}
|
|
}
|
|
|
|
foreach($moduleInfo in $params["RequiredModules"])
|
|
{
|
|
if($moduleInfo.GetType() -eq [System.Collections.Hashtable])
|
|
{
|
|
$DependentModuleNames += $moduleInfo.ModuleName
|
|
}
|
|
}
|
|
|
|
foreach($dependency in $ExternalModuleDependencies)
|
|
{
|
|
if($params["NestedModules"] -notcontains $dependency -and
|
|
$params["RequiredModules"] -notContains $dependency -and
|
|
$DependentModuleNames -notcontains $dependency)
|
|
{
|
|
$message = $LocalizedData.ExternalModuleDependenciesNotSpecifiedInRequiredOrNestedModules -f ($dependency)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidExternalModuleDependencies" `
|
|
-ExceptionObject $Exception `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
}
|
|
if($Data.ContainsKey("ExternalModuleDependencies"))
|
|
{
|
|
$Data["ExternalModuleDependencies"] = $ExternalModuleDependencies
|
|
}
|
|
else
|
|
{
|
|
$Data.Add("ExternalModuleDependencies", $ExternalModuleDependencies)
|
|
}
|
|
}
|
|
if($PackageManagementProviders)
|
|
{
|
|
#Check if the provided value is within the relative path
|
|
$ModuleBase = Microsoft.PowerShell.Management\Split-Path $Path -Parent
|
|
$Files = Microsoft.PowerShell.Management\Get-ChildItem -Path $ModuleBase
|
|
foreach($provider in $PackageManagementProviders)
|
|
{
|
|
if ($Files.Name -notcontains $provider)
|
|
{
|
|
$message = $LocalizedData.PackageManagementProvidersNotInModuleBaseFolder -f ($provider,$ModuleBase)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidPackageManagementProviders" `
|
|
-ExceptionObject $PackageManagementProviders `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
}
|
|
|
|
$Data["PackageManagementProviders"] = $PackageManagementProviders
|
|
}
|
|
$PrivateDataInput = Get-PrivateData -PrivateData $Data
|
|
|
|
#Repleace the PrivateData section by first locating the linenumbers of start line and endline.
|
|
$PrivateDataBegin = Select-String -Path $tempPath -Pattern "PrivateData ="
|
|
$PrivateDataBeginLine = $PrivateDataBegin.LineNumber
|
|
|
|
$newManifest = Microsoft.PowerShell.Management\Get-Content -Path $tempPath
|
|
#Look up the endline of PrivateData section by finding the matching brackets since private data could
|
|
#consist of multiple pairs of brackets.
|
|
$PrivateDataEndLine=0
|
|
if($PrivateDataBegin -match "@{")
|
|
{
|
|
$leftBrace = 0
|
|
$EndLineOfFile = $newManifest.Length-1
|
|
|
|
For($i = $PrivateDataBeginLine;$i -lt $EndLineOfFile; $i++)
|
|
{
|
|
if($newManifest[$i] -match "{")
|
|
{
|
|
$leftBrace ++
|
|
}
|
|
elseif($newManifest[$i] -match "}")
|
|
{
|
|
if($leftBrace -gt 0)
|
|
{
|
|
$leftBrace --
|
|
}
|
|
else
|
|
{
|
|
$PrivateDataEndLine = $i
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
if($PrivateDataEndLine -ne 0)
|
|
{
|
|
#If PrivateData section has more than one line, we will remove the old content and insert the new PrivataData
|
|
$newManifest | where {$_.readcount -le $PrivateDataBeginLine -or $_.readcount -gt $PrivateDataEndLine+1} `
|
|
| ForEach-Object {
|
|
$_
|
|
if($_ -match "PrivateData = ")
|
|
{
|
|
$PrivateDataInput
|
|
}
|
|
} | Set-Content -Path $tempPath -Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
#In lower version, PrivateData is just a single line
|
|
else
|
|
{
|
|
$PrivateDataForDownlevelPS = "PrivateData = @{ `n"+$PrivateDataInput
|
|
|
|
$newManifest | where {$_.readcount -le $PrivateDataBeginLine -or $_.readcount -gt $PrivateDataBeginLine } `
|
|
| ForEach-Object {
|
|
$_
|
|
if($_ -match "PrivateData = ")
|
|
{
|
|
$PrivateDataForDownlevelPS
|
|
}
|
|
} | Set-Content -Path $tempPath -Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
#Verify the new module manifest is valid
|
|
$testModuleInfo = Microsoft.PowerShell.Core\Test-ModuleManifest -Path $tempPath `
|
|
-Verbose:$VerbosePreference `
|
|
}
|
|
#Catch the exceptions from Test-ModuleManifest
|
|
catch
|
|
{
|
|
$message = $LocalizedData.UpdatedModuleManifestNotValid -f ($Path, $_.Exception.Message)
|
|
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "UpdateManifestFileFail" `
|
|
-ExceptionObject $_.Exception `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
return
|
|
}
|
|
|
|
|
|
$newContent = Microsoft.PowerShell.Management\Get-Content -Path $tempPath
|
|
|
|
try{
|
|
#Ask for confirmation of the new manifest before replacing the original one
|
|
if($PSCmdlet.ShouldProcess($Path,$LocalizedData.UpdateManifestContentMessage+$newContent))
|
|
{
|
|
Microsoft.PowerShell.Management\Set-Content -Path $Path -Value $newContent -Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
#Return the new content if -PassThru is specified
|
|
if($PassThru)
|
|
{
|
|
return $newContent
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
$message = $LocalizedData.ManifestFileReadWritePermissionDenied -f ($Path)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "ManifestFileReadWritePermissionDenied" `
|
|
-ExceptionObject $Path `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidArgument
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -LiteralPath $tempPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
}
|
|
|
|
#Utility function to help form the content string for PrivateData
|
|
function Get-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 = ''
|
|
|
|
# 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 "','" | %{"'$_'"}
|
|
$LicenseUri = $PrivateData["LicenseUri"]| %{"'$_'"}
|
|
$ProjectUri = $PrivateData["ProjectUri"] | %{"'$_'"}
|
|
$IconUri = $PrivateData["IconUri"] | %{"'$_'"}
|
|
$ReleaseNotesEscape = $PrivateData["ReleaseNotes"] -Replace "'","''"
|
|
$ReleaseNotes = $ReleaseNotesEscape | %{"'$_'"}
|
|
$ExternalModuleDependencies = $PrivateData["ExternalModuleDependencies"] -join "','" | %{"'$_'"}
|
|
|
|
$DefaultProperties = @("Tags","LicenseUri","ProjectUri","IconUri","ReleaseNotes","ExternalModuleDependencies")
|
|
|
|
$ExtraProperties = @()
|
|
foreach($key in $PrivateData.Keys)
|
|
{
|
|
if($DefaultProperties -notcontains $key)
|
|
{
|
|
$PropertyString = "#"+"$key"+ " of this module"
|
|
$PropertyString += "`r`n "
|
|
$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
|
|
}
|
|
$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
|
|
|
|
# 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
|
|
|
|
# External dependent modules of this module
|
|
$ExternalModuleDependenciesLine
|
|
|
|
} # End of PSData hashtable
|
|
|
|
} # End of PrivateData hashtable"
|
|
return $content
|
|
}
|
|
}
|
|
|
|
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
|
|
)
|
|
|
|
# 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 `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue `
|
|
-Confirm:$false `
|
|
-WhatIf:$false
|
|
}
|
|
|
|
Microsoft.PowerShell.Management\Copy-Item -Path $SourcePath -Destination $DestinationPath -Force -Confirm:$false -WhatIf:$false -Verbose
|
|
|
|
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 Copy-Module
|
|
{
|
|
[CmdletBinding(PositionalBinding=$false)]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$SourcePath,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$DestinationPath,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNull()]
|
|
[PSCustomObject]
|
|
$PSGetItemInfo
|
|
)
|
|
|
|
if(Microsoft.PowerShell.Management\Test-Path $DestinationPath)
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path $DestinationPath -Recurse -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
}
|
|
|
|
# Copy the module to destination
|
|
$null = Microsoft.PowerShell.Management\New-Item -Path $DestinationPath -ItemType Directory -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false
|
|
Microsoft.PowerShell.Management\Copy-Item -Path "$SourcePath\*" -Destination $DestinationPath -Force -Recurse -Confirm:$false -WhatIf:$false
|
|
|
|
# Remove the *.nupkg file
|
|
if(Microsoft.PowerShell.Management\Test-Path "$DestinationPath\$($PSGetItemInfo.Name).nupkg")
|
|
{
|
|
Microsoft.PowerShell.Management\Remove-Item -Path "$DestinationPath\$($PSGetItemInfo.Name).nupkg" -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 Test-FileInUse
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
param
|
|
(
|
|
[string]
|
|
$FilePath
|
|
)
|
|
|
|
if(Microsoft.PowerShell.Management\Test-Path -LiteralPath $FilePath -PathType Leaf)
|
|
{
|
|
# Attempts to open a file and handles the exception if the file is already open/locked
|
|
try
|
|
{
|
|
$fileInfo = New-Object System.IO.FileInfo $FilePath
|
|
$fileStream = $fileInfo.Open( [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None )
|
|
|
|
if ($fileStream)
|
|
{
|
|
$fileStream.Close()
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Write-Debug "In Test-FileInUse function, unable to open the $FilePath file in ReadWrite access. $_"
|
|
return $true
|
|
}
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
function Test-ModuleInUse
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$ModuleBasePath,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$ModuleName,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Version]
|
|
$ModuleVersion
|
|
)
|
|
|
|
$FileList = Get-ChildItem -Path $ModuleBasePath `
|
|
-File `
|
|
-Recurse `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue
|
|
$IsModuleInUse = $false
|
|
|
|
foreach($file in $FileList)
|
|
{
|
|
$IsModuleInUse = Test-FileInUse -FilePath $file.FullName
|
|
|
|
if($IsModuleInUse)
|
|
{
|
|
break
|
|
}
|
|
}
|
|
|
|
if($IsModuleInUse)
|
|
{
|
|
$message = $LocalizedData.ModuleVersionInUse -f ($ModuleVersion, $ModuleName)
|
|
Write-Error -Message $message -ErrorId 'ModuleIsInUse' -Category InvalidOperation
|
|
|
|
return $true
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
function Validate-ModuleAuthenticodeSignature
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
$CurrentModuleInfo,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$InstallLocation,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$IsUpdateOperation,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$SkipPublisherCheck
|
|
)
|
|
|
|
$InstalledModuleDetails = $null
|
|
$InstalledModuleInfo = Test-ModuleInstalled -Name $CurrentModuleInfo.Name
|
|
if($InstalledModuleInfo)
|
|
{
|
|
$InstalledModuleDetails = Get-InstalledModuleAuthenticodeSignature -InstalledModuleInfo $InstalledModuleInfo `
|
|
-InstallLocation $InstallLocation
|
|
}
|
|
|
|
# Skip the publisher check when -SkipPublisherCheck is specified and
|
|
# it is not an update operation.
|
|
if(-not $IsUpdateOperation -and $SkipPublisherCheck)
|
|
{
|
|
$Message = $LocalizedData.SkippingPublisherCheck -f ($CurrentModuleInfo.Version, $CurrentModuleInfo.Name)
|
|
Write-Verbose -Message $message
|
|
|
|
return $true
|
|
}
|
|
|
|
# Validate the catalog signature for the current module being installed.
|
|
$ev = $null
|
|
$CurrentModuleDetails = ValidateAndGet-AuthenticodeSignature -ModuleInfo $CurrentModuleInfo -ErrorVariable ev
|
|
|
|
if($ev)
|
|
{
|
|
return $false
|
|
}
|
|
|
|
if($InstalledModuleInfo)
|
|
{
|
|
$CurrentModuleAuthenticodePublisher = $null
|
|
$IsCurrentModuleSignedByMicrosoft = $false
|
|
|
|
if($CurrentModuleDetails)
|
|
{
|
|
$CurrentModuleAuthenticodePublisher = $CurrentModuleDetails.Publisher
|
|
$IsCurrentModuleSignedByMicrosoft = $CurrentModuleDetails.IsMicrosoftCertificate
|
|
|
|
$message = $LocalizedData.NewModuleVersionDetailsForPublisherValidation -f ($CurrentModuleInfo.Name,
|
|
$CurrentModuleInfo.Version,
|
|
$CurrentModuleDetails.Publisher,
|
|
$CurrentModuleDetails.IsMicrosoftCertificate)
|
|
Write-Verbose $message
|
|
}
|
|
|
|
$InstalledModuleAuthenticodePublisher = $null
|
|
$IsInstalledModuleSignedByMicrosoft = $false
|
|
$InstalledModuleVersion = [Version]'0.0'
|
|
|
|
if($InstalledModuleDetails)
|
|
{
|
|
$InstalledModuleAuthenticodePublisher = $InstalledModuleDetails.Publisher
|
|
$IsInstalledModuleSignedByMicrosoft = $InstalledModuleDetails.IsMicrosoftCertificate
|
|
$InstalledModuleVersion = $InstalledModuleDetails.Version
|
|
|
|
$message = $LocalizedData.SourceModuleDetailsForPublisherValidation -f ($CurrentModuleInfo.Name,
|
|
$InstalledModuleDetails.Version,
|
|
$InstalledModuleDetails.ModuleBase,
|
|
$InstalledModuleDetails.Publisher,
|
|
$InstalledModuleDetails.IsMicrosoftCertificate)
|
|
Write-Verbose $message
|
|
}
|
|
|
|
Write-Debug -Message "Previously-installed module publisher: $InstalledModuleAuthenticodePublisher"
|
|
Write-Debug -Message "Current module publisher: $CurrentModuleAuthenticodePublisher"
|
|
Write-Debug -Message "Is previously-installed module signed by Microsoft: $IsInstalledModuleSignedByMicrosoft"
|
|
Write-Debug -Message "Is current module signed by Microsoft: $IsCurrentModuleSignedByMicrosoft"
|
|
|
|
if($InstalledModuleAuthenticodePublisher)
|
|
{
|
|
if(-not $CurrentModuleAuthenticodePublisher)
|
|
{
|
|
$Message = $LocalizedData.ModuleIsNotCatalogSigned -f ($CurrentModuleInfo.Version, $CurrentModuleInfo.Name, "$($CurrentModuleInfo.Name).cat", $InstalledModuleAuthenticodePublisher, $InstalledModuleDetails.Version, $InstalledModuleDetails.ModuleBase)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'ModuleIsNotCatalogSigned' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
return $false
|
|
}
|
|
elseif($InstalledModuleAuthenticodePublisher -eq $CurrentModuleAuthenticodePublisher)
|
|
{
|
|
$Message = $LocalizedData.AuthenticodeIssuerMatch -f ($CurrentModuleAuthenticodePublisher, $CurrentModuleInfo.Name, $CurrentModuleInfo.Version, $InstalledModuleAuthenticodePublisher, $InstalledModuleInfo.Name, $InstalledModuleVersion)
|
|
Write-Verbose -Message $message
|
|
}
|
|
elseif($IsInstalledModuleSignedByMicrosoft)
|
|
{
|
|
if($IsCurrentModuleSignedByMicrosoft)
|
|
{
|
|
$Message = $LocalizedData.PublishersMatch -f ($CurrentModuleAuthenticodePublisher, $CurrentModuleInfo.Name, $CurrentModuleInfo.Version, $InstalledModuleAuthenticodePublisher, $InstalledModuleInfo.Name, $InstalledModuleVersion)
|
|
Write-Verbose -Message $message
|
|
}
|
|
else
|
|
{
|
|
$Message = $LocalizedData.PublishersMismatch -f ($InstalledModuleInfo.Name, $InstalledModuleVersion, $CurrentModuleInfo.Name, $CurrentModuleAuthenticodePublisher, $CurrentModuleInfo.Version)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'PublishersMismatch' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
|
|
return $false
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$Message = $LocalizedData.AuthenticodeIssuerMismatch -f ($CurrentModuleAuthenticodePublisher, $CurrentModuleInfo.Name, $CurrentModuleInfo.Version, $InstalledModuleAuthenticodePublisher, $InstalledModuleInfo.Name, $InstalledModuleVersion)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'AuthenticodeIssuerMismatch' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
return $false
|
|
}
|
|
}
|
|
}
|
|
|
|
return $true
|
|
}
|
|
|
|
function Validate-ModuleCommandAlreadyAvailable
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[PSModuleInfo]
|
|
$CurrentModuleInfo,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$InstallLocation,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$AllowClobber,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$IsUpdateOperation
|
|
)
|
|
|
|
<#
|
|
Install-Module must generate an error message when there is a conflict.
|
|
User can specify -AllowClobber to avoid the message.
|
|
Scenario: A large module could be separated into 2 smaller modules.
|
|
Reason 1: the consumer might have to change code (aka: import-module) to use the command from the new module.
|
|
Reason 2: it is too confusing to troubleshoot this problem if the user isn't informed right away.
|
|
#>
|
|
# When new module has some commands, no clobber error if
|
|
# - AllowClobber is specified, or
|
|
# - Installing to the same module base, or
|
|
# - Update operation
|
|
if($CurrentModuleInfo.ExportedCommands.Keys.Count -and
|
|
-not $AllowClobber -and
|
|
-not $IsUpdateOperation)
|
|
{
|
|
# 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
|
|
}
|
|
|
|
$InstalledModuleInfo = Test-ModuleInstalled -Name $CurrentModuleInfo.Name
|
|
if(-not $InstalledModuleInfo -or -not $InstalledModuleInfo.ModuleBase.StartsWith($InstallLocation, [System.StringComparison]::OrdinalIgnoreCase))
|
|
{
|
|
# Throw an error if there is a command with the same name from a different source.
|
|
# Get-Command loads the module if a command is already available.
|
|
# To avoid that, appending '*' at the end for each name then comparing the results.
|
|
$CommandNames = $CurrentModuleInfo.ExportedCommands.Values.Name
|
|
$CommandNamesWithWildcards = $CommandNames | Microsoft.PowerShell.Core\Foreach-Object { "$_*" }
|
|
|
|
$AvailableCommand = Microsoft.PowerShell.Core\Get-Command -Name $CommandNamesWithWildcards `
|
|
-ErrorAction SilentlyContinue `
|
|
-WarningAction SilentlyContinue |
|
|
Microsoft.PowerShell.Core\Where-Object { ($CommandNames -contains $_.Name) -and
|
|
($_.Source -ne $CurrentModuleInfo.Name) } |
|
|
Microsoft.PowerShell.Utility\Select-Object -First 1 -ErrorAction SilentlyContinue
|
|
if($AvailableCommand)
|
|
{
|
|
$message = $LocalizedData.ModuleCommandAlreadyAvailable -f ($AvailableCommand.Name, $CurrentModuleInfo.Name)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'CommandAlreadyAvailable' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
|
|
return $false
|
|
}
|
|
}
|
|
}
|
|
|
|
return $true
|
|
}
|
|
|
|
function ValidateAndGet-AuthenticodeSignature
|
|
{
|
|
[CmdletBinding()]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[PSModuleInfo]
|
|
$ModuleInfo
|
|
)
|
|
|
|
$ModuleDetails = $null
|
|
$AuthenticodeSignature = $null
|
|
|
|
$ModuleName = $ModuleInfo.Name
|
|
$ModuleBasePath = $ModuleInfo.ModuleBase
|
|
$CatalogFileName = "$ModuleName.cat"
|
|
$CatalogFilePath = Microsoft.PowerShell.Management\Join-Path -Path $ModuleBasePath -ChildPath $CatalogFileName
|
|
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $CatalogFilePath -PathType Leaf)
|
|
{
|
|
$message = $LocalizedData.CatalogFileFound -f ($CatalogFileName, $ModuleName)
|
|
Write-Verbose -Message $message
|
|
|
|
$AuthenticodeSignature = Microsoft.PowerShell.Security\Get-AuthenticodeSignature -FilePath $CatalogFilePath
|
|
|
|
if(-not $AuthenticodeSignature -or ($AuthenticodeSignature.Status -ne "Valid"))
|
|
{
|
|
$message = $LocalizedData.InvalidModuleAuthenticodeSignature -f ($ModuleName, $CatalogFileName)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'InvalidAuthenticodeSignature' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
|
|
return
|
|
}
|
|
|
|
Write-Verbose -Message ($LocalizedData.ValidAuthenticodeSignature -f @($CatalogFileName, $ModuleName))
|
|
|
|
if(Get-Command -Name Test-FileCatalog -Module Microsoft.PowerShell.Security -ErrorAction SilentlyContinue)
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.ValidatingCatalogSignature -f @($ModuleName, $CatalogFileName))
|
|
|
|
# Skip the PSGetModuleInfo.xml and ModuleName.cat files in the catalog validation
|
|
$TestFileCatalogResult = Microsoft.PowerShell.Security\Test-FileCatalog -Path $ModuleBasePath `
|
|
-CatalogFilePath $CatalogFilePath `
|
|
-FilesToSkip $script:PSGetItemInfoFileName,'*.cat' `
|
|
-Detailed `
|
|
-ErrorAction SilentlyContinue
|
|
if(-not $TestFileCatalogResult -or
|
|
($TestFileCatalogResult.Status -ne "Valid") -or
|
|
($TestFileCatalogResult.Signature.Status -ne "Valid"))
|
|
{
|
|
$message = $LocalizedData.InvalidCatalogSignature -f ($ModuleName, $CatalogFileName)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'InvalidCatalogSignature' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
return
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.ValidCatalogSignature -f @($CatalogFileName, $ModuleName))
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($LocalizedData.CatalogFileNotFoundInNewModule -f ($CatalogFileName, $ModuleName))
|
|
}
|
|
|
|
if($AuthenticodeSignature)
|
|
{
|
|
$ModuleDetails = @{}
|
|
$ModuleDetails['AuthenticodeSignature'] = $AuthenticodeSignature
|
|
$ModuleDetails['Version'] = $ModuleInfo.Version
|
|
$ModuleDetails['ModuleBase']=$ModuleInfo.ModuleBase
|
|
$ModuleDetails['IsMicrosoftCertificate'] = Test-MicrosoftCertificate -AuthenticodeSignature $AuthenticodeSignature
|
|
$ModuleDetails['Publisher'] = Get-AuthenticodePublisher -AuthenticodeSignature $AuthenticodeSignature
|
|
|
|
$message = $LocalizedData.NewModuleVersionDetailsForPublisherValidation -f ($ModuleInfo.Name, $ModuleInfo.Version, $ModuleDetails.Publisher, $ModuleDetails.IsMicrosoftCertificate)
|
|
Write-Debug $message
|
|
}
|
|
|
|
return $ModuleDetails
|
|
}
|
|
|
|
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 }
|
|
if($rootCertificateAuthority)
|
|
{
|
|
return $rootCertificateAuthority.Subject
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
if(-not $SourceModule)
|
|
{
|
|
$SourceModule = $AvailableModules | Microsoft.PowerShell.Utility\Select-Object -First 1
|
|
}
|
|
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
|
|
$ModuleDetails['Publisher'] = Get-AuthenticodePublisher -AuthenticodeSignature $AuthenticodeSignature
|
|
|
|
$message = $LocalizedData.SourceModuleDetailsForPublisherValidation -f ($ModuleName, $SourceModule.Version, $SourceModule.ModuleBase, $ModuleDetails.Publisher, $ModuleDetails.IsMicrosoftCertificate)
|
|
Write-Debug $message
|
|
}
|
|
|
|
return $ModuleDetails
|
|
}
|
|
|
|
function Test-MicrosoftCertificate
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory=$true)]
|
|
[System.Management.Automation.Signature]
|
|
$AuthenticodeSignature
|
|
)
|
|
|
|
if($AuthenticodeSignature.SignerCertificate)
|
|
{
|
|
try
|
|
{
|
|
$X509Chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain
|
|
$null = $X509Chain.Build($AuthenticodeSignature.SignerCertificate)
|
|
}
|
|
catch
|
|
{
|
|
return $false
|
|
}
|
|
|
|
$SafeX509ChainHandle = [Microsoft.PowerShell.Commands.PowerShellGet.Win32Helpers]::CertDuplicateCertificateChain($X509Chain.ChainContext)
|
|
return [Microsoft.PowerShell.Commands.PowerShellGet.Win32Helpers]::IsMicrosoftCertificate($SafeX509ChainHandle)
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
function Test-ValidManifestModule
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$ModuleBasePath,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$InstallLocation,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$SkipPublisherCheck,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$AllowClobber,
|
|
|
|
[Parameter()]
|
|
[Switch]
|
|
$IsUpdateOperation
|
|
)
|
|
|
|
$moduleName = Microsoft.PowerShell.Management\Split-Path $ModuleBasePath -Leaf
|
|
$manifestPath = Microsoft.PowerShell.Management\Join-Path $ModuleBasePath "$moduleName.psd1"
|
|
$PSModuleInfo = $null
|
|
|
|
if(Microsoft.PowerShell.Management\Test-Path $manifestPath)
|
|
{
|
|
$PSModuleInfo = Microsoft.PowerShell.Core\Test-ModuleManifest -Path $manifestPath -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
|
|
|
|
if(-not $PSModuleInfo)
|
|
{
|
|
$message = $LocalizedData.InvalidPSModule -f ($moduleName)
|
|
ThrowError -ExceptionName 'System.InvalidOperationException' `
|
|
-ExceptionMessage $message `
|
|
-ErrorId 'InvalidManifestModule' `
|
|
-CallerPSCmdlet $PSCmdlet `
|
|
-ErrorCategory InvalidOperation
|
|
}
|
|
else
|
|
{
|
|
$ValidationResult = Validate-ModuleAuthenticodeSignature -CurrentModuleInfo $PSModuleInfo `
|
|
-InstallLocation $InstallLocation `
|
|
-IsUpdateOperation:$IsUpdateOperation `
|
|
-SkipPublisherCheck:$SkipPublisherCheck
|
|
|
|
if($ValidationResult)
|
|
{
|
|
# Checking for the possible command clobbering.
|
|
$ValidationResult = Validate-ModuleCommandAlreadyAvailable -CurrentModuleInfo $PSModuleInfo `
|
|
-InstallLocation $InstallLocation `
|
|
-AllowClobber:$AllowClobber `
|
|
-IsUpdateOperation:$IsUpdateOperation
|
|
|
|
|
|
}
|
|
|
|
if(-not $ValidationResult)
|
|
{
|
|
$PSModuleInfo = $null
|
|
}
|
|
}
|
|
}
|
|
|
|
return $PSModuleInfo
|
|
}
|
|
|
|
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-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 Resolve-Location
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([string])]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$Location,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[string]
|
|
$LocationParameterName,
|
|
|
|
[Parameter()]
|
|
$Credential,
|
|
|
|
[Parameter()]
|
|
$Proxy,
|
|
|
|
[Parameter()]
|
|
$ProxyCredential,
|
|
|
|
[Parameter()]
|
|
[System.Management.Automation.PSCmdlet]
|
|
$CallerPSCmdlet
|
|
)
|
|
|
|
# Ping and resolve the specified location
|
|
if(-not (Test-WebUri -uri $Location))
|
|
{
|
|
if(Microsoft.PowerShell.Management\Test-Path -Path $Location)
|
|
{
|
|
return $Location
|
|
}
|
|
elseif($CallerPSCmdlet)
|
|
{
|
|
$message = $LocalizedData.PathNotFound -f ($Location)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "PathNotFound" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Location
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$pingResult = Ping-Endpoint -Endpoint $Location -Credential $Credential -Proxy $Proxy -ProxyCredential $ProxyCredential
|
|
$statusCode = $null
|
|
$exception = $null
|
|
$resolvedLocation = $null
|
|
if($pingResult -and $pingResult.ContainsKey($Script:ResponseUri))
|
|
{
|
|
$resolvedLocation = $pingResult[$Script:ResponseUri]
|
|
}
|
|
|
|
if($pingResult -and $pingResult.ContainsKey($Script:StatusCode))
|
|
{
|
|
$statusCode = $pingResult[$Script:StatusCode]
|
|
}
|
|
|
|
Write-Debug -Message "Ping-Endpoint: location=$Location, statuscode=$statusCode, resolvedLocation=$resolvedLocation"
|
|
|
|
if((($statusCode -eq 200) -or ($statusCode -eq 401)) -and $resolvedLocation)
|
|
{
|
|
return $resolvedLocation
|
|
}
|
|
elseif($CallerPSCmdlet)
|
|
{
|
|
$message = $LocalizedData.InvalidWebUri -f ($Location, $LocationParameterName)
|
|
ThrowError -ExceptionName "System.ArgumentException" `
|
|
-ExceptionMessage $message `
|
|
-ErrorId "InvalidWebUri" `
|
|
-CallerPSCmdlet $CallerPSCmdlet `
|
|
-ErrorCategory InvalidArgument `
|
|
-ExceptionObject $Location
|
|
}
|
|
}
|
|
}
|
|
|
|
function Test-WebUri
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Uri]
|
|
$uri
|
|
)
|
|
|
|
return ($uri.AbsoluteURI -ne $null) -and ($uri.Scheme -match '[http|https]')
|
|
}
|
|
|
|
function Test-WildcardPattern
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
param(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNull()]
|
|
$Name
|
|
)
|
|
|
|
return [System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($Name)
|
|
}
|
|
|
|
# Utility to throw an errorrecord
|
|
function ThrowError
|
|
{
|
|
param
|
|
(
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCmdlet]
|
|
$CallerPSCmdlet,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$ExceptionName,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$ExceptionMessage,
|
|
|
|
[System.Object]
|
|
$ExceptionObject,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$ErrorId,
|
|
|
|
[parameter(Mandatory = $true)]
|
|
[ValidateNotNull()]
|
|
[System.Management.Automation.ErrorCategory]
|
|
$ErrorCategory
|
|
)
|
|
|
|
$exception = New-Object $ExceptionName $ExceptionMessage;
|
|
$errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $ErrorId, $ErrorCategory, $ExceptionObject
|
|
$CallerPSCmdlet.ThrowTerminatingError($errorRecord)
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
# Create install locations for scripts if they are not already created
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path -Path $script:ProgramFilesInstalledScriptInfosPath) -and (Test-RunningAsElevated))
|
|
{
|
|
$null = Microsoft.PowerShell.Management\New-Item -Path $script:ProgramFilesInstalledScriptInfosPath `
|
|
-ItemType Directory `
|
|
-Force `
|
|
-Confirm:$false `
|
|
-WhatIf:$false
|
|
}
|
|
|
|
if(-not (Microsoft.PowerShell.Management\Test-Path -Path $script:MyDocumentsInstalledScriptInfosPath))
|
|
{
|
|
$null = Microsoft.PowerShell.Management\New-Item -Path $script:MyDocumentsInstalledScriptInfosPath `
|
|
-ItemType Directory `
|
|
-Force `
|
|
-Confirm:$false `
|
|
-WhatIf:$false
|
|
}
|
|
|
|
Set-Alias -Name fimo -Value Find-Module
|
|
Set-Alias -Name inmo -Value Install-Module
|
|
Set-Alias -Name upmo -Value Update-Module
|
|
Set-Alias -Name pumo -Value Publish-Module
|
|
Set-Alias -Name uimo -Value Uninstall-Module
|
|
|
|
Export-ModuleMember -Function Find-Module, `
|
|
Save-Module, `
|
|
Install-Module, `
|
|
Update-Module, `
|
|
Publish-Module, `
|
|
Uninstall-Module, `
|
|
Get-InstalledModule, `
|
|
Find-Command, `
|
|
Find-DscResource, `
|
|
Find-RoleCapability, `
|
|
Install-Script, `
|
|
Find-Script, `
|
|
Save-Script, `
|
|
Update-Script, `
|
|
Publish-Script, `
|
|
Get-InstalledScript, `
|
|
Uninstall-Script, `
|
|
Test-ScriptFileInfo, `
|
|
New-ScriptFileInfo, `
|
|
Update-ScriptFileInfo, `
|
|
Get-PSRepository, `
|
|
Register-PSRepository, `
|
|
Unregister-PSRepository, `
|
|
Set-PSRepository, `
|
|
Find-Package, `
|
|
Get-PackageDependencies, `
|
|
Download-Package, `
|
|
Install-Package, `
|
|
Uninstall-Package, `
|
|
Get-InstalledPackage, `
|
|
Remove-PackageSource, `
|
|
Resolve-PackageSource, `
|
|
Add-PackageSource, `
|
|
Get-DynamicOptions, `
|
|
Initialize-Provider, `
|
|
Get-Feature, `
|
|
Get-PackageProviderName, `
|
|
Update-ModuleManifest `
|
|
-Alias fimo, `
|
|
inmo, `
|
|
upmo, `
|
|
pumo
|