powershell - 代理命令

标签 powershell proxy command tee

对于 PowerShell feature request (无论这是否是一个好主意),我尝试使用名为 Write-Table 的代理命令创建一个原型(prototype),该命令基于直接写入的 Format-Table cmdlet主机并根据 PassThru 开关应传递当前输入对象:

function Write-Table {
    [CmdletBinding(HelpUri='https://go.microsoft.com/fwlink/?LinkID=2096703')]
    param(
        [switch]
        ${AutoSize},
    
        [switch]
        ${RepeatHeader},
    
        [switch]
        ${HideTableHeaders},
    
        [switch]
        ${Wrap},
    
        [Parameter(Position=0)]
        [System.Object[]]
        ${Property},
    
        [System.Object]
        ${GroupBy},
    
        [string]
        ${View},
    
        [switch]
        ${ShowError},
    
        [switch]
        ${DisplayError},
    
        [switch]
        ${Force},
    
        [ValidateSet('CoreOnly','EnumOnly','Both')]
        [string]
        ${Expand},
    
        [Parameter(ValueFromPipeline=$true)]
        [psobject]
        ${InputObject},
    
        [switch]
        ${PassThru})
    
    begin
    {
        try {
            $outBuffer = $null
            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
            {
                $PSBoundParameters['OutBuffer'] = 1
            }
    
            if ($PSBoundParameters.TryGetValue('PassThru', [ref]$outBuffer))
            {
                $Null = $PSBoundParameters.Remove('PassThru')
            }
    
            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Format-Table', [System.Management.Automation.CommandTypes]::Cmdlet)
            $scriptCmd = {& $wrappedCmd @PSBoundParameters }
    
            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
            $steppablePipeline.Begin($PSCmdlet)
        } catch {
            throw
        }
    }
    
    process
    {
        try {
            if ($PassThru) { $_ }
            $steppablePipeline.Process($_)
        } catch {
            throw
        }
    }
    
    end
    {
        try {
            $steppablePipeline.End()
        } catch {
            throw
        }
    }
    
    clean
    {
        if ($null -ne $steppablePipeline) {
            $steppablePipeline.Clean()
        }
    }
    <#
    
    .ForwardHelpTargetName Microsoft.PowerShell.Utility\Format-Table
    .ForwardHelpCategory Cmdlet
    
    #>
}

但不知何故,当前对象在传递给主机之前似乎已从管道中删除(我不知道如何防止这种情况)

gci *.txt | Write-Table -PassThru | Get-Item # Final intention: ... | Remove-Item

    Directory: C:\Users\Gebruiker\Downloads\temp

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           7/20/2023  3:44 PM              0 file1.txt
Get-Item: Cannot find path 'Microsoft.PowerShell.Commands.Internal.Format.FormatStartData' because it does not exist.
Get-Item: Cannot find path 'Microsoft.PowerShell.Commands.Internal.Format.GroupStartData' because it does not exist.
Get-Item: Cannot find path 'Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData' because it does not exist.
-a---           7/20/2023  3:44 PM              0 file2.txt
Get-Item: Cannot find path 'Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData' because it does not exist.
-a---           7/20/2023  3:44 PM              0 file3.txt
Get-Item: Cannot find path 'Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData' because it does not exist.
Get-Item: Cannot find path 'Microsoft.PowerShell.Commands.Internal.Format.GroupEndData' because it does not exist.
Get-Item: Cannot find path 'Microsoft.PowerShell.Commands.Internal.Format.FormatEndData' because it does not exist.

有人能解释一下这个问题在哪里以及我如何解决这个问题吗?

最佳答案

如果我理解正确的话,对包装命令的一点更新应该可以解决您的问题,由 Format-Table 生成的输出应该直接发送到主机,从而添加 Out -主机。然后,如果 -PassThru 存在,您很可能希望通过管道发送原始对象,因此:

function Write-Table {
    [CmdletBinding(HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=2096703')]
    param(
        [switch]
        ${AutoSize},

        [switch]
        ${RepeatHeader},

        [switch]
        ${HideTableHeaders},

        [switch]
        ${Wrap},

        [Parameter(Position = 0)]
        [System.Object[]]
        ${Property},

        [System.Object]
        ${GroupBy},

        [string]
        ${View},

        [switch]
        ${ShowError},

        [switch]
        ${DisplayError},

        [switch]
        ${Force},

        [ValidateSet('CoreOnly', 'EnumOnly', 'Both')]
        [string]
        ${Expand},

        [Parameter(ValueFromPipeline = $true)]
        [psobject]
        ${InputObject},

        [switch]
        ${PassThru})

    begin {
        $null = $PSBoundParameters.Remove('PassThru')
        $scriptCmd = { Microsoft.PowerShell.Utility\Format-Table @PSBoundParameters | Out-Host }
        $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
        $steppablePipeline.Begin($PSCmdlet)
    }

    process {
        if ($PassThru.IsPresent) {
            $InputObject
        }

        $steppablePipeline.Process($InputObject)
    }

    end {
        $steppablePipeline.End()
    }

    clean {
        if ($null -ne $steppablePipeline) {
            $steppablePipeline.Clean()
        }
    }
    <#

    .ForwardHelpTargetName Microsoft.PowerShell.Utility\Format-Table
    .ForwardHelpCategory Cmdlet

    #>
}

然后是这样的:

$capture = 0..5 | ForEach-Object { [pscustomobject]@{ Item = $_ } } |
    Write-Table -PassThru |
    ForEach-Object Item

工作得很好:

PS ..\pwsh> $capture = 0..10 | ForEach-Object { [pscustom....

# Output sent to the host:
Item
----
   0
   1
   2
   3
   4
   5

PS ..\pwsh> $capture
   
0
1
2
3
4
5
6
7
8
9
10

关于powershell - 代理命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76730959/

相关文章:

powershell - 如何在 PowerShell 中创建自定义类型以供我的脚本使用?

c# - 使用 Powershell 执行 C# 代码

powershell - 按时间戳对行数组进行排序

git - 在代理模式下使用两个不同的凭证处理两个不同的Git Organization存储库

go - 使用 golang 1.10.2 使用 IKEv2 证书连接到 socks5 代理

Linux 脚本 - 密码步骤减少流程

powershell - 根据属性值获取通用/列表中对象的索引

java - java中返回的 'Proxy.newProxyInstance()'代理对象是线程安全的吗?

php - 如何从 php 运行 linux 命令

linux - 我使用哪个命令来查找从特定目录开始的特定文件?