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
Related
Question:
What would be the best way to import functions to tests that don't reside in the same directory?
Example
📁 src
📄 Get-Emoji.ps1
📁 test
📄 Get-Emoji.Tests.ps1
Inb4
Pester documentation[1] suggests test files are placed in the same directory as the code that they test. No examples of alternatives provided.
Pester documentation[2] suggests dot-sourcing to import files. Only with examples from within same directory
Whether breaking out tests from the src is good practice, is to be discussed elsewhere
Using Powershell Core for cross platform support on different os filesystems (forward- vs backward slash)
[1] File placement and naming convention
Pester considers all files named .Tests.ps1 to be test files. This is the default naming convention that is used by almost all projects.
Test files are placed in the same directory as the code that they test. Each file is called as the function it tests. This means that for a function Get-Emoji we would have Get-Emoji.Tests.ps1 and Get-Emoji.ps1 in the same directory. What would be the best way to referencing tests to functions in Pester.
[2] Importing the tested functions
Pester tests are placed in .Tests.ps1 file, for example Get-Emoji.Tests.ps1. The code is placed in Get-Emoji.ps1.
To make the tested code available to the test we need to import the code file. This is done by dot-sourcing the file into the current scope like this:
Example 1
# at the top of Get-Emoji.Tests.ps1
BeforeAll {
. $PSScriptRoot/Get-Emoji.ps1
}
Example 2
# at the top of Get-Emoji.Tests.ps1
BeforeAll {
. $PSCommandPath.Replace('.Tests.ps1','.ps1')
}
I tend to keep my tests together in a single folder that is one or two parent levels away from where the script is (which is usually under a named module directory and then within a folder named either Private or Public). I just dot source my script or module and use .. to reference the parent path with $PSScriptRoot (the current scripts path) as a point of reference. For example:
Script in \SomeModule\Public\get-something.ps1
Tests in \Tests\get-something.tests.ps1
BeforeAll {
. $PSScriptRoot\..\SomeModule\Public\get-something.ps1
}
Use forward slashes if cross platform compatibility is a concern, Windows doesn't mind if path separators are forward or backslashes. You could also run this path through Resolve-Path first if you wanted to be certain a valid full path is used, but I don't generally find that necessary.
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 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).
For a number of reasons, it would be really useful if I could create a file from a Jenkins pipeline and put it in my workspace. If I can do this, I could avoid pulling in some repositories where I'm currently pulling them in for just one or two files, keep those files in a maintainable place, and I could also use this to create temporary powershell scripts, working around a limitation of the solution described in https://stackoverflow.com/a/42576572
This might be possible through a Pipeline utility, although https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/ doesn't list any such utility; or it might be possible using a batch script - as long as that can be passed in as a string
You can do something like that:
node (''){
stage('test'){
bat """
echo "something" > file.txt
"""
String out = readFile(file.txt).trim()
print out // prints variable out groovy style
out.useFunction() // allows running functions loaded from the file
bat "type %out%" // batch closure can access the variable
}
}
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.