Load PowerShell assemblies from nuget packages
PowerShell can manage NuGet packages since a few years now, but loading a dll, which is part of a installed NuGet package in PowerShell is not that intuitive.
I wanted to directly use the
Microsoft.Azure.Cosmos.Table package from NuGet. You could also use the
AzTable module, but if you want to use the most current Version of the underlying dll’s (if they are even completely loaded from the PowerShell module) or if there is no module available that loads that specific nuget package (e.g. SSH.NET), you have to install them manually.
Since version 9.4.0 of the Microsoft Azure Storage SDK for .NET, the Table service is not supported anymore. Support for table storage is provided by CosmosDB libraries and was recently moved into the
So first, I needed to install the most current version of the package from nuget:
install-package Microsoft.Azure.Cosmos.Table -RequiredVersion 1.0.4-preview -source https://www.nuget.org/api/v2
After installing, you can verify the installation with the following command.
By trying to use one of the classes inside of the
Microsoft.Azure.Cosmos.Table namespace, we can check, if anything is loaded yet:
As the error suggests, we don’t have any namespace available that hosts the class.
If we now want to load the assembly, we only have the path to the nupkg file in the source parameter. As we cannot load nupkg in PowerShell yet, we need a workaround.
The following lines of PowerShell will help with that:
$zip = [System.IO.Compression.ZipFile]::Open((Get-Package Microsoft.Azure.Cosmos.Table).Source,"Read")
$memStream = [System.IO.MemoryStream]::new()
$reader = [System.IO.StreamReader]($zip.entries).Open()
[byte]$bytes = $memStream.ToArray()
What we have done here was
- Opening the nupkg file as a zip file in memory
- Create a memory stream to store the raw bytes
- Create a
StreamReaderinstance and save the raw bytes from the
BaseStreamproperty into our memory stream
- Saving the bytes from the memory stream as a byte array
- Disposing the used objects
Now we can try loading the assembly with the
[System.Reflection.Assembly]::Load() method, which support byte arrays.
Let’s verify, if we can use the namespace now:
You can use these technique to load all kinds of dll’s from within archives, but keep in mind that dependency loading will not work. If you have assemblies with a lot of dependencies, you should think of another way of importing.