ByValue和ByPropertyName的区别
ByValue
以Get-Service命令为例,它的帮助文件中关于-Name参数是这样解释的:
1. "WinRM" | Get-Service
2. "TrustedInstaller","BITS","WinRM" | Get-Service
3. Get-Content services.txt | Get-Service
以上的命令比 Get-Content services.txt | ForEach-Object { Get-Service -Name $_ } 简单明了很多.
那么你要问了,管道符号前面只有一个值,Get-Service命令后面却有很多参数,它怎么知道把前面的值传给后面的哪个参数呢?决定因素就在于位置参数Position:0,这表示-Name参数的优先级最高,管道传过来的值就给这个参数。
ByPropertyName (ByProperty'sName)
还是以Get-Service为例,我们先创建一个自定义对象:
$list = [PSCustomObject]@{ 'computername' = 'server1'}, [PSCustomObject]@{'computername' = 'server2' } #这里一共2个对象;效果和Import-CSV一样
$list | Get-Service #报错。因为-Name是位置参数,你不指定参数时系统就默认为你想将变量list的内容传递给-Name,但却因为不存在叫做类似“server1”这样的服务名而导致传递失败,于是就报错了。但是我们用一个小技巧即可解决这个问题
$list | Get-Service -Name * #先显式指定-Name参数的值,不让它接收管道传来的值,于是系统转而将值传递给-ComputerName
接下来以New-ADUser为例,假如你从HR拿到了一份新员工列表:
你需要为他们创建域账号,显而易见,你不能直接导入这份表格,因为AD中的User可没有这些中文的属性名,怎么办?让Powershell的哈希表来转换:
$userlist | Select -Property @{name="displayName";expression={$_.姓名}}, @{name="SamAccountName";expression={$_.登录名}} | New-ADUser #该命令不完整,重点是中间那段Property Name的转换
这样做的目的就是为了让列表中的值以ByPropertyName的方式传递给New-ADUser命令,只有属性名(displayName,SamAccountName)一样才能传递。
再用Get-Content举一个例子,Get-Content一共有6个支持且只支持ByPropertyName的参数,我选择其中两个-Path和-Tail,然后用下面的命令将内容通过管道进行传递:
[PSCustomObject]@{'Path'='C:\Windows\WindowsUpdate.log'; 'Tail'=10} | Get-Content
这个例子很好的说明了ByPropertyName这种方式“会将管道左边每个匹配的属性名称与管道右边的命令所允许接受的参数进行关联”。
系统会优先使用byValue方法,仅当byValue方法无法执行时才会尝试使用byPropertyName方法。
http://windowsitpro.com/blog/pipeline-parameter-binding-byvalue
http://windowsitpro.com/blog/pipeline-parameter-binding-bypropertyname