试图在Powershell中传递一个高级函数作为函数参数



我有一个包含计算机名称的CSV文件。我导入它们,并希望使用每个值来做一些事情。

$computerNames = import-csv -Path "C:UsersfakePathDesktopProgrammingPowershellremoteAddPrinterscomputers.csv" -header "Computers"
function Iterate-CSV {
param (
# Parameter help description
[Parameter(Mandatory=$true)]
[array]
$csvFilePath,
[scriptblock]$functionCall #?
)
foreach ($computer in ($csvFilePath).Computers) { # Computer is the argument used in other functions.
Write-Host $functionCall.Invoke($computer)
}
}

它接受一个csv文件作为参数,然后循环遍历它。试图将此函数作为参数传递

function Add-NetworkPrinter {
[CmdletBinding()]
param (
# Parameter help description
[Parameter(Mandatory=$true, Position=0)]
[String]
$computerName
)

begin {
$addPrinterCue = "\printServerprintCue"
}

process { # This is a non-terminating error and cannot be handled by try/catch
Write-Output "$addPrinterCue && $computerName"
# invoke-command -ComputerName $computerName -scriptBlock {
#     # cmd.exe /c rundll32 printui.dll,PrintUIEntry /gd /n$addPrinterCue
#     cmd.exe /c rundll32 printui.dll,PrintUIEntry /ga /n$addPrinterCue /q
#     Restart-Service -Name Spooler -Force
#                                     #Creates error to handle
# } -Credential $domainCredentials  #-ErrorVariable errmsg 2>$null
}

end {
Write-Output "Successfully added printer to $computerName"
}
}

这样我就不必编写另一个foreach循环来使用CSV中的值同步执行其他任务,我可以只让函数接受一个参数,迭代变量

您需要传递一个调用您的函数的scriptblock

$func = [scriptblock]{ 
param ($arg)
Add-NetworkPrinter $arg 
}
Iterate-CSV -csvFilePath ... -functionCall $func

要引用注册函数的底层scriptblock定义,请使用function:驱动器前缀将其作为变量传递:

Iterate-Csv ... -scriptBlock ${function:Add-NetworkPrinter}

我没有创建一个名为Add-NetworkPrinter的高级函数,而是创建了一个scriptblock,正如@Andrey指出的那样,同时保留了迭代CSV文件值的高级函数。

$computerNames = import-csv -Path "C:fakePathcomputers.csv" -header "Computers"
function Iterate-CSV {
param (
# Parameter help description
[Parameter(Mandatory=$true)]
[array]
$csvFilePath,
[scriptblock]$functionCall
)
foreach ($computer in ($csvFilePath).Computers) { 
Write-Host $functionCall.Invoke($computer)
}
}
$addNetworkPrinter = [scriptblock]{ 
param ($computer)
$addPrinterCue = "\printServerprintCue"
Write-Output "$addPrinterCue && $computer"
# invoke-command -ComputerName $computerName -scriptBlock {
#     # cmd.exe /c rundll32 printui.dll,PrintUIEntry /gd /n$addPrinterCue
#     cmd.exe /c rundll32 printui.dll,PrintUIEntry /ga /n$addPrinterCue /q
#     Restart-Service -Name Spooler -Force
#                                     #Creates error to handle
# } -Credential $domainCredentials  #-ErrorVariable errmsg 2>$null
}
$restarComputers = [scriptblock]{
param (
[Parameter(Mandatory=$true, Position=0)]
[string]
$computer
)
Write-Output "Restarting computer $computer"
# Restart-Computer -ComputerName $computer -Credential $domainCredentials -Force
}

然后我通过提供csv的路径作为param1和scriptblocks来调用我的Iterate-CSV函数,这些路径为param2使用相同的值。感谢ScriptBlock的信息!

Iterate-CSV -csvFilePath $computerNames -functionCall $addNetworkPrinter
Iterate-CSV -csvFilePath $computerNames -functionCall $restarComputers

最新更新