none
Sortierung einer Hashtable RRS feed

  • Frage

  • Hallo zusammen,
    ich habe ein Script zum auslesen der gesendeten und empfangen Mails von einem Exchange Server. Es funktioniert soweit. Das Problem was ich habe ist, das die Daten in der Hashtabelle mit dem neusten Datum beginnt. Diese bräuchte ich in umbekehrter Reihenfolge. Also das älteste Datum zuerst. Habe schon so einiges probiert mit Sort-Object, komme aber auf keinen grünen Zweig. Hoffe es kann mir hier jemand helfen.
    Hier mal der Code:

    	$daycounter = 1
    	$SendReceivedMailsDaysOutput = Do
    	{
    		$dayendcounter = $daycounter - 1
    		$daystart = (Get-Date -Hour 00 -Minute 00 -Second 00).AddDays(-$daycounter)
    		$dayend = (Get-Date -Hour 00 -Minute 00 -Second 00).AddDays(-$dayendcounter)
    		
    		$DayReceivedMails = $ReceivedMails | Where-Object {
    			$_.timestamp -ge $daystart -and $_.timestamp -le $dayend
    		}
    		$DaySendMails = $sendmails | Where-Object {
    			$_.timestamp -ge $daystart -and $_.timestamp -le $dayend
    		}
    		
    		$daytotalsendmail = $daysendmails | measure-object Totalbytes -sum
    		$daytotalreceivedmail = $dayreceivedmails | measure-object Totalbytes -sum
    		
    		$daytotalsendvol = $daytotalsendmail.sum
    		$daytotalreceivedvol = $daytotalreceivedmail.sum
    		
    		$daytotalsendcount = $daytotalsendmail.count
    		$daytotalreceivedcount = $daytotalreceivedmail.count
    		
    		$day = $daystart | get-date -Format "dd.MM.yy"
    	
    		$daycounter++
    		
    		$SendReceivedMailsDays = [pscustomobject][ordered]@{
    			"Day" = $day
    			"Total send" = $daytotalsendcount
    			"Total send size (GB)" = Convert-Size -Value $daytotalsendvol -From Bytes -To GB -Precision 2
    			"Total received" = $daytotalreceivedcount
    			"Total received size (GB)" = Convert-Size -Value $daytotalreceivedvol -From Bytes -To GB -Precision 2
    		}
    		$SendReceivedMailsDays
    		
    	}
    	While ($daycounter -le $($nIntervallMailStat.Text))

    Und hier mal ein Auszug aus der Tabelle :
    @{Day=22.01.21; Total send=0; Total send size (GB)=0; Total received=0; Total received size (GB)=0} @{Day=21.01.21; Total send=0; Total send size (GB)=0; Total received=0; Total received size (GB)=0} @{Day=20.01.21; Total send=0; Total send size (GB)=0; Tota
    l received=0; Total received size (GB)=0} @{Day=19.01.21; Total send=0; Total send size (GB)=0; Total received=0; Total received size (GB)=0} @{Day=18.01.21; Total send=0; Total send size (GB)=0; Total received=0; Total received size (GB)=0} @{Day=17.01.21; 
    Total send=0; Total send size (GB)=0; Total received=0; Total received size (GB)=0}

    Gruß


    • Bearbeitet Paddy75 Samstag, 23. Januar 2021 10:15 Formatierung geändert
    Samstag, 23. Januar 2021 10:12

Antworten

  • Am Besten ich zeige Dir mal, was ich damit meine:
    @'
    Day,Total send,Total send size (GB),Total received,Total received size (GB)
    22.01.21, 0, 0, 0, 0
    19.01.21, 0, 0, 0, 0
    01.01.11, 0, 0, 0, 0
    18.01.21, 0, 0, 0, 0
    30.05.68, 0, 0, 0, 0
    21.01.21, 0, 0, 0, 0
    20.01.21, 0, 0, 0, 0
    30.12.20, 0, 0, 0, 0
    17.01.21, 0, 0, 0, 0
    '@ |
    ConvertFrom-Csv |
        Select-Object -Property @{Name='Date';Expression={Get-Date $_.Day}},* |
            Sort-Object -Property Date |
                Format-Table

    Ich habe absichtlich mal die Quelldaten durchgewürfelt, um zu zeigen, dass man wirklich nach Datum sortieren kann. ;-) 

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Samstag, 23. Januar 2021 11:54

