Powershell - 无法将类型 "System.Management.Automation.PSCustomObject" 的值转换为类型 "System.Management.Automation.PSCustomObject"
Powershell - Cannot convert value of type "System.Management.Automation.PSCustomObject" to type "System.Management.Automation.PSCustomObject"
我在 Windows 7 下使用 Powershell 4,我的 cmdlet 定义如下:
Function Transfer-File {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[System.Management.Automation.PSCustomObject]
$source,
# other parameters removed for brevity
)
# actual logic does not matter
}
我是这样称呼它的:
$hasError = Transfer-File -source $source -destination $cfg.Destination -logfile $logFile
$source是通过解析一个JSON文件得到的,看起来像这样:
@{Path=some path string here; Pack=False}
Write-Host $source.GetType()
输出:
System.Management.Automation.PSCustomObject
我收到以下错误:
Cannot convert the "@{Path=some path string here; Pack=False}"
value of type "System.Management.Automation.PSCustomObject" to type
"System.Management.Automation.PSCustomObject".
在一次绝望的尝试中,我用 psobject
替换了 System.Management.Automation.PSCustomObject
,它似乎工作正常。
问题:为什么我的 System.Management.Automation.PSCustomObject
似乎不适合 cmdlet 原型中的 System.Management.Automation.PSCustomObject
?
对象创建的完整代码:
### Configuration ###
$cfg = New-Object –TypeName PSObject
$cfg | Add-Member -MemberType NoteProperty –Name Sources –Value @()
# get configuration from json file
$jsonContent = Get-Content .\config.json | Out-String
$jsonObj = ConvertFrom-Json $jsonContent
$cfg.Sources = $jsonObj.Sources
Foreach ($source in $cfg.Sources)
{
# Write-Host $source.GetType()
$hasError = Transfer-File -source $source -destination $cfg.Destination -logfile $logFile
}
正如@VivekKumarSingh 的评论所暗示的,这是一个与加速器相关的bug。
这行不通:
# Error
$y = [System.Management.Automation.PSCustomObject]@{Path='some path string here'; Pack=$False}
这行不通:
$y = [PSCustomObject]@{Path='some path string here'; Pack=$False}
function t ([System.Management.Automation.PSCustomObject]$x) { $x }
# Error
t $y
这会起作用:
$y = [PSCustomObject]@{Path='some path string here'; Pack=$False}
function t ([PSCustomObject]$x) { $x }
t $y
但是,上述 不会 将任何类型强制转换为 PSCustomObject
,因为该类型继承自 Object
:
PS> function t ([PSCustomObject]$x) { $x.GetType().FullName }
PS> t 5
System.Int32
PS> t 'asdf'
System.String
PS> t $(Get-ChildItem)
System.Object[]
PS> t $(Get-Item .)
System.IO.DirectoryInfo
这也可以,但我不确定它是否 100% 等效。
function t ([System.Management.Automation.PSObject]$x) { $x }
我不确定的原因是因为这个怪异:
PS> $a = New-Object -TypeName System.Management.Automation.PSObject -Property @{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Management.Automation.PSCustomObject
PS> $a = New-Object -TypeName System.Management.Automation.PSCustomObject -Property @{Path='some path string here'; Pack=$False}
New-Object : A constructor was not found. Cannot find an appropriate constructor for type System.Management.Automation.PSCustomObject.
PS> $a = [PSCustomObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Management.Automation.PSCustomObject
PS> $a = [System.Management.Automation.PSObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Collections.Hashtable
PS> $a = [PSObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Collections.Hashtable
据我所知,[PSCustomObject]
和[PSObject]
都是System.Management.Automation.PSObject
的加速器。 System.Management.Automation.PSCustomObject
只是他们为使 [PSCustomObject]
成为可能而添加的实现细节,但不幸的是,一切工作的方式感觉有点不一致。但是,我并不完全清楚 [PSObject]
类型加速器的用途。看似什么都不做,但也确实存在:
PS> ([System.Management.Automation.Cmdlet]).Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get.ContainsKey('psobject')
True
我在 Windows 7 下使用 Powershell 4,我的 cmdlet 定义如下:
Function Transfer-File {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[System.Management.Automation.PSCustomObject]
$source,
# other parameters removed for brevity
)
# actual logic does not matter
}
我是这样称呼它的:
$hasError = Transfer-File -source $source -destination $cfg.Destination -logfile $logFile
$source是通过解析一个JSON文件得到的,看起来像这样:
@{Path=some path string here; Pack=False}
Write-Host $source.GetType()
输出:
System.Management.Automation.PSCustomObject
我收到以下错误:
Cannot convert the "@{Path=some path string here; Pack=False}" value of type "System.Management.Automation.PSCustomObject" to type "System.Management.Automation.PSCustomObject".
在一次绝望的尝试中,我用 psobject
替换了 System.Management.Automation.PSCustomObject
,它似乎工作正常。
问题:为什么我的 System.Management.Automation.PSCustomObject
似乎不适合 cmdlet 原型中的 System.Management.Automation.PSCustomObject
?
对象创建的完整代码:
### Configuration ###
$cfg = New-Object –TypeName PSObject
$cfg | Add-Member -MemberType NoteProperty –Name Sources –Value @()
# get configuration from json file
$jsonContent = Get-Content .\config.json | Out-String
$jsonObj = ConvertFrom-Json $jsonContent
$cfg.Sources = $jsonObj.Sources
Foreach ($source in $cfg.Sources)
{
# Write-Host $source.GetType()
$hasError = Transfer-File -source $source -destination $cfg.Destination -logfile $logFile
}
正如@VivekKumarSingh 的评论所暗示的,这是一个与加速器相关的bug。
这行不通:
# Error
$y = [System.Management.Automation.PSCustomObject]@{Path='some path string here'; Pack=$False}
这行不通:
$y = [PSCustomObject]@{Path='some path string here'; Pack=$False}
function t ([System.Management.Automation.PSCustomObject]$x) { $x }
# Error
t $y
这会起作用:
$y = [PSCustomObject]@{Path='some path string here'; Pack=$False}
function t ([PSCustomObject]$x) { $x }
t $y
但是,上述 不会 将任何类型强制转换为 PSCustomObject
,因为该类型继承自 Object
:
PS> function t ([PSCustomObject]$x) { $x.GetType().FullName }
PS> t 5
System.Int32
PS> t 'asdf'
System.String
PS> t $(Get-ChildItem)
System.Object[]
PS> t $(Get-Item .)
System.IO.DirectoryInfo
这也可以,但我不确定它是否 100% 等效。
function t ([System.Management.Automation.PSObject]$x) { $x }
我不确定的原因是因为这个怪异:
PS> $a = New-Object -TypeName System.Management.Automation.PSObject -Property @{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Management.Automation.PSCustomObject
PS> $a = New-Object -TypeName System.Management.Automation.PSCustomObject -Property @{Path='some path string here'; Pack=$False}
New-Object : A constructor was not found. Cannot find an appropriate constructor for type System.Management.Automation.PSCustomObject.
PS> $a = [PSCustomObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Management.Automation.PSCustomObject
PS> $a = [System.Management.Automation.PSObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Collections.Hashtable
PS> $a = [PSObject]@{Path='some path string here'; Pack=$False}
PS> $a.GetType().FullName
System.Collections.Hashtable
据我所知,[PSCustomObject]
和[PSObject]
都是System.Management.Automation.PSObject
的加速器。 System.Management.Automation.PSCustomObject
只是他们为使 [PSCustomObject]
成为可能而添加的实现细节,但不幸的是,一切工作的方式感觉有点不一致。但是,我并不完全清楚 [PSObject]
类型加速器的用途。看似什么都不做,但也确实存在:
PS> ([System.Management.Automation.Cmdlet]).Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get.ContainsKey('psobject')
True