Where-Object not filtering - powershell

Why isn't where-object working in this case?
$controlFlowArgs = #{ waitForEnter = $false }
$controlFlowArgs | Format-Table
$controlFlowArgs | Format-List
$result = $controlFlowArgs | Where-Object -FilterScript { $_.Name -eq "waitForEnter" }
$result
Output
Name Value # Format-Table
---- -----
waitForEnter False
Name : waitForEnter # Format-List
Value : False
# Missing result would be here

$controlFlowArgs is a HashTable. You should probably think it differently.
$result = $controlFlowArgs | Where-Object { $_["waitForEnter"] }
would store $false in $result.
Else you can use the Hashtable directly:
if ($controlFlowArgs["waitForEnter"]) {
...
}

Where-object is working fine. In this example, only the 'joe' hashtable appears. Confusingly the format takes up two lines.
#{name='joe';address='here'},#{name='john';address='there'} | ? name -eq joe
Name Value
---- -----
name joe
address here
It's still considered one thing:
#{name='joe';address='here'},#{name='john';address='there'} | ? name -eq joe |
measure-object | % count
1
If you want the value itself, use foreach-object (or select-object -expandproperty):
#{name='joe';address='here'},#{name='john';address='there'} | ? name -eq joe |
% name
joe
Usually powershell works with pscustomobjects:
[pscustomobject]#{name='joe';address='here'},
[pscustomobject]#{name='john';address='there'} | ? name -eq joe
name address
---- -------
joe here

Related

when exporting to the text file compare-object issue

I want to get an output like below.
My output now :
Name Active PrimarySmtpAddress
---- ------ ------------------
DG_Group1 True mail1#contoso.com
DG_Group2 False mail2#contoso.com
DG_Group3 True mail3#contoso.com
My desired output :
mail1#contoso.com
mail2#contoso.com
mail3#contoso.com
script :
$DistroLists = Get-DistributionGroup -ResultSize Unlimited
$MessageTrace = Get-MessageTrace -RecipientAddress $DistroLists.PrimarySmtpAddress -startdate (Get-Date).AddDays(-8) -EndDate (Get-Date)
$DistroLists |
Foreach-Object {
$_ | Add-Member -MemberType NoteProperty -Name Active -Value (
$_.PrimarySmtpAddress -in $MessageTrace.RecipientAddress
) -PassThru
} |
Select-Object Name, Active, PrimarySmtpAddress | Where-Object Active -EQ "FALSE"
Out-File C:\output.txt
You can use Select-Object -ExpandProperty or ForEach-Object -MemberName to grab only the value of a specific property from one or more piped input objects:
... |Select-Object Name, Active, PrimarySmtpAddress | Where-Object Active -eq $false | ForEach-Object -MemberName PrimarySmtpAddress | Out-File...
You can skip first two lines and split the line using space characters. Finally pick the last column as given below:
Get-Content C:\Projects\logtext.txt | Select-Object -Skip 2 | ForEach-Object { "$(($_
-split '\s+',3)[2])" }
mail1#contoso.com
mail2#contoso.com
mail3#contoso.com

Change arraylist rows to column using Powershell

I am trying to change the format of an arraylist after I have used
group-object
to count all the entries in the list.
this is a sample
$list = [System.Collections.ArrayList]#()
$list = "letter","solo","nap","nap","nap","sharp","ignite","tap","tap","tap","tap","evoke"
$list | Group-Object | select name,count
This is the sample output
Name Count
---- -----
letter 1
solo 1
nap 3
sharp 1
ignite 1
tap 4
evoke 1
What I would like is
letter solo nap sharp ignite tap evoke
-------- ----- ---- ---- ----- ------ ----
1 1 3 4 1 4 1
Then when exporting to excel it would format like this
Everything I have tried doesn't seem to pay off, or even get close to what I am trying to do and I think I am missing something obvious or have hit my PowerShell skill limitations. Could someone please help. Thank you
You could create a PSObject, add the properties to it with Add-Member, then format the output to a table with Format-Table:
$list = "letter","solo","nap","nap","nap","sharp","ignite","tap","tap","tap","tap","evoke"
$groups = $list | Group-Object | Select-Object Name, Count
$psObject = New-Object -TypeName psobject
foreach ($group in $groups) {
$psObject | Add-Member -NotePropertyName $group.Name -NotePropertyValue $group.Count
}
$psObject | Format-Table
Output:
evoke ignite letter nap sharp solo tap
----- ------ ------ --- ----- ---- ---
1 1 1 3 1 1 4
Skip Group-Object altogether - instead, use a dictionary to keep track of the count, then cast the whole dictionary to a custom object:
$properties = [ordered]#{}
$list |ForEach-Object {
$properties[$_]++
}
$counts = [pscustomobject]$properties
$counts will now hold an object like what you describe, formatting as a table gives you:
PS C:\> $counts |Format-Table
letter solo nap sharp ignite tap evoke
------ ---- --- ----- ------ --- -----
1 1 3 1 1 4 1
You may try something like:
$list = [System.Collections.ArrayList]#()
$list = "letter","solo","nap","nap","nap","sharp","ignite","tap","tap","tap","tap","evoke"
$group = $list | Group-Object | select name,count
$a = [PSCustomObject]#{}
foreach ($item in $group) {
$a | Add-Member -NotePropertyName $item.name -NotePropertyValue $item.count
}
$a | ft
One solution would be to put it into an PsObject and then export that object into a CSV:
$list = [System.Collections.ArrayList]#()
$list = "letter","solo","nap","nap","nap","sharp","ignite","tap","tap","tap","tap","evoke"
$hash = $list | Group-Object | select name,count
$object = New-Object psobject
foreach( $item in $hash ) {
$column_name = $item.Name
$row_value = $item.Count
$object | Add-Member -MemberType NoteProperty -Name $column_name -Value $row_value
}
$object | Export-csv 'Path to your CSV' -NoTypeInformation

Is there a way to use more elements than display in an Out-GridView array

