Private/DownloadNuGetPackage.ps1
<#
.SYNOPSIS The DownloadNuGetPackage function download and unzips the specified NuGetPackage using the v3 NuGet API. It also indicated which assembly file (.dll) you should probably use for the PowerShell version (Windows or Core) you are using. .DESCRIPTION See .SYNOPSIS .PARAMETER AssemblyName This parameter is MANDATORY. TODO .PARAMETER NuGetPkgDownloadDirectory This parameter is OPTIONAL. TODO .PARAMETER AllowPreRelease This parameter is OPTIONAL. TODO .PARAMETER Silent This parameter is OPTIONAL. TODO .EXAMPLE # Open an elevated PowerShell Session, import the module, and - PS C:\Users\zeroadmin> DownloadNuGetPackage -AssemblyName Newtonsoft.Json -NuGetPkgDownloadDirectory "$HOME\Downloads" -Silent #> function DownloadNuGetPackage { [CmdletBinding()] Param( [Parameter(Mandatory=$True)] [string]$AssemblyName, [Parameter(Mandatory=$False)] [string]$NuGetPkgDownloadDirectory, [Parameter(Mandatory=$False)] [switch]$AllowPreRelease, [Parameter(Mandatory=$False)] [switch]$Silent ) #region >> Prep if ($PSVersionTable.Platform -ne $null -and $PSVersionTable.Platform -ne "Win32NT" -and !$NuGetPkgDownloadDirectory) { Write-Error "On this OS Platform (i.e. $($PSVersionTable.Platform)), the -NuGetPkgDownloadDirectory parameter is required! Halting!" $global:FunctionResult = "1" return } if ($($PSVersionTable.Platform -ne $null -and $PSVersionTable.Platform -ne "Win32NT") -or $NuGetPkgDownloadDirectory) { #$NuGetPackageUri = "https://www.nuget.org/api/v2/package/$AssemblyName" #$NuGetPackageUri = "https://api.nuget.org/v3-flatcontainer/{id-lower}/{version-lower}/{id-lower}.{version-lower}.nupkg" if ($AllowPreRelease) { $SearchNuGetPackageUri = "https://api-v2v3search-0.nuget.org/query?q=$AssemblyName&prerelease=true" } else { $SearchNuGetPackageUri = "https://api-v2v3search-0.nuget.org/query?q=$AssemblyName&prerelease=false" } $VersionCheckPrep = $($(Invoke-RestMethod -Uri $SearchNuGetPackageUri).data | Where-Object {$_.id -eq $AssemblyName}).versions $LatestVersion = $VersionCheckPrep[-1].Version $LowercaseAssemblyName = $AssemblyName.ToLowerInvariant() $NuGetPackageUri = "https://api.nuget.org/v3-flatcontainer/$LowercaseAssemblyName/$LatestVersion/$LowercaseAssemblyName.$LatestVersion.nupkg" $OutFileBaseName = "$LowercaseAssemblyName.$LatestVersion.zip" $DllFileName = $OutFileBaseName -replace "zip","dll" if ($NuGetPkgDownloadDirectory) { $NuGetPkgDownloadPath = Join-Path $NuGetPkgDownloadDirectory $OutFileBaseName $NuGetPkgExtractionDirectory = Join-Path $NuGetPkgDownloadDirectory $AssemblyName if (!$(Test-Path $NuGetPkgDownloadDirectory)) { $null = New-Item -ItemType Directory -Path $NuGetPkgDownloadDirectory -Force } if (!$(Test-Path $NuGetPkgExtractionDirectory)) { $null = New-Item -ItemType Directory -Path $NuGetPkgExtractionDirectory -Force } } } if ($($PSVersionTable.PSEdition -eq "Desktop" -or $PSVersionTable.Platform -eq "Win32NT") -and !$NuGetPkgDownloadDirectory) { $NuGetConfigContent = Get-Content $(Get-NativePath @($env:AppData, "NuGet", "nuget.config")) $NuGetRepoPathCheck = $NuGetConfigContent | Select-String -Pattern '<add key="repositoryPath" value=' -ErrorAction SilentlyContinue if ($NuGetRepoPathCheck -ne $null) { $NuGetPackagesPath = $($($NuGetRepoPathCheck.Line.Trim() -split 'value=')[-1] -split ' ')[0] -replace '"','' } else { $NuGetPackagesPath = Get-NativePath @($HOME, ".nuget", "packages") } if (!$(Test-Path $NuGetPackagesPath)) { $null = New-Item -ItemType Directory -Path $NuGetPackagesPath -Force } $NuGetPkgExtractionDirectory = Get-NativePath @($NuGetPackagesPath, $AssemblyName) } if ($PSVersionTable.PSEdition -eq "Core") { $PossibleSubDirs = @( [pscustomobject]@{ Preference = 4 SubDirectory = $(Get-NativePath @("lib", "netstandard1.3")) } [pscustomobject]@{ Preference = 3 SubDirectory = $(Get-NativePath @("lib", "netstandard1.6")) } [pscustomobject]@{ Preference = 1 SubDirectory = $(Get-NativePath @("lib", "netstandard2.0")) } [pscustomobject]@{ Preference = 2 SubDirectory = $(Get-NativePath @("lib", "netcoreapp2.0")) } ) } else { $PossibleSubDirs = @( [pscustomobject]@{ Preference = 8 SubDirectory = $(Get-NativePath @("lib", "net40")) } [pscustomobject]@{ Preference = 7 SubDirectory = $(Get-NativePath @("lib", "net45")) } [pscustomobject]@{ Preference = 6 SubDirectory = $(Get-NativePath @("lib", "net451")) } [pscustomobject]@{ Preference = 5 SubDirectory = $(Get-NativePath @("lib", "net46")) } [pscustomobject]@{ Preference = 4 SubDirectory = $(Get-NativePath @("lib", "net461")) } [pscustomobject]@{ Preference = 3 SubDirectory = $(Get-NativePath @("lib", "net462")) } [pscustomobject]@{ Preference = 2 SubDirectory = $(Get-NativePath @("lib", "net47")) } [pscustomobject]@{ Preference = 1 SubDirectory = $(Get-NativePath @("lib", "net471")) } [pscustomobject]@{ Preference = 15 SubDirectory = $(Get-NativePath @("lib", "netstandard1.0")) } [pscustomobject]@{ Preference = 14 SubDirectory = $(Get-NativePath @("lib", "netstandard1.1")) } [pscustomobject]@{ Preference = 13 SubDirectory = $(Get-NativePath @("lib", "netstandard1.2")) } [pscustomobject]@{ Preference = 12 SubDirectory = $(Get-NativePath @("lib", "netstandard1.3")) } [pscustomobject]@{ Preference = 11 SubDirectory = $(Get-NativePath @("lib", "netstandard1.4")) } [pscustomobject]@{ Preference = 10 SubDirectory = $(Get-NativePath @("lib", "netstandard1.5")) } [pscustomobject]@{ Preference = 9 SubDirectory = $(Get-NativePath @("lib", "netstandard1.6")) } [pscustomobject]@{ Preference = 16 SubDirectory = $(Get-NativePath @("lib", "netstandard2.0")) } [pscustomobject]@{ Preference = 17 SubDirectory = $(Get-NativePath @("lib", "netcoreapp2.0")) } ) } #endregion >> Prep #region >> Main if ($($PSVersionTable.PSEdition -eq "Desktop" -or $PSVersionTable.Platform -eq "Win32NT") -and !$NuGetPkgDownloadDirectory) { if (!$(Get-Command nuget.exe -ErrorAction SilentlyContinue)) { $NugetPath = Join-Path $($NuGetPackagesPath | Split-Path -Parent) nuget.exe if(!$(Test-Path $NugetPath)) { Invoke-WebRequest -uri 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' -OutFile $NugetPath } $NugetDir = $NugetPath | Split-Path -Parent # Update PowerShell $env:PATH [System.Collections.Arraylist][array]$CurrentEnvPathArray = $env:PATH -split ';' | Where-Object {![System.String]::IsNullOrWhiteSpace($_)} | Sort-Object | Get-Unique if ($CurrentEnvPathArray -notcontains $NugetDir) { $CurrentEnvPathArray.Insert(0,$NugetDir) $env:PATH = $CurrentEnvPathArray -join ';' } # Update SYSTEM Path $RegistrySystemPath = 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' $CurrentSystemPath = $(Get-ItemProperty -Path $RegistrySystemPath -Name PATH).Path [System.Collections.Arraylist][array]$CurrentSystemPathArray = $CurrentSystemPath -split ';' | Where-Object {![System.String]::IsNullOrWhiteSpace($_)} | Sort-Object | Get-Unique if ($CurrentSystemPathArray -notcontains $NugetDir) { $CurrentSystemPathArray.Insert(0,$NugetDir) $UpdatedSystemPath = $CurrentSystemPathArray -join ';' Set-ItemProperty -Path $RegistrySystemPath -Name PATH -Value $UpdatedSystemPath } } try { $ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo #$ProcessInfo.WorkingDirectory = $NuGetPackagesPath $ProcessInfo.FileName = $(Get-Command nuget).Source $ProcessInfo.RedirectStandardError = $true $ProcessInfo.RedirectStandardOutput = $true $ProcessInfo.UseShellExecute = $false if ($AllowPreRelease) { $ProcessInfo.Arguments = "install $AssemblyName -PreRelease" } else { $ProcessInfo.Arguments = "install $AssemblyName" } $Process = New-Object System.Diagnostics.Process $Process.StartInfo = $ProcessInfo $Process.Start() | Out-Null $stdout = $($Process.StandardOutput.ReadToEnd()).Trim() $stderr = $($Process.StandardError.ReadToEnd()).Trim() $AllOutput = $stdout + $stderr $AllOutput = $AllOutput -split "`n" if ($stderr -match "Unable to find package") { throw } $NuGetPkgExtractionDirectory = $(Get-ChildItem -Path $NuGetPackagesPath -Directory | Where-Object {$_.Name -eq $AssemblyName} | Sort-Object -Property CreationTime)[-1].FullName } catch { Write-Error $_ Write-Error "NuGet.exe was unable to find a package called $AssemblyName! Halting!" $global:FunctionResult = "1" return } } if ($($PSVersionTable.Platform -ne $null -and $PSVersionTable.Platform -ne "Win32NT") -or $NuGetPkgDownloadDirectory) { try { # Download the NuGet Package if (!$Silent) { Write-Host "Downloading $AssemblyName NuGet Package to $NuGetPkgDownloadPath ..." } Invoke-WebRequest -Uri $NuGetPackageUri -OutFile $NuGetPkgDownloadPath if (!$Silent) { Write-Host "NuGet Package has been downloaded to $NuGetPkgDownloadPath" } } catch { Write-Error "Unable to find $AssemblyName via the NuGet API! Halting!" $global:FunctionResult = "1" return } # Step through possble Zip File SubDirs and get the most highest available compatible version of the Assembly try { if (!$Silent) { Write-Host "Attempting to extract NuGet zip file $NuGetPkgDownloadPath to $NuGetPkgExtractionDirectory ..." } if ($(Get-ChildItem $NuGetPkgExtractionDirectory).Count -gt 1) { foreach ($item in $(Get-ChildItem $NuGetPkgExtractionDirectory)) { if ($item.Extension -ne ".zip") { $item | Remove-Item -Recurse -Force } } } Expand-Archive -Path $NuGetPkgDownloadPath -DestinationPath $NuGetPkgExtractionDirectory if (!$Silent) { Write-Host "NuGet Package is available here: $NuGetPkgExtractionDirectory" } } catch { Write-Warning "The Unzip-File function failed with the following error:" Write-Error $$_ $global:FunctionResult = "1" return } } [System.Collections.ArrayList]$NuGetPackageActualSubDirs = @() $(Get-ChildItem -Recurse $NuGetPkgExtractionDirectory -File -Filter "*.dll").DirectoryName | foreach { $null = $NuGetPackageActualSubDirs.Add($_) } $s = [IO.Path]::DirectorySeparatorChar [System.Collections.ArrayList]$FoundSubDirsPSObjects = @() foreach ($pdir in $PossibleSubDirs) { foreach ($adir in $NuGetPackageActualSubDirs) { $IndexOfSlash = $pdir.SubDirectory.IndexOf($s) $pdirToRegexPattern = { $UpdatedString = $pdir.SubDirectory.Remove($IndexOfSlash, 1) $UpdatedString.Insert($IndexOfSlash, [regex]::Escape($s)) }.Invoke() if ($adir -match $pdirToRegexPattern) { $FoundDirPSObj = [pscustomobject]@{ Preference = $pdir.Preference Directory = $adir } $null = $FoundSubDirsPSObjects.Add($FoundDirPSObj) } } } $TargetDir = $($FoundSubDirsPSObjects | Sort-Object -Property Preference)[0].Directory $AssemblyPath = Get-NativePath @($TargetDir, $(Get-ChildItem $TargetDir -File -Filter "*.dll").Name) [pscustomobject]@{ NuGetPackageDirectory = $NuGetPkgExtractionDirectory AssemblyToLoad = $AssemblyPath } #endregion >> Main } |