2017-02-03 17 views
1

これはかなり正直な質問です。私は、たくさんのファイルを読み込むdllを持っています。すべてのファイルの完了はイベントによって示されます。コンソールアプリケーションは、argsからの情報を表示するとすぐにそれを処理します。Powershellの.NETイベントは終了まで処理されません

私はこのdllをpowershellスクリプトから実行し、プログレスバーを表示したいと思います。期待どおりに動作しません。 実行の最後にプログレスバーが表示され、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が彼らと同じ瞬間にイベントに応答するためにできることはありますか?

EDIT:コメントからANSWER これは予想と同じように動作します。スクリプトの最後ではなく、実行中に進捗を報告します。

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

'GetErrorLogs'はどのように機能しますか?それは操作の終わりまでブロックしていますか? 'GetErrorLogs'が呼び出された同じスレッドで' FileQueueProgress'が呼び出されましたか? – PetSerAl

+0

はい、同期して実行され、その間に同じスレッドでイベントが発生します。 – yoger

+0

コンソールのバージョンはPowerShellのバージョンとどのように比較されますか?私はあなたが見ている行動が期待されると思います。 PowerShellでは非同期なものは何もないので、すべてがキューに入れられます。少なくともそれは私がそれを理解する方法です。 –

答えて

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変数にデリゲートオブジェクトを保存するので、私はきちんと後でそれを切り離すことができます。

関連する問題