![](/img/trans.png)
[英]How to dynamically add new properties to custom object in PowerShell
[英]PowerShell - How to add the properties of two custom objects together to create a single merged custom object using
我正在使用一些 PowerShell 函數從一些 REST API 端點獲取數據。 遍歷第一個查詢的結果允許我使用id
字段來檢索第二個查詢中的匹配結果,但是,第二個查詢的返回結果沒有任何與原始結果集匹配的屬性,所以我不'認為我不能執行 JOIN 或類似的操作。
例如,假設查詢第一個 REST 端點的結果存儲在$a
中。
$a =
ID Title Location Internal IP Address
-- ----- -------- -------------------
1 Endpoint 1 UK 10.0.0.1
2 Endpoint 2 US 10.1.0.1
3 Endpoint 3 AUS 10.2.0.1
並使用ID = 1
查詢第二個 REST 端點,我們將以下內容存儲在$b
中:
$b =
NATed IP Address Last Provisioned Time
---------------- ---------------------
1.2.3.4 2022-02-10T04:09:31.988909+01:00
我想做的是結合兩者的屬性,一次一條記錄,所以在我檢索$b
之后,我會創建$c
,它看起來像這樣:
$c =
ID Title Location Internal IP Address NATed IP Address Last Provisioned Time
-- ----- -------- ------------------- ---------------- ---------------------
1 Endpoint 1 UK 10.0.0.1 1.2.3.4 2022-02-10T04:09:31.988909+01:00
由於代碼然后遍歷$a
的結果,所以我應該建立一個完整的合並對象,並且在$a
三個迭代之后,我們應該最終得到類似的結果:
$d =
ID Title Location Internal IP Address NATed IP Address Last Provisioned Time
-- ----- -------- ------------------- ---------------- ---------------------
1 Endpoint 1 UK 10.0.0.1 1.2.3.4 2022-02-10T04:09:31.988909+01:00
2 Endpoint 2 US 10.1.0.1 1.2.3.5 2022-02-10T04:09:31.988909+01:00
3 Endpoint 3 AUS 10.2.0.1 1.2.3.6 2022-02-10T04:09:31.988909+01:00
在我看來,這將相當簡單,但是,我查看了許多不同的帖子和網站,但似乎沒有一個可以幫助我實現我想要的,或者更可能我只是誤解了諸如Add-Member
之類的方法可能會起作用在多個管道循環中,或錯過盲目明顯的內容。
我最接近的是下面的代碼,它實際上產生了一個數組或哈希表(取決於我如何初始化$collection
變量),但結果是相似的:
$collection = @{}
foreach ($item in $a) {
$collection += @{
"Title" = $item.Title
"Location" = $item.Location
"Internal IP Address" = $item."Internal IP Address"
}
}
foreach ($item in $b) {
$collection += @{
"NATed IP Address" = $item."NATed IP Address"
"Last Provisioned Time" = $item."Last Provisioned Time"
}
}
這會產生一個鍵/值表,例如:
Name Value
---- -----
ID 1
Title Endpoint 1
Internal IP Address 10.0.0.1
Location UK
NATed IP Address 1.2.3.4
Last Provisioned Time 2022-02-10T03:21:29.265257+01:00
這意味着我最終會得到一個數組數組(或哈希表的哈希表)。 雖然我認為我仍然可以使用這種類型的數據格式,但我很想了解我需要做什么來實現我的初始目標。
更新
獲取$a
和$b
的代碼如下。 有一些封裝 API 調用的函數:
$a = Get-Endpoints -Creds $Credentials -URI $FQDN
$a| ForEach-Object {
$b = Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -id $_.id |
Select-Object -Property @{Name="NATed IP Address";Expression={$_.ip}}, @{Name="Last Provisioned Time";Expression={$_.ts_created}}
}
更新 2
這是完整的代碼,它可以工作,但有點啰嗦,可能真的效率低下,並產生一個哈希表的哈希表:
$a = Get-Endpoints -Creds $Credentials -URI $FQDN
$a| ForEach-Object {
$b = Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -id $_.id |
Select-Object -Property @{Name="NATed IP Address";Expression={$_.ip}}, @{Name="Last Provisioned Time";Expression={$_.ts_created}}
$EndpointSelectedData = $_ | Select-Object -Property ID, @{Name="Title";Expression={$_.title}}, @{Name="Location";Expression={$_.location}}, @{Name="Internal IP Address";Expression={$_.ip}}
$c = @{}
foreach ($EndpointData in $EndpointSelectedData) {
$c += @{
"ID" = $EndpointData.id
"Title" = $EndpointData.Title
"Location" = $EndpointData.Location
"Internal IP Address" = $EndpointData."Internal IP Address"
}
}
foreach ($ProvisionedD in $ProvisionedData) {
$collection += @{
"NATed IP Address" = $ProvisionedD."NATed IP Address"
"Last Provisioned Time" = $ProvisionedD."Last Provisioned Time"
}
}
$d = $d + @{"Node_$i" = $c}
$i = $i + 1
}
更新 3
在@Santiago 提出建議的答案和@iRon 的指針后,我現在有以下代碼:
$Endpoints = Get-Endpoints -Creds $Credentials -URI $FQDN
foreach($i in $Endpoints) {
foreach($z in Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -Id $i.id) {
[pscustomobject]@{
'ID' = $i.Id
'Title' = $i.Title
'Location' = $i.Location
'Internal IP Address' = $i.Ip
'NATed IP Address' = $z.Ip
'Last Provisioned Time' = $z.Ts_Created
}
}
}
這會導致屏幕轉儲(我猜是管道清理):
ID : 1
Title : Endpoint 1
Location : UK
Internal IP Address : 10.0.0.1
NATed IP Address : 1.2.3.4
Last Provisioned Time : 2022-02-10T04:09:32.126357+01:00
ID : 2
Title : Endpoint 2
Location : US
Internal IP Address : 10.1.0.1
NATed IP Address : 1.2.3.5
Last Provisioned Time : 2022-02-10T04:21:32.657364+01:00
ID : 3
Title : Endpoint 3
Location : Aus
Internal IP Address : 10.2.0.1
NATed IP Address : 1.2.3.6
Last Provisioned Time : 2022-02-10T04:09:31.990202+01:00
...
所以,我想這已經接近我想要的了,但還沒有真正實現。 我現在需要弄清楚如何處理管道輸出......這與思維方式的改變有很大關系,所以可能需要一些頭緒。
更新 4 - 可能的解決方案
好的,因此擴展了上面的代碼塊,我創建了一些額外的邏輯來將pscustomobject
的輸出通過管道傳輸到 CSV 文件。 最終目的是根據前一天的配置檢查各個端點的狀態,看看是否有任何變化(因為它確實發生了變化,而且通常在管理員不知情的情況下!)。
分配一個變量來存儲嵌套foreach
循環的結果。 然后將其用於導出到 CSV。 我在腳本的開頭添加了一些進一步的邏輯來檢查文件是否存在,如果存在則刪除今天的配置文件,這樣腳本會在每天意外運行多次時創建一個新的配置文件.
一旦主循環完成,今天和昨天的文件將被重新導入,並使用Compare-Object
CmdLet 查看是否有任何更改。 如果兩個文件之間存在差異,我可能會添加一些發送電子郵件代碼。
$DateStamp = get-date -Format FileDate
if (Test-Path -Path ".\endpoint-$($DateStamp).csv" -PathType Leaf) {
Remove-Item -Path ".\endpoint-$($DateStamp).csv"
}
$Endpoints = Get-Endpoints -Creds $Credentials -ERMMgr $MgrFQDN
$result = foreach($i in $Endpoints) {
foreach($z in Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -Id $i.id) {
[pscustomobject]@{
'ID' = $i.Id
'Title' = $i.Title
'Location' = $i.Location
'Internal IP Address' = $i.Ip
'NATed IP Address' = $z.Ip
'Last Provisioned Time' = $z.Ts_Created
}
}
}
$result | Export-Csv ".\endpoint-$DateStamp.csv"
if (Test-Path -Path ".\endpoint-$($DateStamp-1).csv" -PathType Leaf) {
$InFile2 = Import-CSV -Path ".\endpoint-$($DateStamp-1).csv"
Compare-Object -ReferenceObject $result -DifferenceObject $InFile2 -Property Title, "NATed IP Address" | Export-Csv ".\endpoint_diff-$DateStamp.csv"
}
從外觀上看,這可能會為您提供所需的內容:
$result = foreach($i in Get-Endpoints -Creds $Credentials -URI $FQDN) {
foreach($z in Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -Id $id.id) {
[pscustomobject]@{
'ID' = $i.Id
'Title' = $i.Title
'Location' = $i.Location
'Internal IP Address' = $i.Ip
'NATed IP Address' = $z.Ip
'Last Provisioned Time' = $z.Ts_Created
}
}
}
基本上可以在運行時創建對象,而不是收集結果$a
和$b
然后加入/合並它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.