Iterating through multiple email bodies and pass to hash array - arrays

I am trying to iterate through emails, that have a specific subject line, and have the body of matching emails parsed and passed to a hash array. There is an issue with how I am trying to deal with multiple email bodies that is causing an issue.
$ol=New-Object -ComObject Outlook.Application
$ns=$ol.GetNameSpace('MAPI')
$inbox=$ns.GetDefaultFolder(6)
$Goodsubject='Interesting Email'
$mail = $InBox.items |
Where-Object{
$_.Unread -and $_.Subject -match $Goodsubject
#$_.Subject -match $Goodsubject
} |
Sort-Object ReceivedTime -Descending |
Select-Object Subject,ReceivedTime,Body,SenderName
# Select-Object Body
$mail | %{
$_.Body | %{$interestinghash = #{}} {
if ($_ -match "(.*): (.*)") {
$interestinghash[$matches[1]]=$matches[2];
}
}
Assuming the email has 4 line, each with a key: value, and I look at $interestinghash, I will only have the a key value pair for a email. I will not have all 4. That said, I can replace the following line:
$mail | %{
$_.Body | %{$interestinghash = #{}} {
if ($_ -match "(.*): (.*)") {
$interestinghash[$matches[1]]=$matches[2];
}
}
With:
$mail | %{$interestinghash = #{}} {
if ($_ -match "(.*): (.*)") {
$interestinghash[$matches[1]]=$matches[2];
}
}
If I do this it will give me all 4 values but will only look at 1 email. I am not sure what I am doing wrong here.

Related

How to Out-Gridview multiple values to one key in Powershell?

I have a hashtable of IP connections that are associated to their Destination Prefixes. Here is the code to gather it all together:
function Get-InterfaceRoutes {
$interfaceIPs = Get-NetIPConfiguration -Detailed |
Where-Object { $_.netadapter.status -eq 'up' } | Get-NetIPAddress -AddressFamily IPv4 |
Select-Object -Property IPAddress, InterfaceIndex, InterfaceAlias
Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) |
Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric |
Where-Object -Property DestinationPrefix -like '*.*.*.*' | Sort-Object -Property ifIndex
[PSCustomObject]#{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPAddress)
Alias = ($interfaceIP.InterfaceAlias)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
RouteMetric = ($route.RouteMetric)
InterfaceMetric = ($route.InterfaceMetric)
}
}
}
$collection = #(Get-InterfaceRoutes)
I am building a UI in PS-5.1(WinForms) to list the various indexes and their properties. With it I have this button that I want to be able to select one of the listed Destination Prefixes (of which there will be at least 1, at most n to choose from) associated with each index (again, 1-n):
$destinationSelectButton.Add_Click({
$selectedDestination = $collection.keys |
Out-GridView -Title "Select Destination Prefix" -PassThru |
ForEach-Object { $_.Values } | Select-Object -Property DestinationPrefix
Write-Host $selectedDestination | Out-String #<<<exists for confirmation in console, ignore.
})
The problem I have with this snippet specifically is that when I select the button, I don't get the GridView box to select from the list of Prefixes. Just nothing. No error message, no window opening, just an acknowledgement in my terminal that the button was clicked.
If I arrange the code any other way, such as:
$selectedDestination = $collection |
Out-Gridview -Title "Select Destination Prefix" -PassThru |
Select-Object -Property DestinationPrefix
I get this:
Here the Destination Prefix is gathered as one object, but I want to display that array broken apart so that one can be selected from the list and sent to $selectedDestination for use later on. I suspect the code block I shared for the button SHOULD do just that, but without the window opening, and no error to say why, I am not sure where to go from here to get it to work.
If I understand correctly, you're just needing to loop through each object resulted from Get-NetRoute and then combine / merge that output with the result of Get-NetIPConfiguration, instead of merging all objects into one object.
For that you can use Select-Object with calculated properties:
$interfaceIPs = Get-NetIPConfiguration -Detailed |
Where-Object { $_.NetAdapter.Status -eq 'up' } |
Get-NetIPAddress -AddressFamily IPv4
$collection = foreach($interfaceIP in $interfaceIPs) {
Get-NetRoute -InterfaceIndex $interfaceIP.InterfaceIndex |
Where-Object -Property DestinationPrefix -like '*.*.*.*' |
Sort-Object -Property ifIndex | Select-Object #(
#{ N = 'Index'; E = { $interfaceIp.InterfaceIndex }}
#{ N = 'Address'; E = { $interfaceIP.IPAddress }}
#{ N = 'Alias'; E = { $interfaceIP.InterfaceAlias }}
'DestinationPrefix'
'NextHop'
'RouteMetric'
'InterfaceMetric'
)
}
$selection = $collection | Out-GridView -PassThru

Display all values in PSCustomObject array [duplicate]

