Binary Powershell Cmdlet not exported from module - powershell

I created a Powershell module containing one Cmdlet implemented by C# and some advanced functions provided by a psm1 file. When loading the module, only the functions implemented in advanced functions are exported.
I registered the assembly to load as part of my module and exported the functions:
RequiredAssemblies = #("lib\provider.dll","lib\myCmdlet.dll")
FunctionsToExport = #('New-assemblyFunction','New-advancedFunction')
Also I tried to mix the above functionstoexport with the cmdlettoexport for the assembly provided Cmdlet. All kind of combinations did not show any success:
CmdletsToExport = #('New-assemblyFunction')
If I start the import-module in verbose mode, I can see that the assemblies are being loaded but only functions implemented in advanced functions are being exported. The New-assemblyFunction does not appear anywhere in the verbose report.
I can load the DLL manually (import-module) and the cmdlet is available.
Any clue what's wrong here or how to further analyse? I deblock-file'd all of them.

That's it:
Value of RequiredAssemblieskey not considered as PowerShell modules. You need to use RootModule (ModuleToProcess) or NestedModules key. – PetSerAl

Related

How to export variables from a PowerShell module

I've defined a variable in a psm1 file but when I try to access it in another script, after importing the module, I'm not seeing the value set in the psm1 file.
globals.psm1
$blah = "hello world"
my-script.ps1
Import-Module "$PSScriptRoot\globals.psm1" -Force -Verbose
Write-Output "blah: ${blah}"
output
PS C:\blah> .\my-script.ps1
VERBOSE: Loading module from path 'C:\blah\globals.psm1'.
blah: ''
I thought all variables get exported by default. I must be interrupting this wrong:
Specifies the variables that the module exports to the caller's session state. Wildcard characters are permitted. By default, all variables ('*') are exported
source: MSFT Docs -> How to write a PowerShell module manifest
(CTRL + F on 'VariablesToExport' to find the quoted text)
And yes, if I export the variable, I can access it but the documentation says: 'By default, all varialbes ('*') are exported so what am I doing wrong or misunderstanding? 🤔
globals.psm1
$blah = "hello world"
Export-ModuleMember -Variable blah
Your module is not using a module manifest (a companion .psd1 file whose RootModule entry points to your .psm1 file in the case of script modules), whereas the documentation you quote pertains to module manifest-based modules.
If a module consists only of a .psm1 file, and that file contains no Export-ModuleMember calls, the following rule applies:
Only functions and aliases are automatically exported.
Conversely, this means: in order to also export variables, you must use an Export-ModuleMember call - and if you do, the slate is wiped clean, so to speak, and you must explicitly specify all definitions you want to export (in the simplest case, use Export-ModuleMember -Function * -Alias * -Variable *).
Also, be sure to place this call at the end of your .psm1 file, to ensure that all definitions to export have already been defined.
Caveat, if a manifest (.psd1) is used:
The manifest's *ToExport keys apply on top of what the .psm1 file - implicitly or explicitly - exports, i.e. you can use it to further narrow what is to be exported, by explicitly enumerating the elements to export, which not only makes the module more self-describing, but also helps performance when PowerShell auto-discovers the commands in available, but not-(yet)-imported modules.
Therefore, if a manifest-based module wants to export variables, it too must have an explicit Export-ModuleMember call in its .psm1 file, with the manifest potentially narrowing down what variables are ultimately to be exported.
Generally, exporting variables from modules is best avoided, because:
it increases the risk of name collisions with variables of the same name defined elsewhere.
discovering which variables are exported by what module isn't as well-known as use of Get-Command is in order to determine what module a given function, cmdlet, or alias comes from. This is because (a) modules that export variables are rare and users generally don't expect it, and (b) the Get-Variable cmdlet - which can tell you what module a variable is defined in - isn't often used in practice.
To see which definitions a given module exports, pass -Verbose to the Import-Module call that imports it. Additionally, pass -Force in order to force re-loading of an already imported module.

PowerShell: Controlling verbose output in a module

