简体   繁体   English

powershell 中的“echo on”或如何使 Powershell output 成为所有命令的命令行,包括脚本调用的本机命令?

[英]"echo on" in powershell or how do I make Powershell output the command lines of all the commands, INCLUDING the native ones invoked by the script?

My question may seem duplicate of PowerShell "echo on" , but it is not.我的问题似乎与PowerShell "echo on"重复,但事实并非如此。

I am not interested in capturing the command output, but in the command line itself of every command executed by the script, including the native commands.我对捕获命令 output 不感兴趣,但对脚本执行的每个命令(包括本机命令)的命令行本身不感兴趣。

This is what "echo on" in cmd does and this is what I am looking for.这就是 cmd 中的“echo on”所做的,这就是我正在寻找的。 Set-PSDebug -Trace 1 does not do it and neither passing the -Verbose flag. Set-PSDebug -Trace 1不会这样做,也不会传递-Verbose标志。

So far I have not see a way except outputing them myself, which is a huge pain in itself.到目前为止,除了自己输出它们之外,我还没有找到其他方法,这本身就是一个巨大的痛苦。

So, can Powershell do what "echo on" does in cmd?那么,Powershell 可以做 cmd 中的“echo on”吗?

EDIT 1编辑 1

Not ideal, but I would accept an answer suggesting to use a wrapper function which would receive a command (native or powershell) with parameters and run the command while faithfully logging the respective command line.不理想,但我会接受建议使用包装器 function 的答案,该包装器将接收带有参数的命令(本机或 powershell)并运行命令,同时忠实地记录相应的命令行。 Of course, the wrapper function code should be part of the answer.当然,包装器 function 代码应该是答案的一部分。

EDIT 2编辑 2

The following trivial example demonstrates why Set-PSDebug -Trace 1 does not do it:以下简单示例演示了为什么Set-PSDebug -Trace 1不这样做:

tasklist `
    /fi "status eq running" | Select-Object -First 4

Please, observe:请注意:

C:\> cat C:\temp\1.ps1
tasklist `
    /fi "status eq running" | Select-Object -First 4
C:\> Set-PSDebug -Trace 1
C:\> C:\temp\1.ps1
DEBUG:    1+  >>>> C:\temp\1.ps1
DEBUG:    1+  >>>> tasklist `

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
csrss.exe                      756 Console                    1      2,816 K
C:\>

EDIT 3编辑 3

For comparison, observe an equivalent script in cmd with echo on :为了比较,请观察 cmd 中带有echo on的等效脚本:

C:\>type c:\temp\1.cmd
@echo on
tasklist ^
    /fi "status eq running" |findstr/n ^^|findstr "^[1-4]:"
C:\>c:\temp\1.cmd

C:\>tasklist     /fi "status eq running"   | findstr/n ^  | findstr "^[1-4]:"
1:
2:Image Name                     PID Session Name        Session#    Mem Usage
3:========================= ======== ================ =========== ============
4:csrss.exe                      756 Console                    1      2,328 K

C:\>

EDIT 4编辑 4

start-transcript does not do it either: start-transcript也不这样做:

C:\WINDOWS\system32> cat c:\temp\1.ps1
tasklist `
    /fi "status eq running" | Select-Object -First 4 | Out-Default
