这是一个非常直截了当的问题。我有一个dll负责阅读大量的文件。每个文件完成都由事件指示。控制台应用程序一旦出现就会正确地显示来自args的信息。
另一方面,我想从powershell脚本运行此dll并显示进度条。它没有按预期工作。 执行结束时显示进度条,在0到100%的范围内快速上升,并且消失。
$isVerbose = $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent
$finder = New-Object ContentFinder.LogFinder
if($isVerbose)
{
Register-ObjectEvent -InputObject $finder -EventName "FileQueueProgress" -Action {Write-Progress ($EventArgs.Percent)} -SourceIdentifier "FileReadingProgressIndicator" | Out-Null
}
try
{
$path = GetPath
$date = GetDate
return $finder.GetErrorLogs($path, $date)
}
catch
{
Write-Host ($_.Exception.Message)
}
finally
{
if($isVerbose)
{
Unregister-Event -SourceIdentifier "FileReadingProgressIndicator"
}
Write-Host "Done"
}
它的名字如下:Get-ErrorLogs -Verbose
。通常我将它分配给变量只是为了能够过滤结果和所有有效的。 我可以采取哪些措施让PS在事件发生的同一时刻对事件做出回应吗?
编辑:答案 这与预期一样有效。报告执行期间的进度,而不是脚本的结尾。
if($isVerbose)
{
$Handler = {Write-Progress ($args[1].Percent)} -as $finder. PSObject. Members. Match('FileQueueProgress')[0]. Value. EventHandlerType;
$finder. add_FileQueueProgress($Handler);
#Register-ObjectEvent -InputObject $finder -EventName "FileQueueProgress" -Action {Write-Progress ($EventArgs.Percent)} -SourceIdentifier "FileReadingProgressIndicator" | Out-Null
}
try
{
$path = GetPath
$date = GetDate
return $finder.GetErrorLogs($path, $date)
}
catch{
Write-Host ($_.Exception.Message)
}
finally
{
if($isVerbose)
{
#Unregister-Event -SourceIdentifier "FileReadingProgressIndicator"
$finder. remove_FileQueueProgress($Handler)
}
Write-Host "Done"
}
答案 0 :(得分:1)
在单线程场景中,您实际上不需要使用Register-ObjectEvent
。 PowerShell允许您将脚本块转换为委托类型对象。您可以通过直接调用事件访问器(add_EventName
/ remove_EventName
)来附加/分离该代表与事件。
$finder = New-Object ContentFinder.LogFinder
if($isVerbose)
{
$Handler = {Write-Progress ($args[1].Percent)} -as $finder.PSObject.Members.Match('FileQueueProgress')[0].Value.EventHandlerType
$finder.add_FileQueueProgress($Handler)
}
try
{
$path = GetPath
$date = GetDate
return $finder.GetErrorLogs($path, $date)
}
catch
{
Write-Host ($_.Exception.Message)
}
finally
{
if($isVerbose)
{
$finder.remove_FileQueueProgress($Handler)
}
Write-Host "Done"
}
注意:我将委托对象保存到$Handler
变量,因此我可以稍后将其正确分离。
答案 1 :(得分:1)
您可以使用此代码段模拟Register-ObjectEvent
来添加“原生”事件。
function Register-NativeEvent {
param($Instance, $EventName, [ScriptBlock] $ScriptBlock)
$handler = $ScriptBlock -as $instance.PSObject.Members.Match($EventName)[0].Value.EventHandlerType
$handlerMethod = "add_$EventName"
$instance.$handlerMethod($handler)
return $handler
}
function Unregister-NativeEvent {
param($Instance, $EventName, $handler)
$handlerMethod = "remove_$EventName"
$instance.$handlerMethod($handler)
}
使用$args[0]
(等于发送者)和$args[1]
(等于处理程序的事件args类型)来访问值。
例如:
$handler = Register-NativeEvent $MyInstance "MyEventName" { Write-Host $args[1].MyProperty }
完成后取消注册:
Unregister-NativeEvent $MyInstance "MyEventName" $handler