6

How do I reference other powershell functions from within my run.ps1 file in my Azure Function written in powershell?

Details:

I have 25 private, "helper" functions that I've written the help manipulate data, hashtables, and generally make it easier for me to write scripts in powershell. I'm constantly changing and adding capabilities to these functions and I'd prefer to have them grouped together in a lib folder then imported when my Azure Function cold-starts.

I can get all of this working by including my "helper" functions in the top of my run.ps1 file (which I don't want to do because this feels kludgy and doesn't allow me to separate each function into it's own file).

How do I get this to work by separating out all my functions into their own files and then source/importing them?

I've tried setting my folder structure like this:

FunctionApp
 | - host.json
 | - profile.ps1
 | - lib
 | | - helperfunction1.ps1
 | | - helperfunction2.ps1
 | | - helperfunction3.ps1
... (etc)
 | - myFunction
 | | - function.json
 | | - run.ps1

And I use this code in my profile.ps1 file to import each function:

$functionFiles = Get-ChildItem -Path "$PSScriptRoot\lib" -Filter *.ps1
Write-Information "Loading scripts"
foreach($file in $functionFiles){
    Write-Information "Sourcing $($file.FullName)"
    . $file.FullName
}

Everything works great when I run/test locally, but when I deploy to Azure it fails with this stacktrace:

2019-07-12T18:25:10.461 [Error] Executed 'Functions.HttpTriggerClientIssues' (Failed, Id=bf6fccdd-8972-48a0-9222-cf5b19cf2d8e)
Result: Failure
Exception: Value cannot be null.
Parameter name: value
Stack:    at Google.Protobuf.ProtoPreconditions.CheckNotNull[T](T value, String name)
   at Microsoft.Azure.WebJobs.Script.Grpc.Messages.StreamingMessage.set_RequestId(String value) in C:\projects\azure-functions-powershell-worker\src\Messaging\protobuf\FunctionRpc.cs:line 309
   at Microsoft.Azure.Functions.PowerShellWorker.Utility.RpcLogger.Log(Level logLevel, String message, Exception exception, Boolean isUserLog) in C:\projects\azure-functions-powershell-worker\src\Logging\RpcLogger.cs:line 46
   at Microsoft.Azure.Functions.PowerShellWorker.PowerShell.PowerShellManager.InvokeProfile(String profilePath) in C:\projects\azure-functions-powershell-worker\src\PowerShell\PowerShellManager.cs:line 181
   at Microsoft.Azure.Functions.PowerShellWorker.PowerShell.PowerShellManager.Initialize() in C:\projects\azure-functions-powershell-worker\src\PowerShell\PowerShellManager.cs:line 106
   at Microsoft.Azure.Functions.PowerShellWorker.PowerShell.PowerShellManagerPool.CheckoutIdleWorker(StreamingMessage request, AzFunctionInfo functionInfo) in C:\projects\azure-functions-powershell-worker\src\PowerShell\PowerShellManagerPool.cs:line 99
   at Microsoft.Azure.Functions.PowerShellWorker.RequestProcessor.ProcessInvocationRequest(StreamingMessage request) in C:\projects\azure-functions-powershell-worker\src\RequestProcessor.cs:line 235

I'm confused why it works locally but not in Azure. In the end I'd really like to be able to define all of my functions in their own files, import them once, and be able to use them in my run.ps1 file (and even better, if I created multiple HTTP triggers within the same FunctionApp, I'd love to be able to share my helper functions across triggers)

3
  • Please provide the detailed error log and if possible , please provide the code. Also try to print the path Get-ChildItem -Path "$PSScriptRoot\lib" and check if the files are available or not under that path.If logging is not enabled please add info logging so that we can understand which line is causing issue. Commented Jul 15, 2019 at 6:17
  • @MohitVerma-MSFT I reread the docs and I'm wondering if "DOT sourcing" my functions will even work within Azure. I followed the instructions at learn.microsoft.com/en-us/azure/azure-functions/… to create a "Modules" folder and place .psm1 files in there but it still doesn't make the functions defined in the .psm1 files available: Result: ERROR: The term 'get-cctestfunction3' is not recognized as the name of a cmdlet, function, script file, or operable program. So either the docs are wrong or I'm not doing it right :-) Commented Jul 16, 2019 at 20:45
  • Rather than assuming that my .psm1 files will get auto imported, I did just try to explicitly import them in my run.ps1: Import-Module 'D:\home\site\wwwroot\Modules\get-cctestfunction3.psm1' $mystring = get-cctestfunction3 $body += "mystring: $mystring<br/>" That worked. But I'm not sure I want to explicitly import all the .psm1 files in my run.ps1? Commented Jul 16, 2019 at 20:59

1 Answer 1

7

I got it figured out.

Place your helper functions in .psm1 files within the Modules folder, like this:

FunctionApp
 | - host.json
 | - profile.ps1
 | - Modules
 | | - helperfunction1.psm1
 | | - helperfunction2.psm1
 | | - helperfunction3.psm1
... (etc)
 | - myFunction
 | | - function.json
 | | - run.ps1

Even though the documentation currently says your helper functions will automatically be available, my experience is showing you still have to import your files:

#in profile.ps1:
foreach($file in Get-ChildItem -Path "$PSScriptRoot\Modules" -Filter *.psm1){
    Import-Module $file.fullname
}

That seems to be working for me for now.

Thank you~!

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for sharing. I did some tests and for the AzFunction to pick up the module automatically, it needs to have a module manifesto (psd1), and your module must be listed in the 'requirements.psd1'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.