1

すぐに実行できる PowerShell コードを作成するか、生成されたスクリプトとして実行するコマンドを生成することを考えています。

このシナリオは避けたい:

if($Generating){
  write-Output "somecommand.exe"
} 
else{
  somecommand.exe  
}

ScriptBlocks を調べてみました。これは、ScriptBlock の内容を実行せずにコンソールに書き込むことができるため、最初は有望に見えました。そのような:

$sc = { somecommand.exe }
$sc
 somecommand.exe

私の具体的な質問は、スクリプトブロックにパラメーターが含まれている場合、スクリプトブロックの内容をコンソールに書き込んでいるときに、スクリプトブロックを呼び出さずにそれらを解決できるかということです。

たとえば、次のスクリプトブロックがあるとします。

$b2 = { Param([string]$P) Write-Host "$P" }

コンソールで「$b2」と入力して Enter キーを押すと、次のように表示されます。

Param([string]$P) Write-Host "$P"

私が見たいのはこれです(パラメータ値が「Foo」の場合):

Param([string]$P) Write-Host "Foo"

これは、「&」または Invoke() を使用して呼び出されたときに実行できることを認識していますが、呼び出さずにパラメーターを解決して、スクリプト生成をもう少しエレガントにする方法はありますか?コード全体のステートメント?

4

5 に答える 5

3

PowerShell v3 では、AST プロパティを介してパラメーター情報を取得できます。

PS> $sb = {param($a,$b) "a is $a b is $b"}
PS> $sb.Ast.ParamBlock

Attributes           Parameters          Extent              Parent
----------           ----------          ------              ------
{}                   {$a, $b}            param($a,$b)        {param($a,$b) "a...
于 2013-01-24T16:27:10.443 に答える
1

二重引用符 @ "でヒア文字列を表示すると、変数が展開されます。展開されるべきではない変数については、バッククォート ( ` ) で変数をエスケープします。

だからこれを試してください:

$P = "Foo"

$b2 = @"
{ Param([string]`$P) Write-Host "$P" }
"@

テスト:

PS-ADMIN > $b2
{ Param([string]$P) Write-Host "Foo" }

再度 scriptblock-type に変換する場合:

#Convert it into scriptblock
$b3 = [Scriptblock]::Create($b2)

PS-ADMIN > $b3
{ Param([string]$P) Write-Host "Foo" }

PS-ADMIN > $b3.GetType().name
ScriptBlock
于 2013-01-24T16:26:37.757 に答える
1

いくつかの提案を使用して、自分のニーズに最適なソリューションを見つけたと思います。次のコードを検討してください

function TestFunc
{
    Param(
        [Parameter(Mandatory=$true)]
        [string]$Folder,

        [Parameter(Mandatory=$true)]
        [string]$Foo
    )    

    $code = @"
Write-Host "This is a folder $Folder"
Write-Host "This is the value of Foo $Foo"
"@

    $block = [Scriptblock]::Create($code)

    Write-Host "Running the block"  -BackgroundColor Green -ForegroundColor Black
    &$block

    Write-Host "Displaying block code" -BackgroundColor Green -ForegroundColor Black
    $block

}

そしてそれは出力です:

Running the block
This is a folder c:\some\folder
This is the value of Foo FOOFOO
Displaying block code
Write-Host "This is a folder c:\some\folder"
Write-Host "This is the value of Foo FOOFOO"

このようにすることで、既存の関数とそのパラメーター、パラメーターの検証、CBH などを保持するというすべての利点が得られます。関数が実行するコードを簡単に生成したり、単に実行させたりすることもできます。すべての意見をありがとう、それは間違いなく良い学習経験でした.

于 2013-01-25T13:25:38.167 に答える
0

ブロックを文字列ではなくブロックとして表現したい場合は、次のようにします。

$printable = invoke-expression ('"' + ($block -replace '"', '`"') + '"')

基本的に、すべてを引用符で囲み、それを式として呼び出します。この-replace呼び出しにより、ブロック自体の引用符が確実にエスケープされます。

これをこの便利な関数で使用しています。これは、呼び出されたコマンドが失敗した場合にも実行を停止します。

# usage: exec { dir $myDir }
function exec($block)
{
    # expand variables in block so it's easier to see what we're doing
    $printable = invoke-expression ('"' + ($block -replace '"', '`"').Trim() + '"')
    write-host "# $printable" -foregroundcolor gray

    & $block
    if ($lastExitCode -ne 0)
    {
        throw "Command failed: $printable in $(pwd) returned $lastExitCode"
    }
}
于 2013-06-13T07:42:23.303 に答える