多次覆盖函数以进行继承调用堆栈记录
Override functions multiple times for inheritant call stack logging
让我们假设以下 CmdLets:
Write-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)`""
}
}
New-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
用它自己的 Write-Verbose
覆盖了 Microsoft.PowerShell.Utility\Write-Verbose
。这完美地工作并输出:
VERBOSE: [New-MyColl] Names: [...]
现在,当调用 Write-MyColl
时,它 应该 覆盖 New-MyColl
中的 Function:\Write-Verbose
并且我希望它输出如下内容:
VERBOSE: [New-MyColl] [Write-MyColl] Writing `$InputObject's Name: "[...]"
正如您可能已经想到的那样,它不起作用。 Write-Verbose
递归调用自身直到天数结束。我已经尝试过局部函数定义和局部变量,但它们对调用的 CmdLet 不可见。
我认为对于我的特定用例,我将使用 Get-PsCallStack
,但是我希望看到一个解决方案来覆盖如上所述的重写函数。
我很难理解的是,为什么第二个Write-Verbose
调用了自己,所以$verb
貌似指向了一个尚未定义的函数。它不应该指向先前定义的函数吗?我已经尝试 Remove-Item
脚本末尾的功能,但它没有改变任何东西。
你知道如何实现这个调用堆栈行为吗?
感谢,我得到了以下解决方案:
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: "[...]"
让我们假设以下 CmdLets:
Write-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)`""
}
}
New-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
用它自己的 Write-Verbose
覆盖了 Microsoft.PowerShell.Utility\Write-Verbose
。这完美地工作并输出:
VERBOSE: [New-MyColl] Names: [...]
现在,当调用 Write-MyColl
时,它 应该 覆盖 New-MyColl
中的 Function:\Write-Verbose
并且我希望它输出如下内容:
VERBOSE: [New-MyColl] [Write-MyColl] Writing `$InputObject's Name: "[...]"
正如您可能已经想到的那样,它不起作用。 Write-Verbose
递归调用自身直到天数结束。我已经尝试过局部函数定义和局部变量,但它们对调用的 CmdLet 不可见。
我认为对于我的特定用例,我将使用 Get-PsCallStack
,但是我希望看到一个解决方案来覆盖如上所述的重写函数。
我很难理解的是,为什么第二个Write-Verbose
调用了自己,所以$verb
貌似指向了一个尚未定义的函数。它不应该指向先前定义的函数吗?我已经尝试 Remove-Item
脚本末尾的功能,但它没有改变任何东西。
你知道如何实现这个调用堆栈行为吗?
感谢
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: "[...]"