Powershell: Combining Arrays - powershell

Using PowerShell I need to combine two arrays $IP_Diff and $Line_Diff:
$IP_Diff = "10.1.101.17"
$Line_IP = (#{N="Initialize"}).N | Select #{N = "Problem_IP";E={$IP_Diff -join ";"}}
$ServerName = "ExServer-01"
$Exist = "False"
$Line_Diff = (#{N="Initialize"}).N | Select #{N = $ServerName;E={$Exist -join ";"}}
I need the Combined Array to be:
Problem_IP ExServer-01
---------- -------------
10.1.101.17 False

It looks like you're trying to construct a [pscustomobject] instance as follows:
$IP_Diff = "10.1.101.17"
$ServerName = "ExServer-01"
$Exist = "False"
[pscustomobject] #{
Problem_IP = $IP_Diff
$ServerName = $exist
}
The above produces the display output shown in your question.

Related

Format-Table not taking effect (Exchange - powershell)

first of all sorry if my english is not the best. but ill try to explain my issue with as much detail as i can
Im having an issue where i cant get Format-Table to effect the output i give it.
below is the part im having issues with atm.
cls
$TotalSize = $($mailboxes. #{name = ”TotalItemSize (GB)”; expression = { [math]::Round((($_.TotalItemSize.Value.ToString()).Split(“(“)[1].Split(” “)[0].Replace(“,”, ””) / 1GB), 2) } });
$UserN = $($mailboxes.DisplayName)
$itemCount = $($mailboxes.ItemCount)
$LastLogonTime = $($mailboxes.ItemCount)
$allMailboxinfo = #(
#lager dataen som skal inn i et objekt
#{Username= $UserN; ItemCount = $itemCount; LastLogonTime = $($mailboxes.ItemCount); Size = $TotalSize}) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }
$Table = $allMailboxinfo | Format-Table | Out-String
$Table
the output of this gives me what almost looks like json syntax below each title of the table.
Username LastLogonTime ItemCount Size
-------- ------------- --------- ----
{username1, username2,username3,userna...} {$null, $null, $null, $null...} {$null, $null, $null, $null...} {$null, $null, $null, $null...}
running the commands by themselves seem to work tho. like $mailboxes.DisplayName gives the exact data i want for displayname. even in table-format.
the reason im making the table this way instead of just using select-object, is because im going to merge a few tables later. using the logic from the script below.
cls
$someData = #(
#{Name = "Bill"; email = "email#domain.com"; phone = "12345678"; id = "043546" }) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }
$moreData = #(
#{Name = "Bill"; company = "company 04"}) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }
$Merge = #(
#plots the data into a new table
#{Name = $($someData.Name); e_mail = $($someData.email); phone = $($someData.phone); id = $($someData.id); merged = $($moreData.company) }) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }
#formatting table
$Table = $Merge | Format-Table | Out-String
#print table
$Table
if you are wondering what im doing with this.
My goal, all in all. is a table with using the info from Exchange;
DisplayName, TotalItemSize(GB), ItemCount, LastLogonTime, E-mail adress, archive + Maxquoata, Quoata for mailbox.
You're creating a single object where each property holds an array of property values from the original array of mailbox objects.
Instead, create 1 new object per mailbox:
# construct output objects with Select-Object
$allMailBoxInfo = $mailboxes |Select #{Name='Username';Expression='DisplayName'},ItemCount,#{Name='LastLogonTime';Expression='ItemCount'},#{Name='Size';Expression={[math]::Round((($_.TotalItemSize.Value.ToString()).Split("(")[1].Split(" ")[0].Replace(",", "") / 1GB), 2) }}
# format table
$Table = $allMailBoxInfo | Format-Table | Out-String
# print table
$Table

Format-Table out of Two Lists?

I've had this idea about getting the output from 2 separate functions, that return a PSCustomObject as a list, and formatting them into one table. My problem is simple... I don't know how to do it. lol
With the various of combinations that I tried, here's whats given me some promising results:
$Var1 = [PSCustomObject]#{
UserName = $env:USERNAME
Stuff1 = 'stuff1'
} | Format-List | Out-String -Stream
$Var2 = [PSCustomObject]#{
ComputerName = $env:COMPUTERNAME
Stuff2 = 'stuff2'
} | Format-List | Out-String -Stream
[PSCustomObject]#{
TableOne = $Var1.Trim().Foreach({$_})
TableTwo = $Var2.Trim()
} | Format-Table -AutoSize
The output:
TableOne TableTwo
-------- --------
{, , UserName : Abraham, Stuff1 : stuff1...} {, , ComputerName : DESKTOP-OEREJ77, Stuff2 : stuff2...}
I say promising in the respect that it shows the actual content of $var1 and 2, whereas my other attempts didn't. I also left the .foreach() operator there to show one of the many many different tricks I tried to get this working. For a quick second I thought the Out-String cmdlet would've done the trick for me, but was unsuccessful.
Has anyone ever done something similar to this?
EDIT:
Nevermind, I figured it out.
Used a for loop to iterate through each line assigning it the the PSCustomObject one at a time. Also used the .Where() operator to remove white spaces, and compared the two arrays to find the largest number to use it as the count.
$Var1 = $([PSCustomObject]#{
UserName = $env:USERNAME
Stuff1 = 'stuff1'
} | Format-List | Out-String -Stream).Where{$_ -ne ''}
$Var2 = $([PSCustomObject]#{
ComputerName = $env:COMPUTERNAME
Stuff2 = 'stuff2'
ExtraStuff = 'More'
} | Format-List | Out-String -Stream).Where{$_ -ne ''}
$Count = ($Var1.Count, $Var2.Count | Measure-Object -Maximum).Maximum
$(for($i=0;$i -lt $Count; $i++) {
[PSCustomObject]#{
TableOne = $Var1[$i]
TableTwo = $Var2[$i]
}
}) | Format-Table -AutoSize
Output:
TableOne TableTwo
-------- --------
UserName : Abraham ComputerName : DESKTOP-OEREJ77
Stuff1 : stuff1 Stuff2 : stuff2
ExtraStuff : More
It's an interesting way to format two collections with corresponding elements.
To indeed support two collections with multiple elements, a few tweaks to your approach are required:
# First collection, containing 2 sample objects.
$coll1 =
[PSCustomObject] #{
UserName = $env:USERNAME
Stuff1 = 'stuff1'
},
[PSCustomObject] #{
UserName = $env:USERNAME + '_2'
Stuff1 = 'stuff2'
}
# Second collection; ditto.
$coll2 =
[PSCustomObject] #{
ComputerName = $env:COMPUTERNAME
Stuff2 = 'stuff2'
ExtraStuff = 'More'
},
[PSCustomObject]#{
ComputerName = $env:COMPUTERNAME + '_2'
Stuff2 = 'stuff2_2'
ExtraStuff = 'More_2'
}
# Stream the two collections in tandem, and output a Format-List
# representation of each object in a pair side by side.
& {
foreach ($i in 0..([Math]::Max($coll1.Count, $coll2.Count) - 1)) {
[PSCustomObject] #{
TableOne = ($coll1[$i] | Format-List | Out-String).Trim() + "`n"
TableTwo = ($coll2[$i] | Format-List | Out-String).Trim() + "`n"
}
}
} | Format-Table -AutoSize -Wrap
The above ensures that multiple objects are properly placed next to each other, and yields something like the following:
TableOne TableTwo
-------- --------
UserName : jdoe ComputerName : WS1
Stuff1 : stuff1 Stuff2 : stuff2
ExtraStuff : More
UserName : jdoe_2 ComputerName : WS1_2
Stuff1 : stuff2 Stuff2 : stuff2_2
ExtraStuff : More_2