Is it possible to display the results of a PowerShell Compare-Object in two columns showing the differences of reference vs difference objects?
For example using my current cmdline:
Compare-Object $Base $Test
Gives:
InputObject SideIndicator
987654 =>
555555 <=
123456 <=
In reality the list is rather long. For easier data reading is it possible to format the data like so:
Base Test
555555 987654
123456
So each column shows which elements exist in that object vs the other.
For bonus points it would be fantastic to have a count in the column header like so:
Base(2) Test(1)
555555 987654
123456
Possible? Sure. Feasible? Not so much. PowerShell wasn't really built for creating this kind of tabular output. What you can do is collect the differences in a hashtable as nested arrays by input file:
$ht = #{}
Compare-Object $Base $Test | ForEach-Object {
$value = $_.InputObject
switch ($_.SideIndicator) {
'=>' { $ht['Test'] += #($value) }
'<=' { $ht['Base'] += #($value) }
}
}
then transpose the hashtable:
$cnt = $ht.Values |
ForEach-Object { $_.Count } |
Sort-Object |
Select-Object -Last 1
$keys = $ht.Keys | Sort-Object
0..($cnt-1) | ForEach-Object {
$props = [ordered]#{}
foreach ($key in $keys) {
$props[$key] = $ht[$key][$_]
}
New-Object -Type PSObject -Property $props
} | Format-Table -AutoSize
To include the item count in the header name change $props[$key] to $props["$key($($ht[$key].Count))"].

PowerShell finding duplicates in CSV and outputting different header

I guess the question is in the title.
I have a CSV that looks something like
user,path,original_path
I'm trying to find duplicates on the original path, then output both the user and original_path line.
This is what I have so far.
$2 = Import-Csv 'Total 20_01_16.csv' | Group-Object -Property Original_path |
Where-Object { $_.count -ge 2 } | fl Group | out-string -width 500
This gives me the duplicates in Original_Path. I can see all the required information but I'll be danged if I know how to get to it or format it into something useful.
I did a bit of Googleing and found this script:
$ROWS = Import-CSV -Path 'Total 20_01_16.csv'
$NAMES = #{}
$OUTPUT = foreach ( $ROW in $ROWS ) {
IF ( $NAMES.ContainsKey( $ROW.Original_path ) -and $NAMES[$ROW.original_path] -lt 2 )
{ $ROW }
$NAMES[$ROW.original_path] += 1 }
Write-Output $OUTPUT
I'm reluctant to use this because, well first I have no idea what it's doing. So little of the makes any sense to me, I don't like using scripts I can't get my head around.
Also, and this is the more important part, it's only giving me a single duplicate, it's not giving me both sets. I'm after both offending lines, so I can find both users with the same file.
If anyone could be so kind as to lend a hand I'd appreciate it.
Thanks
It depends on the output format you need, but to build on what you already have we can use this to show the records in the console:
Import-Csv 'Total 20_01_16.csv' |
Group-Object -Property Original_path |
Where-Object { $_.count -ge 2 } |
Foreach-Object { $_.Group } |
Format-Table User, Path, Original_path -AutoSize
Alternatively, use this to save them in a new csv-file:
Import-Csv 'Total 20_01_16.csv' |
Group-Object -Property Original_path |
Where-Object { $_.count -ge 2 } |
Foreach-Object { $_.Group } |
Select User, Path, Original_path |
Export-csv -Path output.csv -NoTypeInformation

Powershell-File names in a directory with same letters

I need to write a powershell script, which list file names that contains the same letters, only difference is the sort of the letters.
My first oppinion is to sort the letters in alphabet, and if it fit, then they match, but i need some help for do that
Get-ChildItem $path | foreach {$i=1}`
{
$asd=$_ | sort-object
Get-ChildItem $path | foreach {$i=1}`
{
$wasd=$_ | sort-object
if($asd -eq $wasd)
{
Write-Host $_
}
}
}
This files match for my criteria:
asd.txt, dsa.txt, because contains same letters
I think this is doing what you want.
function get-Stringcharacters {
param($string)
[char[]]$string | sort-object
}
dir $path | group-object #{E={get-Stringcharacters $_.Name}} |
where-object {$_.Count -gt 1} |
select-object -ExpandProperty Group |
foreach { write-host $_.Name }
gci | % { ($.BaseName.ToString().toCharArray() | Sort) -join ''} | Group | ? { $.Count -gt 1 } | Select Name

Powershell Hash Table Grouping

I have a CSV like below:
location,id
loc1,1234
loc1,1235
loc1,1236
Running $a = Import-CSV C:\File.csv | Group-Object "location" I get the following output:
Count Name Group
----- ---- -----
3 loc1 {#{location=loc1; id=1234}, #{location=loc1; id=1235), #{location=loc1, id=1236}}
I would like to add all ID's to a single group (Using Add-QADGroupMember) but I can't figure out how to get a group of ID's for $loc1. It seems to be be grouping them correctly but I can't seem to parse the output into a single group. E.g $loc1 = 1234,1235,1236 that I can loop through.
Any suggestions would be appreciated!
Group-Object doesn't handle hashtables well, since the keys aren't real properties.
Assuming:
$csv = Import-CSV C:\File.csv
You should be able to do, for example:
$ids = $csv | %{ $_.id }
to get an array of the ID values. You'd probably want to pipe through Get-Unique for location.
If you wanted to get the location for a single ID quickly:
$location = $csv | ?{ $_.id -eq 42 } | %{ $_.location }
If you wanted to get an array of all IDs for a single location quickly (I think this is what you want):
$loc1 = $csv | ?{ $_.location -eq 'loc1' }
For reference, if you wanted to get a hashtable mapping each location to an array of IDs:
$groups = $csv | %{ $_.location } | &{
begin
{
$hash = #{}
}
process
{
$location = $_.location
$hash[$location] = $csv | ?{ $_.location -eq $location }
}
end
{
$hash
}
}
A bit tricky, but this will do it:
Import-Csv C:\File.csv | Group-Object "location" | %{Set-Variable ($_.Name) ($_.Group | Select-Object -ExpandProperty id)}
After running that, $loc1, $loc2, etc. will be arrays of all the ids for each location.
And yet another option:
(Import-Csv c:\foo.csv | Group Location -AsHashTable).Loc1 | Foreach {$_.id}
And if you're on V3, you can do this:
(Import-Csv c:\foo.csv | Group Location -AsHashTable).Loc1.Id

Resources