遍历对象的属性

Iterating through properties of a object

我有以下对象:

$restrictedPrograms = @(
    @{DisplayName = "Microsoft Visual Studio Test"};
    @{Guid = "102C29B2-4320-4774-8003-6912F0AC19"};
    @{DisplayName = "Microsoft Office 365 ProPlus - en-us"};
    @{Guid = "B24E0C46-B627-4781-975E-620ED53CD98"};
    @{DisplayName = "SourceTre"; Guid = "B24E0C46-B627-4781-975E-620ED53CD981"}
)

受限制的项目只能有一个 属性(DisplayName 或 Guid)或两者。

$installedPrograms = @(
        @{DisplayName = "SourceTree"; Guid = "B24E0C46-B627-4781-975E-620ED53CD981"};
        @{DisplayName = "Microsoft Help Viewer 2.0"; Guid = "FEB375AB-6EEC-3929-8FAF-188ED81DD8B5"}
    )

我想遍历每个 installedPrograms 并比较 restrictedPrograms 中的那些属性。我知道如何通过硬编码 属性 名称(DisplayName 和 Guid)来做到这一点:

foreach($installedProgram in $installedPrograms)
    {
        foreach($restrictedProgram in $restrictedPrograms)
        {
            if($restrictedProgram.DisplayName -and $restrictedProgram.Guid)
            {
                if(($installedProgram.DisplayName -eq $restrictedProgram.DisplayName) -and ($installedProgram.Guid -eq $restrictedProgram.Guid))
                {
                    return $false;
                }
            }
            else
            {
                if($restrictedProgram.DisplayName)
                {
                    if($installedProgram.DisplayName -eq $restrictedProgram.DisplayName)
                    {
                        return $false;
                    }
                }

                if($restrictedProgram.Guid)
                {
                    if($installedProgram.Guid -eq $restrictedProgram.Guid)
                    {
                        return $false;
                    }
                }
            }
        }
    }

但是我如何通过遍历 restrictedProgram 项目的属性来做到这一点,而不是对其进行硬编码:

foreach($installedProgram in $installedPrograms)
    {
        foreach($restrictedProgram in $restrictedPrograms)
        {
            // Foreach property in $restrictedProgram, compare it with the corresponding property in $installedProgram ??
        }
    }

以下代码有帮助:

foreach($installedProgram in $installedPrograms)
    {
        foreach($restrictedProgram in $restrictedPrograms)
        {
            $count = 0
            foreach($key in $restrictedProgram.Keys)
            {
                if($installedProgram.$key -eq $restrictedProgram.$key)
                {
                    $count++
                }
            }

            if($count -eq $restrictedProgram.Keys.Count)
            {
                Write-Host "Found the restricted program " $restrictedProgram.Values " installed"
                return $false;
            }
        }
    }

不确定我是否完全清楚你在事后对结果做了什么,但从它的外观来看,你正在寻找 $installedPrograms 中的任何属性是否存在于相同的 [=26] =] 的值 $restrictedPrograms。我将 PowerShell 对象作为哈希表的对象,因为它开辟了许多途径。大多数情况下,我希望能够使用 Compare-Object,但由于我不确定您期望的结果,所以我跳过了它。

$installedPrograms = @(
        @{DisplayName = "SourceTree"; Guid = "B24E0C46-B627-4781-975E-620ED53CD981"};
        @{DisplayName = "Microsoft Help Viewer 2.0"; Guid = "FEB375AB-6EEC-3929-8FAF-188ED81DD8B5"}
) | ForEach-Object{New-Object PSObject -Property $_}

$restrictedPrograms = @(
    @{DisplayName = "Microsoft Visual Studio Test"};
    @{Guid = "102C29B2-4320-4774-8003-6912F0AC19"};
    @{DisplayName = "Microsoft Office 365 ProPlus - en-us"};
    @{Guid = "B24E0C46-B627-4781-975E-620ED53CD98"};
    @{DisplayName = "SourceTree"; Guid = "B24E0C46-B627-4781-975E-620ED53CD981"}
) | ForEach-Object{
    New-Object PSObject -Property @{
        DisplayName = $_.DisplayName
        Guid = $_.Guid
    }
}


$installedPrograms | Where-Object{$_.DisplayName -in $restrictedPrograms.DisplayName -or $_.Guid -in $restrictedPrograms.Guid}

最后一行很重要。从它的外观来看,您至少拥有 PowerShell 3.0,因此这应该适合您。对于每个 $installedPrograms,我们检查它是否具有匹配的显示名称或 guid。如果找到匹配项,它将通过管道传递。所以我在这里解释的最终结果是计算机上安装的受限程序列表。

DisplayName Guid                                
----------- ----                                
SourceTree  B24E0C46-B627-4781-975E-620ED53CD981

您曾提到过您希望它更具动态性。因此,考虑到这一点,我更改了逻辑以允许动态属性。我们在事先不知道属性是什么的情况下进行比较。为了简单起见,我不会以相同的方式重新制作 PowerShell 对象,因为我不确定您是否对这种方法感兴趣。

$matchedPrograms = @()
$props = ($installedPrograms | Select-Object -First 1).PSObject.Properties | Select-Object -ExpandProperty Name

ForEach($singleProgram in $installedPrograms){
    ForEach($singleProperty in $props){
        # Check to see $singleProperty of $singleProgam is in $restrictedPrograms
        If($singleProgram.$singleProperty -in $restrictedPrograms.$singleProperty){$matchedPrograms += $singleProgram}
    }
}

$matchedPrograms | Select-Object -Unique

由于我们正在单独寻找匹配项,因此可能会有双倍的程序,-Unique 会处理这个问题。