2017-01-24 19 views
3

PowerShellでイベントを使用して責任を分け、モジュール間の依存関係を取り除きたい。子モジュールは、そのアクティビティについて親モジュールに通知する必要があり、イベントを発生させたときに親モジュールからの情報を必要とすることがあります。PowerShellのエンジンイベントハンドラから戻り値を取得する方法は?

これはこれまで私が試したことです。実世界のシナリオでは、登録モジュール、登録解除モジュール、ハンドラ関数の各部分を親モジュールに、New-Event部分を子モジュールに配置します。

function MyHandler { 

    param (
    [System.Management.Automation.PSEventArgs]$Event 
) 

    Write-Host "In MyHandler now!" -ForegroundColor Yellow 

    Write-Host "Sender  : $($Event.Sender)" 
    Write-Host "SourceArgs : $($Event.SourceArgs)" 
    Write-Host "MessageData : $($Event.MessageData)" 
    Write-Host "TimeGenerated : $($Event.TimeGenerated)" 

    $Event.MessageData = "This does not make it back." 

    return "Neither does this." 
} 

# subscribe 
[String]$MessageData = "Input" 
Register-EngineEvent -SourceIdentifier Pipo -Action {MyHandler $Event } 

# raise event and see what we get back 
New-Event -Sender "Me" -SourceIdentifier "Pipo" -EventArguments "MyEventArgs" -MessageData $MessageData 

# cleanup 
Unregister-Event -SourceIdentifier Pipo 

これはMyHandlerの呼び出しをトリガーし、渡された引数とイベントのプロパティにアクセスできます。問題は、イベントハンドラ関数からイベントのレイザーにデータを戻す方法を見つけることができないことです。私の考え方はおそらくあまりにも多すぎるので、私はPSで違ったやり方でやるべきことをしようとしているかもしれません。イベントを起こすためにオブジェクトを作成してパイプラインを送信するという全体のコンセプトは、私にとっては奇妙に思えます。本当に何が起こるのか分かりません。

これを行う正しい方法は何ですか?

+1

'Receive-Job ' – PetSerAl

+0

これはハンドラの「戻り値」を返しますが、イベントを発生させる子モジュールはジョブを認識しません親モジュールにあるRegister-EngineEvent呼び出しの結果、私はこの場合、代わりに子モジュールのものであるNew-Eventの結果であることをジョブが気に入っていました。これは無意味で、バックグラウンドタスクを実行するのにはいいが、イベントシステムには適していないようだ。私のニーズに合わせて間違ったPowerShell機能を見ていますか? –

+0

*間違ったPowerShell機能を私のニーズに合わせて見ていますか?* IMHO、はい。必要に応じて、親モジュールからのそのコードを子モジュールから呼び出し可能にし、それをグローバル関数にします。イベントを発生させる代わりに、このグローバル関数を呼び出します。 – PetSerAl

答えて

0

私のニーズに対応する方法を見つけました。

Pass a function as a parameter in PowerShell

は、私は完全な例にそれを働いた:それは、PowerShellとコールバックを検索するとき、私は、私は私をたくさん助けたこの質問(特にダンカンの答えを)見つけ、間違ったキーワードを検索して判明しました。次に、同じフォルダ内に、「Server.psm1」としてこれを置く

Import-Module -Name ".\Server.psm1" -DisableNameChecking 

$script:ClientVar = "Not seen by server, returned by event handler." 

function Handle_Initialized { 
    Write-Host "Handler Initialized is being called." 

    # a return value is optional 
    return "=== $script:ClientVar ===" 
} 

function Handle_ProcessedData { 

    param (
    $Argument1, 
    $Argument2, 
    $Argument3 
) 

    Write-Host "Handler ProcessedData is called." 
    Write-Host "Arguments are $argument1, $argument2 and $argument3." 

    # a return value is optional 
    return "=== $argument1, $argument2, $argument3 ===" 
} 


Subscribe-Event -Name Initialized -Handler $function:Handle_Initialized 
Subscribe-Event -Name ProcessedData -Handler $function:Handle_ProcessedData 

Write-Host "" 
Write-Host "calling with active subscriptions" 
Write-Host "=================================" 

Do-ServerStuff 

Unsubscribe-Event -Name Initialized 
Unsubscribe-Event -Name ProcessedData 

Write-Host "" 
Write-Host "calling again with no active subscriptions" 
Write-Host "=================================" 

Do-ServerStuff 

Remove-Module -Name "Server" 

[ScriptBlock]$script:Handler_Initialized = $null 
[ScriptBlock]$script:Handler_ProcessedData = $null 

function Subscribe-Event { 

    param (
    [String]$Name, 
    [ScriptBlock]$Handler 
) 

    switch ($Name) { 
    Initialized { $script:Handler_Initialized = $Handler } 
    ProcessedData { $script:Handler_ProcessedData = $Handler } 
    } 
} 

function Unsubscribe-Event { 

    param (
    [String]$Name 
) 

    switch ($Name) { 
    Initialized { $script:Handler_Initialized = $null } 
    ProcessedData { $script:Handler_ProcessedData = $null } 
    } 
} 

function Raise-Initialized { 

    param (
) 

    if ($script:Handler_Initialized) { 
    return & $script:Handler_Initialized 
    } 
} 

function Raise-ProcessedData { 

    param (
    [Object]$Argument1, 
    [Object]$Argument2, 
    [Object]$Argument3 
) 

    if ($script:Handler_ProcessedData) { 
    return & $script:Handler_ProcessedData -Argument1 $Argument1 -Argument2 $Argument2 -Argument3 $Argument3 
    } 
} 

function Do-ServerStuff { 
    Write-Host "Before raising event Initialized." 
    Raise-Initialized 
    Write-Host "After raising event Initialized." 
    Write-Host "" 
    Write-Host "Before raising event ProcessedData." 
    Raise-ProcessedData -Argument1 "AAA" -Argument2 "BBB" -Argument3 "CCC" 
    Write-Host "After raising event ProcessedData." 
} 

そして、あなたは見つけるでしょうこれは、「Client.ps1」として保存されるように、クライアントスクリプトです拡張可能な同期イベント処理システムがあることを確認します。

ほとんどの配管は、サーバモジュール内にあり、ハンドラ機能のプロトタイプを指示します。クライアントコードは、単にイベントを購読し、イベントから購読を取り消し、ハンドラの実装を提供します。通常のPowerShellの方法では、すべてのハンドラの名前付きパラメータと戻り値(実際には出力値)をサポートしています。サーバーは、私がたくさん好むそのクライアントについては何も知りません。依存関係は片方向に過ぎません。

たとえば、このスキームでは、純粋なコアロジックを実行するモジュールをビルドすることができます。いくつかのグローバルオブジェクトを介してロギングするのではなく、サーバーモジュールでメッセージを送信するイベントを発生させ、クライアントはそのイベントの処理方法と送信先を決定できます。これにより、サーバーモジュールのユーザビリティが向上し、テスト可能になります。

これは味の問題かもしれませんが、私は通常、依存性注入よりもイベントを使用することをお勧めします。依存性注入を使用すると、サーバーは注入されるタイプについて知る必要がありますが、これはそうではありません。

お楽しみください!

関連する問題