Last active
March 21, 2025 14:48
-
-
Save Jaykul/bfb9cad99a3c067ba807 to your computer and use it in GitHub Desktop.
(Install and) load the assemblies from a NuGet package into PowerShell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #requires -Module PackageManagement | |
| using namespace NuGet | |
| [CmdletBinding(DefaultParameterSetName = 'MaybeUseExisting')] | |
| param( | |
| [Parameter(Mandatory, Position = 0)] | |
| [String]$Name, | |
| [String]$Destination = "$(Split-Path $Profile)\Libraries", | |
| [switch]$ForceReinstall, | |
| [switch]$AllowPrerelease, | |
| [string]$Version | |
| ) | |
| $ErrorActionPreference = "Stop" | |
| if (!(Test-Path $Destination -Type Container)) { | |
| throw "The destination path ($Destination) must point to an existing folder, NuGet will install packages in subdirectories of this folder." | |
| } | |
| if ((Get-Command nuget.exe -ErrorAction Ignore).Version -lt "6.0") { | |
| # Install-WebBinary is in Install-GithubRelease (which I should make into a module, but later) | |
| . Install-GithubRelease.ps1 Jaykul WebBinary | |
| Install-WebBinary https://dist.nuget.org/win-x86-commandline/latest/nuget.exe nuget.exe | |
| } | |
| Add-Type -AssemblyName (Get-Command nuget).Path | |
| $PackagePath = if (Test-Path "$Destination\$Name") { | |
| Convert-Path "$Destination\$Name" | |
| } elseif (Test-Path "$Destination\$Name*") { | |
| Convert-Path "$Destination\$Name*" | | |
| Sort-Object { [SemanticVersion]($_ -replace ".*?\.([\d\.]+(-.*)?)$", '$1') } -Descending | | |
| Select-Object -First 1 | |
| } | |
| if ($ForceReinstall -or -not $PackagePath){ | |
| $null = $PSBoundParameters.Remove("ForceReinstall") | |
| $PSBoundParameters['Destination'] = $Destination | |
| # Normalize: nuget requires destination NOT end with a slash | |
| $Destination = (Convert-Path $Destination).TrimEnd("\") | |
| if ($Version -and $AllowPrerelease) { | |
| nuget install $Name -OutputDirectory $Destination -Version $Version -Prerelease | |
| } elseif ($AllowPrerelease) { | |
| nuget install $Name -OutputDirectory $Destination -Prerelease | |
| } elseif ($Version) { | |
| nuget install $Name -OutputDirectory $Destination -Version $Version | |
| } else { | |
| nuget install $Name -OutputDirectory $Destination | |
| } | |
| $PackagePath = if (Test-Path "$Destination\$Name") { | |
| Convert-Path "$Destination\$Name" | |
| } elseif (Test-Path "$Destination\$Name*") { | |
| Convert-Path "$Destination\$Name*" | | |
| Sort-Object { [SemanticVersion]($_ -replace ".*?\.([\d\.]+)$", '$1') } -Descending | | |
| Select-Object -First 1 | |
| } else { | |
| $Package | Out-Default | |
| Write-Error "Could not find package after install of Package!" | |
| } | |
| Write-Verbose "Installed $Name to $PackagePath" | |
| } else { | |
| Write-Verbose "Found $Name at $PackagePath" | |
| } | |
| # Nuget packages hide their assemblies in folders with version numbers... | |
| $Versions = @() | |
| if ($PSVersionTable.PSVersion -ge "7.4") { | |
| $Versions += @("net8.0") | |
| } | |
| if ($PSVersionTable.PSVersion -ge "7.3") { | |
| $Versions += @("net7.0") | |
| } | |
| if ($PSVersionTable.PSVersion -ge "7.2") { | |
| $Versions += @("net6.0") | |
| } | |
| if ($PSVersionTable.PSVersion -ge "7.1") { | |
| $Versions += @("net5.0") | |
| } | |
| if ($PSVersionTable.PSVersion -ge "6.0") { | |
| $Versions += @("netstandard2.1", "netstandard2.0", "netstandard1.6", "netstandard1.5", "netstandard1.4", "netstandard1.3", "netstandard1.2", "netstandard1.1", "netstandard1.0") | |
| } | |
| if ($PSVersionTable.PSVersion -ge "4.0") { | |
| $Versions += @("net482","net481","net48","net472","net471","net47","net463","net462","net461","net46", "net452", "net451", "net45", "net40", "net35", "net20") | |
| } elseif ($PSVersionTable.PSVersion -ge "3.0") { | |
| $Versions = "net40", "net35", "net20", "net45", "net451", "net452", "net46" | |
| } else { | |
| $Versions = "net35", "net20" | |
| } | |
| # build full path with \ on the end | |
| $LibraryPath = ($Versions -replace "^", "$PackagePath*\lib\") + "$PackagePath*\lib\" + "$PackagePath*" | | |
| # find the first one that exists | |
| Convert-Path -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| $Number = $LibraryPath -replace '.*?([\d\.]+)$', '$1' -replace '(?<=\d)(?=\d)$', '.' | |
| if (Test-Path "$PackagePath\$Name.nuspec") { | |
| Write-Verbose "Found nuspec file at $PackagePath\$Name.nuspec" | |
| $Document = [xml](Get-Content "$PackagePath\$Name.nuspec") | |
| } elseif (Test-Path "$PackagePath\$Name*.nupkg") { | |
| $Nupkg = Convert-Path "$PackagePath\$Name*.nupkg" | |
| Write-Verbose "Reading nupkg at $Nupkg" | |
| try { | |
| $Package = [System.IO.Packaging.Package]::Open( $Nupkg, "Open", "Read" ) | |
| $Part = $Package.GetPart( $Package.GetRelationshipsByType( "http://schemas.microsoft.com/packaging/2010/07/manifest" ).TargetUri ) | |
| try { | |
| $Stream = $Part.GetStream() | |
| $Reader = [System.IO.StreamReader]$Stream | |
| $Document = [xml]$Reader.ReadToEnd() | |
| } catch [Exception] { | |
| $PSCmdlet.WriteError( [System.Management.Automation.ErrorRecord]::new($_.Exception, "Unexpected Exception", "InvalidResult", $_) ) | |
| } finally { | |
| if ($Reader) { | |
| $Reader.Close() | |
| $Reader.Dispose() | |
| } | |
| if ($Stream) { | |
| $Stream.Close() | |
| $Stream.Dispose() | |
| } | |
| } | |
| if ($Package) { | |
| $Package.Close() | |
| $Package.Dispose() | |
| } | |
| } catch [Exception] { | |
| $PSCmdlet.WriteError( [System.Management.Automation.ErrorRecord]::new($_.Exception, "Cannot Open Path", "OpenError", $Path) ) | |
| } | |
| } | |
| if ($Document) { | |
| Write-Debug $Document.OuterXml | |
| if ($Dependencies = $Document.package.metadata.dependencies) { | |
| Write-Verbose "Importing Dependencies for $number" | |
| foreach ($dependency in @($Dependencies.Group).Where{ $_.targetFramework.EndsWith($number) }.dependency.id) { | |
| Import-NugetLibrary -Destination:$Destination -Name:$dependency | |
| } | |
| } | |
| if ($References = $Document.package.metadata.references) { | |
| Write-Verbose "Importing References for $number" | |
| $group = @($references.Group).Where{ $_.targetFramework.EndsWith($number) } | |
| if ($group) { | |
| $Files = $group.dependency.id | |
| } else { | |
| Write-Warning "Couldn't match $number, try all of them" | |
| # If we can't figure out the right group, just get all the references: | |
| $Files = @($references.SelectNodes("//*[name(.) = 'reference']").File | Select-Object -Unique) | |
| } | |
| $Assemblies = Get-Item ($Files -replace "^", "$LibraryPath\") | |
| } | |
| } | |
| if (!$Assemblies) { | |
| $Assemblies = Get-ChildItem $LibraryPath -Filter *.dll | |
| } | |
| if ($Assemblies) { | |
| # Just for the purpose of the verbose output | |
| Push-Location $Destination | |
| # since we don't know the order, we'll just loop a few times | |
| for ($e = 0; $e -lt $Assemblies.Count; $e++) { | |
| $success = $true | |
| foreach ($assm in $Assemblies) { | |
| Write-Verbose "Import Library $(Resolve-Path $Assm.FullName -Relative)" | |
| Add-Type -Path $Assm.FullName -ErrorAction SilentlyContinue -ErrorVariable failure | |
| if ($failure) { | |
| $success = $false | |
| } else { | |
| Write-Host "LOADING: " -Fore Cyan -NoNewline | |
| Write-Host $LibraryPath\ -Fore Yellow -NoNewline | |
| Write-Host $Assm.Name -Fore White | |
| } | |
| } | |
| # if we loaded everything ok, we're done | |
| if ($success) { | |
| break | |
| } | |
| } | |
| Pop-Location | |
| } | |
| if (!$success) { | |
| throw $failure | |
| } | |
| return |
Author
They changed the module. It's frustrating.
What did this switch do?
Author
The -PackageSaveMode prevented nuget from saving the whole .nupkg file
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I tried this script, unfortunately I get an error that
-PackageSaveModeis missing Install-Package (On Win10)Until now I only found this entry that complains about a breaking change.