PowerShell Module内からFunction:にアクセスすると

PowerShellのモジュールを書いていて、ある名前の関数が定義されているかどうかで挙動を変えたいと思ったが、呼び出し元がインタプリタかバッチかで挙動違う。

# やりたいこと

# 挙動を変えさせたい関数"Invoke-MyCommand"を定義したモジュール"SomeModule"を読みだして
Import-Module -Name "SomeModule" -Force;

# ある関数"Invoke-MyOriginalCommand"が未定義の時の"Invoke-MyCommand"の挙動と
Invoke-MyCommand -MyArg "AA";

# "Invoke-MyOriginalCommand"を定義してから実行する"Invoke-MyCommand"の挙動を変えたい
function Invoke-MyOriginalCommand() {
    Param([Parameter(Mandatory = $true, Position = 1)] [string]$MyArg);
    # Do anything
    Write-Host -Object ">> $MyArg <<";
}
Invoke-MyCommand -MyArg "AA;

モジュールSomeModule.psm1は以下のような定義。

function Invoke-MyCommand() {
    Param(
        [Parameter(Mandatory = $true, Position = 1)]
        [string] $MyArg
    );

    # Function: から目的の関数が定義されているか確認し、存在していればそれを呼ぶ
    if((Test-Path -Path "Function:Invoke-MyOriginalCommand")) {
        $func = Get-Item -Path "Function:Invoke-MyOriginalCommand";
        &$func -MyArg $MyArg;
    } else {
        Write-Host -Object "<< $MyArg >>";
    }
}
Export-ModuleMember -Function "Invoke-MyCommand";

インタプリタから実行した場合:

<< AA >>
>> AA <<

⇒モジュールの外で定義した関数がモジュール内から参照できている。

バッチで実行した場合:

<< AA >>
<< AA >>

⇒モジュールの外で定義した関数がモジュールの中から参照できない。
というか、Get-ChildItem -Path “Function:”したらわかるが、まるっきり定義した関数がなく、PowerShellを実行した直後のような状態になっている。

RunspaceやSessionStateが関係するのだろうか。詳細は追々調べよう。
とりあえず、この目的を実現するならSet関数を作って目的の関数オブジェクトをモジュール内の変数に渡し、それを参照すればいいか(未検証)

$ref = Get-Item -Path "Function:Invoke-MyOriginalCommand";
Set-MyOriginalCommand -CmdletReference $ref;
Invoke-MyCommand -MyArg "AA";
# 的な。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です