Alle Antworten

  • Erstmal ohne tiefer in den Code reinzuschauen ... wenn es um strukturierte Daten geht (Daten, die man in einer Tabelle speichern kann), warum benutzt Du dann nicht einfach eine Tabelle anstatt von Hashtables? Das wäre übersichtlicher, wie ich glaube. Wenn Du eine Tabelle hast und eine Spalte einen DateTime-Wert enthält, kannst Du auch ohne Probleme danach sortieren.  ;-) 

    Davon unabhängig - der von Dir gepostete Code enthält Variablen, die Du offenbar vorher gefüllt hast - er ist also quasi unvollständig und deshalb schwer nachzuvollziehen. ;-) 


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Samstag, 23. Januar 2021 11:31
  • Am Besten ich zeige Dir mal, was ich damit meine:
    @'
    Day,Total send,Total send size (GB),Total received,Total received size (GB)
    22.01.21, 0, 0, 0, 0
    19.01.21, 0, 0, 0, 0
    01.01.11, 0, 0, 0, 0
    18.01.21, 0, 0, 0, 0
    30.05.68, 0, 0, 0, 0
    21.01.21, 0, 0, 0, 0
    20.01.21, 0, 0, 0, 0
    30.12.20, 0, 0, 0, 0
    17.01.21, 0, 0, 0, 0
    '@ |
    ConvertFrom-Csv |
        Select-Object -Property @{Name='Date';Expression={Get-Date $_.Day}},* |
            Sort-Object -Property Date |
                Format-Table

    Ich habe absichtlich mal die Quelldaten durchgewürfelt, um zu zeigen, dass man wirklich nach Datum sortieren kann. ;-) 

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Samstag, 23. Januar 2021 11:54
  • Danke für die Antwort.

    hier noch etwas Hintergrund:
    Die Hash wird anschließend in eine HTML-Tabelle importiert. Hierfür benutze ich PSWriteHTML (Modul). Das funktioniert hier auch wunderbar. In dieser Tabelle kann ich automatisch die Spalte angeben nachder sortiert werden soll.
    Anschließend werden die gleichen Daten genutzt um ein Linechart zu erstellen (mit dem gleichen Modul). Hier wird dann die Linechart in falscher Reihenfolge angezeigt, da in der Hash diese Daten ebenfals in der falschen Reihenfolge sind.

    Hier mal ein Beispiel: Tabelle wurde beits über das Modul sortiert.

    Samstag, 23. Januar 2021 11:57
  • hier noch etwas Hintergrund:

    Ich glaube, die andere Seite des Hintergrunds wäre interessanter gewesen. Ich meine, wie Du zu den Daten kommst. Ich glaube, dass Du Dir das Leben viel schwerer machst als eigentlich nötig.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Samstag, 23. Januar 2021 12:02
  • das kann sein. Aller Anfang ist schwer und man lernt immer wieder was dazu

    $start = (Get-Date -Hour 00 -Minute 00 -Second 00).AddDays(-$($nIntervallMailStat.Text))
    
    $end = (Get-Date -Hour 00 -Minute 00 -Second 00)
    	
    $SendMails = Get-TransportService | Get-MessageTrackingLog -Start $Start -end $End -EventId Send -ea 0 -resultsize unlimited | Where-Object {
    		$_.Recipients -notmatch "HealthMailbox" -and $_.Sender -notmatch "MicrosoftExchange" -and $_.source -match "SMTP"
    	} | Select-Object sender, Recipients, timestamp, totalbytes, clienthostname | Sort-Object -Property timestamp
    
    $ReceivedMails = Get-TransportService | Get-MessageTrackingLog -Start $Start -end $End -EventId Receive -ea 0 -resultsize unlimited | Where-Object {
    		$_.Recipients -notmatch "HealthMailbox" -and $_.Sender -notmatch "MicrosoftExchange" -and $_.source -match "SMTP"
    	} | Select-Object sender, Recipients, timestamp, totalbytes, serverhostname | Sort-Object -Property timestamp
    

    Samstag, 23. Januar 2021 12:18
  • das kann sein. Aller Anfang ist schwer und man lernt immer wieder was dazu

    Na hoffentlich.  ;-)

    Ich habe im Moment kein aktives Exchange zur Verfügung, um das zu testen, aber ich gehe mal davon aus, dass die timestamp-Property serialisiert wurde und deshalb kein [DateTime]-Typ mehr ist. Deshalb kannst Du danach eigentlich nicht mehr sortieren - jedenfalls wird es so nicht mehr nach Datum sortiert. Du kannst das aber wieder in ein [DateTime]-Typ umwandeln. Wie das geht, siehst Du hier unten in meinem Beispiel mit den CSV-Daten. Dann sollte auch das Sortieren wieder zuverlässig funktionieren.  ;-)

    Hier noch eine Kleinigkeit:

    $start = (Get-Date -Hour 00 -Minute 00 -Second 00).AddDays(-$($nIntervallMailStat.Text))
    
    $end = (Get-Date -Hour 00 -Minute 00 -Second 00)

    Das lässt sich ein wenig einfacher machen - da hat Powershell (eigentlich .Net) schon was eingebaut:

    $start = (Get-Date).Date.AddDays( - $($nIntervallMailStat.Text))
    
    $end   = (Get-Date).Date
    
    Und wenn ich es nicht falsch verstanden hab, könnte man Deinen ursprünglichen Code vermutlich auch etwas tweaken. Schau Dir mal bitte das  cmdlet Group-Object an. Wenn Du Dir mittels einer "calculated Property" in Deine Quell-Daten den Tag einfügst, kannst Du nach Tag gruppieren und dann einfach wieder mit Measure-Object die Tagessummen ermitteln. Damit sparst Du Dir eventuell Dein Schleifen-Gedöns. ;-)


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Samstag, 23. Januar 2021 14:15
  • Oh, irgend wie ist hier die Reihenfolge durcheinander geraten. Dein Beispiel steht weiter oben oder alles kommt zeitversetzt rein. Habe es eben erst gesehen.

    endlich mal jemand mit dem man sich unterhalten kann :-)

    ist mein erstes großes Projekt und so viel Ahnung habe ich noch nicht. Kommt eben alles mit der Zeit. Bringt nicht immer viel Bücher zu wälzen. Am besten lernt man eben bei "doing" und Code-Beispielen. Mit dem Group werde ich mir mal anschauen wenn diese Problem hier gelöst ist.
    Habe deinen Code mal 1zu1 in die ISE kopiert zum testen. Nach dem Proberty müsste es nur "Day" heißen. :-) . Nachdem ich -Descending entfernt habe, sah die Tabelle so aus (wie es sein sollte):
    17.01.21
    18.01.21
    19.01.21 usw.

    Ändere ich den 17.01.2021 ab auf den 30.12.20 bekomme ich folgendes:
    18.01.21
    19.01.21
    .
    .
    .
    30.12.20

    Sollte ja dann eigentlich nach dem 30.12.20 mit 18.01.21 weiter gehen (Kopfkratz). Verstehe nicht so ganz wie Powershell hier sortiert. Vermutlich nur nach dem Tag?

    Wenn das funktioniert, müsste ich demnach nur meine Variable pipen nach ConvertFrom-Csv...........


    • Bearbeitet Paddy75 Samstag, 23. Januar 2021 15:39
    Samstag, 23. Januar 2021 15:37
  • Mit dem Group werde ich mir mal anschauen wenn diese Problem hier gelöst ist.

    Ich meinte eigentlich, dass das vielleciht die Lösung Deines Problems sein könnte! ;-)  ... also eher was für jetzt ... nicht für später ;-)

    Habe deinen Code mal 1zu1 in die ISE kopiert zum testen. Nach dem Proberty müsste es nur "Day" heißen. :-)

    Nee ... der Code war so getestet und funktioniert so ... ich habe das Beispiel nochmal um ein paar weitere Daten erweitert ... und bei mir wird es korrekt nach Datum sortiert. Teste den Code mal bitte GENAU SO wie ich ihn gepostet habe.

    Nachdem ich -Descending entfernt habe, sah die Tabelle so aus (wie es sein sollte)

    -Descending ist der Parameter, der Sort-Object dazu bringt, die Liste absteigend zu sortieren. Die Standard-Sortierung ist aufsteigend. Ich würde Dir empfehlen, IMMER die HIlfe für die cmdlets zu lesen, die Du benutzen möchtest. Und zwar komplett von vorn bis hinten inklusive der Beispiele. Dabei lernt man auch schon ne Menge.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Samstag, 23. Januar 2021 16:15