You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Invoke-Command返回对象GetType与Get-Member显示类型不一致?

为什么Get-Member和GetType()对远程返回的对象类型报告不一致?

其实这俩命令看的是对象的不同层面,本质是PowerShell对反序列化远程对象的特殊处理导致的,咱们一步步说清楚:

1. 先搞懂Invoke-Command返回的是什么

当你用Invoke-Command远程执行命令时,返回的对象并不是原服务器上的System.ServiceProcess.ServiceController实例——因为跨进程/机器的对象不能直接传递,PowerShell会把对象序列化成XML(用PSRemoting的序列化格式),传到本地后再反序列化成一个“模拟”原对象的结构。

但这个反序列化出来的对象,并不是直接的原类型实例,而是被PowerShell用PSObject包装起来的容器,同时给它附加了原类型的元数据。

2. Get-Member看的是“逻辑类型”

Get-Member的工作逻辑是:它不会直接去查对象的底层CLR类型,而是优先读取对象的类型名称列表(也就是$obj.PSObject.TypeNames里的内容)。对于远程反序列化的对象,这个列表的第一个元素就是Deserialized.System.ServiceProcess.ServiceController——这是PowerShell给它加的“逻辑类型标识”,目的是让你直观知道这是从远程来的、对应原类型的反序列化对象,同时Get-Member会基于这个逻辑类型展示对应的属性和方法(虽然有些是模拟的,不是原类型的真实方法)。

你可以自己验证一下:

$remoteService = Invoke-Command -ScriptBlock { Get-Service } -ComputerName SERVER01 | Select-Object -First 1
$remoteService.PSObject.TypeNames

输出的第一个结果就是Deserialized.System.ServiceProcess.ServiceController,后面才会出现System.Management.Automation.PSObject。

3. GetType()看的是“底层CLR类型”

而GetType()是直接调用.NET CLR对象的原生方法,它只认最底层的实际类型。因为远程反序列化的对象本质上是被PSObject这个.NET类包装的,所以$_.GetType()返回的就是System.Management.Automation.PSObject——这是对象在CLR层面的真实类型。

总结一下

  • Get-Member展示的是PowerShell给对象赋予的逻辑类型,方便你理解它对应的原对象是什么,以及能使用哪些属性方法;
  • GetType()展示的是对象在CLR层面的实际类型,也就是那个用来包装反序列化数据的PSObject容器。

这俩其实不矛盾,只是看问题的角度不同而已~

内容的提问来源于stack exchange,提问作者lit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:52:24