Powershell Invoke-Command 未返回正确的输出

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

我正在尝试使用 StdRegProv 类从远程服务器收集一些注册表值:

Invoke-Command -ComputerName $ComputerHost -Credential $cred -ScriptBlock { Get-WmiObject -List -Namespace "root\default" | Where-Object { $_.Name -eq "StdRegProv" } }

但它不会在输出中返回这些类的方法:

   NameSpace: ROOT\default

Name                                Methods              Properties                                                                       PSComputerName
----                                -------              ----------                                                                       --------------
StdRegProv
                                                                                                                              

如果我在本地机器中从 ScriptBlock 执行命令,一切正常,输出如下所示:

   NameSpace: ROOT\default

Name                                Methods              Properties                                                                                                                                                                                                
----                                -------              ----------                                                                                                                                                                                                
StdRegProv                          {CreateKey, Delet... {}       

其他一些命令,例如 Get-Service,工作正常,我可以看到输出。这些有什么问题吗? 远程计算机是:安装了 .Net 3.5.1 和 PowerShell 2.0 的 Windows Server 2003

我想,StdRegProv 类在 2003 服务器中不起作用,但在本地可以正常工作

powershell wmi winrm
1个回答
0
投票

顺便说一句:

  • CIM cmdlet(例如,

    Get-CimInstance
    取代了 Windows PowerShell v3(于 2012 年 9 月发布)中的 WMI cmdlet
    (例如,
    Get-WmiObject。因此,应避免使用 WMI cmdlet,尤其是因为 PowerShell (Core) 7+(所有未来工作都将集中于 Windows PowerShell 的现代跨平台成功)甚至不再拥有。但请注意,WMI 仍然是 CIM cmdlet 的“底层”。有关更多信息,请参阅此答案

  • 由于您正在运行 - 早已过时的 -
  • Windows PowerShell

    v2CIM cmdlet 不是一个选项

您正在通过 PowerShell
remoting

 (
Get-WmiObject) 调用 Invoke-Command -ComputerName ,除了少数众所周知的类型之外,这会导致
 类型保真度的损失

值得注意的是,大多数类型的实例都是
    模拟
  • ,具有无方法[psobject]实例,这些实例具有原始对象的
    所有(公共)属性
    的静态副本 - 有关详细信息,请参阅这个答案
这解释了为什么结果对象缺少方法。

您有两个

选择

  • 任一调用远程执行脚本块中的任何方法,其中Get-WmiObject

    输出对象仍具有其所有原始标识。
    例如,以下命令调用 
    .GetStringValue
     方法来检索存储在 
    remote
     计算机上注册表项 
    Path
    HKEY_LOCAL_MACHINE\SOFTWARE\DefaultUserEnvironment 值中的数据:

    Invoke-Command -ComputerName $ComputerHost -Credential $cred -ScriptBlock { (Get-WmiObject -List StdRegProv).GetStringValue(2147483650, 'SOFTWARE\DefaultUserEnvironment', 'Path') }
    
    
  • :使用 WMI cmdlet 提供的 远程处理, 在这种情况下,类型保真度不会损失;但是,请注意,使用与 PowerShell 不同的远程处理基础设施,即过时的基于 DCOM 的基础设施,因此可能需要单独的配置;但是,根据您的反馈,调用者计算机上的 KB5004442 会主动阻止在针对运行较旧 Windows 版本的计算机时使用此基础设施。 # You can call methods such as `.GetStringValue()` directly # on the output object. ( Get-WmiObject -ComputerName $ComputerHost -Credential $cred -List StdRegProv ).GetStringValue(2147483650, 'SOFTWARE\DefaultUserEnvironment', 'Path')

    
    
CIM 解决方案(PowerShell v3+)

为了完整起见,以下是基于 CIM cmdlet 的等效解决方案:

$regProv = Get-CimClass StdRegProv -CimSession (New-CimSession -ComputerName $ComputerHost -Credential $cred) $regProv | Invoke-CimMethod -MethodName GetStringValue -Arguments @{ hDefKey = [Uint32] 2147483650; sSubKeyName = 'SOFTWARE\DefaultUserEnvironment'; sValueName = 'Path' }

但是,在这种情况下,您可以使用
just

Invoke-CimMethod 调用,并通过 -ClassName

 参数指定目标类:
Invoke-CimMethod -ClassName StdRegProv -MethodName GetStringValue -Arguments @{ hDefKey = [Uint32] 2147483650; sSubKeyName = 'SOFTWARE\DefaultUserEnvironment'; sValueName = 'Path' }

“CIM cmdlet
    ”远程处理使用与 PowerShell 远程处理相同的基础设施。
  • 虽然类型保真度没有损失,但请注意,CIM cmdlet 返回的实例没有可以直接调用的

    .NET
  • 方法;相反,必须通过
  • Invoke-CimMethod cmdlet 调用 CIM 方法,如上所示。

    参数
  • 必须通过
  • -Arguments参数传递,其中需要

    参数名称-值对的
    哈希表(字典)。 参数名称可以从

    .Parameters
      返回的 CIM 类实例上可用的
    • .CimClassMethods

      属性的

      Get-CimClass
      属性中收集;对于由
      Get-CimInstance
      返回的 CIM
      instances
      ,请使用 .CimClass.CimClassMethods;例如:
      (Get-CimClass StdRegProv).CimClassMethods | 
        Where Name -eq GetStringValue |
        ForEach Parameters
      
      
      

      这会产生以下显示输出:
        Name CimType Qualifiers ReferenceClassName ---- ------- ---------- ------------------ hDefKey UInt32 {ID, IN} sSubKeyName String {ID, IN} sValueName String {ID, in} sValue String {ID, out}
      • 不幸的是,参数信息
      • 指示
      • 可选

        参数或其默认值;例如,对于 GetStringValue()hDefKey 参数是可选的,默认为 HKEY_LOCAL_MACHINE (

        2147483650
        )
        
        
        
        

      警告
    • 数字类型参数必须由其 exact

      类型绑定,因此对上面的
        [UInt32]
      • 参数进行 hDefKey 强制转换。
        
        
        
        
© www.soinside.com 2019 - 2024. All rights reserved.