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



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

PS> 获取邮箱测试仪 | 选择 -展开属性电子邮件地址 地址 : Tester_IA@contoso.com 地址字符串 : Tester_IA@contoso.com 代理地址字符串:smtp:Tester_IA@contoso.com 前缀 : SMTP 是主要地址 : 假 前缀字符串 : smtp 地址 : TesterIA@contoso.com 地址字符串 : TesterIA@contoso.com 代理地址字符串:SMTP:TesterIA@contoso.com 前缀 : SMTP IsPrimaryAddress : True 前缀字符串 : SMTP 地址 : TesterIA@outlook.contoso.com 地址字符串 : TesterIA@outlook.contoso.com 代理地址字符串:smtp:TesterIA@outlook.contoso.com 前缀 : SMTP 是主要地址 : 假 前缀字符串:smtp

但是当我尝试通过本地计算机上使用远程PowerShell时

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

并运行相同的代码,它只显示以下内容:

PS> 获取邮箱测试仪 | 选择 -展开属性电子邮件地址 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

这可能是因为当您通过 PSRemoting 访问对象时,结果被反序列化。您可以通过查看结果对象的 TypeName 来查看它的情况,方法是将其旋转到Get-Member。您将看到以"类型"为前缀的"反序列化":

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

  • https://blogs.msdn.microsoft.com/powershell/2010/01/07/how-objects-are-sent-to-and-from-remote-sessions/

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

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

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

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

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

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

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


适用于您的案例

通过远程处理,最初包含在Get-MailBoxcmdlet 返回的对象的.EmailAddresses属性中的富电子邮件对象实例的集合将转换为字符串集合,方法是在每个电子邮件对象实例上调用.ToString(),这似乎返回.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()表示形式。

最新更新