簡體   English   中英

PowerShell:如何將嵌套的 hash 表傳遞給接受 3 個參數的 function?

[英]PowerShell: How can I pass a nested hash table to my function that accepts 3 parameters?

我創建了這個 function 但我不知道如何讓它工作。 這是代碼:

function ProgramRegistry {
    param (
        
    [Parameter(Mandatory=$false)][HashTable]$HashTable,
    [Parameter(Mandatory=$false)][String]$AlertPath,
    [Parameter(Mandatory=$false)][String]$AlertName,
    [Parameter(Mandatory=$false)][String]$AlertValue
     )

    

     foreach ($AlertPath in $HashTable.Values){
        foreach($AlertName in $HashTable.Values){
            foreach($AlertValue in $HashTable.Values){
                          
  
    New-Item -Path $AlertPath -Force | Out-Null
    New-ItemProperty -Path $AlertPath -Name $AlertName -Value $AlertValue -PropertyType DWORD -Force
    }


                  
            }
        }
     }
 


$keys = [ordered]@{


    key1 = @{
        AlertPath = 'Path'
        AlertName = 'Name'
        AlertValue = 'Value'

    }

    key2 = @{

        AlertPath = 'Path'
        AlertName = 'Name'
        AlertValue = 'Value'

    }

    # and so on...

}

ModifyRegistry @keys

ModifyRegistry -AlertPath "path" -AlertName "name" -AlertValue "value"

我希望能夠以 2 種不同的方式調用 function(如腳本所示)

  1. 通過在一行中明確定義其 3 個參數。
  2. 或者通過傳遞由多個對象組成的嵌套 hash 表,每個對象都具有函數的 3 個參數。

我怎樣才能做到這一點?

我只想修改 function 而不是我調用它的方式。 我需要多次調用它,並希望盡可能少地調用它,就像這個ModifyRegistry @keys 如果 function 本身又復雜又長也沒關系,但我希望調用 function 只需要很少的代碼。 我可以重復調用 function 而不是嵌套的 hash 表,但它會重復太多代碼,這就是我想要避免的。

您可以修改您的 function 以接受哈希表的哈希表。 您只需要提供一些邏輯來檢查接收到的哈希表是否是包含具有您需要的值的其他哈希表的哈希表,或者它是否是包含您需要的值的單個哈希表。 還需要在不提供哈希表時仍然處理其他參數。 下面的示例顯示了我將如何在高級 function 中使用開始、處理和結束塊來執行此操作。 在開始塊中,我們只需要創建我們將用於篩選輸入的集合 object。 對使用管道時收到的每個輸入 object 重復處理塊。 如果直接將 arguments 提供給 function,則此過程塊將只運行一次。 我們將使用此流程塊來確定輸入對象並將其添加到我們創建的 $inputs arraylist 中。 在結束塊中,我們將對收集到的每個對象執行實際處理。

function ProgramRegistry {
    [cmdletbinding()]
    param (
        # ValueFromPipeline attribute will allow piping hashtables to the function
        [Parameter(Mandatory = $false, ValueFromPipeline)][HashTable]$HashTable,
        [Parameter(Mandatory = $false)][String]$AlertPath,
        [Parameter(Mandatory = $false)][String]$AlertName,
        [Parameter(Mandatory = $false)][String]$AlertValue
    )

    begin {
        # Create an arraylist to collect hashtables for later processing in end block
        $inputs = [System.Collections.ArrayList]::new()
    }

    process {
        if ($HashTable) {
            if ($HashTable.ContainsKey('AlertPath')) {
                # if single hashtable is received with 'AlertPath' key add to inputs for processing in end block
                $inputs.Add($HashTable) | Out-Null
            }
            else {
                foreach ($value in $HashTable.Values) {
                    # check if value of key is a hashtable
                    if ($value -is [hashtable]) {
                        # check if hashtable contains key "AlertPath" and if so add to $inputs for processing in end block
                        if ($value.ContainsKey('AlertPath')) {
                            $inputs.Add($value) | Out-Null
                        }
                        else {
                            Write-Warning "Invalid hashtable format - missing 'AlertPath' key"
                        }
                    } else {
                        Write-Warning "Object is not a hashtable"
                    }
                }
            }
        }
        else {
            # process when not a hashtable by creating a hashtable and adding to $inputs
            $inputs.Add(@{
                    AlertPath  = $AlertPath
                    AlertName  = $AlertName
                    AlertValue = $AlertValue
                }) | Out-Null
        }
    }

    end {
        # Process hashtables collected in $inputs 
        foreach ($hash in $inputs) {
            # your code here
            [pscustomobject]@{
                Path  = $hash.AlertPath
                Name  = $hash.AlertName
                Value = $hash.AlertValue 
            }
        }
    }
}



