-
Notifications
You must be signed in to change notification settings - Fork 102
Description
Prerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues.
Steps to reproduce
# Get existing assemblies that are loaded
$existing = [AppDomain]::CurrentDomain.GetAssemblies() | Select-Object @(
@{ N = 'Name'; E = { $_.GetName().Name } }
'Location'
) | Sort-Object -Property Name
# Use -PassThru to verify version being loaded
Import-Module -Name Microsoft.PowerShell.PSResourceGet -PassThru
# Get list of assemblies PSResourceGet loaded in the main ALC
[AppDomain]::CurrentDomain.GetAssemblies() | Select-Object @(
@{ N = 'Name'; E = { $_.GetName().Name } }
'Location'
) | Where-Object { $_.Name -notin $existing.Name } | Sort-Object -Property NameExpected behavior
Nothing extra outside of $PSHome and Microsoft.PowerShell.PSResourceGet.dll
Actual behavior
Nuget.Versioning is present in the default ALC and has been loaded with PSResourceGet
Name : NuGet.Versioning
Location : /home/jborean/.local/share/powershell/Modules/Microsoft.PowerShell.PSResourceGet/1.2.0/dependencies/NuGet.Versioning.dllThe reason for this is that the module only sets up the ALC in IModuleAssemblyInitializer.OnImport and while this normally works fine there is a risk that when PowerShell goes to load the assembly this OnImport method is set it may have to resolve a dependency before OnImport is called. I don't know the exact details but I've typically found it happens when you have a base class inheritance from an external assembly or some other type metadata (field/property/parameter/etc) contains a type in another assembly and for whatever reason it must be resolved at load time rather than at runtime when it's used.
The solution to this is to use something like AlcLoader. Essentially you want a separate assembly something like Microsoft.PowerShell.PSResourceGet.Loader that sets up the ALC and is used to load Microsoft.PowerShell.PSResourceGet completely in an ALC.
You can see this in action in my various modules but the latest one is PSNetDetour. I have the following files
RootModule->Module.psm1- This loads the Shared/Loader assembly in this case
PSNetDetour.Shared - It uses this Shared/Loader to setup the ALC and load our main module inside the ALC
- The shared loader returns an Assembly object which is imported with
Import-Module - .NET Framework just skips all this and loads the main assembly by path
- https://github.com/jborean93/PSNetDetour/blob/main/module/PSNetDetour.psm1
- This loads the Shared/Loader assembly in this case
- Shared/Loader Assembly ->
LoadContext.cs- Sets up the ALC
- This is unique to this package so won't have a conflict
- Loads the our main assembly in the ALC and subsequently any deps it uses
- Returns the
Assemblyobject for our psm1 to Import-Module - Empty assembly for .NET Framework
- Can also define extra types used in both the module and outside but that's not necessary (or recommended)
- https://github.com/jborean93/PSNetDetour/blob/main/src/PSNetDetour.Shared/LoadContext.cs
- Module Assembly
- This contains our cmdlets and other code
- Loaded in the ALC with any deps it uses
- Even though it's in an ALC PowerShell still can reference any public types due to how
Import-Module -Assembly ...works
Error details
No error but could cause conflicts with anything relying on that assembly and they also load it in the main ALCEnvironment data
ModuleType Version PreRelease Name ExportedCommands
---------- ------- ---------- ---- ----------------
Binary 1.2.0 rc3 Microsoft.PowerShell.PSResourceGet {Compress-PSResource, Find-PSResource, Get-InstalledPSResource, G…
Name Value
---- -----
PSVersion 7.5.1
PSEdition Core
GitCommitId 7.5.1
OS Fedora Linux 43 (Server Edition)
Platform Unix
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0Visuals
No response