C:\WINDOWS\system32> Start-Transcript
Transcript started, output file is ~\Documents\PowerShell_transcript.L-PF0TBKV7.Sr1ntThx.20190611143800.txt
C:\WINDOWS\system32> c:\temp\1.ps1

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
csrss.exe                      756 Console                    1      2,936 K
C:\WINDOWS\system32> Stop-Transcript
Transcript stopped, output file is ~\Documents\PowerShell_transcript.L-PF0TBKV7.Sr1ntThx.20190611143800.txt
C:\WINDOWS\system32> cat ~\Documents\PowerShell_transcript.L-PF0TBKV7.Sr1ntThx.20190611143800.txt
**********************
Windows PowerShell transcript start
Start time: 20190611143800
Username: xyz\me
RunAs User: xyz\me
Configuration Name:
Machine: L-PF0TBKV7 (Microsoft Windows NT 10.0.16299.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Process ID: 25508
PSVersion: 5.1.16299.1004
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.16299.1004
BuildVersion: 10.0.16299.1004
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
Transcript started, output file is ~\Documents\PowerShell_transcript.L-PF0TBKV7.Sr1ntThx.20190611143800.txt
C:\WINDOWS\system32
>
PS>c:\temp\1.ps1

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
csrss.exe                      756 Console                    1      2,936 K
C:\WINDOWS\system32
>
PS>Stop-Transcript
**********************
Windows PowerShell transcript end
End time: 20190611143810
**********************
C:\WINDOWS\system32>

As you can see it does not contain the command line.如您所见,它不包含命令行。

If Event logs is an option, start tracing by enabling this Group Policy.如果事件日志是一个选项,请通过启用此组策略开始跟踪。
Administrative Templates -> Windows Components -> Windows PowerShell

See Microsoft Docs - Script Tracing and Logging请参阅Microsoft Docs - 脚本跟踪和日志记录

Then you would of course need to parse the Event logs accordingly...那么你当然需要相应地解析事件日志......

I expect four answers and you have already mentioned three that do not work for you ( Set-PSDebug , Start-Transaction , -Verbose ).我期待四个答案,而您已经提到了三个对您不起作用的答案( Set-PSDebugStart-Transaction-Verbose )。 As much as they may be viable but not in the format you are looking for, I will not talk more of them.尽管它们可能是可行的,但不是您正在寻找的格式,我不会再谈论它们了。

For the third option, try using Get-History .对于第三个选项,请尝试使用Get-History Now, this will not print out each command as you execute it (only when you call it) like I assume you want.现在,这不会像我假设的那样在您执行它时打印出每个命令(仅在您调用它时)。 It will also likely not print out each of the lines inside another script (you would want a trace but you did not like that because it prints out more than just the execution).它也可能不会打印出另一个脚本中的每一行(您想要跟踪但您不喜欢那样,因为它打印出的不仅仅是执行)。

You can try asking around the PowerShell repository but I do not expect you to find what you are seeking.您可以尝试在PowerShell 存储库中询问,但我不希望您找到您正在寻找的内容。

Firstly, the reason you're dissatisfied with the built-in options is because you're going against the grain;首先,您对内置选项不满意的原因是因为您违背了常规; your requirement is like asking how to put sacks of gravel in the back of a Porsche.您的要求就像询问如何在保时捷后面放几袋砾石。 Powershell comes with Verbose and Debug output streams and a fantastic debugger. Powershell 带有详细和调试 output 流和出色的调试器。

If you have any ability to influence coding standards, look at splatting as an alternative to backtick-continuations.如果您有任何影响编码标准的能力,请将splatting视为反引号延续的替代方法。

If you can count on versions of Windows that are not years past EoL , consider Get-ScheduledTask | Where-Object State -eq 'Ready'如果您可以指望 Windows 的版本不是EoL 之后的几年,请考虑Get-ScheduledTask | Where-Object State -eq 'Ready' Get-ScheduledTask | Where-Object State -eq 'Ready' instead of tasklist . Get-ScheduledTask | Where-Object State -eq 'Ready'而不是tasklist

That said, yes, what you want is possible.也就是说,是的,你想要的是可能的。 Here's a script that will echo across line continuations:这是一个将跨行回显的脚本:

# Echo.ps1

function Disable-Echo
{
    param
    (
        [Parameter(Mandatory)]
        [string]$Path
    )

    $Path = ($Path | Resolve-Path -ErrorAction Stop).Path

    Get-PSBreakpoint -Script $Path | Remove-PSBreakpoint
}

function Enable-Echo
{
    param
    (
        [Parameter(Mandatory)]
        [string]$Path
    )

    $Path = ($Path | Resolve-Path -ErrorAction Stop).Path

    Disable-Echo $Path

    $Ast = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$null, [ref]$null)
    $Statements = $Ast.BeginBlock, $Ast.ProcessBlock, $Ast.EndBlock |
        Select-Object -ExpandProperty Statements |
        Write-Output |
        Where-Object {$_.Extent}

    foreach ($Statement in $Statements)
    {
        $Action = {
            $Text = $Statement.Extent.Text
            $Text = $Text -replace '`\r?\n' # Concatenate lines that are escaped with backtick
            # Alternative to remove superfluous whitespace:
            # $Text = $Text -replace '\s+`\r?\n\s*', ' '
            Write-Host "ECHO: $Text" -ForegroundColor Yellow
            continue   # or 'break' to stop on the line
        }.GetNewClosure()   # Create a closure, to capture the value of $Statement

        $Params = @{
            Script = $Path
            Line   = $Statement.Extent.StartLineNumber
            Column = $Statement.Extent.StartColumnNumber
            Action = $Action
        }
        $null = Set-PSBreakpoint @Params
    }
}

