I have a Powershell-script which includes a lot of PsCustomObjects like this (names do not have a specific pattern):
$myObject1 = [PSCustomObject]#{
Name = 'Kevin'
State = 'Texas'
}
$myObject2 = [PSCustomObject]#{
Name = 'Peter'
Lastname = 'Fonda'
State = 'Florida'
}
Now I need to convert this programmatically into the following object-format to have a global hashtable:
$result = #{
'myObject1.Name' = 'Kevin'
'myObject1.State' = 'Texas'
'myObject2.Name' = 'Peter'
'myObject2.Lastname' = 'Fonda'
'myObject2.Sate' = 'Florida'
}
For this task I need a loop in which I can either read the name of each PsCustomOject or I need to specify the names of all object as a string-array and lookup the object-properties with the matching name.
The loop-constructor could look something like this:
$result = #{}
foreach($name in #('myObject1','myObject2')) {
$obj = myMissingFunction1 $name
foreach($p in $obj.PsObject.Properties) {
$result["$name.$($p.Name)"] = $p.Value
}
}
or this
$result = #{}
foreach($obj in #($myObject1, $myObject2)) {
$name = myMissingFunction2 $obj
foreach($p in $obj.PsObject.Properties) {
$result["$name.$($p.Name)"] = $p.Value
}
}
Unfortunately I cannot bring any of the two approaches to life. Can someone please help?
Here is how you could do it .
$Result = [Ordered]#{}
$index = 0
Foreach ($obj in $ArrayOfObject) {
foreach ($prop in ($obj | Get-Member -MemberType NoteProperty).Name) {
$Result."SomeObject$Index.$Prop" = $obj.$prop
}
$index += 1
}
Result
Name Value
---- -----
SomeObject0.Name Kevin
SomeObject0.State Texas
SomeObject1.Lastname Fonda
SomeObject1.Name Peter
SomeObject1.State Florida
Dataset used for this example
$ArrayOfObject = #(
[PSCustomObject]#{
Name = 'Kevin'
State = 'Texas'
}
[PSCustomObject]#{
Name = 'Peter'
Lastname = 'Fonda'
State = 'Florida'
}
)
Solved it finally. I completely forgot the "Get-Variable" function:
$result = #{}
foreach($name in #('myObject1','myObject2')) {
$obj = (Get-Variable $name).Value
foreach($p in $obj.PsObject.Properties) {
$result["$name.$($p.Name)"] = $p.Value
}
}
I want to extract columns by header name from multiple CSVs into one 'master file'. I have tried multiple things but each time there is something else that occurs.
I have this code which is working now, but extremely tedious typing out which header name I need for every column, as there will be upwards of 20 of columns I need from each CSV.
Anyone have any suggestions? I'm currently using PS, but am open to other methods.
Import-Csv -Path $inputFilePath1 | ForEach-Object {
$File1Values.Add($_.HBA_ID, $_)
}
Import-Csv -Path $inputFilePath2 | Select-Object *,
| Export-Csv -Path $outputFilePath -NoTypeInformation
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TMT_A_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } } |
Export-Csv -Path $outputFilePath -NoTypeInformation
Thanks in advance!
I don't understand why my $ReturnedAnyTypeMembers array doesn't wipe every time the function recurses. I don't want it to wipe. Its actually doing what I want it to do right now, which is keep an accurate growing list. I just don't understand why the contents of the array don't wipe every time the function is called. Any help understanding?
function Get-GroupMembers {
Param($Group)
[System.Collections.ArrayList] $ReturnedAnyTypeMembers = #()
$GroupMembersArray = gam print group-members group $Group | ConvertFrom-Csv
foreach ($GroupMember in $GroupMembersArray) {
$GroupMemberType = ($GroupMember.type)
$GroupMemberEmail = ($GroupMember.email)
$GroupMemberIsAGroup = ($GroupMemberType -eq "GROUP")
$ReturnedAnyTypeMembers.Add($GroupMember) | Out-Null
if($GroupMemberIsAGroup) {
Get-GroupMembers $GroupMemberEmail
}
}
$ReturnedGroupMembers = #{
"all" = $ReturnedAnyTypeMembers
}
Return $ReturnedGroupMembers
}
Is this the result you are after...
function Get-GroupMembers
{
Param($Group)
[System.Collections.ArrayList] $ReturnedAnyTypeMembers = #()
$GroupMembersArray = Get-LocalGroupMember -Group $Group
foreach ($GroupMember in $GroupMembersArray) {
$GroupMemberType = ($GroupMember.type)
$GroupMemberEmail = ($GroupMember.email)
$GroupMemberIsAGroup = ($GroupMemberType -eq "GROUP")
$ReturnedAnyTypeMembers.Add($GroupMember) | Out-Null
if($GroupMemberIsAGroup) {
Get-GroupMembers $GroupMemberEmail
}
}
$ReturnedGroupMembers = #{
"all" = $ReturnedAnyTypeMembers
}
Return $ReturnedGroupMembers
}
'Administrators','Users' |
ForEach-Object {Get-GroupMembers -Group $PSItem} |
Format-Table -AutoSize
# Results
<#
Name Value
---- -----
all {104DB2FE-76B8-4\Administrator, 104DB2FE-76B8-4\WDAGUtilityAccount}
all {NT AUTHORITY\Authenticated Users, NT AUTHORITY\INTERACTIVE}
#>
... or something else?
I'm trying to migrate from a 6.0 vCenter to a 6.5 vCenter, and want to migrate all templates. How can I select all clusters at once to retrieve the full template list?
I have a lot of templates in my 6.0 vCenter and need to export a list to migrate them all at once in my new 6.5 vCenter, using Powercli. The only way I found is by using a foreach loop, in which I must provide a cluster name.
I tried using "get-datacenter" instead of "get-cluster" but the result is even worse.
$toto = foreach ($vmhost in Get-Cluster 'my_cluster'|Get-VMHost) {
Get-Template -Location $vmhost |
select name, #{n='VMHOST';e={$vmhost.name}},
#{n='VMTX';e={$_.extensiondata.config.files.VmPathName}}
}
$toto | Export-Csv C:\scripts\Templates.csv
The code works but doesn't show me all templates in the vCenter.
How can I make it work so that I can have all templates in all clusters at once, without using a loop for each?
The function extracts all templates from a single datacenter target by scanning all available clusters and hosts within; dumping the complete result into an $array_list variable.
Function Render_Template_List {
Clear-Host
$array_list = [System.Collections.ArrayList]#()
if (!($global:templates_bool)) {
$host.ui.RawUI.WindowTitle = "Retrieving available templates for use with '$global:datacenter' datacenter...Please Wait!"
if ($global:datacenter -eq 'none'){
$ESX = get-datacenter | get-VMhost | %{$_.Extensiondata.MoRef}
} else {
$ESX = get-datacenter -name "$global:datacenter" | get-VMhost | %{$_.Extensiondata.MoRef}
}
If ($global:Template -eq 'none') {
$Query = Get-Template | where {$ESX -contains $_.Extensiondata.Runtime.Host} | Sort-Object
} else {
$Query = Get-Template -name "$global:Template" | where {$ESX -contains $_.Extensiondata.Runtime.Host} | Sort-Object
}
$global:templates_bool = $true
$global:templates_query = $query
}
$seperator = "{,}"
$query = 0
$arr = 1
foreach ($template in $global:templates_query ) {
if ($arr -eq 1) {
foreach ($array in $global:templates_array) {
If (!($array -like "*#*")) {
$query = $query + 1
$val_template = $array.split($seperator)[2]
$val_template = $val_template.replace("`"","")
if ("$val_template" -eq "$template") {
$val_datacenter = $array.split($seperator)[1]
$val_datacenter = $val_datacenter.replace("`"","")
if ("$val_datacenter" -eq "$global:datacenter") {
$array_list.Add("$val_template") | Out-Null
}
}
}
}
}
if ($query -eq 0) {
$array_list.Add("$template") | Out-Null
$arr = 0
}
}
return $array_list
}
Say I have a CSV file that looks like:
arch,osversion,kb
32,6.1,KB1,http://kb1
32,6.2,KB2,http://kb2
64,6.1,KB3,http://kb3
64,6.2,KB4,http://kb4
How would this CSV get imported into structured hash table that looks like this?
32 -> 6.1 -> KB1 -> http://kb1
-> 6.2 -> KB2 -> http://kb2
64 -> 6.1 -> KB3 -> http://kb3
-> 6.2 -> KB4 -> http://kb4
The command below yields http://kb1:
$data['32'].'6.1'.'KB1'
Probably Group-Object is what you want.
$csv = #'
arch,osversion,kb,link
32,6.1,KB1,http://kb1
32,6.2,KB2,http://kb2
64,6.1,KB3,http://kb3
64,6.2,KB4,http://kb4
'#
$data = ConvertFrom-Csv $csv
$data | Group-Object -Property arch
Or maybe closer to what you want to query:
$groups = $data | Group-Object -Property arch, osversion, kb
($groups | ? Name -eq '32, 6.1, KB1').Group.link
You could even use variables...
$a = '32'
$o = '6.1'
$k = 'KB1'
($groups | ? Name -eq "$a, $o, $k").Group.link
From this, you can determine if such a pattern works for you.
Interesting task. The following code snippet could help (solves arch duplicates):
Remove-Variable data*, aux* -ErrorAction SilentlyContinue ### clear for debugging purposes
$datacsv = #'
arch,osversion,kb,link
32,6.1,KB1,http://kb1
32,6.2,KB2,http://kb2
64,6.1,KB3,http://kb3
64,6.2,KB4,http://kb4
'#
$datac = ConvertFrom-Csv $datacsv
$datag = #{}
$datac | ForEach-Object {
$auxLeaf = #{ $_.kb = $_.link }
$auxParent = #{ $_.osversion = $auxLeaf }
if ( $datag.ContainsKey( $_.arch) ) {
$auxParent += $datag[ $_.arch]
}
$datag.Set_Item( $_.arch, $auxParent )
}
Then, $datag['32']['6.1']['KB1'] returns desired value http://kb1
Another interesting problem: solve osversion duplicates in a particular arch:
Remove-Variable data*, aux* -ErrorAction SilentlyContinue ### clear for debugging purposes
$datacsv = #'
arch,osversion,kb,link
32,6.1,KB1,http://kb1
32,6.1,KB5,http://kb5
32,6.1,KB7,http://kb7
32,6.2,KB2,http://kb2
64,6.1,KB3,http://kb3
64,6.2,KB4,http://kb4
'#
$datac = ConvertFrom-Csv $datacsv
$datag = #{}
$datac | ForEach-Object {
$auxLeaf = #{ $_.kb = $_.link }
$auxParent = #{ $_.osversion = $auxLeaf }
if ( $datag.ContainsKey( $_.arch) ) {
if ( $datag[$_.arch].ContainsKey($_.osversion) ) {
$auxLeaf += $datag[$_.arch][$_.osversion]
$auxParent = #{ $_.osversion = $auxLeaf }
} else {
$auxParent += $datag[ $_.arch]
}
}
$datag.Set_Item( $_.arch, $auxParent )
}
The latter code snippet is roughly equivalent to
$datag =
#{
'32' = #{ '6.1' = #{ 'KB1'='http://kb1';
'KB5'='http://kb5';
'KB7'='http://kb7' };
'6.2' = #{ 'KB2'='http://kb2' }
};
'64' = #{ '6.1' = #{ 'KB3'='http://kb3' };
'6.2' = #{ 'KB4'='http://kb4' }
}
}