So I have this module I will share with a group of people . I want all the output for all the cmdlets IN the module to be have like their where passed -Verbose. Without requiring the user to actual pass -verbose. I do not want -verbose output of any other modules cmdlets I call into.
So I tried $Global:VerbosePreference = "Continue" , and then explicitly -verbose:$false for cmdlets I all into. But it seems the global version overrides the specific version , and I get way to much verbose output.
Is this possible ?
My module is a multi file module , it has over 10 ps1 in it.
Add $VerbosePreference = 'Continue' to the top-level scope of the *.psm1 script-module file that is referenced in the RootModule entry of your module's manifest file (*.psd1).
This scopes the preference to the commands in your module, without affecting code outside of it.

Difference between using module, Import-Module, and #requires -Modules

Is there any detailed reference for how these 3 different methods for importing PowerShell modules work? I'm currently seeing different behavior with using module vs Import-Module in a script.
It seems importing dependencies works differently. Using Import-Module in order of dependencies can resolve the issue, but with using module it doesn't appear to be able to resolve dependencies.
Is this script defendant on how the import statements are created or is there a documented difference in how these different commands work?
I didn't find any guidelines either, but I made the following comparison to make some sense of what is what.
Import-Module
Well, it's a cmdlet. That means it
Accepts pipelines: 'PSReadLine','PSColor' | Import-Module
Accepts splatting: $params = #{Name = 'PSReadLine'; OutBuffer = 1} ; Import-Module #params
Supports flags and parameters: Import-Module -PassThru PSReadLine
Can be called almost everywhere: function Load {Import-Module PSReadLine}
Therefore, it is well suited for ad-hoc module loading and dynamic reloading.
using module
using is a keyword, so it's not something you can pass around like Import-Module. It doesn't take parameters the same way as cmdlets do, and it does not work with pipelines. In short, it's a primitive. Yet another limitation is that it has to be placed on top of the script, before all other statements.
A case when you need to use using module is when you want to load classes and enums. Neither Import-Module nor #Requires will add classes defined in a module into your scope. Generally speaking, it's designed for casual module loading.
#Requires -Modules
This is used to assert that certain modules are loaded (amongst others). In contrast to the rest, this command fails if the module cannot be loaded with Import-Module. Another difference is that it works only in scripts -- it does nothing in shell.

Does PowerShell import function as module command by naming convention?

I have a PS module and in the .psm1 file for this module all relevant .ps1 files are "dot-sourced", or in my vocabulary: loaded. In one of the .ps1 files, let us say I have a function SetFoo.
If I do an Import-Module I cannot use the SetFoo function. If I list the commands for the module via Get-Command it is not available.
If I change the name of the function to Set-Foo the function is recognized after having done Import-Module and it is listed via Get-Command.
So my question is: is it via function naming convention that Set-Foo is loaded and SetFoo is not? I have googled myself silly, but cannot find anything in the PS docs about this.

Is there ever a reason to explicitly Import-Module?

I was just reading the PowerShell Modules guide page and I noticed a line on the Import-Module section:
The following actions trigger automatic importing of a module, also
known as "module auto-loading."
Using a cmdlet in a command. For
example, typing Get-ExecutionPolicy imports the
Microsoft.PowerShell.Security module that contains the
Get-ExecutionPolicy cmdlet.
So given that, why should we ever care about using Import-Module? Isn't it always taken care for us automatically? In what case would I need to explicitly write out Import-Module?
You have to use Import-Module in the following cases :
The module file is not in a path included in $PSModule Path
You have different modules with the same name but in different paths
The module is already loaded and you want to reload it after making modifications to it. (with -Force)
To import only specific cmdlets, functions or variables from that module (with the -Cmdlet, -Function, and -Variable parameters respectively)
To prevent loading cmdlets or functions from the module that would overwrite the commands with the same name and are already loaded in the current session ( with -NoClobber )
To add a prefix to the nouns of the cmdlets in this module ( with -Prefix)
To import a module from a remote computer (with the -PSSession parameter )
The list is not totally exhaustive but these are the main use cases for the Import-Module cmdlet.
I know there is already an accepted answer, but I wanted to add my two cents.
To explicitly document the dependency of a script upon a module
If $PSModuleAutoloadingPreference is set to "none", modules need to be explicitly loaded. You don't know if users have turned this off or not.