我天真地假设使用PowerShell的管道参数绑定传递给命令行开关的对象与使用命名参数传递它的方法相同。但是,以下脚本似乎表明存在差异:
Function Process-xMsmqQueue{
[CmdletBinding()]
Param(
[Parameter()]$obj,
[Parameter(
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True)]
[System.Messaging.MessageQueue]$queue
)
Write-Host $obj
}
New-MsmqQueue 'xTest1' -ErrorAction Ignore
[System.Reflection.Assembly]::LoadWithPartialName('System.Messaging') | Out-Null
New-Object System.Messaging.MessageQueue('.\private$\xTest1') -OutVariable q
$first = 'first'
$second = 'second'
$q | Process-xMsmqQueue -obj $first
Process-xMsmqQueue -queue $q -obj $second
我希望此脚本能够打印first
和second
。相反,它会在最后一行抛出ParameterArgumentTransformationError
:
$queue
参数的处理差异似乎只显示某些对象类型。例如,将[System.Messaging.MessageQueue]
替换为[System.String]
并将字符串传递给$queue
不会产生任何错误。
我的问题:
System.Messaging.MessageQueue
对象在使用管道传递而不是命名参数时会被区别对待?System.String
不受差异影响?-queue
的命名参数传递工作?答案 0 :(得分:1)
作为@mikez pointed out,一旦你意识到-OutVariable
产生了一个对象的ArrayList,那么这三个问题的答案就很明显了。 -Outvariable
适合管道和seems to exist to facilitate inspection of objects passed through the pipeline进一步消费。
为什么System.Messaging.MessageQueue对象的处理方式不同 使用管道与命名参数传递时?
考虑以下一行:
New-Object System.Messaging.MessageQueue('.\private$\xTest1') -OutVariable q
实际上会生成System.Messaging.MessageQueue[]
(不是System.Messaging.MessageQueue
)类型的对象,它是MessageQueues的Arraylist。
<强>管道强>
考虑这一行:
$q | Process-xMsmqQueue -obj $first
据我了解,Powershell解释了管道运算符,以便后续的命令行开关作用于Arraylist中的每个元素。鉴于上下文,该行等同于以下内容:
foreach($item in $q){
Process-xMsmqQueue -queue $item -obj $first
}
并且,因为$q
只包含一个对象,foreach
的正文只执行一次。
命名参数
既然我们知道$q
实际上是System.Messaging.MessageQueue
个对象的Arraylist,那么以下行会产生错误就不足为奇了:
Process-xMsmqQueue -queue $q -obj $second
-queue
接受System.Messaging.MessageQueue
,但$q
属于Arraylist类型。
旁注:让我误入歧途的是$q | gm
输出TypeName: System.Messaging.MessageQueue
。但是,$q.GetType()
会返回ArrayList
。看看Get-Member文档解释了这种差异:
当您将对象集合传递给Get-Member时,Get-Member会获得 集合中各个对象的成员,例如 字符串数组中每个字符串的属性。
为什么System.String不受差异影响?
如果你以相同的方式获得一个字符串:
New-Object System.String('MyString') -OutVariable $str
$str
是System.String
个对象的ArrayList。如果我将其按名称传递给期望System.String
的参数,我会得到相同的ParameterArgumentTransformationError
。
如何更改此脚本以使命名参数传递为-queue?
有几个选择:
使用=
分配New-Object
的输出:$q=New-Object ...
这种方式$q
包含单个对象,而不是-OutVariable
带来的ArrayList
将Process-xMsmqQueue -queue
更改为接受System.Messaging.MessageQueue[]
。命令行开关需要迭代ArrayList。
索引$q
,如下所示:Process-xMsmqQueue -queue $q[0]
这将获取由New-Object
生成的ArrayList的第一个元素