$keys = [ordered]@{
    key1 = @{
        AlertPath  = 'Path1'
        AlertName  = 'Name1'
        AlertValue = 'Value1'
    }
    key2 = @{
        AlertPath  = 'Path2'
        AlertName  = 'Name2'
        AlertValue = 'Value2'
    }
    # and so on...
}


ProgramRegistry -HashTable $keys
# or 
$keys | ProgramRegistry
# or even
ProgramRegistry -HashTable $keys.key1 #or $keys.key1 | ProgramRegistry

如果不需要流水線和高級 function,您仍然可以在沒有開始、過程和結束塊的情況下執行類似的操作。 我使用嵌套的 function 'processit' 這樣我就不必多次重復處理邏輯

function ProgramRegistry {

    param (
        [Parameter(Mandatory = $false)][HashTable]$HashTable,
        [Parameter(Mandatory = $false)][String]$AlertPath,
        [Parameter(Mandatory = $false)][String]$AlertName,
        [Parameter(Mandatory = $false)][String]$AlertValue
    )
    

    # create nested function to process each hash table.  
    function processit {
        param([hashtable]$hash)

        # add processing logic here
        [pscustomobject]@{
            Path  = $hash.AlertPath
            Name  = $hash.AlertName
            Value = $hash.AlertValue
        }
    }

    if ($HashTable) {
        if ($HashTable.ContainsKey('AlertPath')) {
            # if single hashtable is received with 'AlertPath' key process it
            processit -hash $HashTable
        }
        else {
            foreach ($value in $HashTable.Values) {
                # check if value of key is a hashtable
                if ($value -is [hashtable]) {
                    # check if hashtable contains key "AlertPath" and if so process it
                    if ($value.ContainsKey('AlertPath')) {
                        processit -hash $value
                    }
                    else {
                        Write-Warning "Invalid hashtable format - missing 'AlertPath' key"
                    }
                }
                else {
                    Write-Warning 'Object is not a hashtable'
                }
            }
        }
    }
    else {
        processit @{AlertPath = $AlertPath; AlertName = $AlertName; AlertValue = $AlertValue }
    }
}
    

更新以回應您關於使用密鑰名稱作為 AlertName 的問題

function ProgramRegistry {
    param (
        [Parameter(Mandatory = $false)][HashTable]$HashTable,
        [Parameter(Mandatory = $false)][String]$AlertPath,
        [Parameter(Mandatory = $false)][String]$AlertName,
        [Parameter(Mandatory = $false)][String]$AlertValue
    )
    # create nested function to process each hash table.  
    function processit {
        param([hashtable]$hash)
        # add processing logic here
        [pscustomobject]@{
            Path  = $hash.AlertPath
            Name  = $hash.AlertName
            Value = $hash.AlertValue
        }
    }
    if ($HashTable) {
        if ($HashTable.ContainsKey('AlertPath')) {
            # if single hashtable is received with 'AlertPath' key process it
            processit -hash $HashTable
        }
        else {
            foreach ($item in $HashTable.GetEnumerator()) {
                if ($item.Value -is [hashtable]) {
                    # check if the hashtable has AlertPath and AlertValue keys
                    if ($item.Value.ContainsKey('AlertPath') -and $item.Value.ContainsKey('AlertValue')) {
                        $hash = $item.Value
                        # check if hashtable contains an AlertName key.  
                        if (-not $hash.ContainsKey('AlertName')){
                            # If not use parent key name
                            $hash.AlertName = $item.Key
                        }
                        processit -hash $hash
                    }
                    else {
                        Write-Warning "Invalid hashtable format - missing AlertPath and/or AlertValue key"
                    }
                }
                else {
                    Write-Warning "Item does not contain a hashtable"
                }
            }
        }
    }
    else {
        processit @{AlertPath = $AlertPath; AlertName = $AlertName; AlertValue = $AlertValue }
    }
}

撥打電話 function

$items = @{
    Alert1 = @{
        AlertPath  = 'Path1'
        AlertValue = 'Value1'
    }
    Alert2 = @{
        AlertPath  = 'Path2'
        AlertValue = 'Value2'
    }
    Alert3 = @{
        AlertName = 'Overridden AlertName'
        AlertPath  = 'Path3'
        AlertValue = 'Value3'
    }
    Alert4 = @{
        AlertValue = 'Value2'
    }
    Alert5 = "just a string"
}

ProgramRegistry -HashTable $items

Output

WARNING: Item does not contain a hashtable

WARNING: Invalid hashtable format - missing AlertPath and/or AlertValue key
Path  Name                 Value
----  ----                 -----
Path3 Overridden AlertName Value3
Path2 Alert2               Value2
Path1 Alert1               Value1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM