Array to table in powershell - powershell

Help me with some problem. I am new in PS and
i need output data to table view.
Looks like this.
name1 name2
----- -----
value1 value2
But i have:
$a=(get-service).name
$b=(get-service).Status
foreach ($name in $a)
{
$data = [pscustomobject]#{name1 = $name}
}
$data
RESULT
name1
-----
XboxNetApiSvc
WITHOUT FOREATCH
$a=(get-service).name
$b=(get-service).Status
$data = [pscustomobject]#{name1 = $a ; name2 = $b }
$data
Result
name1 name2
----- -----
{2GISUpdateService, AcronisActiveProtectionService, AcrSch2Svc, AdobeARMservice...} {Stopped, Running, Running, Running...}
All of that i need for this script
$list = ((Get-ADComputer -SearchBase "OU=PC,DC=cbu,DC=lan" -Filter {Enabled -eq "True" } -Properties DNSHostName).DNSHostName)
$encoding = [System.Text.Encoding]::UTF8
$up = #()
$down = #()
$table= #()
foreach ($pc in $list)
{
if ((Test-Connection -Count 1 -computer $pc -quiet) -eq $True)
{
$up += $pc
#write-host $pc "is up"
}
else
{
$down += $pc
#Write-Host $pc "down"
}
}
After all i need output values of $up and $down in 2 columns

You probably have a custom commandlet but you can run something similar to:
(Get-Service) | select Name,Status | Format-Table
UPDATE
After reading your update. At the end of your script you have two arrays $up and $down. I will declare it the static way to make an example easier
$up = #('pc1', 'pc2')
$down = #('pc3','pc4', 'pc5')
Because arrays can be diffrent length you need to calculate maximum length with:
$max = ($up, $down | Measure-Object -Maximum -Property Count).Maximum
And than create an object which "merges" above arrays with:
0..$max | Select-Object #{n="Up";e={$up[$_]}}, #{n="Down";e={$down[$_]}}
The output is:
Up Down
-- ----
pc1 pc3
pc2 pc4
pc5

If you are using Get-Service as example only then, you can just use Select :
Get-Service | Select Name, Status
Else
$MyList | Select Name1, Name2
Moreover, if you have a complex command and you want to extract a table of PSObject :
Get-Process | Select-Object -Property ProcessName, Id, WS
Read more about Select-Object : https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-object?view=powershell-4.0

Yes Piotr Stapp is rights. You can use Format-Table
Example 1:
Get-Process | Sort-Object starttime | Format-Table -View starttime
Example 2:
(Get-Service) | select Name,Status | Format-Table
Example 3:
Get-Process | FT

Related

Powershell - Remove Blank line from hash property variable

I created a script to collect remote SQL servers
#### Get number of SQL servers
$sql_servers = #()
foreach ($server in $servers){
# Loop through each server and check if server has service "MSSQLSERVER"
Try{
$sql = get-service -computername $server.DNSHOstname -ErrorAction Stop | where {$_.Name -eq "MSSQLSERVER"} | select MachineName
$sql_servers += New-Object PSObject -Property #{
Machine = $sql.MachineName
}
}
catch [Exception]
{
if ($_.Exception.GetType().Name -like "*COMException*") {
Write-Verbose -Message ('{0} is unreachable' -f $server.DNSHOstname) -Verbose
}
else{
Write-Warning $Error[0]
}
}
}
I'm getting desired results but variable contains multiple empty lines:
$sql_servers
Machine
-------
SQL1
SQL2
SQL3
I tried following to remove those blank lines without success.
$sql_servers = $sql_servers | Where-Object {$_}
$sql_servers = $sql_servers | ? {$_ -ne ""}
How to remove empty (blank) lines from variable ?
EDIT:
I found a workaround by removing hashtable property, instead of
$sql_servers += New-Object PSObject -Property #{
Machine = $sql.MachineName
}
}
i just set $sql_servers += $sql and no empty lines, but i'm curious is it possible to remove empty line using hash table.
Thanks
First thing to point out is your variable $sql_servers does not contain hashtables, but rather PSCustomObjects with one property. For this specific scenario you could remove empty entries by adjusting your command to
$sql_servers = $sql_servers | Where-Object {$_.machinename}
If it were hashtables, you could use
$sql_servers = $sql_servers | Where-Object {$_.values}
Here is a simple demonstration of both.
PSObject
1..5 | % {
if($_ % 2 -eq 0)
{
$num = $_
}
else
{
$num = $null
}
[PSCustomObject]#{
MachineName = $num
}
} -ov sql_servers
MachineName
-----------
2
4
$sql_servers | ? {$_.machinename} -ov sql_servers
MachineName
-----------
2
4
Hashtable
1..5 | % {
if($_ % 2 -eq 0)
{
$num = $_
}
else
{
$num = $null
}
#{
MachineName = $num
}
} -ov sql_servers
Name Value
---- -----
MachineName
MachineName 2
MachineName
MachineName 4
MachineName
$sql_servers | ? {$_.values} -ov sql_servers
Name Value
---- -----
MachineName 2
MachineName 4

Join arrays in PowerShell similar to concatenating DataFrame columns

Is there a way to join arrays in PowerShell similar to concatenating DataFrame columns in Python Pandas with concat or in R with cbind rather than iterating through every item?
Below is a reproducible example that binds four arrays together as four columns in a PowerShell object. How would I get rid of the for loop and get the same results?
$LogicalProcessors = (Get-WmiObject –class Win32_processor
-Property NumberOfLogicalProcessors).NumberOfLogicalProcessors;
function myTop([String]$SortCol='CPU', [Int32]$top=30) {
$NameArray = get-counter '\Process(*)\ID Process' -EA SilentlyContinue |
Select -Expand CounterSamples | Select InstanceName, CookedValue
$CpuArray = get-counter '\Process(*)\% Processor Time' -EA SilentlyContinue |
Select -Expand CounterSamples | Select CookedValue
$MemArray = get-counter '\Process(*)\Working Set - Private' -EA SilentlyContinue |
Select -Expand CounterSamples | Select CookedValue
$TopTable = For ($i=0; $i -lt $NameArray.Length; $i++) {
if ($NameArray[$i].InstanceName -eq '_total') {continue}
if ($NameArray[$i].InstanceName -eq 'memory compression') {continue}
if ($NameArray[$i].InstanceName -eq 'idle') {
$CPU = ($CpuArray[$i].CookedValue) / $LogicalProcessors;
} else {
$CPU = $CpuArray[$i].CookedValue;
}
[PSCustomObject]#{
Name = $NameArray[$i].InstanceName;
ID = $NameArray[$i].CookedValue;
CPU = $CPU;
Memory = $MemArray[$i].CookedValue;
}
}
$TopTable | sort -des $SortCol | select -f $top |`
select Name, ID,`
#{Name='CPU'; Expression = {("{0:N1}%" -f $_.CPU) } },`
#{Name='Memory'; Expression = {("{0:N0} K" -f ($_.Memory /1kb) )} }
}
myTop -SortCol Memory -top 30 | ft -a
I think PowerShell doesn't provide a way to combine columns. In this case, it can correspond by Group-Object.
function myTop([string]$SortCol = "CPU", [int]$Top = 30)
{
$LogicalProcessors = (Get-WmiObject Win32_processor NumberOfLogicalProcessors).NumberOfLogicalProcessors
Get-Counter '\Process(*)\ID Process','\Process(*)\% Processor Time','\Process(*)\Working Set - Private' -ea SilentlyContinue |
foreach CounterSamples |
where InstanceName -notin "_total","memory compression" |
group { $_.Path.Split("\\")[3] } |
foreach {
[pscustomobject]#{
Name = $_.Group[0].InstanceName
ID = $_.Group[0].CookedValue
CPU = if($_.Name -eq "idle") { $_.Group[1].CookedValue / $LogicalProcessors } else { $_.Group[1].CookedValue }
Memory = $_.Group[2].CookedValue / 1KB
}
} |
sort -des $SortCol |
select -f $Top #(
"Name","ID"
#{ n = "CPU"; e = { ("{0:N1}%" -f $_.CPU) } }
#{ n = "Memory"; e = { ("{0:N0} K" -f $_.Memory) } }
)
}
myTop -SortCol Memory -top 10 | ft -a

