PowerShell 输出在函数之间交叉 [英] PowerShell output is crossing between functions
问题描述
我正在 Windows 10 上编写 5.1 版的 PowerShell 脚本,该脚本获取有关本地系统(以及最终其子网)的某些信息并将它们输出到文本文件中.起初,我在一个函数中拥有所有方面.我在输出 getUsersAndGroups
和 getRunningProcesses
函数时遇到了输出问题,其中 getUsersAndGroups
的输出将被注入到 getRunningProcesses的输出中代码>.
I am writing a PowerShell script in version 5.1 on Windows 10 that gets certain pieces of information about a local system ( and eventually its subnets ) and outputs them into a text file. At first, I had all of the aspects in a single function. I ran into output issues when outputting getUsersAndGroups
and getRunningProcesses
functions, where output from getUsersAndGroups
would be injected into the output of getRunningProcesses
.
这两个函数是:
# Powershell script to get various properties and output to a text file
Function getRunningProcesses()
{
# Running processes
Write-Host "Running Processes:
------------ START PROCESS LIST ------------
"
Get-Process | Select-Object name,fileversion,productversion,company
Write-Host "
------------- END PROCESS LIST -------------
"
}
Function getUsersAndGroups()
{
# Get Users and Groups
Write-Host "Users and Groups:"
$adsi = [ADSI]"WinNT://$env:COMPUTERNAME"
$adsi.Children | where {$_.SchemaClassName -eq 'user'} | Foreach-Object {
$groups = $_.Groups() | Foreach-Object {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
$_ | Select-Object @{n='Username';e={$_.Name}},@{n='Group';e={$groups -join ';'}}
}
}
getRunningProcesses
getUsersAndGroups
当我在 getRunningProcesses
之后调用 getUsersAndGroups
时,输出看起来像这样(根本不输出 getUsersAndGroups
):
When I call getUsersAndGroups
after getRunningProcesses
, the output looks like this ( does not output getUsersAndGroups
at all ):
Running Processes:
------------ START PROCESS LIST ------------
Name FileVersion ProductVersion Company
---- ----------- -------------- -------
armsvc
aswidsagenta
audiodg
AVGSvc
avgsvca
avguix 1.182.2.64574 1.182.2.64574 AVG Technologies CZ, s.r.o.
conhost 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
csrss
csrss
dasHost
dwm
explorer 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
hkcmd 8.15.10.2900 8.15.10.2900 Intel Corporation
Idle
igfxpers 8.15.10.2900 8.15.10.2900 Intel Corporation
lsass
MBAMService
mDNSResponder
Memory Compression
powershell_ise 10.0.14393.103 (rs1_release_inmarket.160819-1924) 10.0.14393.103 Microsoft Corporation
RuntimeBroker 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
SearchFilterHost
SearchIndexer
SearchProtocolHost
SearchUI 10.0.14393.953 (rs1_release_inmarket.170303-1614) 10.0.14393.953 Microsoft Corporation
services
ShellExperienceHost 10.0.14393.447 (rs1_release_inmarket.161102-0100) 10.0.14393.447 Microsoft Corporation
sihost 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
smss
spoolsv
sqlwriter
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
System
taskhostw 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
ToolbarUpdater
wininit
winlogon
WtuSystemSupport
WUDFHost
------------ END PROCESS LIST ------------
Users and Groups:
当我在 getRunningProcesses
之前调用 getUsersAndGroups
时,getUsersAndGroups
的输出被注入到 getRunningProcesses
中,更糟的是,没有运行进程根本没有被列出,而是有很多空行.
When I call getUsersAndGroups
before getRunningProcesses
the output of getUsersAndGroups
is injected in getRunningProcesses
and worse, no running processes are listed at all, but rather a lot of blank lines.
如何分离或控制getUsersAndGroups
的输出,使其在getRunningProcesses
的输出之前输出?
How can I separate or control the output of getUsersAndGroups
so that it outputs before the output of getRunningProcesses
?
注入输出的输出如下所示:
The output of the injected output looks like this:
Running Processes:
------------ START PROCESS LIST ------------
Username Group
-------- -----
Administrator Administrators
debug255 Administrators;Hyper-V Administrators;Performance Log Users
DefaultAccount System Managed Accounts Group
Guest Guests
------------ END PROCESS LIST ------------
非常感谢您的帮助!
推荐答案
tl;博士:
使用格式化 cmdlet 显式强制同步输出到控制台:
Force synchronous output to the console by using a formatting cmdlet explicitly:
getUsersAndGroups | Out-Host
getRunningProcesses | Out-Host
注意:您也可以使用 Format-*
cmdlet 之一,它也强制同步输出;例如,getUsersAndGroups |格式表
.
Note: You can alternatively use one of the Format-*
cmdlets, which also forces synchronous output; e.g., getUsersAndGroups | Format-Table
.
请注意,这主要是一个显示问题,您不需要这个解决方法来捕获文件中的输出或通过管道传递它.
Note that this is primarily a display problem, and you do not need this workaround for capturing output in a file or passing it on through the pipeline.
然而,发送到Out-Host
意味着无法再捕获或重定向命令的输出;请参阅此答案,了解次优的解决方法.
However, sending to Out-Host
means that the commands' output can no longer be captured or redirected; see this answer for a - suboptimal - workaround.
使用MCVE(最小、完整和可验证示例)来演示问题很有帮助:
It's helpful to demonstrate the problem with an MCVE (Minimal, Complete, and Verifiable Example):
Write-Host "-- before"
[pscustomobject] @{ one = 1; two = 2; three = 3 }
Write-Host "-- after"
在 PSv5+ 中,这会产生:
In PSv5+, this yields:
-- before
-- after
one two three
--- --- -----
1 2 3
发生了什么?
Write-Host
调用生成的输出同步.
- 值得注意的是,
Write-Host
绕过了正常的成功输出流并且(实际上)直接写入控制台 - 大多数情况下,即使有合法用途,Write-Host
应该避免.
- It is worth noting that
Write-Host
bypasses the normal success output stream and (in effect) writes directly to the console - mostly, even though there are legitimate uses,Write-Host
should be avoided.
隐式输出 - 不捕获语句 [pscustomobject] @{ one = 1; 的输出二 = 2;三 = 3 }
- 出乎意料地不同步:
The implicit output - from not capturing the output from statement [pscustomobject] @{ one = 1; two = 2; three = 3 }
- was unexpectedly not synchronous:
- 最初生成了一个空白行.
- 所有实际输出遵循最后的
Write-Host
调用.
- A blank line was initially produced.
- All actual output followed the final
Write-Host
call.
这个有用的答案解释了为什么会发生这种情况;简而言之:
This helpful answer explains why that happens; in short:
隐式输出根据输出对象的类型进行格式化;在手头的情况下,
Format-Table
被隐式使用.
Implicit output is formatted based on the type of objects being output; in the case at hand,
Format-Table
is implicitly used.
在Psv5+中,隐式应用Format-Table
现在等待高达300毫秒.以确定合适的列宽.
In Psv5+, implicitly applied Format-Table
now waits up to 300 msecs. in order to determine suitable column widths.
- 但是请注意,这仅适用于类型表格格式说明未预定义;如果是,他们会提前确定列宽,并且不会发生等待.
要测试具有全名
的给定类型是否具有与之关联的表格格式数据,您可以使用以下命令:
- Note, however, that this only applies to output objects for whose type table-formatting instructions are not predefined; if they are, they determine the column widths ahead of time, and no waiting occurs.
To test whether a given type with full name
<FullTypeName>
has table-formatting data associated with it, you can use the following command:
# Outputs $true, if <FullTypeName> has predefined table-formatting data.
Get-FormatData <FullTypeName> -PowerShellVersion $PSVersionTable.PSVersion |
Where-Object {
$_.FormatViewDefinition.Control.ForEach('GetType') -contains [System.Management.Automation.TableControl]
}
不幸的是,这意味着后续命令在该时间窗口内执行并可能产生不相关的输出(通过管道-绕过输出命令,例如Write-Host
) 或提示用户输入 before Format-Table
输出开始.
Unfortunately, that means that subsequent commands execute inside that time window and may produce unrelated output (via pipeline-bypassing output commands such as Write-Host
) or prompt for user input before Format-Table
output starts.
问题行为在在此 GitHub 问题中讨论;虽然仍有希望找到解决方案,但已经很长时间没有活动了.
The problematic behavior is discussed in this GitHub issue; while there's still hope for a solution, there has been no activity in a long time.
注意:这个答案最初错误地归咎于"PSv5+ 300 毫秒.延迟潜在的令人惊讶的标准输出格式化行为(即发送到管道的第一个对象决定了管道中所有对象的显示格式,如果应用了表格格式 - 请参阅这个答案).
Note: This answer originally incorrectly "blamed" the PSv5+ 300 msec. delay for potentially surprising standard output formatting behavior (namely that the first object sent to a pipeline determines the display format for all objects in the pipeline, if table formatting is applied - see this answer).
这篇关于PowerShell 输出在函数之间交叉的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!