Sample script:示例脚本:

# foo.ps1

gci `
    -Name `
    -File `
    -Filter Victor.*

gci -File -Name *.md; gci -File -Name *.psd1

Usage:用法:

# Without echo
❯ .\foo.ps1
Victor.build.ps1
Victor.psd1
Victor.psm1
README.md
Victor.psd1

❯ . .\Echo.ps1
❯ Enable-Echo .\foo.ps1
❯ .\foo.ps1
ECHO: gci     -Name     -File     -Filter Victor.*
Victor.build.ps1
Victor.psd1
Victor.psm1
ECHO: gci -File -Name *.md
README.md
ECHO: gci -File -Name *.psd1
Victor.psd1

Tested on PSv5 and PSv7.在 PSv5 和 PSv7 上测试。 Should work on PSv2, although the sample foo.ps1 is PSv3+ (IIRC).应该在 PSv2 上工作,尽管示例foo.ps1是 PSv3+ (IIRC)。

This will not echo calls to other scripts.这不会回显对其他脚本的调用。 For that, you'd probably want to do more AST inspection, identify CommandAsts that call scripts, and recursively enable echo on those scripts too.为此,您可能想要做更多的 AST 检查,识别调用脚本的 CommandAst,并递归地在这些脚本上启用 echo。 Alternatively, there might be joy in Set-PSBreakpoint -Variable - the $$ variable might be a good place to start - but this would likely be a PITA to work with as it would invoke while you're trying to debug the echo function. You could inspect Get-PSCallStack to skip the action while you're at the command prompt.或者, Set-PSBreakpoint -Variable中可能会有乐趣 - $$变量可能是一个很好的起点 - 但这可能是一个 PITA,因为它会在您尝试调试 echo function 时调用。您可以在命令提示符下检查Get-PSCallStack以跳过操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Powershell脚本中输出被调用命令的所有输出 - How can I output all the output of a called command in Powershell script 如何从 Windows 命令提示符调用提升的 PowerShell 以执行命令和 PowerShell 脚本文件? - How do I call an elevated PowerShell from Windows command prompt to execute commands and a PowerShell script file? 如何在 Powershell 脚本中运行命令? - How do I run commands in a Powershell script? 如何终止从Python GUI调用的PowerShell脚本? - How do I kill a PowerShell script that is invoked from a Python GUI? 如何在 Powershell 脚本的非 Powershell 命令中使用此变量? - How do I use this variable in a non Powershell Command in a Powershell Script? PowerShell中的脚本回显当前命令 - Script echo current command in PowerShell 如何将时间戳添加到PowerShell和输出的各个行? - How do I add timestamps to individual lines of PowerShell & output? 有没有办法抑制来自Powershell的所有命令行输出,包括错误 - Is there a way to surpress all command line output, including errors, from Powershell 如何将命令行 arguments 传递给由 doskey 调用的 PowerShell 脚本 - How to pass command line arguments to a PowerShell script invoked by a doskey 如何结合这两个Powershell脚本行? - How do I combine these two powershell script lines?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM