gpt4 book ai didi

powershell - 如何从 Start-Job 调用脚本中的 powershell 函数?

转载 作者:行者123 更新时间:2023-12-04 01:59:52 28 4
gpt4 key购买 nike

我看到了this questionthis question但找不到我的问题的解决方案。

所以情况如下:
我在脚本 (.ps1) 文件中有两个函数 DoWork 和 DisplayMessage。这是代码:

### START OF SCRIPT ###
function DoWork
{
$event = Register-EngineEvent -SourceIdentifier NewMessage -Action {
DisplayMessage($event.MessageData)
}

$scriptBlock = {

Register-EngineEvent -SourceIdentifier NewMessage -Forward

$message = "Starting work"
$null = New-Event -SourceIdentifier NewMessage -MessageData $message

### DO SOME WORK HERE ###

$message = "Ending work"
$null = New-Event -SourceIdentifier NewMessage -MessageData $message

Unregister-Event -SourceIdentifier NewMessage
}

DisplayMessage("Processing Starts")

$array = @(1,2,3)
foreach ($a in $array)
{
Start-Job -Name "DoActualWork" $ScriptBlock -ArgumentList $array | Out-Null
}

#$jobs = Get-Job -Name "DoActualWork"
While (Get-Job -Name "DoActualWork" | where { $_.State -eq "Running" } )
{
Start-Sleep 1
}

DisplayMessage("Processing Ends")

Get-Job -Name "DoActualWork" | Receive-Job
}

function DisplayMessage([string]$message)
{
Write-Host $message -ForegroundColor Red
}

DoWork

### END OF SCRIPT ###

我正在创建 3 个后台作业(使用具有 3 个元素的 $array)并使用事件将消息从后台作业传递到主机。我希望powershell主机显示“处理开始”和“处理结束”1次,“开始工作”和“结束工作”各3次。但相反,我没有在控制台中显示“开始工作”/“结束工作”。

事件也被视为 powershell 中的作业,因此当我执行 Get-Job 时,我可以看到与事件作业相关的以下错误:

{The term 'DisplayMessage' 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.}



我的问题:我们如何重用(或引用)在我调用 Start-Job 的同一脚本中定义的函数(在我的例子中为 DisplayMessage)?是否可以?
我知道我们可以使用 -InitializationScript 将函数/模块传递给 Start-Job,但我不想编写两次 DisplayMessage 函数,一个在脚本中,另一个在 InitializationScript 中。

最佳答案

后台作业在单独的进程中运行,因此您使用 Start-Job 创建的作业除非您将它们包含在 $scriptblock 中,否则无法与函数交互.

即使您在 $scripblock 中包含该函数, Write-Host在您使用 Get-Job | Receive-Job 之前不会将其内容输出到控制台接收作业结果。

编辑 问题是您的 DisplayMessage函数在本地脚本范围内,而您的事件处理程序在不同的父范围内运行(例如全局,即 session 范围),因此它找不到您的函数。如果您在全局范围内创建函数并从全局范围内调用它,它将起作用。

我已经修改了您的脚本来执行此操作。我还修改了 scriptblock 并在脚本完成后取消注册事件,因此当您多次运行脚本时不会收到 10x 消息 :-)

无标题1.ps1

function DoWork
{
$event = Register-EngineEvent -SourceIdentifier NewMessage -Action {
global:DisplayMessage $event.MessageData
}

$scriptBlock = {

Register-EngineEvent -SourceIdentifier NewMessage -Forward

$message = "Starting work $args"
$null = New-Event -SourceIdentifier NewMessage -MessageData $message

### DO SOME WORK HERE ###

$message = "Ending work $args"
$null = New-Event -SourceIdentifier NewMessage -MessageData $message

Unregister-Event -SourceIdentifier NewMessage
}

DisplayMessage("Processing Starts")

$array = @(1,2,3)
foreach ($a in $array)
{
Start-Job -Name "DoActualWork" $ScriptBlock -ArgumentList $a | Out-Null
}

#$jobs = Get-Job -Name "DoActualWork"
While (Get-Job -Name "DoActualWork" | where { $_.State -eq "Running" } )
{
Start-Sleep 1
}

DisplayMessage("Processing Ends")

#Get-Job -Name "DoActualWork" | Receive-Job
}

function global:DisplayMessage([string]$message)
{
Write-Host $message -ForegroundColor Red
}

DoWork

Get-EventSubscriber | Unregister-Event

测试
PS > .\Untitled1.ps1
Processing Starts
Starting work 1
Starting work 2
Ending work 1
Ending work 2
Starting work 3
Ending work 3
Processing Ends

关于powershell - 如何从 Start-Job 调用脚本中的 powershell 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15520404/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com