【问题标题】:Hashtable in PowershellPowershell 中的哈希表
【发布时间】:2022-01-11 03:56:01
【问题描述】:

我有一个声明为(例如)的变量

$dict_object = @{Firstname="A";Lastname="B"}

我想运行另一个命令,例如任何命令,Get-CIMInstance -class win32_BIOS,我想使用 compare-object 将输出与 $dict_object 变量进行比较。问题是 $dict_object 是一个哈希表,而命令输出不是一个哈希表。这只是示例,但有什么方法可以将 Powershell 命令输出转换为哈希表并将其与哈希表变量/对象进行比较。我尝试使用 Convertfrom-stringData 但它没有按预期分配键值对。

例如,这是带有 convertfrom-stringdata 的命令

PS C:\Windows\System32> Get-CimInstance -class win32_bios | ConvertFrom-StringData
Name                           Value
----                           -----
Win32_BIOS: 1.6.0 (Name        "1.6.0", SoftwareElementID = "1.6.0", SoftwareElementState = 3, TargetOperatingSystem =…

相对于正常输出

PS C:\Windows\System32> Get-CimInstance -class win32_bios

SMBIOSBIOSVersion : 1.6.0
Manufacturer      : Dell Inc.
Name              : 1.6.0
SerialNumber      : BDM8P93
Version           : DELL   - 20170001 

我希望上面的第一列作为键,第二列作为值,但似乎 ConvertFrom-StringData 不是这样工作的。

我需要将现有变量与 Get-WebconfigurationProperty(IIS 模块)的输出进行比较,如果值不正确,则 else 块将执行 Add-webconfigurationProperty,我已经测试过 Add-webconfigurationProperty 将 HashTable 作为输入

【问题讨论】:

  • 为什么要将哈希表与具有可引用属性的对象进行比较?您可以轻松地将哈希表转换为自定义对象,然后将属性与 Compare-Object -> $dict_object = [pstcustomobject]@{Firstname="A";Lastname="B"} 进行比较
  • 不能使用 [pscustomobject] 作为命令的输出,其值在之前创建时未知。

标签: powershell collections hashtable


【解决方案1】:

我会运行一次Get-CimInstance 并根据您需要的值填充哈希表。 例如:

$cimInstance = Get-CIMInstance -class win32_BIOS
$cimHashTable = @{
  Name = $cimInstance.Name
  Version = $cimInstance.Version}
}
if ($cimHashTable.Name -eq 'CorrectValue')
{
  continue
}
else
{
  Fix-Value
}

但是,在这种情况下,我实际上不会努力创建一个新的 HashTable,而只是使用 $cimInstance 变量并直接检查值。

【讨论】:

    【解决方案2】:
    • Get-CimInstance 输出(非字符串)对象,而不是字符串,因此它的输出不能有意义地用作ConvertFrom-StringData 的输入,ConvertFrom-StringData 需要特定格式的字符串。

    • 虽然您不能(直接)将对象转换为hashtables,但您可以直接将预先存在的[1]哈希表转换为([pscustomobject]) 对象;例如:

      $dict_object = 
      $object_from_dict = [pscustomobject] $dict_object
      
    • 当然,您也可以直接将[pscustomobject] 实例直接,作为文字[1]

      $object = [pscustomobject] @{Firstname="A";Lastname="B"}
      

    正如AdminOfThings 所说,一旦您有(非哈希表)对象要比较,您可以使用Compare-Object cmdlet 比较两个[集合]对象的多个属性,传递集合将对象与-Property 参数进行比较的属性:

    # Reference object (the one with comparison values).
    $refObj = [pscustomobject] @{ Manufacturer = 'Dell Inc'; Name = '1.6.0' }
    
    # Difference object (the one to compare against, from command output)
    $diffObj = Get-CimInstance -Class win32_BIOS
    
    # Compare the two objects, by the properties defined on the reference object.
    Compare-Object $refObj $diffObj -Property $obj.psobject.Properties.Name
    

    默认情况下,Compare-Object 仅输出那些不同的输入对象,这些对象包含在 [pscustomobject] 实例中,.SideIndicator 属性指示对象在哪个输入端是唯一的;请参阅this answer 了解更多信息。


    [1] 创建[pscustomobject] literals 甚至使用哈希表语法(例如,[pscustomobject] @{Firstname="A";Lastname="B"}),但这实际上是构造对象的语法糖直接,而不是通过中间哈希表。另请注意,与真正的哈希表不同,这样的文字保留了键/属性名称的定义顺序。

    【讨论】:

    • 我已经给出了这个论坛中所说的例子。在理想情况下,将预定义的字典值与命令的输出进行比较,我希望命令输出与任何内容进行比较,并且比较不会在 2 个对象的属性之间进行,而是对象本身。因此,无论如何,我听说 powershell 命令的输出无法转换为哈希表对象以与另一个字典进行比较,并且只能比较 2 个对象的属性。
    • @VijayanandA,Alex_P 的回答向您展示了如何从对象的属性构造散列表(这也可以在不知道属性名称的情况下提前完成)。至于按属性比较对象:您可以将任意数量的属性传递给Compare-Object-Property 参数。我不明白 将成为对象本身 您评论的一部分。对象作为一个整体 - 除非它们是 .NET 值类型的实例 - 如果它们是不同的实例,通常不会进行有意义的比较。
    猜你喜欢
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-17
    • 2019-04-27
    相关资源
    最近更新 更多