Optimize for each variable powershell script

$allResources = #()
$subscriptions=Get-AzSubscription
ForEach ($vsub in $subscriptions){
Select-AzSubscription $vsub.SubscriptionID
Write-Host
Write-Host "Working on "$vsub
Write-Host
$allResources += $allResources |Select-Object $vsub.SubscriptionID,$vsub.Name
$result=#()
$webapps = Get-AzWebApp
foreach($webapp in $webapps){
$Tier = (Get-AzResource -ResourceId $webapp.ServerFarmId).Sku.Tier
$SKU = (Get-AzAppServicePlan -ResourceGroupName $webapp.ResourceGroup).Sku.Size
$AppServiceName = (Get-AzAppServicePlan -ResourceGroupName $webapp.ResourceGroup).Name
$obj = [PSCustomObject]#{
TenantId = $vsub.TenantId
SubscriptionName = $vsub.Name
WebappName = $webapp.Name
ResourceGroup = $webapp.ResourceGroup
Hostname = $WebApp.DefaultHostName
PricingTier = $Tier
SKU = ($SKU -join ',')
AppServiceName = ($AppServiceName -join ',')
#State = $webapp.State
#Location = $webapp.Location
#AppType = $webapp.Kind
}
$result += $obj
$result | Export-Csv -Path "E:\webapps_filter.csv" -Append -NoTypeInformation
$input = 'E:\webapps_filter.csv'
$inputCsv = Import-Csv $input | Sort-Object * -Unique
$inputCsv | Export-Csv "E:\webapps.csv" -NoTypeInformation}}
Right now I am using the above script to fetch all the required data of web apps from all the subscriptions. Currently, the script is taking time to execute, I need to optimize it and also the script gives a duplicate output so in last have added the filter to sort out it by unique entry.
It seems you are adding stuff to an array variable $allResources you don't use, so get rid of that.
Instead of the costly (time/memory) $result += $obj, better let PowerShell collect the objects using $result = foreach(..)
You are appending a temporary file inside the foreach loop on each iteration, then import this file and filter it on all properties to become unique.
again, inside the loop you are exporting this uniqified data to a CSV file on every iteration
You are calling upon cmdlet Get-AzAppServicePlan twice to get different properties. Use it only once would save time
as aside, you should not use a self-defined variable called $input as this is an Automatic variable
Try:
$subscriptions = Get-AzSubscription
$result = foreach ($vsub in $subscriptions){
Select-AzSubscription $vsub.SubscriptionID
Write-Host
Write-Host "Working on $($vsub.Name)"
Write-Host
foreach($webapp in (Get-AzWebApp)){
$Tier = (Get-AzResource -ResourceId $webapp.ServerFarmId).Sku.Tier
$Plan = Get-AzAppServicePlan -ResourceGroupName $webapp.ResourceGroup
# output the object so it gets collected in $result
[PSCustomObject]#{
TenantId = $vsub.TenantId
SubscriptionName = $vsub.Name
SubscriptionID = $vsub.SubscriptionID
WebappName = $webapp.Name
ResourceGroup = $webapp.ResourceGroup
Hostname = $webapp.DefaultHostName
PricingTier = $Tier
SKU = #($Plan.Sku.Size) -join ','
AppServiceName = #($Plan.Name) -join ','
#State = $webapp.State
#Location = $webapp.Location
#AppType = $webapp.Kind
}
}
}
# sort unique and export the file
$result | Sort-Object * -Unique | Export-Csv -Path "E:\webapps.csv" -NoTypeInformation

