我们假设以下CmdLets:
写MYCOLL
function Write-MyColl {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[psobject] $InputObject
)
$verb = Get-Command Write-Verbose
$fixedName = $PSCmdlet.MyInvocation.InvocationName
function Write-Verbose ($Object) {
& $verb "[$fixedName] $Object"
}
if ($InputObject.name) {
Write-Verbose "Writing `$InputObject's Name: `"$($InputObject.name)`""
}
}
新-MYCOLL
function New-MyColl {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string[]] $Names
)
$verb = Get-Command Write-Verbose
$fixedName = $PSCmdlet.MyInvocation.InvocationName
function Write-Verbose ($Object) {
& $verb "[$fixedName] $Object"
}
Write-Verbose "Names: $Names"
foreach ($name in $Names) {
@{
id = 123;
name = $name
} | Write-MyColl
}
}
正如您所看到的,New-MyColl
会覆盖Microsoft.PowerShell.Utility\Write-Verbose
并使用它自己的Write-Verbose
。这完美地运作并输出:
VERBOSE: [New-MyColl] Names: [...]
现在,当Write-MyColl
被调用时,应该覆盖Function:\Write-Verbose
的{{1}},我希望它输出如下内容:
New-MyColl
正如您可能已经想到的那样,它不起作用。 VERBOSE: [New-MyColl] [Write-MyColl] Writing `$InputObject's Name: "[...]"
以递归方式调用自己,直到几天结束。我已经尝试过本地函数定义和局部变量,但它们对调用的CmdLet不可见。
我认为对于我的具体用例,我会使用Get-PsCallStack
,但我很乐意看到一个解决方案来覆盖上面描述的覆盖函数。
我很难理解的是,为什么第二个Write-Verbose
会调用自己,所以Write-Verbose
似乎指向一个尚未定义的函数。它不应该指向先前定义的函数吗?我已经尝试$verb
脚本结尾处的功能,但它没有改变任何内容。
您是否知道如何实现 call-stack-behavior ?
答案 0 :(得分:0)
感谢PetSerAI's comment,我找到了以下解决方案:
New-Item function::local:Write-Verbose -Value (
New-Module -ScriptBlock { param($verb, $fixedName, $verbose) } -ArgumentList @(
(Get-Command Write-Verbose),
$PSCmdlet.MyInvocation.InvocationName,
$PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent
)
).NewBoundScriptBlock{
param($Message)
if ($verbose) {
& $verb -Message "=>$fixedName $Message" -Verbose
} else {
& $verb -Message "=>$fixedName $Message"
}
} | Write-Verbose
-Verbose
参数不会传递给新创建的函数;这就是我将其添加到-ArgumentList
的原因。我敢肯定,它不是很漂亮,但确实应该如此。为每次通话覆盖Write-Verbose
。
现在输出如下:
VERBOSE: =>[New-MyColl] Names: [...] VERBOSE: =>[New-MyColl]=>[Write-MyColl] Writing `$InputObject's Name: "[...]"