Benutzer mit den meisten Antworten
Es werden nicht alle Mails beim ersten Anlauf gelöscht, loop schafft derzeit abhilfe

Frage
-
Hallo zusammen,
ich habe ein kleines Script geschrieben, um Mails aus Clientpostfächern zu löschen.
Solange das Ganze an einer Mail im Quellordner getestet wird funktioniert alles wunderbar.
Sobald die Anzahl jedoch steigt werden nicht mehr alle Mails beim ersten Anlauf gelöscht, sondern der Prozess muss mehrmals gestartet werden.Das Script sieht wie folgt aus:
################################################################################################################################################################################################################################################################################################################################################################################## # Script zum löschen der gesendeten Elemente im Postfach der x-Anwender von Absender x mit Bearbeitungscode x # Stand: 15.03.2018 ################################################################################################################################################################################################################################################################################################################################################################################## $ErrorActionPreference = "SilentlyContinue" $WarningActionPreference = "SilentlyContinue" # Datum für Logdatei setzen $dateforlog = get-date -format ddMMyy # Dateiname für Logdatei generieren $logfilesentitems = "C:\log\deleteSent("+$dateforlog+").txt" # Startzeit des Scripts ermitteln $starttime = get-date -format hh:mm:ss # Einbinden von Outlook $outlook = new-object -com outlook.application #Setzen des Ordnernamens $global:SENT = "Gesendete Elemente" # Log-Header & Startzeit "Datum"+";"+"Uhrzeit"+";"+"Anwender"+";"+"Betreff" >> $logfilesentitems "$dateforlog"+";"+$starttime+";"+"Administrator"+";"+"Startzeitpunkt des Scripts" >> $logfilesentitems # Filtern der betroffenen Benutzer des VKI $USERS = get-aduser -filter * -Properties * -SearchBase "OU der betroffenen Nutzer" | ? {($_.surname -notlike "" -and $_.givenname -notlike "" -and ($_.physicalDeliveryOfficeName -like "WERT" -or $_.physicalDeliveryOfficeName -like "WERT") -and ($_.Description -notmatch "WERT"))} | sort surname # Einbinden der benötigten Werte foreach($USER in $USERS){ # Postfach auf das zugegriffen wird muss als Displayname eingetragen werden $USER = $USER | select -ExpandProperty displayname $mailbox = $outlook.Session.Folders.Item($USER).Folders.Item($SENT).Items foreach($mail in $mailbox){ # Herausfiltern von Kalendereinträgen. Nur Mails sollen gelöscht werden $mclass = $mail | select -ExpandProperty MessageClass IF($mclass -match "Schedule"){} ELSE{ # laden der Werte Subject und Absender in je eine eigene Variable $subject = $mail | select -ExpandProperty Subject $sender = $mail | select -ExpandProperty SentOnBehalfOfName # Abfrage auf Bearbeitungscode und Absender IF($subject -match "WERT" -and $sender -match "WERT"){ # Datum & Uhrzeit für logging $dd = get-date -format dd.MM.yy $dh = get-date -format hh:mm:ss #$subject $message = $dd+";"+$dh+";"+$USER+";"+$subject $log += $message # Löschen der gefilterten Mail fünf Durchläufe, da der erste nicht jede Mail erwischt for($i = 0; $i -lt 5; $i++){ $mail.Delete() } Clear-Variable log, message, dd, dh $log >> $logfilesentitems } ELSE{} # Löschen der im Verlauf eingesetzten Variablen - keep your ENV cleaned up Remove-Variable subject, sender } Remove-Variable mail, mclass } Remove-Variable mailbox } # Schreiben des Endzeitpunkts ins log $ENDZEIT = get-date -format hh:mm:ss "$dateforlog"+";"+$ENDZEIT+";"+"Administrator"+";"+"Endzeitpunkt des Scripts" >> $logfilesentitems # Löschen aller eingesetzten Variablen - keep your ENV cleaned up Remove-Variable outlook, sent, i, VKIuser, VKIusers, dateforlog, logfilesentitems, starttime, ENDZEIT, WarningActionPreference, ErrorActionPreference exit
Im Eigentlichen geht es um folgenden Block:
for($i = 0; $i -lt 5; $i++){ $mail.Delete() } Clear-Variable log, message, dd, dh $log >> $logfilesentitems } ELSE{}
Gibt es eine Methode, welche bei Durchführung des .Delete auf Erfolg wartet?
Ich bin für jeden zielführenden Hinweis dankbar.
Viele Grüße
Antworten
-
Moin,
ich habe schon lange nichts mehr für Outlook gehackt, dafür aber früher (so bis inkl. OL2013) eine ganze Menge, und es war schon immer so. Zuverlässige Abhilfe konnte in meiner Erfahrung immer nur mit zusätzlichen Bibliotheken geschaffen werden:
- entweder Redemption
- oder EWS Managed MAPI und direkt an Exchange rangehen, wenn Exchange 2010+ dahinter ist.
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
ich habe gerade was im Technet gefunden, was mir sinnig erscheint.
Link: Link
Nach Umbau des bei mir eingesetzten Foreach auf das im Link beschriebene Vorgehen mit For funktioniert es nun beim ersten Durchlauf :-)
Wenn Anzahl Mail = 10 ist der Counter auf 10 und er kann die Mail mit Index 1 beim ersten Durchlauf löschen.
Bei Durchlauf 6 soll Mail 6 mit dem neuen Index 1 gelöscht werden, da Mail 1-5 den Index je um 1 verringert haben.Verworren das Ganze, aber macht irgendwie schon Sinn.
Danke dennoch für die Antwort! Kommentare von Herrn Smirnov lese ich nur zu gern in meinen Threads! ;-)
Finds' immer lustig. Ich poste nen Eintrag im Technet, weil die Suche nichts ergeben hat, Zack keine Minute später gibts bei der Suche ein Ergebnis.
- Bearbeitet BeatYa Donnerstag, 15. März 2018 13:17
- Als Antwort markiert Denniver ReiningMVP, Moderator Sonntag, 18. März 2018 10:47
Alle Antworten
-
Moin,
ich habe schon lange nichts mehr für Outlook gehackt, dafür aber früher (so bis inkl. OL2013) eine ganze Menge, und es war schon immer so. Zuverlässige Abhilfe konnte in meiner Erfahrung immer nur mit zusätzlichen Bibliotheken geschaffen werden:
- entweder Redemption
- oder EWS Managed MAPI und direkt an Exchange rangehen, wenn Exchange 2010+ dahinter ist.
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
-
Moin,
ich habe schon lange nichts mehr für Outlook gehackt, dafür aber früher (so bis inkl. OL2013) eine ganze Menge, und es war schon immer so. Zuverlässige Abhilfe konnte in meiner Erfahrung immer nur mit zusätzlichen Bibliotheken geschaffen werden:
- entweder Redemption
- oder EWS Managed MAPI und direkt an Exchange rangehen, wenn Exchange 2010+ dahinter ist.
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
ich habe gerade was im Technet gefunden, was mir sinnig erscheint.
Link: Link
Nach Umbau des bei mir eingesetzten Foreach auf das im Link beschriebene Vorgehen mit For funktioniert es nun beim ersten Durchlauf :-)
Wenn Anzahl Mail = 10 ist der Counter auf 10 und er kann die Mail mit Index 1 beim ersten Durchlauf löschen.
Bei Durchlauf 6 soll Mail 6 mit dem neuen Index 1 gelöscht werden, da Mail 1-5 den Index je um 1 verringert haben.Verworren das Ganze, aber macht irgendwie schon Sinn.
Danke dennoch für die Antwort! Kommentare von Herrn Smirnov lese ich nur zu gern in meinen Threads! ;-)
Finds' immer lustig. Ich poste nen Eintrag im Technet, weil die Suche nichts ergeben hat, Zack keine Minute später gibts bei der Suche ein Ergebnis.
- Bearbeitet BeatYa Donnerstag, 15. März 2018 13:17
- Als Antwort markiert Denniver ReiningMVP, Moderator Sonntag, 18. März 2018 10:47
-
...aber Du machst ja keinen Count, sondern Foreach, was sich für eine Collection auch gehört.
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
-
> $mailbox = $outlook.Session.Folders.Item($USER).Folders.Item($SENT).Items
Hätte dazu noch was interessantes gefunden: "Zum Löschen aller Elemente in der Items -Auflistung eines Ordners müssen Sie jedes Element löschen, beginnend mit dem letzten Element im Ordner."
https://msdn.microsoft.com/de-de/VBA/Outlook-VBA/articles/mailitem-delete-method-outlookWürde bedeuten, daß Du nicht mit foreach durchlaufen kannst, sondern mit einer for-Schleife. Und da dann rückwärts zählen mußt.
-
Würde bedeuten, daß Du nicht mit foreach durchlaufen kannst, sondern mit einer for-Schleife. Und da dann rückwärts zählen mußt.
Evgenij Smirnov
I work @ msg services ag, Berlin -> http://www.msg-services.de
I blog (in German) @ http://it-pro-berlin.de
my stuff in PSGallery --> https://www.powershellgallery.com/profiles/it-pro-berlin.de/
Exchange User Group, Berlin -> https://exusg.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com
In theory, there is no difference between theory and practice. In practice, there is.
-
Wenn eine Collection mit ForEach durchlaufen wird und Einträge entfernt oder hinzugefügt werden, verschiebt sich natürlich alles.
In .Net gibt es daher eine Exception, dass die Auflistung (Collection) geändert wurde, der ForEach wird dann abgebrochen (da die PowerShell ja eigentlich .Net-basiert ist, frage ich mich allerdings warum das nicht passiert).
Nun gibt es 2 Verfahren:
- Wie oben bereits gesagt, die Collection rückwärts per For-Schleife durcharbeiten.
- Per ForEach die Enträge ermitteln und in einer eigenen Liste sammeln, im 2. Schritt die eigene Liste abarbeiten um dann die gefundenen Einträge zu löschenWichtig ist natürlich, dass während der Bearbeitung kein anderer Prozess an der Collection rumfummelt.
-
Also das nun fertige Script sieht wie folgt aus:
################################################################################################################################################################################################################################################################################################################################################################################## # Script zum löschen der gesendeten Elemente im Postfach der x-Anwender von Absender x mit Bearbeitungscode x* # Stand: 15.03.2018 ################################################################################################################################################################################################################################################################################################################################################################################## $ErrorActionPreference = "SilentlyContinue" $WarningActionPreference = "SilentlyContinue" # Datum für Logdatei setzen $dateforlog = get-date -format ddMMyy # Dateiname für Logdatei generieren $logfilesentitems = "C:\log\deleteSent("+$dateforlog+").txt" # Startzeit des Scripts ermitteln $starttime = get-date -format HH:mm:ss # Einbinden von Outlook $outlook = new-object -com outlook.application #Setzen des Ordnernamens $global:SENT = "Gesendete Elemente" # Log-Header & Startzeit "Datum"+";"+"Uhrzeit"+";"+"Anwender"+";"+"Betreff" >> $logfilesentitems "$dateforlog"+";"+$starttime+";"+"Administrator"+";"+"Startzeitpunkt des Scripts" >> $logfilesentitems # Filtern der betroffenen Benutzer des VKI $Users = get-aduser -filter * -Properties * -SearchBase "OU zum suchen" | ? {($_.surname -notlike "" -and $_.givenname -notlike "" -and ($_.physicalDeliveryOfficeName -like "Raum x" -or $_.physicalDeliveryOfficeName -like "Raum x") -and ($_.Description -notmatch "Description"))} | sort surname # Einbinden der benötigten Werte FOREACH($User in $Users){ # Postfach auf das zugegriffen wird muss als Displayname eingetragen werden $User = $User | select -ExpandProperty displayname $mailbox = $outlook.Session.Folders.Item($User).Folders.Item($SENT).Items $mcount = $mailbox.Count FOR($i = $mcount ; $i -gt 0; $i--){ $mail = $mailbox[$i] #foreach($mail in $mailbox){ --> Foreach hat einen Fehler beim Zähler verursacht # Herausfiltern von Kalendereinträgen. Nur Mails sollen gelöscht werden $mclass = $mail | select -ExpandProperty MessageClass IF($mclass -match "Schedule"){} ELSE{ # laden der Werte Subject und Absender in je eine eigene Variable $subject = $mail | select -ExpandProperty Subject $sender = $mail | select -ExpandProperty SentOnBehalfOfName # Abfrage auf Bearbeitungscode und Absender IF($subject -match "MÄTCH" -and $sender -match "MÄTCH"){ # Datum & Uhrzeit für logging $dd = get-date -format dd.MM.yy $dh = get-date -format hh:mm:ss #$subject $message = $dd+";"+$dh+";"+$User+";"+$subject $log += $message # Löschen der gefilterten Mail fünf Durchläufe, da der erste nicht jede Mail erwischt $mail.Delete() Clear-Variable log, message, dd, dh $log >> $logfilesentitems } ELSE{} # Löschen der im Verlauf eingesetzten Variablen - keep your ENV cleaned up Remove-Variable subject, sender } Remove-Variable mail, mclass } Remove-Variable mailbox } # Schreiben des Endzeitpunkts ins log $ENDZEIT = get-date -format hh:mm:ss "$dateforlog"+";"+$ENDZEIT+";"+"Administrator"+";"+"Endzeitpunkt des Scripts" >> $logfilesentitems # Löschen aller eingesetzten Variablen - keep your ENV cleaned up Remove-Variable alle benutzten Variablen # Bye Bye EXIT
Spart einiges an Ausführungszeit auf diese Weise.
Frage mich dennoch weiterhin auch wie das bei einem FOREACH passieren kann, denn ich arbeite ja nicht mit der Indexnummer, sondern mit dem Betreff und wäre eigentlich davon ausgegangen, dass die Daten im Array so wie sie im Array stehen fortbestehen bleiben. Also wird doch vor dem Foreach eine eigene Liste aufgebaut und abgearbeitet ...
- Bearbeitet BeatYa Freitag, 16. März 2018 11:01
-
Der ForEach baut keine eigene Liste auf, sondern verwendet eben die vorhandene Liste mit einem eigenen internen Zeiger.
Er ist halt nur einfacher zu programmieren, als ein
FOR($i = 0 ; $i -lt $mcount; $i++)
Wenn du hier den Index N dann löscht, verschieben sich alle folgenden Einträge und wenn $mcount nicht neu gesetzt wird, kommt es sogar zu einem Zugriffsfehler.
Man kann u.U. Glück haben, wenn man in der Schleife nach dem Entfernen, $i-- angibt, so dass beim Fortsetzen der Schleife mit $i++ nun der nachgerückte Eintrag (mit dem selben Index) bearbeitet wird.
Allerdings könnte die interne Optimierung $i anders behandeln, so dass $i-- wirkungslos bleibt.
In z.B. C#/C++ ist das durchaus der Fall.Wofür du allerdings das 5-fache Löschen noch brauchst, entzieht sich mir.
Vielleicht hat ja $MailBox eine Remove/Delete-Methode für das Element.
-
Der ForEach baut keine eigene Liste auf, sondern verwendet eben die vorhandene Liste mit einem eigenen internen Zeiger.
Er ist halt nur einfacher zu programmieren, als ein
FOR($i = 0 ; $i -lt $mcount; $i++)
Wenn du hier den Index N dann löscht, verschieben sich alle folgenden Einträge und wenn $mcount nicht neu gesetzt wird, kommt es sogar zu einem Zugriffsfehler.
Man kann u.U. Glück haben, wenn man in der Schleife nach dem Entfernen, $i-- angibt, so dass beim Fortsetzen der Schleife mit $i++ nun der nachgerückte Eintrag (mit dem selben Index) bearbeitet wird.
Allerdings könnte die interne Optimierung $i anders behandeln, so dass $i-- wirkungslos bleibt.
In z.B. C#/C++ ist das durchaus der Fall.Wofür du allerdings das 5-fache Löschen noch brauchst, entzieht sich mir.
Vielleicht hat ja $MailBox eine Remove/Delete-Methode für das Element.
Das 5-fache Löschen ist rausgeflogen, das hatte ich leider übersehen. Musste gleich mehrere Scripts umändern und das Foreach entziehen. Die anderen Scripts laufen fehlerfrei und nun auch rasend schnell durch. Das eine Script was ich hier als Beispiel angeführt habe ist auch das einzige nach Bearbeitung fehlerbehaftete Script gewesen .....^^
Ich such mir Montag mal irgendeine passende Antwort als Antwort raus ;)
- Bearbeitet BeatYa Freitag, 16. März 2018 13:29