Add values to PS object from other PS command

I created the following object:
$PSOhash = #{
ConnectedNode = $ConnectedNode
ConnectedNodeDeviceNumber = $ConnectedNodeDeviceNumber
Serialnumber = $Serialnumber
ProductId = $ProductId
}
$ClusterNodeSSDs = New-Object PSObject -Property $PSOhash
and want to add values from the following command into it:
$SSDModel = "xyz123"
$ClusterNode = "Node1"
gwmi -Namespace root\wmi ClusPortDeviceInformation| select ConnectedNode,ConnectedNodeDeviceNumber, Serialnumber, ProductId | sort ConnectedNodeDeviceNumber | where {($_.ConnectedNode -eq $ClusterNode) -and ($_.ProductId -match "$SSDModel")}
which returns the proper informations, but need them as properties in the object for further processing.
If you want to add a set of property-value pairs to an already existing PSObject ($MyObject in this example) that currently does not have those properties, you can use the Add-Member command for this:
$PSOhash = #{
ConnectedNode = $ConnectedNode
ConnectedNodeDeviceNumber = $ConnectedNodeDeviceNumber
Serialnumber = $Serialnumber
ProductId = $ProductId
}
$MyObject = $MyObject | Add-Member -NotePropertyMembers $PSOHash
Explanation:
The -NotePropertyMembers parameter allows you do add a hash table of property-value pairs to a custom object.
Optionally, you can use a combination of Add-Member's -NotePropertyValue and -NotePropertyName to add properties one at a time.
If you want to update one object's property values with property values (same property names) from another object, you can just use direct assignment and the member access operator (.).
$SSDModel = "xyz123"
$ClusterNode = "Node1"
$WmiObjects = Get-WmiObject -Namespace root\wmi ClusPortDeviceInformation |
Select-Object ConnectedNode,ConnectedNodeDeviceNumber, Serialnumber, ProductId |
Sort-Object ConnectedNodeDeviceNumber |
where {($_.ConnectedNode -eq $ClusterNode) -and ($_.ProductId -match "$SSDModel")}
$ClusterNodeSSDs = foreach ($WmiObject in $WmiObjects) {
$PSOhash = #{
ConnectedNode = $WmiObject.ConnectedNode
ConnectedNodeDeviceNumber = $WmiObject.ConnectedNodeDeviceNumber
Serialnumber = $WmiObject.Serialnumber
ProductId = $WmiObject.ProductId
}
[pscustomobject]$PSOhash
}
Explanation:
Note the use of the foreach loop here because the Get-WmiObject will likely return a collection. So you will need to iterate all of them to create custom objects. However, it just seems that you can just use the Get-WmiObject | Select-Object output to perform the same thing.

