PowerShell:如何在函数内部、Invoke-Command ScriptBlock 内部调用函数?

问题描述 投票:0回答:1

我一直在绞尽脑汁地思考这个问题,并在互联网上寻找答案,但我似乎找不到任何适合我的具体情况的信息。我创建了一组函数,可以帮助我从 Win2016 服务器上的本地“远程桌面用户”组中远程添加/删除用户和组。它们本身工作得很好,但我试图将它们添加到我正在开发的菜单脚本中,以便其他管理员可以使用它们,而无需手动运行它们。

我遇到的问题是,在我的脚本设置中,我创建了一组日志记录函数,我试图在添加/删除用户函数内部使用这些函数,这些函数需要在 Invoke-Command -ScriptBlock 内部使用。但是,这是我得到的错误:

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

以下是我试图协同工作的两个功能。第一个是日志记录功能,第二个是添加/删除功能。

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 "]"
  }
}

“$svrName”变量来自基于菜单中用户输入的主脚本。如果您需要更多详细信息,请告诉我。任何想法将不胜感激,谢谢!

powershell function logging scripting invoke-command
1个回答
0
投票

远程执行的脚本块不与调用者共享任何状态,因此您传递给

Invoke-Command -ComputerName ...
的脚本块不知道调用者的
Write-GreenHost
函数。

因此,您必须将 函数定义传递给脚本块并在那里重新创建函数

function Get-RDPGoupMembers ($svrName) {
  Invoke-Command -ComputerName $svrName -ScriptBlock { 
    ${function:Write-GreenConsole} = $args[0] # recreate the function
    Write-GreenConsole "[ Group members for Server $env:COMPUTERNAME =" (Get-LocalGroupMember -Group 'Remote Desktop Users').Name "]"
  } -ArgumentList ${function:Write-GreenConsole} # pass the function body
}

注:

  • ${function:Write-GreenConsole}
    命名空间变量表示法的示例 - 请参阅此答案了解背景信息。

  • (隐式字符串化)函数体通过

    Invoke-Command
    -ArgumentList
    参数传递,即作为(位置不变的)参数,远程脚本块通过 自动
    $args
    变量访问
    在这种情况下,为简洁起见;不过,您可以自由地声明参数

    • 虽然通常您可以更方便地直接从调用者的范围引用值,但通过
      $using:
      范围
      这似乎可以使用命名空间变量表示法。
© www.soinside.com 2019 - 2024. All rights reserved.