Accessing a hash table through a module - powershell

I have defined this in module as defblah.ps1
$defblah= #{
first = "aaa";
seconf = "bbb";
}
I also have this in module as Blah.ps1
Function Blah
{
Write-Host $defblah.first;
}
I did Export-ModuleMember and then Import-Module, so everything with module definition (export, import) is fine.
Then, after importing I run Blah, it prints "aaa", which is what i expected.
The problem is when I type in
Write-Host $defblah.first;
it returns nothing. How can I make my last statement work and return "aaa"?

Generally, I suggest not exporting variables from a module, even though it is technically supported.
A module's implicit export behavior indeed precludes variables - in PSv5+, only functions and aliases are exported by default - meaning the absence of an Export-ModuleMember and/or module manifest (*.psd1) controlling the exports.
The general expectation is for a module to export commands (functions / cmdlets and possibly also aliases), not data (variables) - and commands alone present enough potential for name collisions.
If you truly want to export variables from your module, use an Export-ModuleMember call with the
-Variable parameter and/or - if your module comes with a manifest file - export the variables via the VariablesToExport key.

Related

PowerShell Azure function - use internal function

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

Why would I need a module manifest - because the module nesting limit has been exceeded

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

Import modules and functions from a file in a specific directory in Julia 1.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>.

Powershell module function not visible in Get-Modules

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.

Initializing powershell module variables that will be exported

I am having trouble understanding why I cannot achieve the following:
Create a set of variables in a module.
Have a function in the module do something and update the parent scope variable with the changed value.
Import the Module into a script that calls the same function and have the updated value available to the script that imported the module.
For example
Module Lib has the following:
$psVarx = -1
function Init {
$psVarx = 2
$script:psVarx = $psVarx
}
Export-Member -variable $psVarx
And the script using the module has the following:
Import-Module Lib -Force
Init
"psVarx is {0}" -f $psVarx
The output received is
psVarx is -1
The question is if I updated the script scoped copy of the variable in the module, why does the script using the module not see the updated value of the variable? I am pretty sure the issue has to do with scoping. What am I missing here?
What is the recommended method for initializing module variables in the situation where the module has work it needs to do to initialize itself and set variables that then should be made available to the code that is Importing the module?
In this particular case I have dozens of variables that I would like to initialize within a module and then export the newly initialized values.
In PowerShell V3 the following works:
$psVarx = -1
function Init {
$psVarx = 2
$script:psVarx = $psVarx
}
Export-ModuleMember -variable psVarx -Function init
Notice that psVarx (not $psVarx) is passed to Export-modulemember (not Export-Member). Also Init is specified.