I am trying to allow a user to multiselect from a list of results returned from a command, using Out-GridView.
However, I seem to have to ask for the elements I need later on AND display them in the Out-GridView. But it gets chaotic in there!
Can I show less of them in the Out-GridView?
I have tried pulling in the command into another variable and then selecting the elements I want to show in the grid view, but that has the same result, or I am not doing it right.
For example:
$Global:delboxes = Get-Mailbox -SoftDeletedMailbox | Select-Object Name,Alias,PrimarySmtpAddress,WhenSoftDeleted,ArchiveName,guid,Emailaddresses | Sort-Object -property Name | Out-GridView -Title "Please select mailbox(es)" -PassThru
Returns:
PS> $delboxes | ft
Name Alias PrimarySmtpAddress WhenSoftDeleted ArchiveName Guid EmailAddresses
---- ----- ------------------ --------------- ----------- ---- --------------
person1 person.one person.one#mycompany.com 25/09/2016 20:53:56 {archive} d25cb74b-46cf-4582-9c32-6c146f59f013 {X500:/o=mycompany/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/...
person2 person.two person.two#mycompany.com 25/09/2016 20:53:56 {} 1670a21e-a00b-461e-ae84-2ff646e2a434 {SMTP:person.two#mycompany.com, smtp:person.2#mycompany, X500:/o=mycompany/ou=Exchan...
Although $delboxes will return everything I asked for in the Get-Mailbox | Select-Object part, there is too much to display on the screen when there are many EmailAddresses. So the Name and Alias get shrunk to a few characters
So I want just a few of the elements to show in the Out-GridView, but to be able to use them all later on in my script.
If I only put this in the script
$Global:delboxes = Get-Mailbox -SoftDeletedMailbox | Select-Object Name,Alias | Sort-Object -property Name | Out-GridView -Title "Please select mailbox(es)" -PassThru
I am unable to use the element ArchiveName without requerying the Get-Mailbox command
PS> $delboxes | ft
Name Alias
---- -----
person1 person.one
person2 person.two
PS> $delboxes.ArchiveName | ft
There is nothing :-(
And using default display set gives me an unusable Out-GridView and not the elements I require either
$Global:delboxes = Get-Mailbox -SoftDeletedMailbox | Sort-Object -property WhenSoftDeleted | Out-GridView -Title "Please select mailbox(es)" -PassThru
PS> $delboxes | ft
RunspaceId Database MailboxProvisioningConstraint IsMonitoringMailbox MailboxRegion MailboxRegionLastUpdateTime MessageRecallProcessingEnabled MessageCopyForSentAsEnabled MessageCopyForSendOnBehalfEnabled
---------- -------- ----------------------------- ------------------- ------------- --------------------------- ------------------------------ --------------------------- ------
20edeed1-036f-4832-8463-486827c61405 EURP195DG024-db030 False True False False
20edeed1-036f-4832-8463-486827c61405 EURP195DG013-db099 False True False False
20edeed1-036f-4832-8463-486827c61405 EURP195DG007-db072 False True False False
To have the Out-Gridview with only reduced properties and nevertheless afterwards have access to all properties,
you might save the selection and use Compare-Object with -IncludeEqual -ExcludeDifferent
## Q:\Test\2019\03\27\SO_55377562.ps1
$Global:delboxes = Get-Mailbox -SoftDeletedMailbox |
Select-Object Name,Alias,PrimarySmtpAddress,WhenSoftDeleted,ArchiveName,guid,Emailaddresses |
Sort-Object -Property Name
$Selection = $delboxes | Select-Object Name,Alias |
Out-GridView -Title "Please select mailbox(es)" -PassThru
$SelectedDelboxes = Compare-Object -Ref $delboxes -Diff $Selection -Property Name,Alias `
-IncludeEqual -ExcludeDifferent -PassThru |
Select-Object * -Exclude SideIndicator

How to Group data from two arrays and get the count

if I have two arrays and region column has no same values
like
$data1=
Region Type
------ -----------
EuropeWest Operational
EuropeWest Operational
EuropeWest Operational
EuropeNorth Operational
USCentral Operational
USCentral Operational
AsiaEast Operational
AsiaEast Operational
AsiaEast Operational
$data2=
Region Type
------ -----------
EuropeWest MigrateSource
EuropeWest MigrateSource
EuropeNorth MigrateSource
USCentral MigrateSource
USEast MigrateSource
output should be as:
Region Operational MigrateSource
------ ----------- -----------
EuropeWest 4 2
EuropeNorth 1 1
USCentral 2 0
AsiaEast 3 1
Useast 0 1
Any help much appreciated?
I was able to group it but did'nt get any clue how to use foreach loop here:
$data1 | group -Property region | select name,#{n='Operationaclcount';e={$_.count}}
$data2 | group -Property region | select name,#{n='Migratesourcecountt';e={$_.count}}
Since you have two objects with a property name, if we combine these together we have a full list of names. With a ForEach loop, we'll loop over these names and use a Where-Object to filter each of the two objects you created for the count. We'll then create a new object with [pscustomobject]. Finally a quick test if a name is missing from a group that means the count was zero.
$OpCount = $data1 |
Group-Object -Property region |
Select-Object name,#{n='Operationalcount';e={$_.count}}
$MigCount = $data2 |
Group-Object -Property region |
Select-Object name,#{n='Migratesourcecount';e={$_.count}}
$CombinedNames = $OpCount.name + $MigCount.name
Foreach ($Name in $CombinedNames) {
$entry = [pscustomobject]#{
Operational = $OpCount |
Where-Object {$_.name -eq $Name} |
Select-Object -Expand Count
MigrateSource = $MigCount |
Where-Object {$_.name -eq $Name} |
Select-Object -Expand Count
}
if ($entry.Operational -eq $null) { $entry.Operational = 0 }
if ($entry.MigrateSource -eq $null) { $entry.MigrateSource = 0 }
$entry
}
If you want to combine two arrays just use a plus. Something like this:
$data1 + $data2 | Group-Object region | % {
New-Object psobject -property #{
Name = $_.Name
Operational = $_.Count
MigrateSource = #($_.Group | Select Type -Unique).Count
}
}

Modifying CSV content with Powershell

I have a CSV file, Devices.csv, containing IP Address, DeviceName, SerialNumber, MAC Address, UserName.
The Users column in all the rows of Devices.csv is prepopulated with a value [Unknown]
The code...
{Import-CSV Devices.csv | Where-Object {$_.IPAddress -eq '192.168.2.124'} | Select-Object -last 1 | FT IPAddress, devicveName, SerialNumber, MACAddress, User -AutoSize }
....outputs
IPAddress deviceName SNumber MACAddress User
--------- ----- ------- ---------- ----
192.168.2.124 ComputerA 1ABCDEFG 00xxYYbbCCdd [Unknown]
I want to be able to replace the [Unknown] text with a Username I have retrieved from a different source. Can I update just the User column on this line in Devices.csv using powershell and keep the rest of the CSV file intact ?
Thanks, Brian
$csv = Import-CSV Devices.csv
$csv | Where-Object {$_.IPAddress -eq '192.168.2.124'} | Select-Object -Last 1 | ForEach-Object {$_.User = $user}
$csv | Export-Csv Devices.csv -NoTypeInformation
Try this:
$otheruser = '...'
Import-Csv Devides.csv | % {
if ($_.User -eq '[Unknown]') { $_.User = $otheruser }
$_
} | Export-Csv Divices_modified.csv -NoTypeInformation