Powershell output not formatting properly

I'm using this script to get some basic info from virtual machines on our HyperV cluster:
#Establish global variables and MasterList array
$VMList = Get-VM
$MasterList = #()
#Loop through VMs and get Name, Processor count, assigned memory, add to MasterList
foreach($vm in $VMList) {
$ALLVHD = Get-VHD $vm.harddrives.path -ComputerName $vm.computername
$MyObject = New-Object PSObject -Property #{
Name = ($vm).VMName
ProcessorCount = (Get-VMProcessor $vm).Count
AssignedMemory = ($vm).MemoryAssigned
DiskType = $VHD.VhdType
'Total(GB)' = [math]::Round($VHD.Size/1GB)
'Used(GB)' = [math]::Round($VHD.FileSize/1GB)
'Free(GB)' = [math]::Round($VHD.Size/1GB- $VHD.FileSize/1GB)
}
$MasterList += $MyObject
}
$MasterList | Out-GridView
It mostly works, but there are several problems. The column order is wrong, it outputs DiskType,Name,AssignedMemory,Free(GB),ProcessorCount,Used(GB),Total(GB) and I have no idea why because that's now how it's ordered in the code. Also, the Free,Used, and Total amounts are 71, 29, and 100 for all items when that is incorrect.
If any Powershell experts can help me with this, it would be much appreciated.
I figured it out, thanks for the suggestions
#Establish global variables and MasterList array
$VMList = Get-VM
$MasterList = #()
#Loop through all VMs on node
foreach($vm in $VMList) {
$ALLVHD = Get-VHD $vm.HardDrives.path -ComputerName $vm.computername
foreach($VHD in $ALLVHD){
$MyObject = New-Object PSObject -Property #{
Name = $vm.Name
DiskType = $VHD.VhdType
Path = $VHD.Path
'Total(GB)' = [math]::Round($VHD.Size/1GB)
'Used(GB)' = [math]::Round($VHD.FileSize/1GB)
'Free(GB)' = [math]::Round($VHD.Size/1GB- $VHD.FileSize/1GB)
ProcessorCount = (Get-VMProcessor $vm).Count
AssignedMemory = ($vm).MemoryAssigned
}
#Add information to MasterList array
$Masterlist += $MyObject
}
}
#Change this line to print output however you want
$MasterList | select Name,DiskType,Path,'Total(GB)','Used(GB)','Free(GB)',ProcessorCount,#{Expression={$_.AssignedMemory/1GB};Label="AssignedMemory(GB)"}