(icm $hi {Get-ClusterNetwork 'cluster backups'}).role
直接登录系统,运行此语句,并获得以下输出:
(Get-ClusterNetwork 'cluster backups').role
None
这很完美...简单也很漂亮。
但是,当我使用invoke-command从远程计算机运行完全相同的语句时,直到现在我一直只是假设就像在计算机的CLI中键入此完全相同的语句一样,我得到的是此输出
Invoke-Command -Session $hi -ScriptBlock {(Get-ClusterNetwork 'cluster backups').role}
PSComputerName RunspaceId Value
-------------- ---------- -----
dumdum a84b6c89-dumdum-80d3-ed43230ee8ab None
现在这真的很有趣。如果我将一个变量分配给invoke-command输出,则它将具有上面显示的相同输出,除非-我将其通过管道传递到set-clipboard
所以变量
$hello = invoke-command -session $hi -scriptblock {(get-networkcluster 'cluster backups').role}
现在在提示符下输入$ hello,我得到:
PSComputerName RunspaceId Value
-------------- ---------- -----
dumdum a84b6c89-dumdum-80d3-ed43230ee8ab None
这是预期的。但是现在,当我将其通过管道传递到set-clipboard并粘贴-值是:
$hello | set-clipboard;
get-clipboard
None
这是我想要的实际值。设置剪贴板的某种方式知道只能拉出我最初要求的属性。即使变量,具有所有属性。当我运行$ hello.gettype()时-我看到的值为Int32。如果$ hello仅返回我想要的值,这是有道理的,但是...不是。
但是如果还不够怪异-我正在invoke-command中运行一些功能,那只是一件-所有功能都返回一个我要报告的值。因此:
$row = '' | select computername, ClusterNetworkRole, IP;
$row.computername = $name;
$row.clusternetworkrole = $hello;
$row.ip = dum.dum.dum.dum;
Return $row;
您知道$ row.clusternetworkrole的输出是什么吗?大胆猜测。这是除我想要的财产以外的所有财产。
$row
PSComputerName : ST-SQL-MP2-31a
RunspaceId : b898bdad-dumdum-9eff-8a2beeefe78a
ClusterNetworkRole :
Computername : dum
IP : dum.dum.dum.dum
不仅为我提供了我不想要的确切属性-它实际上将这些属性添加为$ row的成员。
$row.RunspaceID
b898bdad-dumdum-9eff-8a2beeefe78a
现在,我可以通过在语句末尾附加“ .value”来获得我想要的值,因此,这不是一个要解决的问题,而只是一个关于powershell到底在做什么的问题。采取了这个简单,优美的小声明-对我的生活造成了严重破坏。
在您的特定情况下 枚举值的实例(System.Enum
派生类型的实例的实例):
使用[int] $hello
获得原始枚举(源自System.Enum
的值)的数值]],而没有远程处理基础结构添加的额外NoteProperty
成员,例如PSComputerName
(请参见下面)。
使用$hello.Value
获得枚举值的[[string
System.Enum
派生类型,并且该类型在本地会话中也可用,则可以cast
[Microsoft.Foo.Bar.ClusterRole] $hello
$hello
从技术上讲是[int]
,但装饰有额外的属性,并且有关original
.pstypenames
数组中,该信息反映了具有类型名称的原始类型的继承层次结构前缀为Deserialized.
;例如Deserialized.Microsoft.Foo.Bar.ClusterRole
; PowerShell的输出格式系统使此类对象通过[隐式应用] Format-Table
进行格式化,在这种情况下,该对象显示所有内容[[but实际[int]
值-仅显示NoteProperty
成员。] >通常],您可以排除不需要的属性,如下所示:
strings和。NET基本类型
(例如[int]
,[long]
,...)以及更多(请参阅MS-PSRP,PowerShell远程协议规范),您可以访问$hello.psobject.BaseObject
以获取没有任何NoteProperty
成员的基础对象。 对于其他人,您可以通过将具有不需要的属性[pscustomobject]
输送到Select-Object
,来创建new
对象(始终为Lee Dailey类型):$hello | Select-Object * -Exclude PSComputerName, PSShowComputerName, RunspaceId
或者,您可以专注于选择
继续阅读,以了解为什么这样做是必要的。 PowerShell的远程处理基础结构将以下属性作为NoteProperty
成员添加到远程调用返回的
every对象中:PSComputerName
...远程计算机的名称
[RunspaceId
...在其中执行远程命令的运行空间的ID。
PSShowComputerName
...一个
$true
的Invoke-Command
开关返回的所有对象设置为-HideComputerName
时,将抑制PSComputerName
的display
默认输出中的]属性(但该属性仍然存在);仅当将远程接收的对象通过管道传输到PSShowComputerName
时,您才能看到Get-Member -Force
本身。另外,System.Enum
派生的类型作为[int]
实例返回,添加了[string]
类型的Value
属性NoteProperty
成员,该成员包含枚举值的PSComputerName
和RunspaceId
属性可用于一次远程处理multiple
PSShowComputerName
属性允许您控制默认的显示行为-但是,奇怪的是,它对是否显示RunspaceId
没有影响。Value
派生类型的System.Enum
属性可补偿通常在远程命令(和后台作业)中发生的类型保真度损失-仅有限的一组已知类型会以类型保真度反序列化-请参见this answer。
尽管这些属性总是
默认显示
取决于返回对象的特定类型,以及与它们关联的格式数据或默认情况下由PowerShell应用的格式数据。[此外,当您显式地管道传输到Format-*
cmdlet时以及在序列化期间(例如,使用ConvertTo-Json
,它们可能会显示。 (icm $hi {Get-ClusterNetwork 'cluster backups'}).role
(icm $hi {Get-ClusterNetwork 'cluster backups'}).role