-ExpandProperty不会通过Remote PowerShell显示所有属性

时间:2017-06-29 12:19:31

标签: powershell exchange-server

当我在Exchange服务器上的Exchange PowerShell中运行以下代码时,它会显示所有属性:

PS> Get-Mailbox Testeria | select -ExpandProperty EmailAddresses

SmtpAddress        : Tester_IA@contoso.com
AddressString      : Tester_IA@contoso.com
ProxyAddressString : smtp:Tester_IA@contoso.com
Prefix             : SMTP
IsPrimaryAddress   : False
PrefixString       : smtp

SmtpAddress        : TesterIA@contoso.com
AddressString      : TesterIA@contoso.com
ProxyAddressString : SMTP:TesterIA@contoso.com
Prefix             : SMTP
IsPrimaryAddress   : True
PrefixString       : SMTP

SmtpAddress        : TesterIA@outlook.contoso.com
AddressString      : TesterIA@outlook.contoso.com
ProxyAddressString : smtp:TesterIA@outlook.contoso.com
Prefix             : SMTP
IsPrimaryAddress   : False
PrefixString       : smtp

但是当我尝试通过

在本地计算机上使用Remote PowerShell时
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri ("http://" + $Server + "/PowerShell/") -Authentication Kerberos
Import-PSSession $Session

并运行它只显示的相同代码:

PS> Get-Mailbox Testeria | select -ExpandProperty EmailAddresses

smtp:Tester_IA@contoso.com
SMTP:TesterIA@contoso.com
smtp:TesterIA@outlook.contoso.com

如何理解这种行为?如何通过Remote PowerShell获取所有属性?

本地计算机上的PSVersion是5.1.14409.1005

Exchange Server上的PSVersion是4.0

2 个答案:

答案 0 :(得分:3)

这可能是因为当您通过PSRemoting访问对象时,结果被反序列化。您可以通过将结果对象的TypeName查询到Get-Member来查看这种情况。您将看到反序列化的前缀为Type:

  

具有"反序列化的对象。"其类型名称中的前缀是属性包,其中包含反序列化的public表示形式   相应的远程,活动对象的属性。如你看到的   在Get-Member的输出中,这些属性包不会暴露任何   除ToString()之外的方法,因为通常无法调用方法   在远程会话中(例如,System.Diagnostics.Process.Kill()   无法对远程进程采取行动)。同样设置和获取属性   属性包的值不执行任何代码(例如   的WorkingSet属性   Deserialized.System.Diagnostics.Process.WorkingSet只是一个快照   并且当远程进程使用更多内存时不会更新。

我的假设是EmailAddresses属性是一个脚本属性,这意味着它在被调用以获取其子属性时执行脚本。通过远程处理检索对象时,您将无法执行此脚本。

不幸的是,我现在没有Exchange系统来验证这一点。

答案 1 :(得分:0)

Mark Wragg's answer 提供了有用的提示,但让我详细说明一下:

  • 通过 PowerShell 的 remoting 基础架构传输的对象在远程源进行基于 XML 的序列化,并在远程源进行反序列化来电者收到。

  • 除了少数几个知名类型之外,类型保真度在序列化/反序列化过程中会丢失,并且反序列化对象是原始对象的模拟,如其类型名称中的 Deserialized. 前缀所示(正如您可以通过访问 .pstypenames[0]通过管道将其反序列化的实例 Get-Member);具体来说,这些模拟的限制——除了没有与原版相同的类型标识——是:

    • 反序列化的对象缺乏原始的方法
    • 对于嵌套(标量)对象(由多个属性组成的对象,其值也是由多个属性组成的对象,...),对象图的深度限制为 {{1} }.
      • 在实践中,这意味着非知名(标量)类型的实例进行序列化,使得本身不是知名类型实例的属性值被替换为它们的{{1} } 表示

有关作为 PowerShell 远程处理基础结构一部分的序列化的更全面概述,请参阅 this answer


适用于您的案例

通过远程处理,最初包含在 Get-MailBox cmdlet 返回的对象的 1 属性中的丰富电子邮件对象实例的集合被转换为 字符串 的集合,通过在每个电子邮件对象实例上调用 .ToString(),它似乎返回 .EmailAddresses 属性值。


示例

为简单起见,以下通过使用 Start-Job 调用创建的本地后台作业(后台作业也使用 PowerShell 的远程处理基础设施)演示了递归深度(字符串化)问题:

.ToString()

如您所见,存储在属性 .ProxyAddressString 中的 PS> Start-Job { # Define a custom class, which is by definition not a well-known type. # Give it a property of another non-well-known type, [regex]. class Foo { $Bar = [regex] 'hi' } # Output an instance of the custom class. [Foo]::new() } | Receive-Job -Wait -AutoRemove | ForEach-Object { $_.Bar # Output the .Bar property value... $_.Bar.GetType().FullName # ... and its data type. } hi System.String 实例已被其 [regex] 表示替换。