gpt4 book ai didi

powershell - 为什么PowerShell.BeginInvoke不调用回调?

转载 作者:行者123 更新时间:2023-12-03 01:17:00 25 4
gpt4 key购买 nike

我无法让PowerShell调用提供的回调:

$rs = [RunspaceFactory]::CreateRunspace()
$rs.Open()

$ps = [PowerShell]::Create()
$ps.Runspace = $rs

$ps.AddScript( {
Get-Service
} ) | Out-Null

$psdcInputs = New-Object Management.Automation.PSDataCollection[String]
$psdcInputs.Complete()
$psdcOutputs = New-Object Management.Automation.PSDataCollection[Object]
$psis = New-Object Management.Automation.PSInvocationSettings

$asyncCallback = {
Param (
[IAsyncResult]$result
)

Write-EventLog -LogName Application -Source Testing -EntryType Information `
-Category 0 -EventId 1234 -Message "Test."

$result.AsyncState.EndInvoke($result)
}

$aResult = $ps.BeginInvoke($psdcInputs, $psdcOutputs, $psis, $asyncCallback, $ps)

如预期的那样, scriptblock运行,并且 $psdcOutputs包含一组 ServiceController对象。但是 $asyncCallback scriptblock中的代码未运行,并且该事件未写入事件日志。我看不到我在做什么错。你能帮忙吗?

注意:我实际上并不担心要写入事件日志-在这里我还想做其他事情-但是我需要从原始代码中抽象出来以使其具有合理的大小。

最佳答案

AsyncCallbacks,Actions,EventHandlers等...大多在后台进程中运行
因此无法访问主线程中的变量。

事件发布者总是将自己和一组预定义的事件参数传递给
你的经理。这些事件参数的内容由
Activity ,您对此无话可说。除非您使用C#路线。

但是..... Add-Member是您的救星。我已重新编写您的样本以演示
我正在谈论的概念。

$asyncCallback = {
Param (
# Event source object
[System.Management.Automation.Powershell]
$sender,

# Inheritor of [System.EventArgs]
[System.Management.Automation.PSInvocationStateChangedEventArgs]
$e
)

# Ignore initial state change on startup
if ($e.InvocationStateInfo.State -eq [System.Management.Automation.PSInvocationState]::Running)
{
return
}

Write-Host $sender.Message
Write-Host "Event Fired!"
Write-Host ("Invocation State: {0}" -f $e.InvocationStateInfo.State)

#Write-EventLog -LogName Application -Source Testing -EntryType Information `
# -Category 0 -EventId 1234 -Message "Test."

# Use the NoteProperty references attached to the Powershell object by Add-Member
[void]$sender.EndInvoke($sender.AsyncResult)

# Clean up if you like
$sender.Dispose()

#
# You can unregister the event from within the event handler, but you
# shouldn't do so if you plan on recycling/restarting the background
# powershell instance.
#
# Unregister the event subscription
Unregister-Event -SourceIdentifier $sender.EventSubscriber.Name

#
# WARNING!
# Call To Remove-Job From Parent Thread!
#
# You cannot dispose of the EventJob (THIS) from within the job itself.
# That would kind of be like a snake trying to eat it's own tail...
#
# As such, you should be very careful about how you remove background jobs. If
# you use the command sequence below from anywhere within your main thead, you
# will break this event handler (and any others created by Register-ObjectEvent).
#
# (Dispose of Job)
# Get-Job | Remove-Job
#
}

<#
# This section is unnecessary unless you are modifying the apartment state
# of the runspace before opening it. The shell returned by Create() already
# has a runspace.
#
# $rs = [RunspaceFactory]::CreateRunspace()
# $rs.Open()
# $ps.Runspace = $rs
#>
$ps = [PowerShell]::Create().AddScript( {
#Get-Service
Get-Process
Start-Sleep -Seconds 2
} )

#
# Subscribe to the Powershell state changed event. Attach the registration object
# to the Powershell object for future reference.
#
Add-Member -InputObject $ps -MemberType NoteProperty -Name EventSubscriber -Value (
Register-ObjectEvent -InputObject $ps -EventName InvocationStateChanged -Action $asyncCallback)

<#
# This call structure is unnecessary as you aren't using the InvocationSettings
#
# $psis = New-Object Management.Automation.PSInvocationSettings
# $aResult = $ps.BeginInvoke($psdcInputs, $psdcOutputs, $psis, $asyncCallback, $ps)
#>

#
# Initialize invocation parameters
#
# Attach references to any data/objects/scriptblocks that you must be accessable
# within your event handler using Add-Member.
#
Add-Member -InputObject $ps -MemberType NoteProperty -Name Message -Value (
"Hello World! It's Me {0}" -f $ps.EventSubscriber.Name)

$psdcInputs = New-Object Management.Automation.PSDataCollection[String]
$psdcInputs.Complete()
$psdcOutputs = New-Object Management.Automation.PSDataCollection[Object]

Add-Member -InputObject $ps -MemberType NoteProperty -Name AsyncResult -Value (
$ps.BeginInvoke($psdcInputs, $psdcOutputs))

# Watch for race conditions
Start-Sleep -Seconds 10

# Kill all remaining background jobs (including the EventJob asyncCallback)
Get-Job

Get-Job | Remove-Job | Out-Null

关于powershell - 为什么PowerShell.BeginInvoke不调用回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27405657/

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