使PowerShell认为对象不可枚举

时间:2010-10-14 15:37:09

标签: powershell

我一直在研究一些PowerShell函数来管理我们创建的程序集中实现的对象。我一直在使用的类之一实现了IEnumerable。不幸的是,这导致PowerShell在每个机会展开对象。 (我无法改变该类实现IEnumerable的事实。)

我通过创建PSObject并将自定义对象的属性复制到PSObject,然后返回而不是自定义对象来解决这个问题。但我真的宁愿返回我们的自定义对象。

是否有某种方法,可能是使用我的types.ps1xml文件,从PowerShell隐藏此类的GetEnumerator()方法(或以其他方式告诉PowerShell永远不会展开它)。

3 个答案:

答案 0 :(得分:8)

包裹PSObject可能是最好的方式。

你也可以将它显式地包装在另一个集合中 - PowerShell只打开一个级别。

当您在调用WriteObject时在C#/ VB / ...中编写cmdlet时,请使用带有第二个参数的重载:如果为false,则PowerShell将不会枚举作为第一个参数传递的对象。

答案 1 :(得分:5)

检查写入输出替换http://poshcode.org/2300,它具有-AsCollection参数,可以避免展开。但基本上,如果您正在编写一个输出集合的函数,并且您不希望该集合展开,则需要使用CmdletBinding和PSCmdlet:

function Get-Array {
    [CmdletBinding()]
    Param([Switch]$AsCollection) 

    [String[]]$data = "one","two","three","four"
    if($AsCollection) {
        $PSCmdlet.WriteObject($data,$false)
    } else {
        Write-Output $data
    }
}

如果你用-AsCollection调用它,你会得到非常不同的结果,虽然他们会在控制台中看到相同的结果。

C:\PS> Get-Array 

one
two
three
four

C:\PS> Get-Array -AsCollection

one
two
three
four

C:\PS> Get-Array -AsCollection| % { $_.GetType() }


IsPublic IsSerial Name       BaseType                             
-------- -------- ----       --------                             
True     True     String[]   System.Array                         



C:\PS> Get-Array | % { $_.GetType() }


IsPublic IsSerial Name       BaseType                             
-------- -------- ----       --------                             
True     True     String     System.Object                        
True     True     String     System.Object                        
True     True     String     System.Object                        
True     True     String     System.Object   

答案 2 :(得分:0)

这可能无法直接回答原始问题,因为从技术上讲它不会返回自定义对象本身,但是在尝试显示实现IEnumerable的自定义类型的属性时,我遇到了类似的问题认为值得分享。将此对象放入Get-MemberSelect-Object之类的cmdlet中,始终会枚举集合的内容。但是,直接使用这些cmdlet并将对象传递给-InputObject参数会产生预期的结果。在这里,我以ArrayList为例,但是$list可以是您的自定义集合类型的实例:

# Get a reference to a collection instance
$list = [System.Collections.ArrayList]@(1,2,3)

# Display the properties of the collection (in this case, the ArrayList),
# not the items it contains (Int32)
Select-Object -InputObject $list -Property *

# List the members of the ArrayList class, not the contained items
Get-Member -InputObject $list

正如其他评论所提到的,您可以将Select-Object的结果另存为变量,创建一个新的PSObject,您可以直接使用它而无需枚举内容:

# Wrap the collection in a PSObject
$obj = Select-Object -InputObject $list -Property *

# Properties are displayed without enumerating contents
$obj
$obj | Format-List
$obj | Format-Table