2013-01-24 64 views
1

我正在研究編寫一些可以立即執行的PowerShell代碼,或者生成將作爲生成腳本執行的命令。我可以在不調用的情況下解析PowerShell腳本塊參數嗎?

我想避免這種情況:

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

我被看ScriptBlocks,起初看起來前途無量,因爲我可以寫腳本塊到控制檯的內容但不執行。如:

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

我的具體問題是,如果我的腳本塊中包含的參數,我可以讓他們當我寫的腳本塊內容到控制檯解決,而無需調用的腳本塊?

例如給出下面的腳本塊:

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

當我只需要輸入「$ B2」在控制檯並回車我看到這一點:

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

我想看到什麼這是(如果參數值是「富」):

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

我知道這是可以做到時,它的調用,無論是通過「&「或使用Invoke(),但是有沒有什麼辦法可以讓參數解析,而不需要調用我的腳本生成器,而不需要在整個代碼中使用大量的條件語句?

回答

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等我的所有的好處也可以輕鬆生成該函數將執行的代碼或者只是讓它執行。感謝所有的投入,這絕對是一次很好的學習體驗。

+0

這也是一個有趣的問題。以防萬一,你可以接受你自己的答案。 –

1

當顯示此處的字符串用雙引號@,它擴展了變量對於should'nt擴大,反引號(`)逃離可變的變量

那麼試試這個。:

$P = "Foo" 

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

測試:

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

如果你想將其轉換爲再次腳本塊型:

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

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

PS-ADMIN > $b3.GetType().name 
ScriptBlock 
+0

問題是,$ b2的類型是[字符串]而不是[scriptblock],它似乎沒有效果。 '$ c = [scriptblock] :: create($ b2)'並使用'$ c' –

+0

他只是說他想要輸出,而不是它應該是scriptblock,如果是的話,他可以使用'$ b3 = [Scriptblock]: :創建($ B2)'。包括現在在回答中 –

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... 
2

解決方案適合的PowerShell V2:

# given the script block 
$b2 = { Param([string]$P) Write-Host "$P" } 

# make a function of it and "install" in the current scope 
Invoke-Expression "function tmp {$b2}" 

# get the function and its parameters 
(Get-Command tmp).Parameters 
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" 
    } 
} 
相關問題