Powershell 动力壳压痕

Powershell 动力壳压痕,powershell,Powershell,我正在编写一个部署应用程序的大型脚本。此脚本基于几个嵌套函数调用 有没有办法根据深度“识别”输出 例如,我有: function myFn() { Write-Host "Start of myfn" myFnNested() Write-Host "End of myfn" } function myFnNested() { Write-Host "Start of myFnNested" Write-Host "End of myFnNested" }

我正在编写一个部署应用程序的大型脚本。此脚本基于几个嵌套函数调用

有没有办法根据深度“识别”输出

例如,我有:

function myFn()
{
    Write-Host "Start of myfn"
    myFnNested()
    Write-Host "End of myfn"
}
function myFnNested()
{
    Write-Host "Start of myFnNested"
    Write-Host "End of myFnNested"
}

Write-Host "Start of myscript"
Write-Host "End of myscript"
脚本的输出将是:

我想要实现的是这个输出:

因为我不想几乎不编码空格的数量(因为我不知道复杂脚本中的深度级别)。我怎样才能简单地达到我的目标

也许是这样的

function myFn()
{
    Indent()
    Write-Host "Start of myfn"
    myFnNested()
    Write-Host "End of myfn"
    UnIndent()
}
function myFnNested()
{
    Indent()
    Write-Host "Start of myFnNested"
    Write-Host "End of myFnNested"
    UnIndent()
}

Write-Host "Start of myscript"
Write-Host "End of myscript"

您可以在
write host
周围使用包装函数,该函数使用
$MyInvocation
确定堆栈深度,以创建大量空格作为消息前缀

将其与
Get Variable
-scopeèn›
参数相结合,以拉出每个调用级别…类似于从Windows PowerShell中改编的
showstack
函数(Payette,第1版):


在由于作用域计数过高而导致
获取变量
失败之前,您需要管道中的最大值
$\ucode>。

您可以使用Console.CursorLeft设置其位置。请注意,写入输出将重置任何自定义位置,因此您需要在每次输出后重置它。以下是一个示例:

$i = 0 function Indent() { [console]::CursorLeft += 2 $i = [console]::CursorLeft $i } function UnIndent() { if($i -gt 0) { $i -= 2 } [console]::CursorLeft = $i $i } function WriteIndent([string]$s) { [console]::CursorLeft += $i write-host $s # Reset indent, as write-host will set cursor to indent 0 [console]::CursorLeft += $i } function myFnNested() { $i = Indent WriteIndent "Start of myFnNested" WriteIndent "End of myFnNested" $i = UnIndent } function myFn() { $i = Indent WriteIndent "Start of myfn" myFnNested WriteIndent "End of myfn" $i = UnIndent } WriteIndent "Start of myscript" myFn WriteIndent "End of myscript" $i=0 函数缩进(){ [控制台]::CursorLeft+=2 $i=[控制台]::光标左键 $i } 函数UnIndent(){ 如果($i-gt 0){$i-=2} [控制台]::CursorLeft=$i $i } 函数WriteIndent([string]$s){ [控制台]::CursorLeft+=$i 写入主机$s #重置缩进,因为写入主机将光标设置为缩进0 [控制台]::CursorLeft+=$i } 函数myFnNested(){ $i=缩进 WriteIndent“myFnNested的开始” WriteIndent“myFnNested的结尾” $i=未登录 } 函数myFn(){ $i=缩进 WriteIndent“myfn的开始” myFnNested WriteIndent“myfn的结束” $i=未登录 } WriteIndent“myscript的开始” myFn WriteIndent“myscript的结尾” 输出:

PS C:\scripting> .\Indent-Output.ps1 Start of myscript Start of myfn Start of myFnNested End of myFnNested End of myfn End of myscript PS C:\scripting>\Indent-Output.ps1 myscript的开始 多年筹资框架的开始 myfn的开始 myfn结束 myfn的结束 myscript的结尾
编写一个调试函数。两个参数,一个是标志,用于开始、停止或注释;另一个参数应该是调试文本。(我将使用1、-1和0作为标志,然后您可以将标志添加到缩进变量以设置增量深度。虽然很愚蠢,但足以进行调试。)

查看此脚本

如果加载该写详细包装器,可以设置
$WriteHostAutoIndent=$true
,然后调用Write Host,它将根据堆栈深度缩进。根据您最初定义的这些函数:

function myFn()
{
   Write-Host "Start of myfn"
   myFnNested
   Write-Host "End of myfn"
}
function myFnNested()
{
   Write-Host "Start of myFnNested"
   Write-Host "End of myFnNested"
}
在不做任何更改的情况下,您只需点源一个脚本文件,其中包含Write Host wrapper函数:

C:\PS> . C:\Users\Jaykul\Documents\WindowsPowerShell\PoshCode\3386.ps1
然后在调用函数之前只需设置首选项变量:

C:\PS> $WriteHostAutoIndent = $true
C:\PS> myFn
  Start of myfn
    Start of myFnNested
    End of myFnNested
  End of myfn

漂亮的缩进输出,就像魔术一样;-)

我用了另一种思路。我设置了一个计数变量,该变量在函数开始时递增,然后使用以下代码填充我正在写入的行:

write-host ($string).PadLeft( ($string).length + (2 * $count) )

这将为每个递归缩进两个空格。

在使用“&”运算符和名称空间调用原始字符串之前,您可以重写
Write Host
以写入缩进。您可能能够从当前堆栈范围派生缩进量,但是全局变量提供了更多的控制

$global:writeHostIndent

function Write-Host
{
    Microsoft.PowerShell.Utility\Write-Host (' ' * $global:writeHostIndent) -NoNewline
    & 'Microsoft.PowerShell.Utility\Write-Host' $args
}

隐马尔可夫模型。。。虽然这里的解决方案对某些人来说是显而易见的,但对每个人来说可能都不那么显而易见。。。好吧,也许只是我有精神障碍。如何调整写入主机包装函数中的想法?@msorens这里的基本想法是循环堆栈,依靠
Get Variable
在到达堆栈顶部时抛出。在这种情况下,需要过滤表示堆栈帧的
$MyInvocation
值,在堆栈帧中需要额外的缩进级别(例如,调用
MyRecursiveFunction
)。您如何找到时间编写如此出色的脚本?:)github上有一个指向此脚本的链接,以防其他人正在查找它:
&'Microsoft..\WriteHost'$args
似乎无法正确解析args,我在命令行上传递的任何其他选项都是消息的一部分。糟糕的方法是,每次写主机调用都必须重复此操作。保持干燥
C:\PS> $WriteHostAutoIndent = $true
C:\PS> myFn
  Start of myfn
    Start of myFnNested
    End of myFnNested
  End of myfn
write-host ($string).PadLeft( ($string).length + (2 * $count) )
$global:writeHostIndent

function Write-Host
{
    Microsoft.PowerShell.Utility\Write-Host (' ' * $global:writeHostIndent) -NoNewline
    & 'Microsoft.PowerShell.Utility\Write-Host' $args
}