Sorting 2 columns in powershell Array object to find the diff

I have a system.Array in this format
A_Site B_Site
----------- -----------
BN6 BIO70
BY21 BN6
BY4 BY21
CBR20 BY4
is there a way to sort this is such a way like this ? idea is to know if there are missing site codes in column A or missing site codes in column B..
A_Site B_Site
----------- -----------
BN6 BN6
BY21 BY21
BY4 BY4
CBR20
BIO70
If the two columns in your sample input are stored in separate arrays, the following yields the desired output (PSv3+):
$arr1 = "BN6", "BY21", "BY4", "CBR20"
$arr2 = "BIO70", "BN6", "BY21", "BY4"
Compare-Object $arr1 $arr2 -IncludeEqual |
Select-Object #{ n='A_Site'; e={ if ($_.SideIndicator -in '==', '<=') { $_.InputObject } } },
#{ n='B_Site'; e={ if ($_.SideIndicator -in '==', '=>') { $_.InputObject } } }
Other method:
$arr1 = "BN6", "BY21", "BY4", "CBR20"
$arr2 = "BIO70", "BN6", "BY21", "BY4"
$arr1+ $arr2 | select -Unique | %{
$Value=$_;
[pscustomobject]#{
Value=$_
IsInArray1=(($arr1 | where {$_ -eq $Value} | select -First 1) -ne $null)
IsInArray2=(($arr2 | where {$_ -eq $Value} | select -First 1) -ne $null)
}
}

Reading txt-file, change rows to columns, save txt file

I have a txt files (semicolon separated) containing over 3 million records where columns 1 to 4 have some general information. Columns 5 and 6 have detailed information. There can be up to 4 different detailed information for the same general information in columns 1 to 4.
My sample input:
Server;Owner;Company;Username;Property;Value
Srv1;Dave;Sandbox;kwus91;Memory;4GB
Srv1;Dave;Sandbox;kwus91;Processes;135
Srv1;Dave;Sandbox;kwus91;Storage;120GB
Srv1;Dave;Sandbox;kwus91;Variant;16
Srv2;Pete;GWZ;aiwq71;Memory;8GB
Srv2;Pete;GWZ;aiwq71;Processes;234
Srv3;Micael;P12;mxuq01;Memory;16GB
Srv3;Micael;P12;mxuq01;Processes;239
Srv3;Micael;P12;mxuq01;Storage;160GB
Srv4;Stefan;MTC;spq61ep;Storage;120GB
Desired output:
Server;Owner;Company;Username;Memory;Processes;Storage;Variant
Srv1;Dave;Sandbox;kwus91;4GB;135;120GB;16
Srv2;Pete;GWZ;aiwq71;8GB;234;;
Srv3;Micael;P12;mxuq01;16GB;239;160GB;
Srv4;Stefan;MTC;spq61ep;;;120GB;
If a values doesn't exist for general information (Columns 1-4) it has to stay blank.
My current code:
$a = Import-csv .\Input.txt -Delimiter ";"
$a | FT -AutoSize
$b = #()
foreach ($Server in $a.Server | Select -Unique) {
$Props = [ordered]#{ Server = $Server }
$Owner = ($a.where({ $_.Server -eq $Server})).Owner | Select -Unique
$Company = ($a.where({ $_.Server -eq $Server})).Company | Select -Unique
$Username = ($a.where({ $_.Server -eq $Server})).Username | Select -Unique
$Props += #{Owner = $Owner}
$Props += #{Company = $Company}
$Props += #{Username = $Username}
foreach ($Property in $a.Property | Select -Unique){
$Value = ($a.where({ $_.Server -eq $Server -and
$_.Property -eq $Property})).Value
$Props += #{ $Property = $Value }
}
$b += New-Object -TypeName PSObject -Property $Props
}
$b | FT -AutoSize
$b | Export-Csv .\Output.txt -NoTypeInformation -Delimiter ";"
After a lot of trying and getting errors: My script works.
But it takes a lot of time.
Is there a possibility to make performance better for around 3 Million lines in txt file? I'm calculating with more or less 2.5 Million unique values for $Server.
I'm running Windows 7 64bit with PowerShell 4.0.
try Something like this:
#Import Data and create empty columns
$List=import-csv "C:\temp\file.csv" -Delimiter ";"
#get all properties name with value not empty
$ListProperty=($List | where Value -ne '' | select property -Unique).Property
#group by server
$Groups=$List | group Server
#loop every rows and store data by group and Property Name
$List | %{
$Current=$_
#Take value not empty and group by Property Name
$Group=($Groups | where Name -eq $Current.Server).Group | where Value -ne '' | group Property
#Add all property and first value not empty
$ListProperty | %{
$PropertyName=$_
$PropertyValue=($Group | where Name -eq $PropertyName | select -first 1).Group.Value
$Current | Add-Member -Name $PropertyName -MemberType NoteProperty -Value $PropertyValue
}
$Current
} | select * -ExcludeProperty Property, Value -unique | export-csv "c:\temp\result.csv" -notype -Delimiter ";"

