2017-10-02 6 views
2

私は、私が書いたすべてのpowershellファイルにドット・ソースするユーティリティ関数と他のコードのコレクションを持っています。それに影響を与える呼び出し元のスコープ変数でビットを取得したので、私はそれをpowershellモジュールに変更する方法を検討し始めました。PowerShellモジュールが呼び出し元のスコープで取得する方法はありますか?

私は実際にスコープ間のやりとりをしたいときに私が行う特別なことのいくつかの問題に遭遇しました。私はpowershellモジュールに移動している間、この機能を維持するためにモジュールの呼び出し側のスコープを「取得」する必要があるのか​​どうか疑問に思っています。

もしそうでなければ、これらのより特殊化されたものをドットソースファイルに保存してより伝統的なユーティリティー機能をモジュールに移行するのが最善の道ですか?ここでは簡単にモジュールに移動しないものです:維持する

  • strictモードとエラー・アクションのプリファレンスを設定するには、SANE、例えば:これは(予想通り)には影響を与えません

    Set-StrictMode -Version Latest 
    $ErrorActionPreference = "Stop" 
    $PSDefaultParameterValues['*:ErrorAction']='Stop' 
    

    コードが.psm1 powershellモジュールから実行されるときの呼び出し元の環境。これらの変更を行うためにpsm1スコープから呼び出し元スコープに渡る方法はありますか?

  • 例えば、トップレベルのスクリプト呼び出しについての情報をプリントアウト:

    $immediateCallerPath = Get-Variable -scope 1 -name PSCommandPath -ValueOnly 
    Write-Host "Starting script at $immediateCallerPath" 
    $boundParameters = Get-Variable -scope 1 -name PSBoundParameters -ValueOnly 
    Write-Host "Bound parameters are:" 
    foreach($psbp in $boundParameters.GetEnumerator()) 
    { 
         "({0},{1})" -f $psbp.Key,$psbp.Value | Write-Host 
    } 
    

    は同様に、これらのコマンドは、もはやかつて.psm1ファイルに配置された最上位の呼び出しスコープを見ることができない

答えて

0

あなたが何をしっかり理解しているかわかりません。私は、あなたのモジュールのコマンドレットを呼び出すコードがどこにあるのか知りたいと思っています。たぶんそれ以上に。

私が正しい場合、Get-PSCallStackを使用してスタックトレースを取得できます。ファイルは私には明らかではないが、これは、それはあなたが達成したい内容に応じて、この

PS C:\Users\asarafian> Get-PSCallStack 

Command  Arguments Location 
-------  --------- -------- 
File1.ps1   <No file> 

のようになります。その後、保存された場合は保存されていないスクリプトから例えばそれは、この

PS C:\Users\asarafian> Get-PSCallStack 

Command  Arguments Location 
-------  --------- -------- 
<ScriptBlock> {}  <No file> 

のように見え、リストをGet-PSCallStackから[x]まで実行したコードである[0]から移動する必要があります。

XWriteをビルドするときに、スタックからのエントリがスクリプトファイル、モジュールのコマンドレット部分、または<ScriptBlock>のような不明なものであるかどうかを確認したかったのです。

私の実装はGet-XCommandSource.ps1であり、それは.ps1で終わる場合、それは、スクリプトファイルのスタックトレース

  1. からの指令値に対して次のロジックに従います。
  2. <ScriptBlock>の場合はスクリプトブロックです。
  3. コマンドは、その後Get-Commandをロードすることができる場合
    1. それはモジュールを持っている場合、それは、モジュール内のコマンドレットです。
    2. それ以外の場合は、.\cmdlet.ps1パターンでインポートされたコマンドレット/関数です。ここで

実装です:

function Get-XCommandSource 
{ 
    [CmdletBinding(SupportsShouldProcess=$true)] 
    Param(
     [Parameter(Mandatory=$true)] 
     [AllowEmptyString()] 
     [AllowNull()] 
     [string]$Command 
    ) 
    begin { 

    } 

    process { 
     if(-not $Command) 
     { 
      "Unknown" 
     } 
     elseif($Command.EndsWith(".ps1")) 
     { 
      "Script" 
     } 
     elseif($Command -eq "<scriptblock>") 
     { 
      "Unknown" 
     } 
     else 
     { 
      $cmdlet=Get-Command -Name $command -ErrorAction SilentlyContinue 
      if($cmdlet) 
      { 
       $moduleName=$cmdlet|Select-Object -ExpandProperty ModuleName 

       if($moduleName) 
       { 
        $moduleName 
       } 
       else 
       { 
        "Function" 
       } 
      } 
      else 
      { 
       "Unknown" 
      } 
     } 
    } 

    end { 

    } 
} 
1

$PSCmdlet.SessionStateは、呼び出しサイトは、モジュールの外に提供される呼び出しサイトの変数にスクリプトモジュールへのアクセスの内部機能を提供しているようです。 (呼び出しサイトは、モジュール内にある場合、あなただけのGet-Set-Variable -Scopeを使用することができます。)ここでSessionStateを使用した例です。

私は SessionStateがあったかどうかはわからない

original value 
new value 

を出力

New-Module { 
    function Get-CallerVariable { 
     param([Parameter(Position=1)][string]$Name) 
     $PSCmdlet.SessionState.PSVariable.GetValue($Name) 
    } 
    function Set-CallerVariable { 
     param(
      [Parameter(ValueFromPipeline)][string]$Value, 
      [Parameter(Position=1)]$Name 
     ) 
     process { $PSCmdlet.SessionState.PSVariable.Set($Name,$Value)} 
    } 
} | Import-Module 

$l = 'original value' 
Get-CallerVariable l 
'new value' | Set-CallerVariable l 
$l 

この方法で使用することを意図しています。それが価値があるのは、Get-CallerPreference.ps1で使用されているのと同じテクニックです。また、PowerShellのバージョン2から5.1を通過するいくつかのテストケースhereがあります。

+0

これは本当に有望ですね、ありがとう。私はすぐにそれを試してみるでしょう。 – aggieNick02

関連する問題