I’m creating custom modules, and I have a function that has an inner helper function, but when I call it, Powershell complains it doesn’t know it. I do have the inner function defined just after the parameter block at top of outer function. I have a button -Onclick event set to run the inner function, but it throws the error.
Appreciate any help or insight.
It sounds like you are talking about creating a powershell module, for use within a powershell universal app/dashboard?
I’m reading into your post a little here - as there’s limited information to go by, but it sounds also like you are defining all your code for these functions within the code of the app/dashboard itself?
Doing this you are likely to run into scoping issues.
I would research and learn about Powershell modules in general, how to create them, module manifest files (psm1/psd1), how private and public folders work regarding private/public functions, and how to then package/install those modules.
I suppose what I’m getting at is, if you create a module with private and public functions, in this scenario, your private functions are imported by the module and accessible to it. Your public functions will be defined in the manifest.
The module can sit in your user, system or PSU module folder, then those functions will be accessible within your dashboard and you won’t have the scoping issues I think you’re describing here.
Though of course I could be completely misunderstanding what you’re trying to ask, I think we’d all need to understand the use case, scenario, how your code is written, where its situated etc in order to advise further
Thanks for reply. I’m writing a custom module to centralize commonly used homemade cmdlets. I have a module function that creates a modal dialog box for user to input data. Inside that function, I have inner helper functions to make code easier to read. But when I call the inner function from the main outer function, PSU says "The term is not recognized as a name of a cmdlet, function etc, etc. So either I’m doing something wrong, or I don’t uderstand the scoping that PSU uses or ?
Correct me if I’m misunderstanding but it sounds like you want to call a nested child function (nested inside another function) from a parent scope. This isn’t PSU specific but sounds like just a general powershell scoping issue and normal to me. You’d have to define the function at the right level / write a module and export the function properly so that it’s accessible publicly. Though being honest we’d need to see some code or examples in order to really understand and offer advise because I could be misinterpreting this entirely.
I don’t mind pasting the code below. I’m thinking it is because of a scoping issue(?) Here is the function in my custom module. A button below tries to call the “Generate-Password” nested function, but PSU says
PSU support is recommending I move Generate-Password out of this function and up to the Module to give it global scope, but I’m hoping for a better way.
Thank you.
function Show-CBLModalPasswordReset {
[CmdletBinding()]
param(
[string]$UserPrincipalName,
[string]$DisplayName
)
#Function to execute when 'Generate' button is pushed.
function Generate-Password {
$length = (get-UDElement -ID 'txtLength').Value
Set-UDElement -id 'txtPassword' -Properties @{ 'Value' = (Get-CBLRandomPassword -Length $length ) }
}
#modal Header
$Header = { new-UDTypography -Text "Reset Password: $UserPrincipalName" -FontWeight "bold" -Variant "subtitle1"}
#card headers
$Header2 = New-UDCardHeader -SubHeader "Either 'Generate' a password, or create your own"
$Header3 = New-UDCardHeader -SubHeader "Send an Email Notification" -Action (New-UDCheckbox -Checked $true -Label "Send Email?" -Id "chkSendEmail" )
#Modal window footer
$Footer = {
New-UDButton -Text "Submit" -color 'success' -OnClick { Send-MailMessage -To 'joe.smith@example.com' `
-Subject (Get-UDElement -Id 'txtSubject').Value -Body (Get-UDElement -Id 'txtEmail').Value }
New-UDButton -Text "Cancel" -OnClick { Hide-UDModal } }
#Password creation card
$Body1 = New-UDCardBody -Content {
New-UDGrid -Container -ColumnSpacing 1 -Children {
New-UDGrid -Item -ExtraSmallSize 4 -Children { new-UDTextbox -Label "Password" -Placeholder "Enter Password" -FullWidth -ID 'txtPassword' -OnChange Generate-Password }
New-UDGrid -Item -ExtraSmallSize 2 -Children { new-UDTextbox -Label "Length" -Type 'number' -Value 10 -id 'txtLength' }
new-UDGrid -Item -ExtraSmallSize 4 -Children { New-UDButton -Text "Generate" -Icon ( New-UDIcon -Icon 'arrows-rotate' -size '2x' ) -OnClick Generate-Password
}
New-UDGrid -Item -Children { new-UDCheckBox -Checked $true -Label "Require reset next login?" -LabelPlacement "start" -ID 'chkChangeRequired' -OnChange `
Set-UDElement -id 'txtEmail' -Properties @{ 'Value' = (Get-EmailBody -DisplayName $DisplayName -UserPrincipalName $UserPrincipalName -RequirePasswordReset ) } }
}
}
#Email send card
$Body2 = New-UDCardBody -Content {
New-UDStack -Children {
new-UDStack -Children {
New-UDTypography -Text "To:"
new-UDTextbox -FullWidth -Id 'txtTo' -Value 'hr@example.com'
} -Spacing 2
new-UDStack -Children {
New-UDTypography -Text "Subject:"
new-UDTextbox -Id 'txtSubject' -FullWidth -Value "***Access for $UserPrincipalName"
} -Spacing 2
New-UDTextbox -Multiline -Rows 10 -FullWidth -Id 'txtEmail' -Value $Email
} -Direction 'column' -Spacing 2
}
#Show the actual Modal window. Everything above is config sections
show-UDModal -Header $Header -Content {
new-udcard -Body $Body1 -Header $Header2
new-udcard -Body $Body2 -Header $Header3
} -Footer $Footer
}
“PSU support is recommending I move Generate-Password out of this function and up to the Module to give it global scope, but I’m hoping for a better way.”
This is the better way! I don’t see anywhere in your code generate-password actually being called. Only defined. In the code you’ve shown, only Show-CBLModalPasswordReset is aware of the function because it’s defined within. This is just standard PS scoping. If you call that function from outside Show-CBLModalPasswordReset, it’s never going to know what it is because you’re then out off scope.
If you define it at a parent scope then it will be available to that parent scope and child scopes.
I’d say this isn’t PSU related, more just a general understanding of powershell scoping. If you do run into genuine PSU scoping related issues, you can always create an actual module (psm1/psd1) and then put that into the PSU module folder, and import the module wherever you need to use it. Any functions you want can be made public and called once imported.
I would recommend watching a few YouTube tutorials on writing modules and getting your head around private and public folders, module manifests and installing / importing them. It may be beneficial here!
Edit: sorry I just spotted it. The onclick (expected that to be wrapped as a script block). I’d go for the above and create a fully fledged module with generate-password as a top level module function and then just import that into your dashboard. Sometimes endpoints and script blocks are out of scope so you’ll run into this issue. If you go down the module import route you only have to have it defined in one place too.
I’ll take a look and read up on modules. Thanks for taking the time to respond.