I have a PowerShell Modul: SQLModul.psm1 with a variable:
$logFile="C:\logfiles\SQLLog.txt".
I also have a manifest for this module: SQLModul.psd1 where I state:
VariablesToExport = '*'
When I Import this module: import-modul SQLModul all Functions but not this variable will be exported.
Thansk for your help.
Think of the module manifest as a facade or proxy in front of the module(s) it load(s) - the manifest exporting * variables will only affect whatever variables were already exported from a nested psm1 or managed module.
Place Export-ModuleMember -Variable list,of,variable,names at the bottom of your psm1 file, in your case:
# define module functions, variables etc.
# ...
Export-Module -Variable logfile
Placing Export-ModuleMember -Variable * in the psm1 should also work, although that's probably a pretty bad idea, and is generally considered an anti-pattern
Related
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.
I created a custom powershell module in the
C:\Program Files\WindowsPowerShell\Modules\PennoniAppManagement directory. Whenever I make changes to a function in the module, then import the module into a script, the updated code won't take effect. Any solutions?
Make sure you remove the already-loaded version of the module from the session before re-importing it:
Remove-Module PennoniAppManagement -Force
Import-Module PennoniAppManagement
Normally, Import-Module-Force - by itself - is enough to force reloading of an updated module into the current session.
Import-Module -Force implicitly performs Remove-Module before reloading the module (if the module isn't currently loaded, -Force just loads the module normally).
Also note that force-reloading a module is not an option if you're loading it via a using module statement (at least as of PowerShell 7.1.2). Notably the using module method of importing is required if a module exports custom class definitions that the caller should see - see this answer for details.
Mathias' two-step approach - Remove-Module -Force, followed by Import-Module - is apparently needed in some cases, and seems to be required in yours.
It would be good to understand when the two-step approach is needed. Mathias thinks it is related to cached versions of custom class definitions (used module-internally) lingering instead of getting reloaded and redefined when Import-Module -Force is called. That is, while the module overall may get reloaded, it may be operating on stale classes. At least in the simple scenario below I was not able to reproduce this problem, neither in Windows PowerShell 5.1, nor in PowerShell (Core) 7.2.1, but there may be scenarios where the problem does surface.
The Remove-Module documentation describes the -Force parameter solely as relating to the - rarely used - .AccessMode property available on a loaded module's module-information object (you can inspect it with (Get-Module ...).AccessMode). The default value is ReadWrite, which allows unloading (removal) of the module anytime. If the property value is ReadOnly, Remove-Module -Force is needed to unload; if it is Constant, the module cannot be removed from the session at all, once loaded - at least not with Remove-Module.
Notably, the implicit unloading that happens with Import-Module -Force is not subject to these restrictions and implicitly unloads a module even if its .AccessMode is Constant (as of PowerShell 7.1.2; I am unclear on whether that is by design).
Test code involving reloading a module with a modified class definition, to see if Import-Module -Force is enough:
# Create a template for the content of a sample script module.
# Note: The doubled { and } are needed for use of the string with
# with the -f operator later.
$moduleContent = #'
class MyClass {{
[string] $Foo{0}
}}
function Get-Foo {{
# Print the property names of custom class [MyClass]
[MyClass]::new().psobject.Properties.Name
}}
'#
# Create the module with property name .Foo1 in the [MyClass] class.
$moduleContent -f 1 > .\Foo.psm1
# Import the module and call Get-Foo to echo the property name.
Import-Module .\Foo.psm1; Get-Foo
# Now update the module on disk by changing the property name
# to .Foo2
$moduleContent -f 2 > .\Foo.psm1
# Force-import (reload) the module and
# see if the property name changed.
Import-Module -Force .\Foo.psm1; Get-Foo
# Clean up.
Remove-Item .\Foo.psm1
In both Windows PowerShell (whose latest and last version is v5.1) and PowerShell (Core) 7.2.1 (current as of this writing), the above yields, as expected:
Foo1 # Original import.
Foo2 # After modifying the class and force-reloading
I'm new with PowerShell and I've just started to create my own module.
I created the script & manifest files and placed them into the directory C:\Program Files\WindowsPowerShell\Modules\ who is one listed of the $env:PSModulePath command.
I can import and remove the module as well but it's not recognized as an applet or command when I try to call one of the function.
I use the Import-Module command :
Import-Module MyModule
My script file is something like this :
function MyFunction() {}
Export-ModuleMember -Function *
And my manifest looks like this :
FunctionsToExport = '*'
Do I need to write all of the exported functions into the manifest ?
Thank you for your help.
Ok so after a few hours I found the answer :
ExportedCommand empty custom module PowerShell
You need to put RootModule = 'MyModule.psm1' into the manifest.
Have a nice day !
for me, the following ( based on Mica's answer) worked:
Change the RootModule as Mica suggested in the psd1 file to the psm1 file.
Use the Import-Module -Force MyModule command
(with the '-Force' flag:
"This parameter causes a module to be loaded, or reloaded, over top of the current one." as said at https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/import-module?view=powershell-7.1#examples)
To export everything:
Module manifest (.psd1):
FunctionsToExport = '*'
Module script file (.psm1):
Export-ModuleMember -Function *
To restrict what gets exported:
Module manifest (.psd1):
FunctionsToExport = 'Foo', 'Bar'
Module script file (.psm1):
Export-ModuleMember -Function Foo, Bar
Note that if quotes are not used in this specific way, it will not work, and no error will be reported.
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
How do I retrieve a variable exported from my module after an import?
# in mymodule.psm1
$myVar = New-Object VarClass
#assume a function or two here.
Export-Modulemember -Function * -Variable *
# in myScript.ps1 after module import
# how do I reference this variable?
$myScriptVar = $myVar
Sorry for the basic question, I cannot find any examples on this simple problem.
You must explicitly state the functions and variables in the export module-member cmdlet when exporting both. My problem was that I had a functions as well.
From powershell documentation:
If you want to export a variable, in addition to exporting the
functions in a module, the Export-ModuleMember command must include
the names of all of the functions and the name of the variable.
In this instance I have to have the following in my module:
Export-Modulemember -Function Verb-Noun -Variable myVar
I got stuck because the same is true in the manifest, you cannot use a wildcard if you're exporting both.
# Functions to export from this module
FunctionsToExport = 'Verb-Noun'
# Variables to export from this module
VariablesToExport = 'myVar'