-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
using custom ALC for module written in PowerShell (not c#) #13
Comments
Unfortunately there is no built in way to do this. The closest you can get is to manually create your own ALC, hold on to instances of the @daxian-dbw did some pretty extensive research into the possibility of adding support for script based ALC isolation, you can read about the blockers that were discovered in his RFC on the topic. The conclusion was that it is not feasible to support the scenario. |
@gaelcolas I'm so sorry that I didn't notice this issue until Steve mentioned it within the team. @SeeminglyScience is right, you cannot use ALC for a script module, unless some fundamental support is built into powershell, such as in type resolution, assembly loading, and caching/caching invalidation. I wrote another RFC in 2021 trying to tackle this problem, which has lots of details about what needs to be done and what problems we will be facing. The RFC was closed in the end because of some usability problems and potentially breaking changes in behavior (see the summary). |
@daxian-dbw, @SeeminglyScience, I wonder if instead of a general-purpose load/unload for PowerShell script modules themselves it would be possible to devise a pattern for a dependency wrapper module and make that easier. For example, instead of being able to define One of the biggest drawbacks to the ALC model right now is that the majority of community modules are written purely in PowerShell without any C# and the community of practice doesn't have particularly strong experience with the toolchain for testing and publishing C# code. Moving first-party module dependencies into the ALC (in my case, YamlDotNet for PlatyPS and MarkDig for the markdown renderer) goes a long way towards helping avoid conflicts for community modules, but doesn't fully resolve the problem. That leaves people with the choice of migrating to a fully binary module (much higher friction for typical PowerShell authors), trying to reimplement the functionality they need in PowerShell itself, or giving up on that functionality. If there was a functional pattern for being able to get at those classes and methods without having to write the entire module in C#, I can think that would make using external libraries much less prone to conflicts, even if still higher friction than merely vendoring the library directly for usage. As it stands right now, using any external libraries in a script module risks dependency conflicts and there doesn't seem to be a way around that without switching to a binary module all-up. |
We already have the sample code for this pattern -- you basically will need a bridge assembly to wrap the dependency and expose the dependent types/APIs in a different way from the bridge assembly. Then the script module then can just depend on the bridge assembly. However, having a bridge assembly to forward the calls to real dependency types/APIs has limitations and also increase complexity to the module design. It's non-trivial work to powershell users who are not too familiar with C#. The dependency for script module should ideally be mitigated by PowerShellGet. In an ideal world, script modules would not need to ship dependency assemblies along with the module, but just declare it, and then it's the PowerShellGet's job to sort out the dependency and always use the latest version of the dependency assembly. |
Dongbo laid it out excellently here but just in case you read this thinking it can be applied to the script portion of a module - you still can't directly reference the dependencies from script using this pattern. You would need to write a bunch of proxy APIs in order to use them in the script portion. |
Thank you for this repo, lots of information in there!
I'm trying to understand if there's a way to adapt those approaches in modules written in PowerShell.
Let me describe my scenario, what I understand, and what I think I don't know...
Scenario
I would like to fork & rename the Powershell-Yaml module to experiment with some things, while I still use the
Powershell-Yaml
module (i.e. for building that module).What I think I understand
What I'd like clarification/guidance on
Could the resolver DLL be loaded before parse time using RequiredAssemblies or ScriptToProcess in the ModuleManifest?
If I list the assemblies in the module manifest, like so, should it work?
RequiredAssemblies = @('resolver.dll','conflict.dll')
Will the loading order be respected (so that registration of
AssemblyResolve
happen first)?Why don't you use this approach in your sample and prefer a nested module? Is it for the OnImport() call?
Are nested module (resolver.dll) loaded before the RootModule psm1 is parsed?
Since the module (let's call it MyModule) isn't a binary module, in
IsAssemblyMatching()
the requestingAssembly will be null? Does that mean I can't select which library will it resolve to, so anything calling it in my PowerShell session will now go to that newer lib?Thanks for the clarification!
The text was updated successfully, but these errors were encountered: