0

I have an .NET assembly that will get imported by a Powershell session using:

Import-Module MyAssemblyFirst.dll

What I need is to automatically load another custom assembly (MyAssemblySecond.dll) that I know about when MyAssemblyFirst.dll gets imported.

The scenario I am looking for is:

Import-Module MyAssemblyFirst.dll
Import-Module MyAssemblySecond.dll

but I would rather like to have only one Import-Module call:

Import-Module MyAssemblyFirst.dll

...and somehow to trigger loading the second assembly as well.

The 2 assemblies do not reference each other but I am the owner of both. I'm just trying to simplify importing multiple assemblies by importing only one.

So in a broader example, I am looking to simplify a PS script like this:

Import-Module MyAssemblyFirst.dll
Import-Module MyAssemblySecond.dll
Import-Module MyAssemblyThird.dll

...

Import-Module MyAssemblyNth.dll

to a single line:

Import-Module MyAssemblyFirst.dll

EDIT: The purpose for this is that based on a certain logic located in MyAssemblyFirst.dll I might want to automatically import some other assemblies that expose some new specific PS commands.

Adi
  • 5,113
  • 6
  • 46
  • 59
  • Start here https://msdn.microsoft.com/en-us/library/dd878337(v=vs.85).aspx and create a manifest, I'm not sure if you'll need `RequiredModules` or `RequiredAssemblies`, try them and add the info to your question. – Eris Jul 11 '16 at 20:01
  • Looks promising, however I need if possible to load the external module from MyAssemblyFirst.dll code. Based on some logic, I might want to skip loading of MyAssemblySecond.dll and only load MyAssemblyThird.dll – Adi Jul 11 '16 at 20:06
  • Possibly this other SO question may help? http://stackoverflow.com/questions/5489494/powershell-module-manifest-automatically-loading-a-required-module – Eris Jul 11 '16 at 20:07
  • Which PowerShell version are you targeting? – user4003407 Jul 11 '16 at 20:45
  • PS version 4.0 minimum – Adi Jul 11 '16 at 20:59

1 Answers1

1

You can implement IModuleAssemblyInitializer interface to provide module initialization code:

Add-Type -TypeDefinition @‘
    using System;
    using System.Management.Automation;
    [Cmdlet(VerbsLifecycle.Invoke, "Command1")]
    public class Command1 : Cmdlet {
        protected override void ProcessRecord() {
            WriteObject("Command 1");
        }
    }
    public class ModuleInitializer : IModuleAssemblyInitializer {
        public void OnImport() {
            using(PowerShell ps = PowerShell.Create(RunspaceMode.CurrentRunspace)) {
                ps.AddCommand("Write-Host").AddArgument("Before submodule import").AddStatement().
                   AddCommand("Import-Module").AddArgument(".\\Assembly2.dll").AddStatement().
                   AddCommand("Write-Host").AddArgument("After submodule import").Invoke();
            }
        }
    }
’@ -OutputAssembly .\Assembly1.dll

Add-Type -TypeDefinition @‘
    using System;
    using System.Management.Automation;
    [Cmdlet(VerbsLifecycle.Invoke, "Command2")]
    public class Command2 : Cmdlet {
        protected override void ProcessRecord() {
            WriteObject("Command 2");
        }
    }
    public class ModuleInitializer : IModuleAssemblyInitializer {
        public void OnImport() {
            using(PowerShell ps = PowerShell.Create(RunspaceMode.CurrentRunspace)) {
                ps.AddCommand("Write-Host").AddArgument("Importing submodule").Invoke();
            }
        }
    }
’@ -OutputAssembly .\Assembly2.dll

Write-Host 'Before module import'
Import-Module .\Assembly1.dll
Write-Host 'After module import'

Invoke-Command2
user4003407
  • 21,204
  • 4
  • 50
  • 60
  • Just a note for anyone wondering about the lifetime of the `IModuleAssemblyInitializer` object... I was hoping it would stay live during the duration of while the DLL is loaded by powershell. However, the instance lasts just long enough for the `OnImport` call (modulo GC). – tig Apr 07 '20 at 01:11