I have been racking my brain over this and scouring the internet for an answer, but I can't seem to find anything for my specific situation. I have created a set of Functions that help me add/remove users and groups from the local "Remote Desktop Users" group on Win2016 Servers remotely. By themselves, they work fine, but I am trying to add them to a menu script that I am developing so other admins can use them without having to run them manually.
The problem I am having is that in my script setup, I have created groups of logging functions that I am trying to use inside of my Add/Remove User functions, which needs to be used inside of an Invoke-Command -ScriptBlock. However, this is the error that I get:
The term 'Write-GreenConsole' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
+ CategoryInfo : ObjectNotFound: (Write-GreenConsole:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : SERVER01
Here are two of the functions am trying to get to work together. The first one is the logging function, the second one is the Add/Remove function.
function Write-GreenConsole ( $Details ) {
$today = Get-Date -UFormat %d%b%Y
$LogPath = "\\Network_Path\RDP_Logs_$today.log"
$LogDate = Get-Date -UFormat "%D %T"
$LogLevel = "INFO"
$Results = Write-Output "[$LogDate] [$LogLevel] [$ServerName]: $Details"
$Results | Out-File -FilePath $LogPath -Append
Write-Host "[$LogDate] [$LogLevel] [$ServerName]: $Details" -ForegroundColor Green -BackgroundColor Black
}
function Get-RDPGoupMembers ( $svrName ) {
Invoke-Command -ComputerName $svrName -ScriptBlock {
Write-GreenConsole "[ Group members for Server $env:COMPUTERNAME =" (Get-LocalGroupMember -Group 'Remote Desktop Users').Name "]"
}
}
The "$svrName" variable comes from the main script based on user inputs from the menu. Please let me know if you need any more details. Any ideas would be greatly appreciated, thank you!
A remotely executing script block shares no state with the caller, so the script block you're passing to
Invoke-Command-ComputerName ...doesn't know about the caller'sWrite-GreenHostfunction.Therefore, you must pass the function definition to the script block and recreate the function there:
Note:
The above focuses just on recreating your function as-is.
${function:Write-GreenConsole}is an example of namespace variable notation: on getting the value, the function's body is returned; on setting it, the function created (or its existing body is redefined). See this answer for background information.Note the use of an aux. variable,
$funcDef, to store the function body in the caller's scope, which is then referenced in the remote script block via the$using:scope.The reason is that trying to combine
$using:with namespace variable notation currently (as of PowerShell (Core) 7.3.x) causes parser errors with function names containing-and is quietly ignored with function names that don't; that is,${using:function:Write-GreenConsole}does not work.Arguably, however, it should, especially given that it does work with
Start-Job. See GitHub issue #20422.