Powershell 使用SilentlyContinue时如何处理写入信息管道输出
当Powershell 使用SilentlyContinue时如何处理写入信息管道输出,powershell,stream,pipeline,Powershell,Stream,Pipeline,当$InformationPreference是SilentlyContinue时,Write Information似乎会输出不需要的记录。特别是由于默认值是SilentlyContinue,我认为这是一个问题 function foo { $VerbosePreference = 'SilentlyContinue' Write-Verbose "verbose silent" $VerbosePreference = 'Continue' Write-Ve
$InformationPreference
是SilentlyContinue
时,Write Information
似乎会输出不需要的记录。特别是由于默认值是SilentlyContinue
,我认为这是一个问题
function foo {
$VerbosePreference = 'SilentlyContinue'
Write-Verbose "verbose silent"
$VerbosePreference = 'Continue'
Write-Verbose "verbose continue"
$InformationPreference = 'SilentlyContinue'
Write-Information "info silent"
$InformationPreference = 'Continue'
Write-Information "info continue"
}
$PSVersionTable.PSVersion.ToString()
# 5.1.15063.1805
foo
# VERBOSE: verbose continue
# info continue
foo *>&1 | % { "redirected: $_" }
# redirected: verbose continue
# redirected: info silent
# redirected: info continue
正如所料,SilentlyContinue
的$Verbose首选项
会导致Write Verbose
不生成消息,因此没有要重定向的消息
同样如预期的那样,SilentlyContinue
的$InformationPreference
在控制台上没有正确显示任何内容,但是消息会沿着管道重定向
这似乎是错误的,因为一旦消息在管道中,消费者如何确定该信息消息是否应该被默默地丢弃
InformationRecords的流水线是否已中断,或者作为流水线消费者,我如何才能正确过滤掉不需要的InformationRecords?很有趣。但是,有一个基于帮助主题中的以下语句的解决方法:
-InformationAction:Ignore
抑制信息性消息并
继续运行该命令。不同于SilentlyContinue,
忽略
完全忘记信息信息;它不会将信息消息添加到信息流中
在以下脚本中,我做了一些修改:
Debug InfoAction*>&1 | ForEach对象{“redirected:$\}
及其结果)InformationAction
参数(不幸的是,ActionPreference
变量不支持值Ignore
;因此,此调整成为解决方案的关键点)InformationAction
参数覆盖,但不替换
当
参数在命令中用于运行脚本或函数
脚本:
function Debug-InfoAction {
param(
[System.Management.Automation.ActionPreference]
$InfoAction='Ignore'
)
Write-Verbose "verbose…………$InfoAction" -Verbose
Write-Information "InfoAction=$InfoAction" -InformationAction $InfoAction
}
foreach ( $InfoAction in @(
'SilentlyContinue',
'Continue',
'Ignore'
) # exclude from testing: 'Stop', 'Inquire', 'Suspend'
) {
$aux = ''
$aux = Debug-InfoAction -InfoAction $InfoAction 6>&1
'{0,16}:{1}' -f $InfoAction, $aux
}
# check newly defined default InformationAction
$InfoAction = 'Default'
$aux = ''
$aux = Debug-InfoAction 6>&1
'{0,16}:{1}' -f $InfoAction, $aux
Debug-InfoAction *>&1 | ForEach-Object { "redirected: $_" }
输出:
D:\PShell\SO\57303102a.ps1
D:\PShell\SO\57303102c.ps1
编辑 不幸的是,如果我的 函数调用其他人使用
写入信息的代码
然后,当我的代码重定向(或捕获)信息流时,
那我就没有办法丢弃用它写的信息了
SilentlyContinue
后一个符合条件的抗议表明了我的不足……让我们来做以下简单的捕获:
$c = Write-Information "Continue" -InformationAction Continue 6>&1
$s = Write-Information "Silently" -InformationAction SilentlyContinue 6>&1
两者都是[系统.管理.自动化.信息记录]
类型。我试图找出差异(即使在它们的子属性中),但除了数据中的差异外,我无法找到:
param(
[switch]$IncludeEqual = $false
)
begin {
Function Compare-Property {
param(
$RefObject,
$DifObject,
[switch]$IncludeEqual
)
# compare objects
Compare-Object $RefObject $DifObject -IncludeEqual |
Select-Object -Property SideIndicator,
@{N='objects';E={'Function Compare-Property'}},
InputObject
Write-Verbose $RefObject.GetType().FullName -Verbose:$IncludeEqual
# a level down: compare properties of objects individually
$cpe = $RefObject.PsObject.Properties.GetEnumerator()
$spe = $DifObject.PsObject.Properties.GetEnumerator()
While ( $cpe.MoveNext() -and $spe.MoveNext() ) {
Compare-Object $cpe.Current.Value `
$spe.Current.Value -IncludeEqual:$IncludeEqual |
Select-Object -Property SideIndicator,
@{N='objects';E={$spe.Current.Name}},
InputObject
# more level down:
# compare properties of properties of objects individually
$cpeIn = $cpe.Current.PsObject.Properties.GetEnumerator()
$speIn = $spe.Current.PsObject.Properties.GetEnumerator()
While ( $cpeIn.MoveNext() -and $speIn.MoveNext() ) {
Compare-Object $cpeIn.Current.Value `
$speIn.Current.Value -IncludeEqual:$IncludeEqual |
Select-Object -Property SideIndicator,
@{N='objects';
E={ $cpe.Current.Name + '.' + $cpeIn.Current.Name}},
InputObject
}
}
}
$c = Write-Information "Continue" -InformationAction Continue 6>&1
$s = Write-Information "Silently" -InformationAction SilentlyContinue 6>&1
}
process {
Compare-Object $c.GetType() $s.GetType() -IncludeEqual |
Select-Object -Property SideIndicator,
@{N='objects';E={'.GetType()'}}, InputObject
Compare-Object $c.PsObject.TypeNames `
$s.PsObject.TypeNames -IncludeEqual |
Select-Object -Property SideIndicator,
@{N='objects';E={'.PsObject.TypeNames'}},
InputObject
Compare-Object ($c | Get-Member -MemberType Properties -Force).PsTypeNames `
($s | Get-Member -MemberType Properties -Force).PsTypeNames `
-IncludeEqual |
Select-Object -Property SideIndicator,
@{N='objects';E={'(gm).PsTypeNames'}},
InputObject
Compare-Object $c $s -IncludeEqual |
Select-Object -Property SideIndicator,
@{N='objects';E={"$($c.GetType().Name) itself"}},
InputObject
Compare-Property -RefObject $c `
-DifObject $s -IncludeEqual:$IncludeEqual
Compare-Property -RefObject $c.PsObject `
-DifObject $s.PsObject -IncludeEqual:$IncludeEqual
}
输出:
D:\PShell\SO\57303102a.ps1
D:\PShell\SO\57303102c.ps1
SideIndicator对象InputObject
------------- ------- -----------
==.GetType()系统。管理。自动化。信息记录
==.PsObject.TypeNames System.Management.Automation.InformationRecord
==.PsObject.TypeNames系统对象
==(gm).PsTypeNames系统.Object[]
==(gm).PsTypeNames系统.数组
==(gm).PsTypeNames系统.Object
=>信息自动记录
函数以静默方式比较属性
无提示的消息数据
MessageData.Value静默
即时数据库对象
ImmediateBaseObject.Value无提示
基本对象静默
BaseObject.Value是静默的
这是一个很好的额外信息,可以解释Ignore和SilentlyContinue之间的一个重要区别。不幸的是,如果我的函数调用其他人使用写入信息的代码,那么当我的代码重定向(或捕获)信息流时,我就无法丢弃使用SilentlyContinue写入的信息,这并不能真正解决核心问题。感谢您对这两条记录进行了额外的编辑。我接受你的回答,尽管它不幸地得出结论,我想要的东西无法实现。我必须说,我认为Powershell流设计似乎有很多不一致之处。