none
Alle Kategorien eines Postfachs per Powershell löschen RRS feed

  • Frage

  • Hallo zusammen,

    ich habe ein Script, womit ich die Kategorien einer Exchange Mailbox mittels CSV importieren und exportieren kann.
    Nun möchte ich die Geschichte jedoch vollautomatisiert laufen lassen und die Importliste täglich erstellen, wodurch die Kategorien täglich aktuelle Userdaten aufweisen.
    Das Ganze funktioniert soweit auch ganz gut, nur fehlt mir leider das Vorgehen, um alle bestehenden Kategorien zu löschen.
    Habe schon etwas herumprobiert und gesucht, jedoch komme ich nicht weiter.

    Ich wäre für jeden zielführenden Hinweis dankbar.

    Hier noch das Script:

    <# 
    .SYNOPSIS 
        Imports/exports choosen Outlook categories from/to text file. 
     
    .DESCRIPTION 
        Imports/exports choosen Outlook categories (Name, Color, ShortcutKey) from/to text file. 
        If category already exists on destination, it updates Name (upper/lower case), Color and ShortcutKey. 
         
        Minimum Requirements 
        --------------------------------------------------------------------- 
        PowerShell 2.0 
        Microsoft Outlook 2007 
         
        Revision History 
        --------------------------------------------------------------------- 
        1.1 Community release 
        1.2 Get-Culture cmdlet to retrieve list separator 
        1.3 Fixed CreateItem method for TaskItem object (olTaskItem) 
     
        Author: Luca Fabbri 
        E-mail: luca[dot]fabbri[at]outlook.com 
         
    .PARAMETER Import 
        <$true | $false>. Optional. $false argument is default (export). 
     
    .PARAMETER Filename 
        Required. Specify full import/export file name path. 
     
    .EXAMPLE 
        ImportExport-OutlookCategories.ps1 -Filename C:\TEMP\MyCategories.txt 
        Export Outlook categories. 
         
        Note: Outlook shows categories window where to select Categories to export. 
     
    .EXAMPLE 
        ImportExport-OutlookCategories.ps1 -Import $true -Filename C:\TEMP\MyCategories.txt 
        Import Outlook categories. 
     
    .LINK 
        https://gallery.technet.microsoft.com/office/Outlook-Categories-759d4add#content 
     
    #> 
     
    [CmdletBinding()] 
    Param( 
        [Parameter(Mandatory=$false,Position=1)] 
        [bool]$Import = $false, 
         
        [Parameter(Mandatory=$true,Position=2)] 
        [string]$Filename 
    ) 
     
    # Prepare output collection 
    $return = @()  
    $mailboxname = "Testmailbox"
    $outlook = New-Object -ComObject Outlook.Application 
    $namespace = $outlook.GetNamespace("MAPI") 
    $mailbox = $namespace.Stores["$mailboxname"]
    $categories = $mailbox | select -ExpandProperty Categories
    #$categories
    $listSeparator = (Get-Culture).TextInfo.ListSeparator 
     
    #Import Categories 
    If ($Import) { 
        If (Test-Path $Filename -PathType Leaf){ 
             
            $InputCategories = Import-Csv -Path $Filename -Delimiter $listSeparator 
            If ($InputCategories) { 
                ForEach ($InputCategory in $InputCategories) { 
                    #Check differences between Outlook Categories and those to be imported 
                    $diffs = @(Compare-Object -ReferenceObject ($categories | %{$_.Name}) -DifferenceObject $InputCategory.Name -IncludeEqual) 
                     
                    ForEach ($dif in $diffs) { 
                        Switch ($dif.SideIndicator) 
                        {  
                            #Import Outlook Category 
                            "=>" { 
                                $categories.Add($InputCategory.Name, $InputCategory.Color, $InputCategory.ShortCutKey) | Out-Null 
                                Write-Host "Category '$($InputCategory.Name)' was imported." 
                            } 
                             
                            #Update Outlook Category 
                            "==" { 
                                $Category = $categories.Item($dif.InputObject) 
                                If ($Category.Name -cne $InputCategory.Name) { 
                                    $Category.Name = "$($InputCategory.Name)-$(Get-Random)" 
                                    $Category.Name = $InputCategory.Name 
                                    $message = "Category '$($dif.InputObject)' was updated." 
                                } Else { 
                                    $message = "Category '$($InputCategory.Name)' already exists. Color and Shortcut were updated." 
                                } 
                                $Category.Color = $InputCategory.Color 
                                $Category.ShortcutKey = $InputCategory.ShortcutKey 
                                Write-Host $message 
                            } 
                        } 
                    } 
                } 
                Write-Host "Import completed." 
            } Else { 
                Write-Host "No Categories were imported. Input file was empty." 
            } 
        } Else { 
            Write-Host "Wrong input file was specified." 
        } 
    } Else { 
        #Export Categories 
        If (Test-Path(Split-Path $Filename -Parent)) { 
     
            $Task = $outlook.CreateItem("olTaskItem") 
            #Show Outlook Categories to be exported 
            $Task.ShowCategoriesDialog() 
             
            If ($Task.Categories) { 
                $TaskCategories = $Task.Categories -Split "$listSeparator\s" 
                ForEach ($TaskCategory in $TaskCategories) { 
                    $obj = "" | Select-Object Name, Color, ShortcutKey 
                    $obj.Name = $categories.Item($TaskCategory).Name 
                    $obj.Color = [int]$categories.Item($TaskCategory).Color 
                    $obj.ShortcutKey = [int]$categories.Item($TaskCategory).ShortcutKey 
                    $return += $obj 
                } 
                $return | Export-Csv -Path $Filename -Delimiter $listSeparator -Force -noTypeInformation -Encoding UTF8 
                 
                Write-Host "Selected Categories were exported to '$($Filename)' file." 
            } Else { 
                Write-Host "No Categories selected. No Categories were exported." 
            } 
        } Else { 
            Write-Host "Wrong export file was specified." 
        } 
    }

    Dienstag, 20. Februar 2018 12:33

