![](/img/trans.png)
[英]Invoking Restmethod URI in Powershell Scriptblock not working
[英]Can I resolve PowerShell scriptblock parameters without invoking?
我正在看寫一些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()調用它來完成此操作,但是可以通過任何方式獲取要解析的參數,而無需調用使我的腳本生成更加優雅,而無需使用大量條件整個代碼中的語句?
在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...
適用於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
當顯示帶有雙引號@ “的here-string時,它將擴展變量。對於不應該擴展的變量,請使用反引號(`)對該變量進行轉義。
所以試試這個:
$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
通過使用一些建議,我認為我已經找到了滿足自己需求的最佳解決方案。 考慮以下代碼
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等的所有好處。我還可以輕松地生成該功能將執行的代碼或僅讓其執行的代碼。 感謝您的所有投入,這絕對是一次很好的學習體驗。
如果要將塊表示為塊而不是字符串,則可以使用以下方法:
$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"
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.