1

I know I can limit exported commands from module that is imported like this:

Import-Module C:\...\MyModule or Import-Module C:\...\MyModule\MyModule.psd1

Then I can use CmdletsToExport in .psd1.

But, what if I import module from .dll? Import-Module C:\...\MyModule.dll

How to limit exported commands (cmdlets)?

There are cmdlets in our .dll that should be "hidden" in default and we want to allow calls of them only if some environment variable has some value.

I was thinking that Powershell maybe uses reflection to get commands from .dll, so maybe there is some way to catch some "module initialized" event where I could somehow influence what cmdlets should be exported.

4
  • 2
    Why make them cmdlets if you want them private then ? make a private / internal class that doesnt inherit PSCmdlet then Commented May 15, 2024 at 16:58
  • 1
    @SantiagoSquarzon, it appears that the OP -does- want to be able to invoke the code IFF an environment variable is set. Commented May 15, 2024 at 18:50
  • 1
    Can you just add some validation code to the start of your “conditionally available” cmdlets that checks the environment variable value before it runs the main body - that could throw a meaningful exception if the value isn’t what you expect, and would involve less headscratching about why the cmdlets are “visible” on some machines but not others for no obvious reason :-)… Commented May 16, 2024 at 3:37
  • If you quietly update your question without engaging with prior commenters / answers, your update is likely to go unnoticed. There is a mechanism that allows you to run code in your DLL on import - see stackoverflow.com/a/51624757/45375 - but I'm not aware of any ability to control what gets exported that way. Commented May 16, 2024 at 16:38

1 Answer 1

0

I can't think of an environment variable-based solution, but if executing a command to make the "hidden" cmdlets visible is acceptable, you can take the following approach:

  • Create a full-fledged, directory-based module around your cmdlet-containing *.dll, through whose module manifest (.psd1) you can limit what cmdlets are made available to the caller on import.

  • If you want to (later or alternatively) load all cmdlets, run Import-Module -Force directly on the *.dll, which will import all cmdlets (all public Cmdlet and/or PSCmdlet-derived classes).


If you define helper function Import-AllCmdlets (source code below), you can force importing of all cmdlets as follows, assuming your module's name is Foo:

# -Verbose shows what cmdlets are imported.
Get-Module -ListAvailable Foo | Import-AllCmdlets -Verbose
Import-AllCmdlets source code:
function Import-AllCmdlets {
  param(
    [Parameter(ValueFromPipeline)]
    [psmoduleinfo] $module
  )
  process {
    if ($module.RootModule -notlike '*.dll') {
      Write-Error "Module $module has no binary root module."
      return
    }
    Import-Module -Force (Join-Path (Split-Path $module.Path) $module.RootModule)
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.