I have a powershell module file C:\Program Files\WindowsPowerShell\Modules\MathModule\MathModule.psm1
I have added this so that I can access the functions in the module easily from anywhere. Lets say this contains a function called Add-Numbers.
I have another project where I have MathModule.psm1 with another implementation of Add-Numbers function. From test.ps1 in the same directory I write
Import-Module ".\MathModule.psm1"
Add-Numbers 1 2 3
I was expecting this to use the Add-Numbers definition from the locally imported MathModule.psm1. However, it continues to use the definition from C:\Program Files\WindowsPowerShell\Modules\MathModule\MathModule.psm1
How can I override Add-Numbers from local MathModule.psm1 in test.ps1 instead of the one in Program Files?
If the MathModule module was previously loaded you'll need to add -Force to truly reload it (even from a different psm1 file).
Related
I had a powershell script, which I am not trying to convert to an Azure Function. The script is quite simple, but uses function definitions - something like this:
function InternalFunction {
# Do some processing
...
}
$someData = ...
$someOtherData =
...
# now call internal function
InternalFunction $someData
...
InternalFunction $someOtherData
Now I put this code in run.ps1 in my Azure function code - and it fails complaining that InternalFunction is not a known cmdlet. Specifically, I get this in the log:
The Function app may be missing a module containing the 'InternalFunction'...
So, is there a way to do it using "internal" functions or do I need to rewrite everything to be one function?
You're probably better off defining your functions inside a module and uploading the module with your code.
You can add your own modules by creating a Modules folder at the root of your functionapps directory, this is then appended to your $PSModulePath when the host starts up so that your module is discoverable.
You can find the docs on the folder structure here
I just got an error in Powershell:
because the module nesting limit has been exceeded. Modules can only be nested to 10 levels.
I found this and found something called a "module manifest". I already have a module .psm1 files - why do I also need this?
Note: I dont have 10 levels of modules, I have 10 modules, all loaded in by one import.psm1 file.
The module nesting level getting exceeded is typically the result of accidentally getting into an infinite recursion during module import (irrespective of whether you import via Import-Module or the PSv5+ using module statement).
This can happen whether or not your module has a manifest; the answer to the linked question shows how it can happen with a manifest; here's an example without one: the following foo.psm1 module causes an infinite recursion that results in the error message you saw
# Create sample module (without manifest).
#'
# Accidentally try to import the module itself.
using module .\foo.psm1
function bar { 'hi from module foo' }
'# > foo.psm1
# This fails, because an infinite import loop is entered,
# eventually causing the nesting limit to be exceeded.
Import-Module .\foo.psm1
Why creating a (script) module with a manifest is a good idea:
While module manifests are optional - standalone *.psm1 files can serve as modules by themselves - there are good reasons to use them:
A module manifest is a *.psd1 file that accompanies your *.psm1 file and specifies important metadata, notably the version number, in the form of a hashtable literal; for the best user experience, both files should be placed in a directory of the same name (e.g., Foo.psm1 and its manifest, Foo.psd1, should be placed in a directory named Foo).
By using a manifested module, you enable several important use cases:
You need a manifest to properly support your module's software-development processes, notably version management.
It is also a prerequisite for supporting side-by-side installations of multiple versions of your module.
You need a manifest to automatically load associated resources, such as other modules or auxiliary .NET assemblies, and to define help resources.
You need a manifest in order to integrate with PowerShell's module auto-loading mechanism: If you place your properly manifested module into one of the directories listed in $env:PSModulePath, PowerShell will:
Discover the module and its commands even before the module is imported.
Will import it on demand, the first time you try to call a command from the session.
You need a manifest in order to publish a module to the official online repository for PowerShell modules, the PowerShell Gallery
To quickly outline the steps for creating a module with manifest:
Create a directory named for the base name of your .psm1 file; e.g., Foo
Place the script code as file Foo.psm1 file in that directory.
In the same directory, using the New-ModuleManifest cmdlet, create the manifest .psd1 file with the same base name (e.g., Foo.psd1)
At the very least, update the RootModule entry in the new .psd1 file to point to your .psm1 file (e.g., RootModule = 'Foo.psm1')
To integrate with the auto-loading feature, place your module directory in one of the locations listed in $env:PSModulePath; for the current user, that location is:
Windows PowerShell:
$HOME\Documents\WindowsPowerShell\Modules
PowerShell [Core] v6+:
Windows: $HOME\Documents\PowerShell\Modules
Linux, macOS: $HOME/.local/share/powershell/Modules
To support module discovery and auto-loading efficiently and to explicitly control and signal what a module exports, it is best to explicitly list the individual exported module members in the FunctionsToExport,
CmdletsToExport, VariablesToExport, and AliasesToExport entries of the manifest.
To make module creation easier, the community has provided helper modules:
Plaster is a "template-based file and project generator written in PowerShell", that can also be used to scaffold modules:
The built-in "New PowerShell Manifest Module" template scaffolds a module directory with all necessary files and support for Pester tests.
See this blog post for a walk-through.
Stucco builds on Plaster to provide an "opinionated Plaster template for building high-quality PowerShell modules."
Stucco is an advanced tool that goes beyond mere module creation, by scaffolding an entire project structure that includes psake tasks, scaffolding for CI/CD integration, licensing, and help authoring.
A quick example with Plaster:
# Install Plaster for the current user, if necessary.
Install-Module Plaster -Scope CurrentUser
# Get the template for creating a new script module.
$template = Get-PlasterTemplate | Where TemplatePath -match ScriptModule
# Scaffold a module in subdirectory 'Foo'
# * This will present a series of prompts, most of them with default values.
# * IMPORTANT: Be sure to also choose 'Foo' as the module *name* when prompted,
# so that the module auto-loading feature can discover your module
# (if placed in a dir. in $env:PSModulePath) and also so that you
# you can load it by its *directory* path; e.g., Import-Module ./Foo
Invoke-Plaster -TemplatePath $template.TemplatePath -Destination Foo
# Add a test function to the `.psm1` file.
# Note:
# * This is just for illustrative purposes. In real life, you would
# obviously use an editor to add functions to your module.
# * The function must be placed *before* the `Export-ModuleMember` call in order
# to be exported.
# * As stated, it is additionally recommended to list the exported members
# *explicitly*, one by one, in the *ToExport keys of the *.psd1 file.
(Get-Content -Raw ./Foo/Foo.psm1) -replace '\r?\n\r?\n', "`n`nfunction Get-Foo { 'Hi from module Foo.' }`n" | Set-Content -Encoding utf8 ./Foo/Foo.psm1
# Import the newly created module by its *directory* path.
# IMPORTANT:
# As stated, this assumes that you specified 'Foo' as the module name, i.e.
# that your manifest's file name is 'Foo.psd1', and your script module's
# 'Foo.psm1'.
Import-Module ./Foo -Verbose -Force
'---'
# Call the test function
Get-Foo
'---'
# Invoke the module's tests.
# Note: The scaffolding creates a single test to ensure that the
# module manifest (*.psd1) is valid.
Invoke-Pester ./Foo
You should see output such as the following:
VERBOSE: Loading module from path 'C:\Users\jdoe\Foo\Foo.psd1'.
VERBOSE: Loading module from path 'C:\Users\jdoe\Foo\Foo.psm1'.
VERBOSE: Importing function 'Get-Foo'.
---
Hi from module Foo.
---
____ __
/ __ \___ _____/ /____ _____
/ /_/ / _ \/ ___/ __/ _ \/ ___/
/ ____/ __(__ ) /_/ __/ /
/_/ \___/____/\__/\___/_/
Pester v4.9.0
Executing all tests in './Foo'
Executing script C:\Users\jdoe\Foo\test\Foo.Tests.ps1
Describing Module Manifest Tests
[+] Passes Test-ModuleManifest 128ms
Tests completed in 375ms
Tests Passed: 1, Failed: 0, Skipped: 0, Pending: 0, Inconclusive: 0
Let's say I had a file File.jl that had a module MyModule containing the functions foo and bar in it. In the same directory as the module-file, I had a script Script.jl, and I wanted to use the functions in MyModule in the script.
How would one go about doing this?
In order to find Modules that are not in the standard LOAD_PATH and be able to import them, you need to update your LOAD_PATH variable for the current folder explicitly
push!( LOAD_PATH, "./" )
then you will be able to import a module appropriately.
Note that, if the file is called File.jl and defines the module MyModule, what you should be importing is import MyModule, not import File. It is generally recommended you use the same name for the file as for the defined module in this kind of scenario, to avoid confusion.
Also note, As #crstnbr noted above, you can also simply 'dump' the file's contents into the current session by simply 'including' it; note however that this simply creates the module on the spot, so any precompilation directives etc will not be honoured.
Somewhat related questions / answers (disclaimer: by me) you might find useful:
https://stackoverflow.com/a/50627721/4183191
https://stackoverflow.com/a/49405645/4183191
You include the file with the module definition and call the functions in your script file:
include(joinpath(#__DIR__,"File.jl"))
MyModule.foo()
MyModule.bar()
# or just foor() and bar() if MyModule exports those functions
The #__DIR__ expands to the directory of the script file, see
help?> #__DIR__
#__DIR__ -> AbstractString
Expand to a string with the absolute path to the directory of the file containing the macrocall. Return the current working directory if run from a REPL or if evaluated by julia -e <expr>.
I have a simple powershell module containing a single function, an abridged version of this is as follows:
function My-Func
{
.
.
.
}
Export-ModuleMember -Function 'My-Func'
My manifest file contain a line to explicitly export this:
FunctionsToExport = "My-Func"
Everything uploads to the powershell gallery via Publish-Module without any problems, then when I come to install this and run Get-Module, I do not see the function in the export commands column of the output, also I when I attempt to call the function powershell tells me it does not exist.
I have a psm1 file for my module and a psd1 manifest, for some reason when I only see Manifest as the module type, I'm guessing I need to see script ?.
Any ideas ?
in your .psm1:
remove the Exported-ModuleMember line
in your .psd1:
RootModule = 'yourmodule.psm1'
FunctionsToExport = #('function1','function2')
the psd1 file FunctionsToExport works like the Exported-ModuleMember command. it's a cleaner way to define things from one centralized file.
I have developed a powershell module in C#, implemented a few commands.
How can I execute C# code in this module when it's imported by Powershell?
Create a module manifest with the ModuleToProcess (or RootModule in V3) field set to the PSM1 file and the NestedModules set to the DLL e.g.:
RootModule = 'Pscx.psm1'
NestedModules = 'Pscx.dll'
This is what we do in the PowerShell Community Extensions where we do the same thing - fire up a script first. You can see our PSD1 file here.
This is a very basic solution, simply replace code within the {} with your source. (my test below)
add-type 'public class c{public const string s="Hello World";}';[c]::s
enjoy
I'm also writing a binary cmdLet in .NET. I have found that if you create a class that inherits from at least DriveCmdletProvider, that class can implement InitializeDefaultDrives.
This method will get call when import-module is called on your DLL.
You could use this 'feature' to stand up some session (or module session) data.