Ric*_*ook 14 powershell powershell-2.0
PowerShell函数能否确定它是否作为管道的一部分运行?我有一个函数,它填充一个数组,FileInfo如果函数以这种方式运行,我希望"屈服"到管道的实例,或者如果函数是从命令行自己调用的话,产生一些漂亮的输出.
function Do-Something {
$file_infos = @()
# Populate $file_infos with FileInfo instances...
if (INVOKED_IN_PIPELINE) {
return $file_infos
}
else {
foreach ($file_info in $file_infos) {
write-host -foregroundcolor yellow $file_info.fullname
}
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,我正在试图弄清楚如何实施INVOKED_IN_PIPELINE.如果它在一个管道(例如Do-Something | format-table fullname)中运行,我只会产生数组,但如果直接运行(例如Do-Something),它会将数组的内容漂亮地打印到控制台.
有没有办法做到这一点?如果有更"惯用"的方式来实现这种事情,我也有兴趣知道.
Jef*_*SFT 18
此信息作为$ PSCmdlet.MyInvocation的一部分提供.这是一个cmdlet,您可以使用它来试验这个.如果为任何命令执行写出该属性的内容一次然后传递对象(这样你就可以用更大的管道来操纵对象)它是做什么的.您将看到的是,PipelineLength当您自己运行此命令时,有一个属性等于1,并且管道中的每个项目都会增加.还要注意PipelinePosition.它告诉您此命令在管道中的位置.
注意: $PSCmdlet仅在编写高级功能时可用(例如,具有[CmdletBinding()]属性).
function test-PSCmdlet
{
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true)]
$test
)
Begin{
$once = $false
}
process
{
if (!$once)
{
write-host ($PSCmdlet.MyInvocation |out-string)
$once = $true
}
Write-Output $_
}
}
Run Code Online (Sandbox Code Playgroud)
这里有些例子:
PS C:\Users\jsnover.NTDEV> test-PSCmdlet
MyCommand : test-PSCmdlet
BoundParameters : {}
UnboundArguments : {}
ScriptLineNumber : 1
OffsetInLine : 14
HistoryId : 61
ScriptName :
Line : test-PSCmdlet
PositionMessage :
At line:1 char:14
+ test-PSCmdlet <<<<
InvocationName : test-PSCmdlet
PipelineLength : 1
PipelinePosition : 1
ExpectingInput : False
CommandOrigin : Runspace
PS C:\Users\jsnover.NTDEV> gps lsass | test-PSCmdlet |Format-table Name,Id -auto
MyCommand : test-PSCmdlet
BoundParameters : {[test, System.Diagnostics.Process (lsass)]}
UnboundArguments : {}
ScriptLineNumber : 1
OffsetInLine : 26
HistoryId : 62
ScriptName :
Line : gps lsass | test-PSCmdlet |Format-table Name,Id -auto
PositionMessage :
At line:1 char:26
+ gps lsass | test-PSCmdlet <<<< |Format-table Name,Id -aut
o
InvocationName : test-PSCmdlet
PipelineLength : 3
PipelinePosition : 2
ExpectingInput : True
CommandOrigin : Runspace
Name Id
---- --
lsass 620
Run Code Online (Sandbox Code Playgroud)
执行此操作的"惯用"方法是输出特定对象类型,然后定义该对象的格式数据.该对象可以是自定义(基于C#/ VB的对象)或命名的PSObject.这种方法的优点是你可以只输出这些对象,如果没有进一步的管道输出格式化(即使用Format命令),那么你将使用你定义的默认输出格式.否则,其中一个Format命令可以覆盖该默认格式.这是一个例子:
PS> $obj = new-object psobject -Property @{FName = 'John'; LName = 'Doe'; `
BirthDate = [DateTime]"5/7/1965"}
PS> $obj.psobject.TypeNames.Insert(0, "MyNamespace.MyCustomTypeName")
PS> $obj
BirthDate FName LName
--------- ----- -----
5/7/1965 12:00:00 AM John Doe
PS> Update-FormatData .\MyCustomFormatData.ps1xml
PS> $obj
FName LName BirthDate
----- ----- ---------
John Doe 5/7/1965 12:00:00 AM
Run Code Online (Sandbox Code Playgroud)
请注意我们第二次发送$obj管道时默认输出是如何不同的.这是因为它使用了提供的自定义格式化指令,因为没有使用显式格式化命令.
顺便说一句,总有一条管道,$obj因为它是隐式管道的Out-Default.
这是在.ps1xml我命名为MyCustomFormatData.xml 的文件中定义的自定义格式定义:
<Configuration>
<ViewDefinitions>
<View>
<Name>MyNamespace.MyCustomTypeName</Name>
<ViewSelectedBy>
<TypeName>MyNamespace.MyCustomTypeName</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>FName</Label>
<Width>25</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>LName</Label>
<Width>25</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>BirthDate</Label>
<Width>25</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>FName</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>LName</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>BirthDate</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>
Run Code Online (Sandbox Code Playgroud)
有关如何格式化自定义对象的更多示例,请查看此命令输出的文件:
Get-ChildItem $pshome\*.format.ps1xml
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2832 次 |
| 最近记录: |