【问题标题】:-ExpandProperty doesn't show all the properties via Remote PowerShell-ExpandProperty 不会通过远程 PowerShell 显示所有属性
【发布时间】:2017-12-03 03:29:25
【问题描述】:

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

PS> Get-Mailbox Testeria |选择 -ExpandProperty 电子邮件地址 SmtpAddress:Tester_IA@contoso.com 地址字符串:Tester_IA@contoso.com ProxyAddressString : smtp:Tester_IA@contoso.com 前缀:SMTP IsPrimaryAddress : 假 前缀字符串:smtp SmtpAddress:TesterIA@contoso.com 地址字符串:TesterIA@contoso.com ProxyAddressString : SMTP:TesterIA@contoso.com 前缀:SMTP IsPrimaryAddress : 真 前缀字符串:SMTP SmtpAddress:TesterIA@outlook.contoso.com 地址字符串:TesterIA@outlook.contoso.com ProxyAddressString:smtp:TesterIA@outlook.contoso.com 前缀:SMTP IsPrimaryAddress : 假 前缀字符串:smtp

但是当我尝试在本地机器上使用远程 PowerShell 时

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri ("http://" + $Server + "/PowerShell/") -Authentication Kerberos
Import-PSSession $Session

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

PS> Get-Mailbox Testeria |选择 -ExpandProperty 电子邮件地址 smtp:Tester_IA@contoso.com SMTP:TesterIA@contoso.com smtp:TesterIA@outlook.contoso.com

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

本地机器上的 PSVersion 是 5.1.14409.1005

Exchange Server 上的 PSVersion 为 4.0

【问题讨论】:

    标签: powershell exchange-server


    【解决方案1】:

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

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

    我的假设是EmailAddresses 属性是一个脚本属性,这意味着它在调用时执行一个脚本来获取它的子属性。当您通过 Remoting 检索对象时,您将无法执行此脚本。

    很遗憾,我目前没有 Exchange 系统来验证这一点。

    【讨论】:

    • 好指针,但我认为EmailAddresses 对象转向字符串的真正原因是远程处理基础结构应用于非知名(标量)对象的隐式递归深度限制,它取代了属性值本身不是具有 .ToString() 值的知名类型的实例。
    【解决方案2】:

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

    • 通过PowerShell 的remoting 基础架构 传输的对象在远程源进行基于XML 的序列化,并在调用方接收到反序列化

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

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

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


    适用于您的案例

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


    示例

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

    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
    

    如您所见,存储在属性.Bar 中的[regex] 实例已被其.ToString() 表示所取代。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-28
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 2016-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多