Simple script to ping PCs, output table - what's wrong?

I was trying to write a simple script to ping a list of computers, and output the result in a table. I ended up doing this, which works fine:
Get-ADComputer -searchbase "OU=Materials,OU=MMC Computers,OU=REI,DC=REIDOMAIN,DC=LOCAL" -filter * | select -expand name | % {
$output = New-Object PSObject
$output | Add-Member NoteProperty "Computer name"($_)
$output | Add-Member NoteProperty "Ping result"("$($(Test-Connection $_ -count 1 -quiet).ToString())")
write $output }
However, I'd like to understand why my first two attempts didn't work, so that I can avoid making the same mistakes later. Here they are:
Script 1: See edit below
Get-ADComputer -searchbase "OU=Materials,OU=MMC Computers,OU=REI,DC=REIDOMAIN,DC=LOCAL" -filter * |
select -expand name | % { $computer = $_; $obj = "" |
select #{Name="Computer";Expression="$computer"},`
#{Name="Pingable";Expression="$($(Test-Connection $computer -count 1 -quiet).ToString())"}
$obj }
Output 1:
Computer Pingable
-----— -----—
Note: Under the table headers, this script actually prints one blank line for each computer I'm pinging.
Script 2:
$table = #{Expression={$_};Label="Computer"},#{Expression={"$($(Test-Connection $_ -count 1 -quiet).ToString())"};Label="Pingable"}
Get-ADComputer -searchbase "OU=Materials,OU=MMC Computers,OU=REI,DC=REIDOMAIN,DC=LOCAL" -filter * | select -expand name | format-table $table
Output 2:
mickeymouse
goofy
minnie
pluto
frank
This one doesn't even output a table...it just prints one computer name per line.
I'd appreciate if someone could explain what's going wrong in these two attempts. Thanks!
Edit: Got Script 1 to work.
Get-ADComputer -searchbase "OU=Materials,OU=MMC Computers,OU=REI,DC=REIDOMAIN,DC=LOCAL" -filter * |
select #{Name="Computer";Expression={$_.Name}},#{Name="Pingable";Expression={"$($(Test-Connection $_.Name -count 1 -quiet).ToString())"}};
Still curious about Script 2
In your second example, you are using the -ExpandProperty of Select-Object which effectively strips the data from the object and outputs an array of strings which format-table then outputs as a list.
See this example:
#First create the array of objects
$rawData = #( #{"Name"="First Obj"; "OtherParam"=1;}, #{"Name"="Second Obj"; "OtherParam"=2;})
$objects = $rawData | %{new-object -type psobject -prop $_}
#Just output the objects
$objects | format-table
Output:
Name OtherParam
---- ----------
First Obj 1
Second Obj 2
Now select the name property, this gives an array of objects with just a single property "name"
$objects | select name | format-table
Output:
Name
----
First Obj
Second Obj
Expand the name property, this gives an array of strings that format table just lists with no heading:
$objects | select -expand name | format-table
Output:
First Obj
Second Obj