作为一名C#开发人员,我仍然在学习PowerShell的基础知识并经常感到困惑。 为什么$ _。在第一个例子中给出了智能属性名称的智能感知列表,但不是第二个?
Get-Service | Where {$_.name -Match "host" }
Get-Service | Write-Host $_.name
这两个例子的基本区别是什么?
当我运行第二个时,它会在每次Get-Service迭代时出现此错误:
Write-Host : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters
that take pipeline input.
At line:3 char:15
+ Get-Service | Write-Host $_.name
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (wuauserv:PSObject) [Write-Host], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.WriteHostCommand
我的同事和我第一次使用foreach循环来迭代Get-commandlet,我们不知道要出现属性名称。我们试图简化,直到我们进入上面的核心基础。
有时候只是弄清楚它在命令行记录中是一个错字,第一个失败是因为命令行开关应该是Get-Service而不是Get-Services。
foreach ($item in Get-Services)
{
Write-Host $item.xxx #why no intellisense here?
}
foreach ($item in Get-Service)
{
Write-Host $item.Name
}
答案 0 :(得分:4)
第一部分:你不能像这样使用$_
,它只代表脚本块中的当前管道对象。这些脚本块通常与任何*-Object
cmdlet一起使用(但也有其他用例)。并非所有参数/ cmdlet都支持它。 Write-Host是其中之一。
第二:看起来你正在使用自己的函数(GetServices)。 PowerShell v3 intellisense取决于命令元数据(OutputType)。如果任何cmdlet /函数产生对象但对OutputType保持沉默,则intellisense不起作用。获得它非常简单,你可以撒谎并仍然可以获得任何现有类型的正确智能感知:
function Get-ServiceEx {
[OutputType('System.ServiceProcess.ServiceController')]
param ()
'This is not really a service!'
}
(Get-ServiceEx).<list of properties of ServiceController object>
您可以阅读有关it on my blog的更多信息。
答案 1 :(得分:3)
如果将$_
放入脚本块中,Intellisense将起作用。
以下将触发intellisense:
Get-Service | Foreach-Object {$_.Name} # Intellisense works
Get-Service | Where-Object {$_.Name} # Intellisense works
Get-Service | Write-Host {$_.Name} # Intellisense works
请注意,您的命令不一定是有效命令:第三个示例不起作用,但intellisense将显示$_
的自动完成,因为它位于一个脚本块中。
我怀疑是因为$_
只能在一个脚本块中使用(例如switch,%,?),但我没有确凿的证据。
答案 2 :(得分:0)
$_
是管道中的当前对象。它与$item
中的foreach ($item in $array)
相同。
Get-Service | Where {$_.name -Match "host" }
Get-Service | Write-Host $_.name
这两行之间的区别是PowerShell设计的基本部分。管道应该很容易。你应该能够前。搜索和删除文件简单如下:
Get-ChildItem *.txt | Remove-Item
这很干净,简单,每个人都可以使用它。构建cmdlet以识别传入对象的类型,适应支持特定类型,并处理对象。
但是,有时您需要在管道中进行更高级的对象操作,这就是Where-Object
和Foreach-Object
的用武之地。两个cmdlet都允许您编写自己的处理逻辑,而无需创建函数或cmdlet第一。为了能够访问代码中的对象(处理逻辑),您需要一个标识符,即$_
。其他一些特殊cmdlet也支持$_
,但大多数cmdlet(包括Write-Host
)都没有使用它。
另外,foreach ($item in Get-Service)
中的智能感知有效。你有一个错字。