Antworten

  • Eine Möglichkeit wäre, ein neues $categories Array (z.B. $categoriesToSet) zu erstellen und lediglich die Elemente, die neu hinzugefügt und aktualisert wurden, hinzuzufügen.

    Im weiteren bzw. unteren Teil des Scripts müsste dann allerdings $categories durch $categoriesToSet ersetzt werden.

    Mittwoch, 21. Februar 2018 12:49

Alle Antworten

  • Hi,

    Dazu müsstest Du wohl den Switch/Case des Objektvergleichs wie folgt erweitern:

    ForEach ($dif in $diffs) { 
        Switch ($dif.SideIndicator) 
        {  
            #Import Outlook Category 
            "=>" { 
                # Import code...
            } 
                             
            #Update Outlook Category 
            "==" { 
                # Update code...
            } 
    
            #Remove Outlook Category 
            "<=" { 
                $categories.Remove($InputCategory.Name) | Out-Null 
                Write-Host "Category '$($InputCategory.Name)' was removed." 
            } 
        } 
    }

    Klappt das so?

    Mittwoch, 21. Februar 2018 09:59
  • Das hatte ich bereits probiert.
    Auch mit leeren Klammern, ohne Klammern, mit allen drei Werten in Klammern .... es kommt im aufgezeigten Fall zu folgendem Fehler:

    Das Element steht in der Sammlung nicht zur Verfügung. Es wurde möglicherweise gelöscht.
    At %HIER STEHT DER PFAD%.ps1:102 char:25
    + ...                    $categories.Remove($InputCategory.Name) | Out-Null
    +                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : OperationStopped: (:) [], COMException
        + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException

    Mit Einbau im Switch hätte es aber eh nicht funktioniert, da der Switch ja dafür herhalten soll zu sehen, ob es neu angelegt werden muss oder nicht. Bei jedem Durchlauf würde mit drittem Side Indicator jeder gesetzte Eintrag wieder gelöscht werden von der Ablauflogik her. (Jeder Name wird ^x mit diesem dritten "<=" Side Indicator durchlaufen)

    Ich würde aber auch gerne einfach am Anfang alle außer einer fest definierten Kategorie löschen, die so heißt wie das Postfach, da es mir scheint, dass Kategorien per Shell erst verfügbar sind, sobald zumindest eine Kategorie vorhanden ist.



    • Bearbeitet BeatYa Mittwoch, 21. Februar 2018 12:53
    Mittwoch, 21. Februar 2018 12:42
  • Eine Möglichkeit wäre, ein neues $categories Array (z.B. $categoriesToSet) zu erstellen und lediglich die Elemente, die neu hinzugefügt und aktualisert wurden, hinzuzufügen.

    Im weiteren bzw. unteren Teil des Scripts müsste dann allerdings $categories durch $categoriesToSet ersetzt werden.

    Mittwoch, 21. Februar 2018 12:49
  • Danke für den Denkanstoß. Habe mich gestern irgendwie nur im Kreis gedreht.
    Funktioniert nun wie es soll .... habe gestern immer nur versucht das Entfernen über die Variablen Vorzunehmen. Als ich gerade einen String einfach entfernen konnte kam dann der entscheidende Funke ... :)
    Mittwoch, 21. Februar 2018 13:48
  • Hallo BeatYa

    darf ich über den Hintergrund der Aktion nachfragen? Seit Exchange 2010 werden Kategorien direkt im Postfach gespeichert. Daher denke ich wäre der manuell Aufwand geringer als ein Script zu schreiben.


    Chris

    Mittwoch, 21. Februar 2018 18:57
  • Hi Chris,

    im Unternehmen wurde nun der Umgang mit bestimmten Gruppenpostfächern eingeführt, auf welchem jeder Nutzer der Abteilung mit Druck auf einen Knopf, der mit einem Makro hinterlegt ist, seinen Namen als Kategorie setzen können.
    Ist der Name nun nicht als Kategorie hinterlegt wird das VBScript in der Form ausgeführt, dass der Name ohne Farbe als nicht gespeicherte Kategorie gesetzt wird.
    Es ist jedoch gewünscht eine Farbe zu hinterlegen mit richtigem Namen. Da es eine relative Fluktuation in der Abteilung gibt müssen oftmals neue Namen für die Kategorien angelegt werden.

    Ich lasse somit nun jeden Morgen die Kategorien bis auf den Namen des Postfaches (als defaultwert) löschen, lese alle User der Abteilung automatisiert aus dem AD aus, erstelle daraus eine CSV Datei und lasse die Kategorie im nächsten Schritt jeden Morgen mit allen aktiven Usern der Abteilung neu erstellen.
    So gibt es zukünftig keinen Pflegebedarf der Kategorien und es läuft alles schön automatisiert ab.

    Ein Schritt um Kategorien automatisch anhand von AD-Werten zu definieren war mir leider nicht bekannt.

    Script zum User auslesen:

    #Auslesen der betroffenen User aus dem AD
    $user = get-aduser -filter * -Properties * -SearchBase "DistinguishedName" | ? {$_.surname -notlike "" -and $_.givenname -notlike "" -and ($_.physicalDeliveryOfficeName -like "Wert" -or $_.physicalDeliveryOfficeName -like "Wert")} | sort surname | select surname, givenname
    #Zuweisen von Vor- und Zunamen
    $surname = $user.surname
    $givenname = $user.givenname
    #Setzen der drei Farben
    $color = "Blue", "Green", "Yellow"
    foreach ($col in $color){
    switch($col){
    {$_ -eq "Blue"}{$global:farbe = "8" ; $global:line = "_Name_Postfach1"}
    {$_ -eq "Green"}{$global:farbe = "5" ; $global:line = "_Name_Postfach2"}
    {$_ -eq "Yellow"}{$global:farbe = "4" ; $global:line = "_Name_Postfach3"}
    }
    $filename = "%Pfad%"+$col+".txt"
    #Entfernen der alten Userliste:
    rm $Filename -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
    #Setzen des CSV-Headers
    $firstline = '"Name";"Color";"ShortcutKey"'
    $secondline = '"'+$line+'"'+';'+'"'+$farbe+'"'+';'+'"0"'
    #Schreiben des Headers in die .txt
    $firstline > $filename
    $secondline >> $filename
    #Schreiben der Benutzer in die .txt
    for($i=0; $i -lt $user.count; $i++){
    $catuser = '"'+$surname[$i]+"-"+$givenname[$i]+'"'+';'+'"'+$farbe+'"'+';'+'"0"'
    $catuser >> $filename
    }
    }

    Script für Kategorien:

    <# 
    .SYNOPSIS 
        Imports/exports choosen Outlook categories from/to text file. 
     
    .DESCRIPTION 
        Imports/exports choosen Outlook categories (Name, Color, ShortcutKey) from/to text file. 
        If category already exists on destination, it updates Name (upper/lower case), Color and ShortcutKey. 
         
        Minimum Requirements 
        --------------------------------------------------------------------- 
        PowerShell 2.0 
        Microsoft Outlook 2007 
         
        Revision History 
        --------------------------------------------------------------------- 
        1.1 Community release 
        1.2 Get-Culture cmdlet to retrieve list separator 
        1.3 Fixed CreateItem method for TaskItem object (olTaskItem) 
     
        Author: Luca Fabbri 
        E-mail: luca[dot]fabbri[at]outlook.com 
         
    .PARAMETER Import 
        <$true | $false>. Optional. $false argument is default (export). 
     
    .PARAMETER Filename 
        Required. Specify full import/export file name path. 
     
    .EXAMPLE 
        ImportExport-OutlookCategories.ps1 -Filename C:\TEMP\MyCategories.txt 
        Export Outlook categories. 
         
        Note: Outlook shows categories window where to select Categories to export. 
     
    .EXAMPLE 
        ImportExport-OutlookCategories.ps1 -Import $true -Filename C:\TEMP\MyCategories.txt 
        Import Outlook categories. 
     
    .LINK 
        https://gallery.technet.microsoft.com/office/Outlook-Categories-759d4add#content 
     
    #> 
     
    [CmdletBinding()] 
    Param( 
        [Parameter(Mandatory=$false,Position=1)] 
        [bool]$Import = $true 
         
        #[Parameter(Mandatory=$false,Position=2)] 
        #[string]$Filename = "%Pfad%\Userliste.txt"
    ) 
    # Prepare output collection 
    $date = Get-Date
    $logfile = "%Pfad%\Categories.log"
    $return = @()  
    $mailboxname = "Postfach 1", "Postfach 2", "Postfach 3"
    foreach($mailboxname1 in $mailboxname){
    switch($mailboxname1){
    {$_ -eq "Postfach 1"}{$global:filename = "%Pfad%\BLUE.txt"}
    {$_ -eq "Postfach 2"}{$global:filename = "%Pfad%\GREEN.txt"}
    {$_ -eq "Postfach 3"}{$global:filename = "%Pfad%\YELLOW.txt"}
    }
    $outlook = New-Object -ComObject Outlook.Application 
    $namespace = $outlook.GetNamespace("MAPI") 
    $mailbox = $namespace.Stores["$mailboxname1"]
    $categories = $mailbox | select -ExpandProperty Categories
    $categorienames = $categories | select -ExpandProperty name
    $CSVnames = Import-Csv $Filename -Delimiter ";"
    $CSVnames2 = $CSVnames.Name
    $Comparison = Compare-Object $categorienames $CSVnames2
    $Comparison = $Comparison | ? {$_.SideIndicator -like "<="} | select -ExpandProperty InputObject
    $Comparison
    foreach($deletion in $Comparison){
    if($deletion -match "$mailboxname"){
    }
    ELSE{
    $categories.Remove($deletion)
    #Write-Host 
    "Date: $date Category $deletion was not seen in userlist and got deleted" >> $logfile
    }
    }
    $listSeparator = (Get-Culture).TextInfo.ListSeparator 
     
    #Import Categories 
    If ($Import) { 
        If (Test-Path $Filename -PathType Leaf){ 
             
            $InputCategories = Import-Csv -Path $Filename -Delimiter $listSeparator 
            If ($InputCategories) { 
                ForEach ($InputCategory in $InputCategories) { 
                    #Check differences between Outlook Categories and those to be imported 
                    $diffs = @(Compare-Object -ReferenceObject ($categories | %{$_.Name}) -DifferenceObject $InputCategory.Name -IncludeEqual) 
                     
                    ForEach ($dif in $diffs) { 
                        Switch ($dif.SideIndicator) 
                        {  
                            #Import Outlook Category 
                            "=>" { 
                                $categories.Add($InputCategory.Name, $InputCategory.Color, $InputCategory.ShortCutKey) | Out-Null 
                                #Write-Host 
                                "Date: $date Category '$($InputCategory.Name)' was imported."  >> $logfile
                            } 
                             
                            #Update Outlook Category 
                            "==" { 
                                $Category = $categories.Item($dif.InputObject) 
                                If ($Category.Name -cne $InputCategory.Name) { 
                                    $Category.Name = "$($InputCategory.Name)-$(Get-Random)" 
                                    $Category.Name = $InputCategory.Name 
                                    $message = "Date: $date Category '$($dif.InputObject)' was updated." 
                                } Else { 
                                    $message = "Date: $date Category '$($InputCategory.Name)' already exists. Color and Shortcut were updated." 
                                } 
                                $Category.Color = $InputCategory.Color 
                                $Category.ShortcutKey = $InputCategory.ShortcutKey 
                                #Write-Host 
                                $message  >> $logfile
                            } 
                        } 
                    } 
                } 
                #Write-Host 
                "Import completed." >> $logfile
            } Else { 
                #Write-Host 
                  "No Categories were imported. Input file was empty."   >> $logfile
            } 
        } Else { 
            #Write-Host 
            "Wrong input file was specified." >> $logfile
        } 
    } Else { 
        #Export Categories 
        If (Test-Path(Split-Path $Filename -Parent)) { 
     
            $Task = $outlook.CreateItem("olTaskItem") 
            #Show Outlook Categories to be exported 
            $Task.ShowCategoriesDialog() 
             
            If ($Task.Categories) { 
                $TaskCategories = $Task.Categories -Split "$listSeparator\s" 
                ForEach ($TaskCategory in $TaskCategories) { 
                    $obj = "" | Select-Object Name, Color, ShortcutKey 
                    $obj.Name = $categories.Item($TaskCategory).Name 
                    $obj.Color = [int]$categories.Item($TaskCategory).Color 
                    $obj.ShortcutKey = [int]$categories.Item($TaskCategory).ShortcutKey 
                    $return += $obj 
                } 
                $return | Export-Csv -Path $Filename -Delimiter $listSeparator -Force -noTypeInformation -Encoding UTF8 
                 
                Write-Host "Selected Categories were exported to '$($Filename)' file." 
            } Else { 
                Write-Host "No Categories selected. No Categories were exported." 
            } 
        } Else { 
            Write-Host "Wrong export file was specified." 
        } 
    }
    }

    Ich weiß ... die Scripte könnten weitaus schöner aussehen, aber sie erfüllen Ihren Zweck.
    Das Kategorien-Script kam ursprünglich aus dem Technet und ich habe es ein wenig nach Bedarf angepasst.


    Und ja es ist viel Aufwand für so ne Kleinigkeit, aber nun ist es automatisiert, also bleibt mehr Zeit zum Kaffee trinken!

    • Bearbeitet BeatYa Donnerstag, 22. Februar 2018 09:53
    Donnerstag, 22. Februar 2018 09:37
  • Hallo BeatYa

    bei uns geht das ohne Makro und ohne Script.

    wir nutzen ein gemeinsames Helpdesk Postfach. Jeder der ein Mail übernimmt vergibt über die Outlook GUI seine Kategorie. Wenn ein User Vollzugriff auf das Postfach hat werden alle Kategoriennamen und Farben bei allen User - die das shared Postfach haben -  angezeigt. D.h. man muss die Namen und Farben nur 1x eintragen (ohne Marko und ohne Script). Der Rest ist organisatorisch.

    Der Trick ist der Vollzugriff am Shared Postfach!


    Chris

    Donnerstag, 22. Februar 2018 11:19
  • Dann dürfen bei euch alle alles am Postfach machen wenn ich das richtig verstehe.
    Und es ist dann bei euch so, dass sich jeder seine eigene Kategorie anlegen darf?

    Das heißt wenn ich deine Kategorie löschen will darf ich das machen?

    Wie funktioniert das bei Postfächern, die über eine Gruppe freigegeben werden?

    Wie ist es mit scheidenden Mitarbeitern, geht die Kategorie dann auch verloren?

    Wie ist es, wenn es nur eine Farbe für das gesamte Postfach geben soll und das auch vorgabe vom Chef ist, macht das euer Postfach dann auch von selbst?

    • Bearbeitet BeatYa Donnerstag, 22. Februar 2018 15:36
    Donnerstag, 22. Februar 2018 15:32
  • theoretisch  ja, klingt aber schlimmer als es ist. Bisher gab es NOCH NIE ein Problem deswegen. Und wer legt schon jeden Tag freiwillig irgendwelche Kategorien an. Ich habe einmal die Kategorien angelegt und 1-2 Mal erweitert. Da stellte sich die Frage nicht dass jeder Kategorieren ändert? Wie ich schon geschrieben habe, der Rest ist organisatorisch.

    ich würde es einfach einmal probieren. Passiert ja nichts schlimmes. Fällt auch gleich auf wenn ein Kategorie fehlen würde.

    Gruppen. müsste ich morgen nachsehen. Sollte kein Unterschied sein. Es geht ja nur darum das die User alle Properties der shared Mailbox auslesen dürfen.

    scheidende Mitarbeiter: da die Farben und Kategorien in der shared Mailbox gespeichert sind und nicht wie früher bei jedem User in der Registry hat es keine Auswirkung wenn jemand ausscheidet. 

    Farbvorgabe vom Chef: Da die Farben zentral im shared Postfach gespeichert sind, kann man dort auch zentral eine Farbe vorgeben!

    einfach mal testen

    LG, Ch

     

    Chris

    Donnerstag, 22. Februar 2018 16:59
  • Naja da brauche ich nichts testen.
    So wie es jetzt umgesetzt ist bedeutet, dass die Vorgaben erfüllt sind.
    Das genannte vorgehen bedeutet, dass es manuell justiert werden muss und das war explizit NICHT gewünscht. Darauf zielten meine Fragen aber auch nicht ab.
    Die Antwort galt einer anderen Konstellation.

    Soll aber ja auch egal sein, da es nun umgesetzt ist und läuft.

    Nochmal herzlichsten Dank an TobyU für den Denkanstoß!

    Freitag, 23. Februar 2018 07:11