本地语句输出与调用命令输出非常不同

问题描述 投票:1回答:2

直接登录系统,运行此语句,并获得以下输出:

(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到底在做什么的问题。采取了这个简单,优美的小声明-对我的生活造成了严重破坏。

powershell powershell-remoting powershell-ets
2个回答
0
投票

在您的特定情况下 枚举值的实例(System.Enum派生类型的实例的实例):

  • 使用[int] $hello获得原始枚举(源自System.Enum的值)的数值]],而没有远程处理基础结构添加的额外NoteProperty成员,例如PSComputerName(请参见下面)。

  • 使用$hello.Value获得枚举值的[[string

  • 表示形式(其符号name而不是其number)。
  • 如果您知道原始的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成员的基础对象。 对于其他人,您可以通过将具有不需要的属性
  • excluded
  • 的管道[pscustomobject]输送到Select-Object,来创建

    new

    对象(始终为Lee Dailey类型):
      $hello | Select-Object * -Exclude PSComputerName, PSShowComputerName, RunspaceId
  • 或者,您可以专注于选择

  • do所需的属性。
  • 继续阅读,以了解为什么这样做是必要的。

    PowerShell的远程处理基础结构将以下属性作为NoteProperty成员添加到远程调用返回的


    every对象中:

      PSComputerName ...远程计算机的名称

  • [RunspaceId ...在其中执行远程命令的运行空间的ID。

  • PSShowComputerName ...一个

  • hidden
  • 属性,当对通过$trueInvoke-Command开关返回的所有对象设置为-HideComputerName时,将抑制PSComputerName

    display

    默认输出中的]属性(但该属性仍然存在);仅当将远程接收的对象通过管道传输到PSShowComputerName时,您才能看到Get-Member -Force本身。另外,System.Enum派生的类型作为[int]实例返回,添加了[string]类型的Value属性NoteProperty成员,该成员包含枚举值的
  • 符号名称
  • PSComputerNameRunspaceId属性可用于一次远程处理multiple

    计算机的命令:鉴于不能保证接收输出的顺序,这些属性会告诉您给定输出对象的起源来自。

    PSShowComputerName属性允许您控制默认的显示行为-但是,奇怪的是,它对是否显示RunspaceId没有影响。Value派生类型的System.Enum属性可补偿通常在远程命令(和后台作业)中发生的类型保真度损失-仅有限的一组已知类型会以类型保真度反序列化-请参见this answer

    尽管这些属性总是


    exist,它们是否

    默认显示

    取决于返回对象的特定类型,以及与它们关联的格式数据或默认情况下由PowerShell应用的格式数据。[此外,当您显式地管道传输到Format-* cmdlet时以及在序列化期间(例如,使用ConvertTo-Json,它们可能会显示。

    我相信,如果您不希望使用计算机名,这将可行:
    (icm $hi {Get-ClusterNetwork 'cluster backups'}).role

    0
    投票
    (icm $hi {Get-ClusterNetwork 'cluster backups'}).role
    © www.soinside.com 2019 - 2024. All rights reserved.