PowerShell FAQ - 傳入 Callback 函式參數
0 |
最近常在寫自動化及半自動化工作腳本,愈發覺得 PowerShell 好用,尤其能無縫整合 .NET 程式庫這點讓它威力無極限。但也開始學到一些實用但我之前沒學過的用法,會在 PowerShell FAQ 系列陸續整理分享。
【問題】PowerShell Function 如何接收外部函式作為輸入參數,並在函式內呼叫?
用 C# 比喻,就是指下列 DoJob 方法的 Action<string> reportProgress 參數:
public class Job
{
public string JobId { get; set; }
public Job(string jobId)
{
JobId = jobId;
}
public void Execute()
{
Console.WriteLine($"Job [{JobId}] is executing...");
}
}
static void DoJob(Job[] jobs, Action<string> reportProgress)
{
int c = 0;
jobs.ToList().ForEach(job =>
{
job.Execute();
c++;
reportProgress($"{c}/{jobs.Length} done");
});
}
static void Main(string[] args)
{
var jobs = new Job[]
{
new Job("Coding"),
new Job("Build"),
new Job("Deploy")
};
DoJob(jobs, (m) =>
{
Console.WriteLine(m);
});
Console.ReadLine();
}
以下是 PowerShell 傳入 Callback 函式的範例:(連 C# Job Class 部分也試著用 PowerShell 實作,建構式、屬性、方法,PowerSehll 的類別都支援,一點不含糊,是可以認真應用的好語言)
補充:Class 要 PowerShell 5.0+,Windows Server 2016+ 才內建,Windows 2012R2 需另外安裝 Windows Management Framework 5.1 參考
function ShowProgress() {
param ([string] $msg)
Write-Host $msg
}
class Job {
[string]$JobId
Job([string]$jobId) {
$this.JobId = $jobId
}
Execute() {
Write-Host "Job [$($this.JobId)] is executing..."
}
}
function DoJobs([Job[]] $jobs, [scriptblock] $reportProgress) {
$c = 0;
$jobs | ForEach-Object {
$_.Execute()
$c++;
$reportProgress.Invoke("$c/$($jobs.Length) done")
}
}
$jobs = (
[Job]::new("Coding"),
[Job]::new("Build"),
[Job]::new("Deploy")
)
DoJobs $jobs $Function:ShowProgress
有三個關鍵處:
- Callback 參數型別請用 [ScriptBlock]
- 呼叫 Callback 時用 .Invoke
- 傳入 [ScriptBlock] 時寫成 $Function:函式名稱
用 Visual Studio Code 開發及測試 PowerShell,整體體驗順手流暢,推。實測結果如下,成功!
等等,C# 裡是用 Lambda 表示式提供 reportProgress,PowerShell 行不行?當然沒問題:
DoJobs $jobs { Param($m) Write-Host $m }
發現目前版本的 VSCode PowerShell (v2020.4.0) 解析上述寫法時會彈出 Missing closing '}' in statement block or type definition. 警告,推測是 Bug,但不影響執行。
Tips of how to pass callback parameters to PowerShell function.
Comments
Be the first to post a comment