From bd599ed62a5dd318ca3da38deefd4310b0794a0a Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Fri, 1 Apr 2016 19:00:51 -0700 Subject: [PATCH] Move Module files from psl-monad submodule to super-project This commit uses master branch 8abffd25ebc33cbc0b4ce224b46e699704b01728 --- .../Microsoft.PowerShell.Diagnostics.psd1 | 16 + .../Microsoft.PowerShell.Utility.psd1 | 33 + .../Microsoft.PowerShell.Diagnostics.psd1 | 13 + .../AppxProvider/AppxProvider.Resource.psd1 | Bin 0 -> 5082 bytes src/Modules/AppxProvider/AppxProvider.psd1 | Bin 0 -> 1222 bytes src/Modules/AppxProvider/AppxProvider.psm1 | 956 ++ .../ArchiveResources.psd1 | Bin 0 -> 5124 bytes .../Microsoft.PowerShell.Archive.psd1 | 12 + .../Microsoft.PowerShell.Archive.psm1 | Bin 0 -> 105036 bytes .../Microsoft.PowerShell.Host.psd1 | 14 + .../Microsoft.PowerShell.Management.psd1 | 99 + .../Microsoft.PowerShell.Security.psd1 | 14 + .../Microsoft.PowerShell.Utility.psm1 | 709 + .../Microsoft.WSMan.Management.psd1 | 15 + src/Modules/PSDiagnostics/PSDiagnostics.psd1 | Bin 0 -> 1214 bytes src/Modules/PSDiagnostics/PSDiagnostics.psm1 | Bin 0 -> 23122 bytes src/Modules/PSGet/PSGet.Format.ps1xml | 202 + src/Modules/PSGet/PSGet.Resource.psd1 | Bin 0 -> 69704 bytes src/Modules/PSGet/PSGet.psd1 | Bin 0 -> 3940 bytes src/Modules/PSGet/PSModule.psm1 | 13064 ++++++++++++++++ 20 files changed, 15147 insertions(+) create mode 100644 src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1 create mode 100644 src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 create mode 100644 src/Microsoft.PowerShell.Host/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1 create mode 100644 src/Modules/AppxProvider/AppxProvider.Resource.psd1 create mode 100644 src/Modules/AppxProvider/AppxProvider.psd1 create mode 100644 src/Modules/AppxProvider/AppxProvider.psm1 create mode 100644 src/Modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1 create mode 100644 src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psd1 create mode 100644 src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1 create mode 100644 src/Modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1 create mode 100644 src/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1 create mode 100644 src/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 create mode 100644 src/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 create mode 100644 src/Modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1 create mode 100644 src/Modules/PSDiagnostics/PSDiagnostics.psd1 create mode 100644 src/Modules/PSDiagnostics/PSDiagnostics.psm1 create mode 100644 src/Modules/PSGet/PSGet.Format.ps1xml create mode 100644 src/Modules/PSGet/PSGet.Resource.psd1 create mode 100644 src/Modules/PSGet/PSGet.psd1 create mode 100644 src/Modules/PSGet/PSModule.psm1 diff --git a/src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1 b/src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1 new file mode 100644 index 0000000000..d72eb9e283 --- /dev/null +++ b/src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1 @@ -0,0 +1,16 @@ +@{ +GUID="CA046F10-CA64-4740-8FF9-2565DBA61A4F" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.0.0.0" +PowerShellVersion="3.0" +CLRVersion="4.0" +AliasesToExport = @() +FunctionsToExport = @() +CmdletsToExport="Get-WinEvent", "Get-Counter", "Import-Counter", "Export-Counter", "New-WinEvent" +NestedModules="Microsoft.PowerShell.Commands.Diagnostics.dll" +TypesToProcess="GetEvent.types.ps1xml" +FormatsToProcess="Event.format.ps1xml","Diagnostics.format.ps1xml" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390783' +} diff --git a/src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 b/src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 new file mode 100644 index 0000000000..618763603d --- /dev/null +++ b/src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 @@ -0,0 +1,33 @@ +@{ +GUID="1DA87E53-152B-403E-98DC-74D7B4D63D59" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.1.0.0" +PowerShellVersion="3.0" +CLRVersion="4.0" +CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide", + "Out-File", "Out-Printer", "Out-String", + "Out-GridView", "Get-FormatData", "Export-FormatData", "ConvertFrom-Json", "ConvertTo-Json", + "Invoke-RestMethod", "Invoke-WebRequest", "Register-ObjectEvent", "Register-EngineEvent", + "Wait-Event", "Get-Event", "Remove-Event", "Get-EventSubscriber", "Unregister-Event", + "New-Event", "Add-Member", "Add-Type", "Compare-Object", "ConvertTo-Html", "ConvertFrom-StringData", + "Export-Csv", "Import-Csv", "ConvertTo-Csv", "ConvertFrom-Csv", "Export-Alias", "Invoke-Expression", + "Get-Alias", "Get-Culture", "Get-Date", "Get-Host", "Get-Member", "Get-Random", "Get-UICulture", + "Get-Unique", "Export-PSSession", "Import-PSSession", "Import-Alias", "Import-LocalizedData", + "Select-String", "Measure-Object", "New-Alias", "New-TimeSpan", "Read-Host", "Set-Alias", "Set-Date", + "Start-Sleep", "Tee-Object", "Measure-Command", "Update-List", "Update-TypeData", "Update-FormatData", + "Remove-TypeData", "Get-TypeData", "Write-Host", "Write-Progress", "New-Object", "Select-Object", + "Group-Object", "Sort-Object", "Get-Variable", "New-Variable", "Set-Variable", "Remove-Variable", + "Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug", + "Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint", "Get-PSBreakpoint", + "Remove-PSBreakpoint", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack", + "Send-MailMessage", "Get-TraceSource", "Set-TraceSource", "Trace-Command", "Show-Command", "Unblock-File", + "Get-Runspace", "Debug-Runspace", "Enable-RunspaceDebug", "Disable-RunspaceDebug", "Get-RunspaceDebug", "Wait-Debugger", + "ConvertFrom-String", "Convert-String" +FunctionsToExport= "Get-FileHash", "New-TemporaryFile", "New-Guid", "Format-Hex", "Import-PowerShellDataFile", + "ConvertFrom-SddlString" +AliasesToExport= "CFS", "fhx" +NestedModules="Microsoft.PowerShell.Commands.Utility.dll","Microsoft.PowerShell.Utility.psm1" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390787' +} diff --git a/src/Microsoft.PowerShell.Host/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1 b/src/Microsoft.PowerShell.Host/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1 new file mode 100644 index 0000000000..dec59a24f7 --- /dev/null +++ b/src/Microsoft.PowerShell.Host/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1 @@ -0,0 +1,13 @@ +@{ +GUID="CA046F10-CA64-4740-8FF9-2565DBA61A4F" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.0.0.0" +PowerShellVersion="3.0" +CmdletsToExport="Get-WinEvent", "New-WinEvent" +NestedModules="Microsoft.PowerShell.Commands.Diagnostics.dll" +TypesToProcess="..\..\GetEvent.types.ps1xml" +FormatsToProcess="..\..\Event.format.ps1xml" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390783' +} \ No newline at end of file diff --git a/src/Modules/AppxProvider/AppxProvider.Resource.psd1 b/src/Modules/AppxProvider/AppxProvider.Resource.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..f9c68ab194864bd775cf6037292a3aac443c9365 GIT binary patch literal 5082 zcmdUzTW{M&5QX=-K>x!6eMk!=M$^7E5D+(QfBd5}sDSM{;ItL8FN60h z_r#s+iukM*p`QZkmqPZrd$ji&e^0gQwfjXfkmP%xK9V5ZNLKCM3Co2d4X&+ZFLX9@ zucRx*!4D$gWtErykM3LdkA5wxeXTDgua)hm`klK!_R@*rm5!~Bb%^53T`2QvNu0XF z%X+fwJ`2#ilk7J_7DUOMwen>qoGx{?4)?w60o_UxS&b#v`<=NCFSP2AtvAxnsz&R* z_HA^9JyBk*?8U;}0c61UgEWx!mHSP*-?_IT#tDm7HlVEu)=@itzou)`m9%g542!AB zm3HlPa1VT*h6qK(@S5{nzu#LBx!L$xnK0+Rf#;s=o@>9b%pw?X#ZMaLi17k95>AUhH=`dLBGJmTjpvSuf8;irfIRbP!W?AD6&e+2{M3iN7McG%=c^A;aLV8uMt2E(`<3rzs zYi?ynr777gV`c#L^MKMK@MbroA}6G-Ij5H1FG#I6W8s&k@ggp%E&T>Wz%* z&hs<9+r-R|9MQ$Z_Hr-nPO~Mb|DfYO&L3LS@9imr@`yz3{nhckD(Nk;6TP_PH8aD| zqGSQ@{<*iqY@-@2`mvu3t%jZL9WU1IQrEHXSdMnt`OsSc`VURc%-|*8PZV<|t@zKy z&+0b(pJ7~Ky_ffXIK?J{ytmqvpVs@(e~?${;Mb;-(p+!vsMrh_4s*l)C+hxl@<{)y G;Ke78gG2KG literal 0 HcmV?d00001 diff --git a/src/Modules/AppxProvider/AppxProvider.psd1 b/src/Modules/AppxProvider/AppxProvider.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..b9f746d7e634645f09759b74cbe8833e08f297f2 GIT binary patch literal 1222 zcmbu9YfBqZ5Qg8+h5m=&msHSLV~kXg8f`gnAZD`-;< zwTX}ASdP7Lj}+grMtP=9Vm{BmEb52O)zr7#XGb+{tIMj9BhtF>5&JrtI%gf}3-(x- zNL}ryimpcHI+0bhk+$ZT+T1@QCef*`IR~s_Y}<}2FlkVMDgI;PvMRLTa^)3B(RZ?&yKcZV#{Xi1dDJ6}%f>h0;>46m0^! z)GKw%9#f6L {1}" -f ($o, $options[$o]) ) + } + + if($options.ContainsKey('Source')) + { + $SourceNames = $($options['Source']) + Write-Verbose ($LocalizedData.SpecifiedSourceName -f ($SourceNames)) + foreach($sourceName in $SourceNames) + { + if($script:AppxPackageSources.Contains($sourceName)) + { + $Sources += $script:AppxPackageSources[$sourceName] + } + else + { + $sourceByLocation = Get-SourceName -Location $sourceName + if ($sourceByLocation -ne $null) + { + $Sources += $script:AppxPackageSources[$sourceByLocation] + } + else + { + $message = $LocalizedData.PackageSourceNotFound -f ($sourceName) + ThrowError -ExceptionName "System.ArgumentException" ` + -ExceptionMessage $message ` + -ErrorId "PackageSourceNotFound" ` + -CallerPSCmdlet $PSCmdlet ` + -ErrorCategory InvalidArgument ` + -ExceptionObject $sourceName + } + } + } + } + else + { + Write-Verbose $LocalizedData.NoSourceNameIsSpecified + $script:AppxPackageSources.Values | Microsoft.PowerShell.Core\ForEach-Object { $Sources += $_ } + } + + if($options.ContainsKey($script:Architecture)) + { + $Architecture = $options[$script:Architecture] + } + if($options.ContainsKey($script:ResourceId)) + { + $ResourceId = $options[$script:ResourceId] + } + } + + foreach($source in $Sources) + { + $location = $source.SourceLocation + if($request.IsCanceled) + { + return + } + if(-not(Test-Path $location)) + { + $message = $LocalizedData.PathNotFound -f ($Location) + Write-Verbose $message + continue + } + + $packages = Get-AppxPackagesFromPath -path $location + foreach($pkg in $packages) + { + if($request.IsCanceled) + { + return + } + + $pkgManifest = Get-PackageManfiestData -PackageFullPath $pkg.FullName + if(-not $pkgManifest) + { + continue + } + + # $pkgManifest.Name has to match any of the supplied names, using PowerShell wildcards + if(-not($namesParameterEmpty)) + { + if(-not(($names | Microsoft.PowerShell.Core\ForEach-Object { if ($pkgManifest.Name -like $_){return $true; break} } -End {return $false}))) + { + continue + } + } + + # Version + if($RequiredVersion) + { + if($RequiredVersion -ne $pkgManifest.Version) + { + continue + } + } + else + { + if(-not((-not $MinimumVersion -or ($MinimumVersion -le $pkgManifest.Version)) -and + (-not $MaximumVersion -or ($MaximumVersion -ge $pkgManifest.Version)))) + { + continue + } + } + + + if($Architecture) + { + $wildcardPattern = New-Object System.Management.Automation.WildcardPattern $Architecture, $script:wildcardOptions + if(-not($wildcardPattern.IsMatch($pkgManifest.Architecture))) + { + continue + } + } + + if($ResourceId) + { + $wildcardPattern = New-Object System.Management.Automation.WildcardPattern $ResourceId, $script:wildcardOptions + if(-not($wildcardPattern.IsMatch($pkgManifest.ResourceId))) + { + continue + } + } + + $sid = New-SoftwareIdentityFromPackage -Package $pkgManifest -Source $source.Name + $fastPackageReference = $sid.fastPackageReference + if($streamedResults -notcontains $fastPackageReference) + { + $streamedResults += $fastPackageReference + Write-Output -InputObject $sid + } + } + } +} + +function Get-InstalledPackage +{ + [CmdletBinding()] + param + ( + [Parameter()] + [string] + $Name, + + [Parameter()] + [string] + $RequiredVersion, + + [Parameter()] + [string] + $MinimumVersion, + + [Parameter()] + [string] + $MaximumVersion + ) + + Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Get-InstalledPackage')) + + $Architecture = $null + $ResourceId = $null + + $options = $request.Options + if($options) + { + if($options.ContainsKey($script:Architecture)) + { + $Architecture = $options[$script:Architecture] + } + if($options.ContainsKey($script:ResourceId)) + { + $ResourceId = $options[$script:ResourceId] + } + } + + $params = @{} + if($Name) + { + $params.Add("Name", $Name) + } + $packages = Appx\Get-AppxPackage @params + + foreach($package in $packages) + { + if($RequiredVersion) + { + if($RequiredVersion -ne $package.Version) + { + continue + } + } + else + { + if(-not((-not $MinimumVersion -or ($MinimumVersion -le $package.Version)) -and + (-not $MaximumVersion -or ($MaximumVersion -ge $package.Version)))) + { + continue + } + } + + if($Architecture) + { + $wildcardPattern = New-Object System.Management.Automation.WildcardPattern $Architecture, $script:wildcardOptions + if(-not($wildcardPattern.IsMatch($package.Architecture))) + { + continue + } + } + if($ResourceId) + { + $wildcardPattern = New-Object System.Management.Automation.WildcardPattern $ResourceId,$script:wildcardOptions + if(-not($wildcardPattern.IsMatch($package.ResourceId))) + { + continue + } + } + + $sid = New-SoftwareIdentityFromPackage -Package $package + write-Output $sid + } +} + +function Install-Package +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] + $fastPackageReference + ) + + Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Install-Package')) + Write-Debug -Message ($LocalizedData.FastPackageReference -f $fastPackageReference) + + Appx\Add-AppxPackage -Path $fastPackageReference +} + +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) + + Appx\Remove-AppxPackage -Package $fastPackageReference +} + +function Add-PackageSource +{ + [CmdletBinding()] + param + ( + [string] + $Name, + + [string] + $Location, + + [bool] + $Trusted + ) + + Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Add-PackageSource')) + + Set-PackageSourcesVariable -Force + + if(-not (Microsoft.PowerShell.Management\Test-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.PackageSourceNameContainsWildCards -f ($Name) + ThrowError -ExceptionName "System.ArgumentException" ` + -ExceptionMessage $message ` + -ErrorId "PackageSourceNameContainsWildCards" ` + -CallerPSCmdlet $PSCmdlet ` + -ErrorCategory InvalidArgument ` + -ExceptionObject $Name + } + + $LocationString = Get-ValidPackageLocation -LocationString $Location -ParameterName "Location" + + # Check if Location is already registered with another Name + $existingSourceName = Get-SourceName -Location $LocationString + + if($existingSourceName -and + ($Name -ne $existingSourceName)) + { + $message = $LocalizedData.PackageSourceAlreadyRegistered -f ($existingSourceName, $Location, $Name) + ThrowError -ExceptionName "System.ArgumentException" ` + -ExceptionMessage $message ` + -ErrorId "PackageSourceAlreadyRegistered" ` + -CallerPSCmdlet $PSCmdlet ` + -ErrorCategory InvalidArgument + } + + # Check if Name is already registered + if($script:AppxPackageSources.Contains($Name)) + { + $currentSourceObject = $script:AppxPackageSources[$Name] + $null = $script:AppxPackageSources.Remove($Name) + } + + # Add new package source + $packageSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ + Name = $Name + SourceLocation = $LocationString + Trusted=$Trusted + Registered= $true + }) + + $script:AppxPackageSources.Add($Name, $packageSource) + $message = $LocalizedData.SourceRegistered -f ($Name, $LocationString) + Write-Verbose $message + + # Persist the package sources + Save-PackageSources + + # return the package source object. + Write-Output -InputObject (New-PackageSourceFromSource -Source $packageSource) + +} + +function Resolve-PackageSource +{ + Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Resolve-PackageSource')) + + Set-PackageSourcesVariable + + $SourceName = $request.PackageSources + + if(-not $SourceName) + { + $SourceName = "*" + } + + foreach($src in $SourceName) + { + if($request.IsCanceled) + { + return + } + + $wildcardPattern = New-Object System.Management.Automation.WildcardPattern $src,$script:wildcardOptions + $sourceFound = $false + + $script:AppxPackageSources.GetEnumerator() | + Microsoft.PowerShell.Core\Where-Object {$wildcardPattern.IsMatch($_.Key)} | + Microsoft.PowerShell.Core\ForEach-Object { + $source = $script:AppxPackageSources[$_.Key] + $packageSource = New-PackageSourceFromSource -Source $source + Write-Output -InputObject $packageSource + $sourceFound = $true + } + + if(-not $sourceFound) + { + $sourceName = Get-SourceName -Location $src + if($sourceName) + { + $source = $script:AppxPackageSources[$sourceName] + $packageSource = New-PackageSourceFromSource -Source $source + Write-Output -InputObject $packageSource + } + elseif( -not (Test-WildcardPattern $src)) + { + $message = $LocalizedData.PackageSourceNotFound -f ($src) + Write-Error -Message $message -ErrorId "PackageSourceNotFound" -Category InvalidOperation -TargetObject $src + } + } + } +} + +function Remove-PackageSource +{ + param + ( + [string] + $Name + ) + + Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Remove-PackageSource')) + + Set-PackageSourcesVariable -Force + + $SourcesToBeRemoved = @() + + foreach ($sourceName in $Name) + { + if($request.IsCanceled) + { + return + } + + # Check if $Name contains any wildcards + if(Test-WildcardPattern $sourceName) + { + $message = $LocalizedData.PackageSourceNameContainsWildCards -f ($sourceName) + Write-Error -Message $message -ErrorId "PackageSourceNameContainsWildCards" -Category InvalidOperation -TargetObject $sourceName + continue + } + + # Check if the specified package source name is in the registered package sources + if(-not $script:AppxPackageSources.Contains($sourceName)) + { + $message = $LocalizedData.PackageSourceNotFound -f ($sourceName) + Write-Error -Message $message -ErrorId "PackageSourceNotFound" -Category InvalidOperation -TargetObject $sourceName + continue + } + + $SourcesToBeRemoved += $sourceName + $message = $LocalizedData.PackageSourceUnregistered -f ($sourceName) + Write-Verbose $message + } + + # Remove the SourcesToBeRemoved + $SourcesToBeRemoved | Microsoft.PowerShell.Core\ForEach-Object { $null = $script:AppxPackageSources.Remove($_) } + + # Persist the package sources + Save-PackageSources +} +#endregion + +#region Common functions + +function Get-AppxPackagesFromPath +{ + param + ( + [Parameter(Mandatory=$true)] + $Path + ) + + $filterAppxPackages = "*"+$script:AppxPackageExtension + $packages = Get-ChildItem -path $Path -filter $filterAppxPackages + + return $packages + +} + +function Get-PackageManfiestData +{ + param + ( + [Parameter(Mandatory=$true)] + $PackageFullPath + ) + $guid = [System.Guid]::NewGuid().toString() + try + { + [System.IO.Compression.ZipFile]::ExtractToDirectory($PackageFullPath, "$env:TEMP\$guid") + } + catch + { + Write-Verbose( $LocalizedData.MetaDataExtractionFailed -f ($PackageFullPath) ) + return $null + } + + [xml] $packageManifest = Get-Content "$env:TEMP\$guid\$script:AppxManifestFile" -ErrorAction SilentlyContinue + if($packageManifest) + { + $Identity = $packageManifest.Package.Identity + $manifestData = new-object psObject -Property @{Name=$Identity.Name; Architecture=$Identity.ProcessorArchitecture; Publisher=$Identity.Publisher; Version=$Identity.Version; ResourceId=$Identity.resourceId; PackageFullName=$PackageFullPath} + Remove-Item -Path "$env:TEMP\$guid" -Recurse -Force -ErrorAction SilentlyContinue + return $manifestData + } + else + { + Write-Verbose ($LocalizedData.MetaDataExtractionFailed -f ($PackageFullPath) ) + } + return $null +} + +function New-FastPackageReference +{ + param + ( + [Parameter(Mandatory=$true)] + [string] + $PackageFullName + ) + return "$PackageFullName" +} + +function New-SoftwareIdentityFromPackage +{ + param + ( + [Parameter(Mandatory=$true)] + $Package, + + [string] + $Source + + ) + + $fastPackageReference = New-FastPackageReference -PackageFullName $Package.PackageFullName + + if(-not($Source)) + { + $Source = $Package.Publisher + } + $details = @{ + Publisher = $Package.Publisher + Architecture = $Package.Architecture + ResourceId = $Package.ResourceId + PackageFullName = $Package.PackageFullName + } + + $params = @{ + FastPackageReference = $fastPackageReference; + Name = $Package.Name; + Version = $Package.Version; + versionScheme = "MultiPartNumeric"; + Source = $source; + Details = $details; + } + + $sid = New-SoftwareIdentity @params + return $sid +} + +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) +} + +function DeSerialize-PSObject +{ + [CmdletBinding(PositionalBinding=$false)] + Param + ( + [Parameter(Mandatory=$true)] + $Path + ) + $filecontent = Microsoft.PowerShell.Management\Get-Content -Path $Path + [System.Management.Automation.PSSerializer]::Deserialize($filecontent) +} + +function Get-SourceName +{ + [CmdletBinding()] + [OutputType("string")] + Param + ( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] + $Location + ) + + Set-PackageSourcesVariable + + foreach($source in $script:AppxPackageSources.Values) + { + if($source.SourceLocation -eq $Location) + { + return $source.Name + } + } +} + +function WebRequestApisAvailable +{ + $webRequestApiAvailable = $false + try + { + [System.Net.WebRequest] + $webRequestApiAvailable = $true + } + catch + { + } + return $webRequestApiAvailable +} + +function Ping-Endpoint +{ + param + ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [string[]] + $Endpoint + ) + + $results = @{} + + if(WebRequestApisAvailable) + { + $iss = [System.Management.Automation.Runspaces.InitialSessionState]::Create() + $iss.types.clear() + $iss.formats.clear() + $iss.LanguageMode = "FullLanguage" + + $WebRequestcmd = @' + try + {{ + $request = [System.Net.WebRequest]::Create("{0}") + $request.Method = 'GET' + $request.Timeout = 30000 + $response = [System.Net.HttpWebResponse]$request.GetResponse() + $response + $response.Close() + }} + catch [System.Net.WebException] + {{ + "Error:System.Net.WebException" + }} +'@ -f $EndPoint + + $ps = [powershell]::Create($iss).AddScript($WebRequestcmd) + $response = $ps.Invoke() + $ps.dispose() + + if ($response -ne "Error:System.Net.WebException") + { + $results.Add($Script:ResponseUri,$response.ResponseUri.ToString()) + $results.Add($Script:StatusCode,$response.StatusCode.value__) + } + } + else + { + $response = $null + try + { + $httpClient = New-Object 'System.Net.Http.HttpClient' + $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__) + } + } + return $results +} + +function Get-ValidPackageLocation +{ + [CmdletBinding()] + Param + ( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] + $LocationString, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] + $ParameterName + ) + + # Get the actual Uri from the Location + if(-not (Microsoft.PowerShell.Management\Test-Path $LocationString)) + { + $results = Ping-Endpoint -Endpoint $LocationString + + if ($results.ContainsKey("Exception")) + { + $Exception = $results["Exception"] + if($Exception) + { + $message = $LocalizedData.InvalidWebUri -f ($LocationString, $ParameterName) + ThrowError -ExceptionName "System.ArgumentException" ` + -ExceptionMessage $message ` + -ErrorId "InvalidWebUri" ` + -ExceptionObject $Exception ` + -CallerPSCmdlet $PSCmdlet ` + -ErrorCategory InvalidArgument + } + } + + if ($results.ContainsKey("ResponseUri")) + { + $LocationString = $results["ResponseUri"] + } + } + + return $LocationString +} + +function Set-PackageSourcesVariable +{ + param([switch]$Force) + + if(-not $script:AppxPackageSources -or $Force) + { + if(Microsoft.PowerShell.Management\Test-Path $script:AppxPackageSourcesFilePath) + { + $script:AppxPackageSources = DeSerialize-PSObject -Path $script:AppxPackageSourcesFilePath + } + else + { + $script:AppxPackageSources = [ordered]@{} + } + } +} + +function Save-PackageSources +{ + if($script:AppxPackageSources) + { + if(-not (Microsoft.PowerShell.Management\Test-Path $script:AppxLocalPath)) + { + $null = Microsoft.PowerShell.Management\New-Item -Path $script:AppxLocalPath ` + -ItemType Directory -Force ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue ` + -Confirm:$false -WhatIf:$false + } + Microsoft.PowerShell.Utility\Out-File -FilePath $script:AppxPackageSourcesFilePath -Force -InputObject ([System.Management.Automation.PSSerializer]::Serialize($script:AppxPackageSources)) + } +} + +function New-PackageSourceFromSource +{ + param + ( + [Parameter(Mandatory)] + $Source + ) + + # create a new package source + $src = New-PackageSource -Name $Source.Name ` + -Location $Source.SourceLocation ` + -Trusted $Source.Trusted ` + -Registered $Source.Registered ` + + Write-Verbose ( $LocalizedData.PackageSourceDetails -f ($src.Name, $src.Location, $src.IsTrusted, $src.IsRegistered) ) + + # return the package source object. + Write-Output -InputObject $src +} +#endregion + +# 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 + +Export-ModuleMember -Function Find-Package, ` + Install-Package, ` + Uninstall-Package, ` + Get-InstalledPackage, ` + Remove-PackageSource, ` + Resolve-PackageSource, ` + Add-PackageSource, ` + Get-DynamicOptions, ` + Initialize-Provider, ` + Get-PackageProviderName \ No newline at end of file diff --git a/src/Modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1 b/src/Modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..914f951df0fc7ca023e898d5f507f03564e11d25 GIT binary patch literal 5124 zcmd6r%WfM-5Jh`!ApbCc7urNboU8>zkz|;F6BCKzMRqhvi2}rjhm;jX@UJJir;DxX z;q*|Xokc+KF+JV&ymhOF|NQ+jRN-w{gi#oV+i(;93X?F_+G(h@Hr2`}t^BI@O1tjj zD!+SSsn2nE6}|~C;`>bZ=W%x(*5S2wF2XDvhu?HnOU^u8hjVFJ>s^H(!%;l-GVmH` z*W2(eoW-?4+%*lqNCJ}3JD08t$w6uzPQs;Zn@G-bv$vAG$M9YFtnW&9Zgi3zwXViG zgUywsAd&ljYR4-6MqU-K{5}?bl4K%6G_Lf0t5cQEJj8Po`R3Yt(e4XL#U5;J#;>on z_fPW9qcv;EoJZ?#WYt_TAU4xyeZ%g|DpX$#oqkJv$amo zrQ58{b765W#c-v}E%ibp=ZWP|za3e5Y_Hc^c#dFB!7r^i1IkbjTjTVezfR8lJDZlxy~Yq44A(BjN9&&VHMk*uWuy@M9riF zj&K=ePuh{QT>820xJ{G=qE*Qo`#z4m0Fqdx>T11by24K?+PpN|;0-F7y;h&Z5$mza zR;j5;xQ{!^2(>D2SB5c3UJ;jjBLR*vJH`>y9)CEt3cqjsP1ritisyQl=U=7Xqvt;r2kpn z>_YXhl>8=tm9Y)m(mfN~QrC9Yw9wsI0jn#$%+u?q>!0LFt*%UF*A2ex(wFyZuSM%F z$qJ%Dw27+g>M7P{)kW5E|67ajgNS>_+t;R3om(mn?I|F27_0`vF8k+AREP3%vRCvH za+-5b>WEZ|bz5V>RCl{4kA&+ckG7{LvNBRN-fbAQr>T)?!RD%_XK>h?=&Lcc@3pQz z%%WAYxb4w?K1`)IF@5sByT9BEUw86|?r0s=5t*hII0Ve5YPShutTX+X&6z$I9W%v= z*4atqt~YXQR!!CAy(ppNRPu6sW5-~_7blvO{RCEfHJQY|H2E}F=7=Qiu+G(mJTO0! zhgVP78%AEk=OzcIe5CmfiQC=V&|z$|P-fs%i=82Q7W2gnO<#an(YtF#w|;6Yv5TSI zzh><`hAtkiG&R_>M&9GP(KeO8aJ|Vd;jNUzZ7iJ2-}(s=r5x^>`E$h3l@8C|K6Uv2 z&uZC=@?3RTmeVu=&#z;?$$OfVnfNX9-f6~>vn}_D1<1P1m#fC}?`z32y!%9-b5>pt z&JBjtR42J+ude5wVVnb*p>1Mv9}}`oiq|Bks2`qb4xf3Sn>b;eN^_1q?c7TPF;5ki zo&oloL`zkJ^*?N^Z~JVxU{d*#h+4kEA?!u>EVH#ggBoALeMHiph4b8lh;H`D(O@hK z?vidhYm+Duv>oYblV^dUaLeuzN0qB-pfhm3dw@p%eF1gcOH-e7Z*FCK0!cZrN!{jj z?{>SqM;}j#Wh$++k%d$LH4e8T3-? X*uv!ar8;v2y1vrCY)ASJjv3}(wXc>j literal 0 HcmV?d00001 diff --git a/src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psd1 b/src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psd1 new file mode 100644 index 0000000000..859ea55124 --- /dev/null +++ b/src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psd1 @@ -0,0 +1,12 @@ +@{ +GUID="eb74e8da-9ae2-482a-a648-e96550fb8733" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="1.0.0.0" +FunctionsToExport = @('Compress-Archive', 'Expand-Archive') +CmdletsToExport = @() +AliasesToExport = @() +NestedModules="Microsoft.PowerShell.Archive.psm1" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?LinkId=393254' +} diff --git a/src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1 b/src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1 new file mode 100644 index 0000000000000000000000000000000000000000..b301646d6e2d70578f66a644f2a06ad5352fd9c3 GIT binary patch literal 105036 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 literal 0 HcmV?d00001 diff --git a/src/Modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1 b/src/Modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1 new file mode 100644 index 0000000000..9b3ecfc5f2 --- /dev/null +++ b/src/Modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1 @@ -0,0 +1,14 @@ +@{ +GUID="56D66100-99A0-4FFC-A12D-EEE9A6718AEF" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.0.0.0" +PowerShellVersion="3.0" +CLRVersion="4.0" +AliasesToExport = @() +FunctionsToExport = @() +CmdletsToExport="Start-Transcript", "Stop-Transcript" +NestedModules="Microsoft.PowerShell.ConsoleHost.dll" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390784' +} diff --git a/src/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1 b/src/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1 new file mode 100644 index 0000000000..425e64b78b --- /dev/null +++ b/src/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1 @@ -0,0 +1,99 @@ +@{ +GUID="EEFCB906-B326-4E99-9F54-8B4BB6EF3C6D" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.1.0.0" +PowerShellVersion="3.0" +CLRVersion="4.0" +NestedModules="Microsoft.PowerShell.Commands.Management.dll" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390785' +AliasesToExport = @("gcb", "scb") +FunctionsToExport = @() +CmdletsToExport=@("Add-Content", + "Clear-Content", + "Clear-ItemProperty", + "Join-Path", + "Convert-Path", + "Copy-ItemProperty", + "Get-EventLog", + "Clear-EventLog", + "Write-EventLog", + "Limit-EventLog", + "Show-EventLog", + "New-EventLog", + "Remove-EventLog", + "Get-ChildItem", + "Get-Content", + "Get-ItemProperty", + "Get-ItemPropertyValue", + "Get-WmiObject", + "Invoke-WmiMethod", + "Move-ItemProperty", + "Get-Location", + "Set-Location", + "Push-Location", + "Pop-Location", + "New-PSDrive", + "Remove-PSDrive", + "Get-PSDrive", + "Get-Item", + "New-Item", + "Set-Item", + "Remove-Item", + "Move-Item", + "Rename-Item", + "Copy-Item", + "Clear-Item", + "Invoke-Item", + "Get-PSProvider", + "New-ItemProperty", + "Split-Path", + "Test-Path", + "Get-Process", + "Stop-Process", + "Wait-Process", + "Debug-Process", + "Start-Process", + "Remove-ItemProperty", + "Remove-WmiObject", + "Rename-ItemProperty", + "Register-WmiEvent", + "Resolve-Path", + "Get-Service", + "Stop-Service", + "Start-Service", + "Suspend-Service", + "Resume-Service", + "Restart-Service", + "Set-Service", + "New-Service", + "Set-Content", + "Set-ItemProperty", + "Set-WmiInstance", + "Get-Transaction", + "Start-Transaction", + "Complete-Transaction", + "Undo-Transaction", + "Use-Transaction", + "New-WebServiceProxy", + "Get-HotFix", + "Test-Connection", + "Enable-ComputerRestore", + "Disable-ComputerRestore", + "Checkpoint-Computer", + "Get-ComputerRestorePoint", + "Restart-Computer", + "Stop-Computer", + "Restore-Computer", + "Add-Computer", + "Remove-Computer", + "Test-ComputerSecureChannel", + "Reset-ComputerMachinePassword", + "Rename-Computer", + "Get-ControlPanelItem", + "Show-ControlPanelItem", + "Clear-Recyclebin", + "Get-Clipboard", + "Set-Clipboard") +} diff --git a/src/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 b/src/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 new file mode 100644 index 0000000000..a5a678d7b8 --- /dev/null +++ b/src/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 @@ -0,0 +1,14 @@ +@{ +GUID="A94C8C7E-9810-47C0-B8AF-65089C13A35A" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.0.0.0" +PowerShellVersion="3.0" +CLRVersion="4.0" +AliasesToExport = @() +FunctionsToExport = @() +CmdletsToExport="Get-Acl", "Set-Acl", "Get-PfxCertificate", "Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "Get-AuthenticodeSignature", "Set-AuthenticodeSignature", "ConvertFrom-SecureString", "ConvertTo-SecureString", "Get-CmsMessage", "Unprotect-CmsMessage", "Protect-CmsMessage" , "New-FileCatalog" , "Test-FileCatalog" +NestedModules="Microsoft.PowerShell.Security.dll" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390786' +} diff --git a/src/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 b/src/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 new file mode 100644 index 0000000000..85eaf15336 --- /dev/null +++ b/src/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 @@ -0,0 +1,709 @@ +function Get-FileHash +{ + [CmdletBinding(DefaultParameterSetName = "Path", HelpURI = "http://go.microsoft.com/fwlink/?LinkId=517145")] + param( + [Parameter(Mandatory, ParameterSetName="Path", Position = 0)] + [System.String[]] + $Path, + + [Parameter(Mandatory, ParameterSetName="LiteralPath", ValueFromPipelineByPropertyName = $true)] + [Alias("PSPath")] + [System.String[]] + $LiteralPath, + + [Parameter(Mandatory, ParameterSetName="Stream")] + [System.IO.Stream] + $InputStream, + + [ValidateSet("SHA1", "SHA256", "SHA384", "SHA512", "MACTripleDES", "MD5", "RIPEMD160")] + [System.String] + $Algorithm="SHA256" + ) + + begin + { + # Construct the strongly-typed crypto object + + # First see if it has a FIPS algorithm + $hasherType = "System.Security.Cryptography.${Algorithm}CryptoServiceProvider" -as [Type] + if ($hasherType) + { + $hasher = $hasherType::New() + } + else + { + # Check if the type is supported in the current system + $algorithmType = "System.Security.Cryptography.${Algorithm}" -as [Type] + if ($algorithmType) + { + if ($Algorithm -eq "MACTripleDES") + { + $hasher = $algorithmType::New() + } + else + { + $hasher = $algorithmType::Create() + } + } + else + { + $errorId = "AlgorithmTypeNotSupported" + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::AlgorithmTypeNotSupported -f $Algorithm + $exception = [System.InvalidOperationException]::New($errorMessage) + $errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null) + $PSCmdlet.ThrowTerminatingError($errorRecord) + } + } + + function GetStreamHash + { + param( + [System.IO.Stream] + $InputStream, + + [System.String] + $RelatedPath, + + [System.Security.Cryptography.HashAlgorithm] + $Hasher) + + # Compute file-hash using the crypto object + [Byte[]] $computedHash = $Hasher.ComputeHash($InputStream) + [string] $hash = [BitConverter]::ToString($computedHash) -replace '-','' + + if ($RelatedPath -eq $null) + { + $retVal = [PSCustomObject] @{ + Algorithm = $Algorithm.ToUpperInvariant() + Hash = $hash + } + } + else + { + $retVal = [PSCustomObject] @{ + Algorithm = $Algorithm.ToUpperInvariant() + Hash = $hash + Path = $RelatedPath + } + } + $retVal.psobject.TypeNames.Insert(0, "Microsoft.Powershell.Utility.FileHash") + $retVal + } + } + + process + { + if($PSCmdlet.ParameterSetName -eq "Stream") + { + GetStreamHash -InputStream $InputStream -RelatedPath $null -Hasher $hasher + } + else + { + $pathsToProcess = @() + if($PSCmdlet.ParameterSetName -eq "LiteralPath") + { + $pathsToProcess += Resolve-Path -LiteralPath $LiteralPath | Foreach-Object ProviderPath + } + if($PSCmdlet.ParameterSetName -eq "Path") + { + $pathsToProcess += Resolve-Path $Path | Foreach-Object ProviderPath + } + + foreach($filePath in $pathsToProcess) + { + if(Test-Path -LiteralPath $filePath -PathType Container) + { + continue + } + + try + { + # Read the file specified in $FilePath as a Byte array + [system.io.stream]$stream = [system.io.file]::OpenRead($filePath) + GetStreamHash -InputStream $stream -RelatedPath $filePath -Hasher $hasher + } + catch [Exception] + { + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FileReadError -f $FilePath, $_ + Write-Error -Message $errorMessage -Category ReadError -ErrorId "FileReadError" -TargetObject $FilePath + return + } + finally + { + if($stream) + { + $stream.Dispose() + } + } + } + } + } +} + +<# This cmdlet is used to create a new temporary file in $env:temp #> +function New-TemporaryFile +{ + [CmdletBinding( + HelpURI='http://go.microsoft.com/fwlink/?LinkId=526726', + SupportsShouldProcess=$true)] + [OutputType([System.IO.FileInfo])] + Param() + + Begin + { + try + { + if($PSCmdlet.ShouldProcess($env:TEMP)) + { + $tempFilePath = [System.IO.Path]::GetTempFileName() + } + } + catch + { + $errorRecord = [System.Management.Automation.ErrorRecord]::new($_.Exception,"NewTemporaryFileWriteError", "WriteError", $env:TEMP) + Write-Error -ErrorRecord $errorRecord + return + } + + if($tempFilePath) + { + Get-Item $tempFilePath + } + } +} + +<# This cmdlet is used to generate a new guid #> +function New-Guid +{ + [CmdletBinding(HelpURI='http://go.microsoft.com/fwlink/?LinkId=526920')] + [OutputType([System.Guid])] + Param() + + Begin + { + [Guid]::NewGuid() + } +} + +<############################################################################################ +# Format-Hex cmdlet helps in displaying the Hexadecimal equivalent of the input data. +############################################################################################> +function Format-Hex +{ + [CmdletBinding( + DefaultParameterSetName="Path", + HelpUri="http://go.microsoft.com/fwlink/?LinkId=526919")] + [Alias("fhx")] + [OutputType("Microsoft.PowerShell.Commands.ByteCollection")] + param + ( + [Parameter (Mandatory=$true, Position=0, ParameterSetName="Path")] + [ValidateNotNullOrEmpty()] + [string[]] $Path, + + [Parameter (Mandatory=$true, ParameterSetName="LiteralPath")] + [ValidateNotNullOrEmpty()] + [Alias("PSPath")] + [string[]] $LiteralPath, + + [Parameter(Mandatory=$true, ParameterSetName="ByInputObject", ValueFromPipeline=$true)] + [Object] $InputObject, + + [Parameter (ParameterSetName="ByInputObject")] + [ValidateSet("Ascii", "UTF32", "UTF7", "UTF8", "BigEndianUnicode", "Unicode")] + [string] $Encoding = "Ascii", + + [Parameter(ParameterSetName="ByInputObject")] + [switch]$Raw + ) + + begin + { + $bufferSize = 16 + $inputStreamArray = [System.Collections.ArrayList]::New() + <############################################################################################ + # The ConvertToHexadecimalHelper is a helper method used to fetch unicode bytes from the + # input data and display the hexadecimial representaion of the of the input data in bytes. + ############################################################################################> + function ConvertToHexadecimalHelper + { + param + ( + [Byte[]] $inputBytes, + [string] $path, + [Uint32] $offset + ) + + # This section is used to display the hexadecimal + # representaion of the of the input data in bytes. + if($inputBytes -ne $null) + { + $byteCollectionObject = [Microsoft.PowerShell.Commands.ByteCollection]::new($offset, $inputBytes, $path) + Write-Output -InputObject $byteCollectionObject + } + } + + <############################################################################################ + # The ProcessFileContent is a helper method used to fetch file contents in blocks and + # process it to support displaying hexadecimal formating of the fetched content. + ############################################################################################> + function ProcessFileContent + { + param + ( + [string] $filePath, + [boolean] $isLiteralPath + ) + + if($isLiteralPath) + { + $resolvedPaths = Resolve-Path -LiteralPath $filePath + } + else + { + $resolvedPaths = Resolve-Path -Path $filePath + } + + # If Path resolution has failed then a corresponding non-terminating error is + # written to the pipeline. We continue processing any remaining files. + if($resolvedPaths -eq $null) + { + return + } + + if($resolvedPaths.Count -gt 1) + { + # write a non-terminating error message indicating that path specified is resolving to multiple file system paths. + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexResolvePathError -f $filePath + Write-Error -Message $errorMessage -Category ([System.Management.Automation.ErrorCategory]::InvalidData) -ErrorId "FormatHexResolvePathError" + } + + $targetFilePath = $resolvedPaths.ProviderPath + + + if($targetFilePath -ne $null) + { + $buffer = [byte[]]::new($bufferSize) + + try + { + try + { + $currentFileStream = [System.IO.File]::Open($targetFilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) + } + catch + { + # Failed to access the file. Write a non terminating error to the pipeline + # and move on with the remaining files. + $exception = $_.Exception + if($null -ne $_.Exception -and + $null -ne $_.Exception.InnerException) + { + $exception = $_.Exception.InnerException + } + + $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception,"FormatHexFileAccessError", ([System.Management.Automation.ErrorCategory]::ReadError), $targetFilePath) + $PSCmdlet.WriteError($errorRecord) + } + + if($null -ne $currentFileStream) + { + $srcStream = [System.IO.BinaryReader]::new($currentFileStream) + $displayHeader = $true + $offset = 0 + $blockCounter = 0 + while($numberOfBytesRead = $srcStream.Read($buffer, 0, $bufferSize)) + { + # send only the bytes that have been read + # if we send the whole buffer, we'll have extraneous bytes + # at the end of an incomplete group of 16 bytes + if ( $numberOfBytesRead -eq $bufferSize ) + { + # under some circumstances if we don't copy the buffer + # and the results are stored to a variable, the results are not + # correct and one object replicated in all the output objects + ConvertToHexadecimalHelper ($buffer.Clone()) $targetFilePath $offset + } + else + { + # handle the case of the partial (and probably last) buffer + $bytesReadBuffer = [byte[]]::New($numberOfBytesRead) + [Array]::Copy($buffer,0, $bytesReadBuffer,0,$numberOfBytesRead) + ConvertToHexadecimalHelper $bytesReadBuffer $targetFilePath $offset + } + $displayHeader = $false + $blockCounter++; + + # Updating the offset value. + $offset = $blockCounter*0x10 + } + } + } + finally + { + If($null -ne $currentFileStream) + { + $currentFileStream.Dispose() + } + If($null -ne $srcStream) + { + $srcStream.Dispose() + } + } + } + } + } + + process + { + switch($PSCmdlet.ParameterSetName) + { + "Path" + { + ProcessFileContent $Path $false + } + "LiteralPath" + { + ProcessFileContent $LiteralPath $true + } + "ByInputObject" + { + # If it's an actual byte array, then we directly use it for hexadecimal formatting. + if($InputObject -is [Byte[]]) + { + ConvertToHexadecimalHelper $InputObject $null + return + } + # if it's a single byte, we'll assume streaming + elseif($InputObject -is [byte]) + { + $null = $inputStreamArray.Add($InputObject) + } + # If the input data is of string type then directly get bytes out of it. + elseif($InputObject -is [string]) + { + # The ValidateSet arribute on the Encoding paramter makes sure that only + # valid values (supported on all paltforms where Format-Hex is avaliable) + # are allowed through user input. + $inputBytes = [Text.Encoding]::$Encoding.GetBytes($InputObject) + ConvertToHexadecimalHelper $inputBytes $null + return + } + elseif($InputObject -is [System.IO.FileSystemInfo]) + { + # If file path is provided as an input, use the file contents to show the hexadecimal format. + $filePath = ([System.IO.FileSystemInfo]$InputObject).FullName + ProcessFileContent $filePath $false + return + } + elseif($InputObject -is [int64]) + { + $inputBytes = [BitConverter]::GetBytes($InputObject) + $null = $inputStreamArray.AddRange($inputBytes) + } + elseif($InputObject -is [int64[]]) + { + foreach($i64 in $InputObject) + { + $inputBytes = [BitConverter]::GetBytes($i64) + $null = $inputStreamArray.AddRange($inputBytes) + } + } + elseif($InputObject -is [int]) + { + # If we get what appears as ints, it may not be what the user really wants. + # for example, if the user types a small set of numbers just to get their + # character representations, as follows: + # + # 170..180 | format-hex + # Path: + # 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F + #00000000 AA AB AC AD AE AF B0 B1 B2 B3 B4 ª«¬­®¯°±²³´ + # + # any integer padding is likely to be more confusing than this + # fairly compact representation. + # + # However, some might like to see the results with the raw data, + # -Raw exists to provide that behavior: + # PS# 170..180 | format-hex -Raw + # + # Path: + # + # 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F + # + # 00000000 AA 00 00 00 AB 00 00 00 AC 00 00 00 AD 00 00 00 ª...«...¬...­... + # 00000010 AE 00 00 00 AF 00 00 00 B0 00 00 00 B1 00 00 00 ®...¯...°...±... + # 00000020 B2 00 00 00 B3 00 00 00 B4 00 00 00 ²...³...´... + # + # this provides a representation of the piped numbers which includes all + # of the bytes which are in an int32 + if ( $Raw ) + { + $inputBytes = [BitConverter]::GetBytes($InputObject) + $null = $inputStreamArray.AddRange($inputBytes) + } + else + { + # first determine whether we can represent this as a byte + $possibleByte = $InputObject -as [byte] + # first determine whether we can represent this as a int16 + $possibleInt16 = $InputObject -as [int16] + if ( $possibleByte -ne $null ) + { + $null = $inputStreamArray.Add($possibleByte) + } + elseif ( $possibleint16 -ne $null ) + { + $inputBytes = [BitConverter]::GetBytes($possibleInt16) + $null = $inputStreamArray.AddRange($inputBytes) + } + else + { + # now int + $inputBytes = [BitConverter]::GetBytes($InputObject) + $null = $inputStreamArray.AddRange($inputBytes) + } + } + } + else + { + # Otherwise, write a non-terminating error message indicating that input object type is not supported. + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexTypeNotSupported -f $InputObject.GetType() + Write-Error -Message $errorMessage -Category ([System.Management.Automation.ErrorCategory]::ParserError) -ErrorId "FormatHexFailureTypeNotSupported" + } + # Handle streaming case here + # during this process we may not have enough characters to create a ByteCollection + # if we do, create as many ByteCollections as necessary, each being 16 bytes in length + if ( $inputStreamArray.Count -ge $bufferSize ) + { + $rowCount = [math]::Floor($inputStreamArray.Count/$bufferSize) + $arrayLength = $bufferSize * $rowCount + for($i = 0; $i -lt $rowCount; $i++) + { + $rowOffset = $i * $bufferSize + ConvertToHexadecimalHelper -inputBytes $inputStreamArray.GetRange($rowOffset, $bufferSize) -path ' ' -offset $offset + $offset += $bufferSize + } + # We use RemoveRange because of the pathological case of having + # streamed combination of bytes, int16, int32, int64 which are greater + # than 16 bytes. Consider the case: + # $i = [int16]::MaxValue + 3 + # $i64=[int64]::MaxValue -5 + # .{ $i;$i;$i;$i64 } | format-hex + # which create an arraylist 20 bytes + # we need to remove only the bytes from the array which we emitted + $inputStreamArray.RemoveRange(0,$arrayLength) + } + } + } + } + end + { + # now manage any left over bytes in the $inputStreamArray + if ( $PSCmdlet.ParameterSetName -eq "ByInputObject" ) + { + ConvertToHexadecimalHelper $inputStreamArray $null -path ' ' -offset $offset + } + } + +} + +## Imports a PowerShell Data File - a PowerShell hashtable defined in +## a file (such as a Module manifest, session configuration file) +function Import-PowerShellDataFile +{ + [CmdletBinding(DefaultParameterSetName = "ByPath", HelpUri = "http://go.microsoft.com/fwlink/?LinkID=623621")] + [OutputType("System.Collections.Hashtable")] + param( + [Parameter(ParameterSetName = "ByPath", Position = 0)] + [String[]] $Path, + + [Parameter(ParameterSetName = "ByLiteralPath", ValueFromPipelineByPropertyName = $true)] + [Alias("PSPath")] + [String[]] $LiteralPath + ) + + begin + { + function ThrowInvalidDataFile + { + param($resolvedPath, $extraError) + + $errorId = "CouldNotParseAsPowerShellDataFile$extraError" + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidData + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::CouldNotParseAsPowerShellDataFile -f $resolvedPath + $exception = [System.InvalidOperationException]::New($errorMessage) + $errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null) + $PSCmdlet.WriteError($errorRecord) + } + } + + process + { + foreach($resolvedPath in (Resolve-Path @PSBoundParameters)) + { + $parseErrors = $null + $ast = [System.Management.Automation.Language.Parser]::ParseFile(($resolvedPath.ProviderPath), [ref] $null, [ref] $parseErrors) + if ($parseErrors.Length -gt 0) + { + ThrowInvalidDataFile $resolvedPath + } + else + { + $data = $ast.Find( { $args[0] -is [System.Management.Automation.Language.HashtableAst] }, $false ) + if($data) + { + $data.SafeGetValue() + } + else + { + ThrowInvalidDataFile $resolvedPath "NoHashtableRoot" + } + } + } + } +} + +## Converts a SDDL string into an object-based representation of a security +## descriptor +function ConvertFrom-SddlString +{ + [CmdletBinding(HelpUri = "http://go.microsoft.com/fwlink/?LinkId=623636")] + param( + ## The string representing the security descriptor in SDDL syntax + [Parameter(Mandatory, Position = 0)] + [String] $Sddl, + + ## The type of rights that this SDDL string represents, if any. + [Parameter()] + [ValidateSet( + "FileSystemRights", "RegistryRights", "ActiveDirectoryRights", + "MutexRights", "SemaphoreRights", "CryptoKeyRights", + "EventWaitHandleRights")] + $Type + ) + + ## Translates a SID into a NT Account + function ConvertTo-NtAccount + { + param($Sid) + + if($Sid) + { + $securityIdentifier = [System.Security.Principal.SecurityIdentifier] $Sid + + try + { + $ntAccount = $securityIdentifier.Translate([System.Security.Principal.NTAccount]).ToString() + } + catch{} + + $ntAccount + } + } + + ## Gets the access rights that apply to an access mask, preferring right types + ## of 'Type' if specified. + function Get-AccessRights + { + param($AccessMask, $Type) + + ## All the types of access rights understood by .NET + $rightTypes = [Ordered] @{ + "FileSystemRights" = [System.Security.AccessControl.FileSystemRights] + "RegistryRights" = [System.Security.AccessControl.RegistryRights] + "ActiveDirectoryRights" = [System.DirectoryServices.ActiveDirectoryRights] + "MutexRights" = [System.Security.AccessControl.MutexRights] + "SemaphoreRights" = [System.Security.AccessControl.SemaphoreRights] + "CryptoKeyRights" = [System.Security.AccessControl.CryptoKeyRights] + "EventWaitHandleRights" = [System.Security.AccessControl.EventWaitHandleRights] + } + $typesToExamine = $rightTypes.Values + + ## If they know the access mask represents a certain type, prefer its names + ## (i.e.: CreateLink for the registry over CreateDirectories for the filesystem) + if($Type) + { + $typesToExamine = @($rightTypes[$Type]) + $typesToExamine + } + + + ## Stores the access types we've found that apply + $foundAccess = @() + + ## Store the access types we've already seen, so that we don't report access + ## flags that are essentially duplicate. Many of the access values in the different + ## enumerations have the same value but with different names. + $foundValues = @{} + + ## Go through the entries in the different right types, and see if they apply to the + ## provided access mask. If they do, then add that to the result. + foreach($rightType in $typesToExamine) + { + foreach($accessFlag in [Enum]::GetNames($rightType)) + { + $longKeyValue = [long] $rightType::$accessFlag + if(-not $foundValues.ContainsKey($longKeyValue)) + { + $foundValues[$longKeyValue] = $true + if(($AccessMask -band $longKeyValue) -eq ($longKeyValue)) + { + $foundAccess += $accessFlag + } + } + } + } + + $foundAccess | Sort-Object + } + + ## Converts an ACE into a string representation + function ConvertTo-AceString + { + param( + [Parameter(ValueFromPipeline)] + $Ace, + $Type + ) + + process + { + foreach($aceEntry in $Ace) + { + $AceString = (ConvertTo-NtAccount $aceEntry.SecurityIdentifier) + ": " + $aceEntry.AceQualifier + if($aceEntry.AceFlags -ne "None") + { + $AceString += " " + $aceEntry.AceFlags + } + + if($aceEntry.AccessMask) + { + $foundAccess = Get-AccessRights $aceEntry.AccessMask $Type + + if($foundAccess) + { + $AceString += " ({0})" -f ($foundAccess -join ", ") + } + } + + $AceString + } + } + } + + $rawSecurityDescriptor = [Security.AccessControl.CommonSecurityDescriptor]::new($false,$false,$Sddl) + + $owner = ConvertTo-NtAccount $rawSecurityDescriptor.Owner + $group = ConvertTo-NtAccount $rawSecurityDescriptor.Group + $discretionaryAcl = ConvertTo-AceString $rawSecurityDescriptor.DiscretionaryAcl $Type + $systemAcl = ConvertTo-AceString $rawSecurityDescriptor.SystemAcl $Type + + [PSCustomObject] @{ + Owner = $owner + Group = $group + DiscretionaryAcl = @($discretionaryAcl) + SystemAcl = @($systemAcl) + RawDescriptor = $rawSecurityDescriptor + } +} diff --git a/src/Modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1 b/src/Modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1 new file mode 100644 index 0000000000..972d368861 --- /dev/null +++ b/src/Modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1 @@ -0,0 +1,15 @@ +@{ +GUID="766204A6-330E-4263-A7AB-46C87AFC366C" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.0.0.0" +PowerShellVersion="3.0" +CLRVersion="4.0" +AliasesToExport = @() +FunctionsToExport = @() +CmdletsToExport="Disable-WSManCredSSP", "Enable-WSManCredSSP", "Get-WSManCredSSP", "Set-WSManQuickConfig", "Test-WSMan", "Invoke-WSManAction", "Connect-WSMan", "Disconnect-WSMan", "Get-WSManInstance", "Set-WSManInstance", "Remove-WSManInstance", "New-WSManInstance", "New-WSManSessionOption" +NestedModules="Microsoft.WSMan.Management.dll" +FormatsToProcess="WSMan.format.ps1xml" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390788' +} diff --git a/src/Modules/PSDiagnostics/PSDiagnostics.psd1 b/src/Modules/PSDiagnostics/PSDiagnostics.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..3d73330c0a96c15203b362028fe12f57c9f6c791 GIT binary patch literal 1214 zcmbu9*-pY>5QWdRiSIzX(nN?TiZ>(>Tw)@Ih|6__f=$>$>lWh!`I724BZ@7qF-_Z_ znK?6O=1h5hs_I^gT2O9!?dwzr+EGPIYHLeHb$G6;tZn7B#wpMSr;_{37AVA0_R}W* z5{MF!0k$ru5}B7$HEOz2qDzf5@j4Af)SB=+=I-LlsqWsfKLacgr(q_K#SAp2(olCg z;yr+iG5=4-F}Wtx>%lPbY>)8yeZ~UOHTAi2AM(WhE2P5^>ow1g3YmTy^wVKBeY|HL z7f<`Po{Ge;z2E7HHbLGvq6O>FtIuaxcXS$A*P)I-srDLM&?Ys@u74W$k?RT7o33A* z+A){$ZK}l{MX1t4AJf)UZ1XOlS&UZ2O#e1Di?6utoeG@gYl1Hbm95)-qQ(e0+1p8)h}Ys>AgYJ(D!%%KH_Ye|Ad|) zvyr=G_@2pp#4OwExAHZQG7Kgm3*2ReDp^$Jk7vh<7}lO6%8g30)aFKR25e P))D%rJ@#+);2ZD)XDGiD literal 0 HcmV?d00001 diff --git a/src/Modules/PSDiagnostics/PSDiagnostics.psm1 b/src/Modules/PSDiagnostics/PSDiagnostics.psm1 new file mode 100644 index 0000000000000000000000000000000000000000..d36168f27d69af230b08b017761397df82fd8b03 GIT binary patch literal 23122 zcmeHPX>S|J5$&%IkpIAyh(LyyvUS_uI9S_~6C;*wSjOgq)>w!XB`a$kktoZX&HnWy z?{%@%$J8{35_LET2x^AYN8Qy`)jj&pzyIi_-S6G+TnnGSxjlE_w%wsSb0_%y*5CEr zvDAT=OKCx@T=#0ujBW&J4K)V`Hb%|ZqK*wN3AW4IK=n?<{?DF z+QRn)BL}!1x*hyI1Kcflgby)bYY*2w{2urb1I)dJd&RzwnYLWl!n$6*)0iA$9WI={t@*&+04_a}eHzU>6l$LY$TCx=0K2?QClgPAFZ79h69f+;g8 zXZo0Tc8Es_@)0OF1Wl8Jt26FFrzn5oF#rb!MGjEDC;03E8_H6s7n+1KHWf#Hlr{D( zbpQQOPwKeO(K)`<#eHByiLV16>Mretx;=26%+@-lt=YH=HFfZm<|Z)3-roT~8`2@D z60Yg2_uZSJJ<{@o%UkGUkEh17^%vi_H=K(cx$mB4ZT1Y5eHV7Sn~YsOe`=39L;GjI zJoRutjcIlH=(6RV0J9@dNl&tWu5o;7<3>uV{rOb-(}U~)^8;v%a<~N@q^~^2-%g~B z?ECAv|Dy+gdydIW@_aLDp^v3S%|Pyy&^G?kKORF)PvD(s`={vfZ88IAuYTwgX>E$> z6ZgQ~bsvnL@mTe!e71@4gh)@gi;;0#8+6Au`5KtgroKI&KkjYQSjBM8W0;OC;qb=m z(UJfA0(jD|lFwX!QXVzMV17&t-hw~$uIdXff(50L(!AlZo5DNlL%=`XIn$G}0KGM4y!{);Pp_;up`;q4@c*>*3y{&EEz zTo7wwHmLA{Ui82{gY0+kk#&eV-bC&>mYaSq3&s}KwH(I0TXM@2g%d;A051OoJugAs zUjbYEJLyt8O?4&smEb+bqwf_YvK`X#VukBJ>brDK5j`pq0+%< zi*ZxW+b>52Z=xh5WdG#7&pwIT8D=lce+EGf4_OkKS)-vArz%j;k zEvyHW$O-N(Onx(;T0H~KC4WbF2Y^T}9e|_E2(Feo#_erH9bC(8A3QnANBP<7r~b%m zQXA_{c?Fmp4`NSx{q)jqQg1#v$}C?VD16{;iBS+SU}Tj0v=)u1u+B{Dx{LQ=%eXOCh#gp2+sI_ETq%2n(HeLP`Ae=U@rNCy(LyC6 ziYZbY^g0?EBSLB%HUA=z?8u8X)Ds^+DJF8YaJ?RWS&$XC$#BVnka8z@2lg%bfi*;( zTH|F6ZDUx&2o*Zcka8}DKMi?G)%6&agt%o2qaL_LIsky_ZlHQyJ6Git#SyjoZnE9&jhE%b=+biaPkU1iF?y7ka>z zTW%|b7+TfOud0v$bz>B%6!pF ze*wK%86h_oLHCO10lBf@@0QS?x

|(MnEszY=b|MBcTI8VT3K&xz)c7t7u%wsBqY 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 HXUgiom*a%< literal 0 HcmV?d00001 diff --git a/src/Modules/PSGet/PSGet.Format.ps1xml b/src/Modules/PSGet/PSGet.Format.ps1xml new file mode 100644 index 0000000000..54ff00a1fe --- /dev/null +++ b/src/Modules/PSGet/PSGet.Format.ps1xml @@ -0,0 +1,202 @@ + + + + + PSRepositoryItemInfo + + Microsoft.PowerShell.Commands.PSRepositoryItemInfo + + + + + 10 + + + 35 + + + 10 + + + 20 + + + + + + + + Version + + + Name + + + Type + + + Repository + + + Description + + + + + + + + PSRepository + + Microsoft.PowerShell.Commands.PSRepository + + + + + 25 + + + 25 + + + 20 + + + + + + + + Name + + + PackageManagementProvider + + + InstallationPolicy + + + SourceLocation + + + + + + + + PSScriptInfo + + Microsoft.PowerShell.Commands.PSScriptInfo + + + + + 10 + + + 25 + + + 20 + + + + + + + + Version + + + Name + + + Author + + + Description + + + + + + + + PSGetDscResourceInfo + + Microsoft.PowerShell.Commands.PSGetCommandInfo + Microsoft.PowerShell.Commands.PSGetDscResourceInfo + + + + + 35 + + + 10 + + + 35 + + + + + + + + Name + + + Version + + + ModuleName + + + Repository + + + + + + + + PSGetRoleCapabilityInfo + + Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo + + + + + 35 + + + 10 + + + 35 + + + + + + + + Name + + + Version + + + ModuleName + + + Repository + + + + + + + + diff --git a/src/Modules/PSGet/PSGet.Resource.psd1 b/src/Modules/PSGet/PSGet.Resource.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..5177bec6b84b495f13b5c0b5aa366aba6e0eaa08 GIT binary patch literal 69704 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 literal 0 HcmV?d00001 diff --git a/src/Modules/PSGet/PSGet.psd1 b/src/Modules/PSGet/PSGet.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..9fa416ac9861be505c0c091165e7c53e57178224 GIT binary patch literal 3940 zcmcJS+fEZv6o%KeiSIyqQ#DeoMHCGY0)kD1G?sE-+EOO=WEl>|@Ibz#`u%%%+UY<~ z(~`-Y_x|@f{A=yC{{7vx-}c;|*>~%5gm%oeZr9ebhOOBSXVywq9{ZlNo?Thn^8C}> z_?$E5_4yls(-|V13d*~3_B~tWo_Yu~WduyPX?0>_xj=jAeCG@y; z-^;AqaC0B`Q^EPj&pLEAX`^)r>M3s}XS*5*R~(V_V#g8RLgvQjc$Vbt4y&~Wk{sfd z4nBzN>~X&^#(N;L$*#R%Mv<{sjIBC}*T;C4wbzb&YsfM0kwv}$%sT9eb2c4T8M$QV zRbW-nzwRu(8oUyAKF4YS_PcyU!nG8(^FCfrctt#0-j)@-BF{XPw|yjw%ksYboyGzq z_8cH-jhv}S=wj*9DwS$ITNE zZl45sG8a}OdE`g!eaZsby;Spr-216xwG5IhJq>jcPAtwL>C!|G zDT9FsnB6J;gj#<6=n39og5Qb=RqQjWpsX zS_Y1X<8B-Xr5L6S^YuBG3(RV?D1+_7|D+4e!xZ5 z*a3B=s_q8ek?vLUyE=uaSDTdsGIL1iYxx`2sogQJOrIoO}< o5p(!jec%QWdF$f7gYP%&vneX{T*QVubfw#zZ|Py94%f@@AMc3rW&i*H literal 0 HcmV?d00001 diff --git a/src/Modules/PSGet/PSModule.psm1 b/src/Modules/PSGet/PSModule.psm1 new file mode 100644 index 0000000000..6ddcc4db7e --- /dev/null +++ b/src/Modules/PSGet/PSModule.psm1 @@ -0,0 +1,13064 @@ + +######################################################################################### +# +# 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: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 = $Message -creplace "packagesource", "psrepository" + $tempMessage = $Message -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 = $Message -creplace "packagesource", "psrepository" + $tempMessage = $Message -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 + +# 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" + ) + +$source = @" +using System; +using System.Management.Automation; + +namespace Microsoft.PowerShell.Get +{ + 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 }); + } + + } +} +"@ + +# Telemetry is turned off by default. +$script:TelemetryEnabled = $false + +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()] + [ValidateSet("1.0")] + [Version] + $FormatVersion, + + [Parameter()] + [string[]] + $ReleaseNotes, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string[]] + $Tags, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $LicenseUri, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $IconUri, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $ProjectUri + ) + + 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 + } + + 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 + } + + # 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 -Name $moduleName ` + -Repository $Repository ` + -Tag 'PSScript' ` + -Verbose:$VerbosePreference ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue ` + -Debug:$DebugPreference | + 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 + } + + $currentPSGetItemInfo = Find-Module -Name $moduleInfo.Name ` + -Repository $Repository ` + -Verbose:$VerbosePreference ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue ` + -Debug:$DebugPreference | + Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $moduleInfo.Name} | + Microsoft.PowerShell.Utility\Select-Object -Last 1 + + if($currentPSGetItemInfo -and $currentPSGetItemInfo.Version -ge $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($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()] + [ValidateNotNullOrEmpty()] + [string[]] + $Repository + ) + + Begin + { + Get-PSGalleryApiAvailability -Repository $Repository + + Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet + } + + 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()] + [switch] + $Force + ) + + Begin + { + Get-PSGalleryApiAvailability -Repository $Repository + + Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet + + # 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()] + [ValidateSet("CurrentUser","AllUsers")] + [string] + $Scope = "AllUsers", + + [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 + + # 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()] + [Switch] + $Force + ) + + Begin + { + Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet + + # 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] + $RequiredVersion, + + [Parameter()] + [switch] + $AllVersions, + + [Parameter()] + [ValidateNotNull()] + [string[]] + $Tag, + + [Parameter()] + [ValidateNotNull()] + [string] + $Filter, + + [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] + $RequiredVersion, + + [Parameter()] + [switch] + $AllVersions, + + [Parameter()] + [ValidateNotNull()] + [string[]] + $Tag, + + [Parameter()] + [ValidateNotNull()] + [string] + $Filter, + + [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] + $RequiredVersion, + + [Parameter()] + [switch] + $AllVersions, + + [Parameter()] + [ValidateNotNull()] + [string[]] + $Tag, + + [Parameter()] + [ValidateNotNull()] + [string] + $Filter, + + [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 + ) + + 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 + } + + 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 + { + # 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 -Name $scriptName ` + -Repository $Repository ` + -Tag 'PSModule' ` + -Verbose:$VerbosePreference ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue ` + -Debug:$DebugPreference | + 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 + } + + $currentPSGetItemInfo = $null + $currentPSGetItemInfo = Find-Script -Name $scriptName ` + -Repository $Repository ` + -Verbose:$VerbosePreference ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue ` + -Debug:$DebugPreference | + Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $scriptName} | + Microsoft.PowerShell.Utility\Select-Object -Last 1 + + if($currentPSGetItemInfo -and $currentPSGetItemInfo.Version -ge $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($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()] + [ValidateNotNullOrEmpty()] + [string[]] + $Repository + ) + + Begin + { + Get-PSGalleryApiAvailability -Repository $Repository + + Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet + } + + 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()] + [switch] + $Force + ) + + Begin + { + Get-PSGalleryApiAvailability -Repository $Repository + + Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet + + # 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()] + [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 + + # 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()] + [Switch] + $Force + ) + + Begin + { + Install-NuGetClientBinaries -CallerPSCmdlet $PSCmdlet + + # 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(PositionalBinding=$false, + HelpUri='http://go.microsoft.com/fwlink/?LinkID=517129')] + Param + ( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] + $Name, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [Uri] + $SourceLocation, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $PublishLocation, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $ScriptSourceLocation, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $ScriptPublishLocation, + + [Parameter()] + [ValidateSet('Trusted','Untrusted')] + [string] + $InstallationPolicy = 'Untrusted', + + [Parameter()] + [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 + + 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 + $SourceLocation = Resolve-Location -Location (Get-LocationString -LocationUri $SourceLocation) ` + -LocationParameterName 'SourceLocation' ` + -CallerPSCmdlet $PSCmdlet + if(-not $SourceLocation) + { + # Above Resolve-Location function throws an error when it is not able to resolve a location + return + } + + if($InstallationPolicy -eq "Trusted") + { + $PSBoundParameters.Add("Trusted", $true) + } + + $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["Provider"] = $script:PSModuleProviderName + + $PSBoundParameters["Location"] = Get-LocationString -LocationUri $SourceLocation + $null = $PSBoundParameters.Remove("SourceLocation") + $null = $PSBoundParameters.Remove("InstallationPolicy") + + $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)] + [ValidateNotNullOrEmpty()] + [string] + $Name, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $SourceLocation, + + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $PublishLocation, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $ScriptSourceLocation, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Uri] + $ScriptPublishLocation, + + [Parameter()] + [ValidateSet('Trusted','Untrusted')] + [string] + $InstallationPolicy, + + [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 + + 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' ` + -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 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 + if(Get-Command Microsoft.PowerShell.Management\Test-Connection -ErrorAction SilentlyContinue) + { + $connected = Microsoft.PowerShell.Management\Test-Connection -ComputerName "www.microsoft.com" -Count 1 -Quiet + } + else + { + $connected = NetTCPIP\Test-NetConnection -ComputerName "www.microsoft.com" -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 +{ + param + ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] + $Endpoint, + + [Parameter()] + [switch] + $AllowAutoRedirect = $true + ) + + $results = @{} + + if(HttpClientApisAvailable) + { + $response = $null + try + { + $handler = New-Object System.Net.Http.HttpClientHandler + $handler.UseDefaultCredentials = $true + $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 = @' + try + {{ + $request = [System.Net.WebRequest]::Create("{0}") + $request.Method = 'GET' + $request.Timeout = 30000 + $request.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials + $request.AllowAutoRedirect = ${1} + $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) + $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-ModuleSourcesVariable +{ + [CmdletBinding()] + param([switch]$Force) + + 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)) + { + $isPersistRequired = $true + $psgalleryLocation = Resolve-Location -Location $Script:PSGallerySourceUri ` + -LocationParameterName 'SourceLocation' ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue + + $scriptSourceLocation = Resolve-Location -Location $Script:PSGalleryScriptSourceUri ` + -LocationParameterName 'ScriptSourceLocation' ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue + if($psgalleryLocation) + { + $result = Ping-Endpoint -Endpoint $Script:PSGalleryPublishUri -AllowAutoRedirect:$false + if ($result.ContainsKey($Script:ResponseUri) -and $result[$Script:ResponseUri]) + { + $script:PSGalleryPublishUri = $result[$Script:ResponseUri] + } + $moduleSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ + Name = $Script:PSGalleryModuleSource + SourceLocation = $psgalleryLocation + PublishLocation = $Script:PSGalleryPublishUri + ScriptSourceLocation = $scriptSourceLocation + ScriptPublishLocation = $Script:PSGalleryPublishUri + Trusted=$false + Registered=$true + InstallationPolicy = 'Untrusted' + PackageManagementProvider=$script:NuGetProviderName + ProviderOptions = @{} + }) + + $moduleSource.PSTypeNames.Insert(0, "Microsoft.PowerShell.Commands.PSRepository") + $script:PSGetModuleSources.Add($Script:PSGalleryModuleSource, $moduleSource) + } + } + } + + # 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 + + 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()] + [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 + } + + 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 + + # 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 + + 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 using Import-LocalizedData cmdlet + # to get the RequiredVersion details. + Import-LocalizedData -BindingVariable ModuleManifestHashTable ` + -FileName (Microsoft.PowerShell.Management\Split-Path $PSModuleInfo.Path -Leaf) ` + -BaseDirectory $PSModuleInfo.ModuleBase ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue + + 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" + + Import-LocalizedData -BindingVariable ModuleManifestHashTable ` + -FileName (Microsoft.PowerShell.Management\Split-Path $ManifestPath -Leaf) ` + -BaseDirectory (Microsoft.PowerShell.Management\Split-Path $ManifestPath -Parent) ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue + + + 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 += "" + } + + # Populate the nuspec elements + $nuspec = @" + + + + $(Get-EscapedString -ElementValue "$Name") + $($Version) + $(Get-EscapedString -ElementValue "$Author") + $(Get-EscapedString -ElementValue "$CompanyName") + $(Get-EscapedString -ElementValue "$Description") + $(Get-EscapedString -ElementValue "$ReleaseNotes") + $(Get-EscapedString -ElementValue "$Copyright") + $(if($Tags){ Get-EscapedString -ElementValue ($Tags -join ' ')}) + $(if($LicenseUri){ + "$(Get-EscapedString -ElementValue "$LicenseUri") + true" + }) + $(if($ProjectUri){ + "$(Get-EscapedString -ElementValue "$ProjectUri")" + }) + $(if($IconUri){ + "$(Get-EscapedString -ElementValue "$IconUri")" + }) + + $dependencies + + + +"@ + + $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 + + # 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, '-NonInteractive', '-ApiKey', $NugetApiKey) ` + -RedirectStandardError $tempErrorFile ` + -RedirectStandardOutput $tempOutputFile ` + -NoNewWindow ` + -Wait + + $errorMsg = Microsoft.PowerShell.Management\Get-Content -Path $tempErrorFile -Raw + + if($errorMsg) + { + 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) + + Write-Output -InputObject (New-DynamicOption -Category $category ` + -Name $script:PSArtifactType ` + -ExpectedType String ` + -IsRequired $false ` + -PermittedValues @($script:PSArtifactTypeModule,$script:PSArtifactTypeScript, $script:All)) + + switch($category) + { + Package { + 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 "Scope" -ExpectedType String -IsRequired $false -PermittedValues @("CurrentUser","AllUsers")) + 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')) + + Set-ModuleSourcesVariable -Force + + $IsNewModuleSource = $false + $Options = $request.Options + + foreach( $o in $Options.Keys ) + { + Write-Debug ( "OPTION: {0} => {1}" -f ($o, $Options[$o]) ) + } + + 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)) + { + $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)) + { + $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)) + { + $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 + } + } + } + + # Ping and resolve the specified location + $Location = Resolve-Location -Location $Location ` + -LocationParameterName 'Location' ` + -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" + + # 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 + } + + $currentSourceObject = $null + + # Check if Name is already registered + if($script:PSGetModuleSources.Contains($Name)) + { + $currentSourceObject = $script:PSGetModuleSources[$Name] + } + + 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)) + { + $packageSource = $SelectedProvider.ResolvePackageSources( (New-Request -Sources @($LocationString)) ) + } + 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)) + $packageSource = $provider.ResolvePackageSources((New-Request -Option @{} -Sources @($LocationString))) + + 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 + } + 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) + { + $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) + ThrowError -ExceptionName "System.ArgumentException" ` + -ExceptionMessage $message ` + -ErrorId "RepositoryNotFound" ` + -CallerPSCmdlet $PSCmdlet ` + -ErrorCategory InvalidArgument ` + -ExceptionObject $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' + + $pkgs = $provider.FindPackages($names, + $requiredVersion, + $minimumVersion, + $maximumVersion, + (New-Request -Sources @($Location) -Options $providerOptions) ) + + 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 + $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('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('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)) + + $newRequest = New-Request -Options @{Destination=$tempDestination; + ExcludeVersion=$true} ` + -Sources @($SourceLocation) + + 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 + + if(-not $CurrentModuleInfo) + { + $message = $LocalizedData.InvalidPSModule -f ($pkg.Name) + Write-Error -Message $message -ErrorId "InvalidManifestModule" -Category InvalidOperation + continue + } + } + + # 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) + } + } + } + + # Remove the old module base folder if it is different from the required destination module path when -Force is specified + if($Force -and + $InstalledModuleInfo2 -and + -not $destinationModulePath.StartsWith($InstalledModuleInfo2.ModuleBase, [System.StringComparison]::OrdinalIgnoreCase)) + { + Microsoft.PowerShell.Management\Remove-Item -Path $InstalledModuleInfo2.ModuleBase ` + -Force -Recurse ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue ` + -Confirm:$false -WhatIf:$false + } + + if($IsSavePackage) + { + $message = $LocalizedData.ModuleSavedSuccessfully -f ($psgItemInfo.Name) + } + else + { + $message = $LocalizedData.ModuleInstalledSuccessfully -f ($psgItemInfo.Name) + } + 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) + } + else + { + $message = $LocalizedData.ScriptInstalledSuccessfully -f ($psgItemInfo.Name) + } + 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 "", + # 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 "", + # 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 ) + $details.Add( "Type" , $Type ) + + 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) + { + $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 + ) + + # 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('/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 ` + -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 ` + -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()] + [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 + ) + + + Import-LocalizedData -BindingVariable ModuleManifestHashTable ` + -FileName (Microsoft.PowerShell.Management\Split-Path $Path -Leaf) ` + -BaseDirectory (Microsoft.PowerShell.Management\Split-Path $Path -Parent) ` + -ErrorAction SilentlyContinue ` + -WarningAction SilentlyContinue + + if(-not (Microsoft.PowerShell.Management\Test-Path $Path)) + { + $message = $LocalizedData.UpdateModuleManifestPathCannotFound -f ($Path) + ThrowError -ExceptionName "System.ArgumentException" ` + -ExceptionMessage $message ` + -ErrorId "InvalidModuleManifestFilePath" ` + -ExceptionObject $Path ` + -CallerPSCmdlet $PSCmdlet ` + -ErrorCategory InvalidArgument + } + + #Get the original module manifest and migrate all the fields to the new module manifest, including the specified parameter values + try + { + $moduleInfo = Microsoft.PowerShell.Core\Test-ModuleManifest -Path $Path -ErrorAction Stop + } + catch + { + $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($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 _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 Test-ValidManifestModule +{ + [CmdletBinding()] + [OutputType([bool])] + Param + ( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] + $ModuleBasePath + ) + + $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 + } + + return $PSModuleInfo +} + +function Get-ScriptSourceLocation +{ + [CmdletBinding()] + Param + ( + [Parameter()] + [String] + $Location + ) + + $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' ` + -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()] + [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 + $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