derwowusste
Goto Top

Outlook Anhänge per Script löschen

Moin Kollegen.

Kennt jemand eine Möglichkeit, per Skript eine PST von Ihren Anhängen zu befreien?

Die Anhänge liegen ausschließlich im Bereich Kalender, falls das die Sache einfacher macht.
Bislang nutze ich ein Makro, das beim Start von Outlook automatisch startet:
Private Sub Application_Startup()

     Dim objOutlookFile As Outlook.Folder
    Dim objFolder As Outlook.Folder
 
    'Change to your own Outlook file  
    Set objOutlookFile = Outlook.Application.Session.Folders("Name der PST")  
 
    For Each objFolder In objOutlookFile.Folders
        If objFolder.DefaultItemType = olAppointmentItem Then
           Call LoopCalendars(objFolder)
        End If
    Next
End Sub

Sub LoopCalendars(ByVal objCalendar As Outlook.Folder)
    Dim i, n As Long
    Dim objCalendarItem As Outlook.AppointmentItem
    Dim nDateDiff As Integer
    Dim objAttachments As Outlook.Attachments
    Dim objSubCalendar As Outlook.Folder
 
    For i = objCalendar.Items.Count To 1 Step -1
        Set objCalendarItem = objCalendar.Items(i)
 
        Set objAttachments = objCalendarItem.Attachments
           If objAttachments.Count > 0 Then
              For n = objAttachments.Count To 1 Step -1
                  objAttachments(n).Delete
              Next
           End If
           objCalendarItem.Save
        'End If  
    Next

    'Process all subfolders recursively  
    If objCalendar.Folders.Count > 0 Then
       For Each objSubCalendar In objCalendar.Folders
           Call LoopCalendars(objSubCalendar)
       Next
    End If
End Sub
Das funktioniert zwar, ist aber unschön für den weiteren Ablauf meines Skriptes.

Content-ID: 581219

Url: https://administrator.de/contentid/581219

Ausgedruckt am: 18.11.2024 um 07:11 Uhr

jrglndmnn
jrglndmnn 22.06.2020 um 15:18:35 Uhr
Goto Top
Hallo,

wieso ist das so unschön? weil es bei jedem start abgefahren wird?

Beste Grüße
Jörg
DerWoWusste
DerWoWusste 22.06.2020 um 15:31:18 Uhr
Goto Top
Hi.

Ja, vor allem deswegen.
jrglndmnn
jrglndmnn 22.06.2020 aktualisiert um 15:47:09 Uhr
Goto Top
Du könntets einen eigenen Button erstellen und diesen mit dem .vba (eingebunden als Makro) verknüpfen. Damit wäre das ganze dann Ereignisgesteuert.

Datei >> Optionen >> Menüband anpasen //
Neue Registerkarte

dann den Befehl i. d. Liste auswählen (hier Makros) und die Prozedur auswählen
beidermachtvongreyscull
beidermachtvongreyscull 22.06.2020 um 16:51:54 Uhr
Goto Top
Unter DWWs Code steht

Das funktioniert zwar, ist aber unschön für den weiteren Ablauf meines Skriptes.

Ich nehme an, dass da also noch mehr folgt und es weniger um ein vom Benutzer getriggertes Event geht, sondern um eine andere Möglichkeit,
den Bereinigungsprozess als prüfbare Subroutine aus einem Scriptablauf zu starten.

So weiß man, dass Outlook sich öffnet, aber von außen ist nicht oder nur schwierig prüfbar, ob Outlook mit der Arbeit durch ist, oder nicht.
Es sei denn, DWWs VBA-Code legt vorher im Dateisystem eine "Kontrolldatei" an, die das externe Script prüft und dann solange wartet, bis die VBA-Routine diese Datei wieder entfernt.

Dann noch einen kleinen Sleep-Timer dazu und von extern ließe sich Outlook dann hart schließen.

Bißchen MacGyverismus.

Gruß
bdmvg
DerWoWusste
DerWoWusste 22.06.2020 um 17:08:48 Uhr
Goto Top
So weiß man, dass Outlook sich öffnet, aber von außen ist nicht oder nur schwierig prüfbar, ob Outlook mit der Arbeit durch ist, oder nicht
So ist es.

Hast Du eine Idee, wie man ohne Hilfsdateien und Prüfschleifen auskommen könnte?
colinardo
Lösung colinardo 22.06.2020 aktualisiert um 19:07:18 Uhr
Goto Top
Servus zusammen.
Hier mal Schnellschuss mit Powershell (VBA war mir jetzt zu viel geschreibsel, time is money face-smile)
# pstfile
$pstfile = 'E:\Teststore.pst'  

if (!(Test-Path $pstfile)){
    write-error -Message "File does not exist!" -Category InvalidArgument  
    return
}

# load outlook
[void][reflection.assembly]::LoadWithPartialName("microsoft.visualbasic")  
$objOL = [microsoft.visualbasic.interaction]::GetObject($null,"Outlook.Application")  
if (!$objOL){$objOL = New-Object -Com Outlook.Application}

# recursive function
function Remove-Attachments($folder){
    $folder.Items | ?{$_.Attachments.Count -gt 0} | %{
        while($_.Attachments.Count -gt 0){
            write-host "Removing attachment with filename '$($_.Attachments[1].Filename)' from appointment with subject '$($_.Subject)'." -F Green  
            $_.Attachments[1].Delete()
        }
        $_.Save()
    }
    $folder.Folders | %{Remove-Attachments $_}
}

# add store to session
$objOL.Session.AddStore($pstfile)
$objOL.Session.Stores | ?{$_.FilePath -eq $pstfile} | %{
    # remove attachments starting in root folder
    Remove-Attachments -folder $_.GetRootFolder()
    # unload store
    $objOL.Session.RemoveStore($_.GetRootFolder())
}
write-host "Done." -F Cyan  
Grüße Uwe
DerWoWusste
DerWoWusste 22.06.2020 aktualisiert um 19:58:25 Uhr
Goto Top
Sehr cool. Das versuche mal einer zu ergooglen. Scheint entweder keiner zu wissen, oder keiner zu brauchen. Teste ich morgen, danke!
beidermachtvongreyscull
beidermachtvongreyscull 22.06.2020 um 20:53:43 Uhr
Goto Top
Zitat von @DerWoWusste:

So weiß man, dass Outlook sich öffnet, aber von außen ist nicht oder nur schwierig prüfbar, ob Outlook mit der Arbeit durch ist, oder nicht
So ist es.

Hast Du eine Idee, wie man ohne Hilfsdateien und Prüfschleifen auskommen könnte?

Nein. Tut mir leid.
Ich hätte mich wahrscheinlich an einem Addin versucht, um die Programmierungseinschränkungen in Outlook zu umgehen, aber Uwes Ansatz sieht wirklich cool aus.
DerWoWusste
DerWoWusste 23.06.2020 um 08:54:29 Uhr
Goto Top
Läuft hervorragend.
Das ist doch weitaus besser als vorher!

Vielen Dank!
colinardo
colinardo 23.06.2020 um 08:57:10 Uhr
Goto Top
👍
DerWoWusste
DerWoWusste 27.08.2020 um 13:06:48 Uhr
Goto Top
Servus Uwe.

Ich könnte noch mal einen Schuss geballte Kompetenz gebrauchen.
Das Skript lief bislang gut - nun kommen aber (verständlicherweise) solche Meldungen bei signierten Nachrichten, die den Skriptablauf aufhalten:
capture
Gibst da ein "silently continue?"?

Grüße
DWW
colinardo
colinardo 27.08.2020 aktualisiert um 18:14:12 Uhr
Goto Top
Zitat von @DerWoWusste:
Gibst da ein "silently continue?"?
Out of the box, nicht das ich wüsste das es in Outook einen Schalter wie in Excel gäbe (DisplayAlerts = false). Müsste man sich via Win32 ein Fenster-Monitor zusätzlich mit einbauen der solche Dialoge von selbst bestätigt(klickt). Oder einfacher (aber) unsicherer ein SendKeys nach Prüfung auf vorhandene Signatur.

Mal schnell was zusammen geschrotet was die Dialoge automatisch bestätigen sollte, natürlich nicht schön aber probiers mal.
(Nur getestet unter einem Outlook 2019 ( Office Professional Plus Volume) auf W10 2004)
# pstfile
$pstfile = 'E:\Teststore.pst'  

if (!(Test-Path $pstfile)){
    write-error -Message "File does not exist!" -Category InvalidArgument  
    return
}

# load outlook
[void][reflection.assembly]::LoadWithPartialName("microsoft.visualbasic")  
$objOL = [microsoft.visualbasic.interaction]::GetObject($null,"Outlook.Application")  
if (!$objOL){$objOL = New-Object -Com Outlook.Application}

# recursive function
function Remove-Attachments($folder){
    $folder.Items | ?{$_.Attachments.Count -gt 0} | %{
        while($_.Attachments.Count -gt 0){
            write-host "Removing attachment with filename '$($_.Attachments[1].Filename)' from appointment with subject '$($_.Subject)'." -F Green  
            $_.Attachments[1].Delete()
        }
        # signed message / register bg job to accept dialog box
        if ($_.MessageClass -eq 'IPM.Note.SMIME.MultipartSigned'){  
            $bgjob = [Powershell]::Create().AddScript({
                Add-Type –MemberDefinition '  
                    [DllImport("user32.dll")] public static extern bool SetForegroundWindow (IntPtr hWnd);  
                    [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);  
                ' -name "tools" -namespace Win32 -EA SilentlyContinue | out-null  
                $shell = New-Object -Com WScript.Shell
                $w = 0
                while($w -eq 0){
                    $w = [Win32.tools]::FindWindow('#32770','Microsoft Outlook')  
                    sleep -Milliseconds 50
                }
                [Win32.tools]::SetForegroundWindow($w)
                sleep -Milliseconds 50
                $shell.SendKeys('{ENTER}')  
            })
            $handle = $bgjob.BeginInvoke()
        }
        $_.Save()
        # cleanup bg job
        if ($bgjob){
            $bgjob.Dispose()
            $bgjob = $null
        }
    }
    $folder.Folders | %{Remove-Attachments $_}
}

# add store to session
$objOL.Session.AddStore($pstfile)
$objOL.Session.Stores | ?{$_.FilePath -eq $pstfile} | %{
    # remove attachments starting in root folder
    Remove-Attachments -folder $_.GetRootFolder()
    # unload store
    $objOL.Session.RemoveStore($_.GetRootFolder())
}
write-host "Done." -F Cyan  
DerWoWusste
DerWoWusste 27.08.2020 um 18:07:41 Uhr
Goto Top
Hallo Uwe,

Ich hab's damit probiert, es ändert sich nichts. Allerdings fiel mir dabei auf, dass diese Termine gar keine Termine sind (wer signiert auch seine Termine?), sondern normale Mails. Was die nun überhaupt in der PST verloren haben (ich hatte nur einen Export des Kalenders veranlasst), bleibt zu klären. Somit steht das Troubleshooting wieder hinten an.

Auf jeden Fall Danke für die Mühe!
DWW
DerWoWusste
DerWoWusste 28.08.2020 aktualisiert um 09:01:59 Uhr
Goto Top
So, ich habe aufgeklärt, was diese Nachrichten mit Signatur im Kalender zu suchen haben...
Benutzt man beim Export am Exchangeserver NICHT den Parameter -ExcludeDumpster, dann werden "recoverable items" mit exportiert und das sind mitnichten nur gelöschte Termine, sondern auch gelöschte Mails (was ein Unsinn, da ja beim Export angegeben wurde, nur den Kalender zu exportieren).

Hat sich also erledigt, -ExcludeDumpster wird nun benutzt.
colinardo
colinardo 28.08.2020 aktualisiert um 09:15:09 Uhr
Goto Top
OK. Du könntest alternativ auch die MessageClass bzw. Class der Elemente auswerten und so nur AppointmentItems in die Löschvorgänge aufnehmen wenn man wollte das wäre kein Problem, im Moment verarbeitet der Code ja sämtliche Kategorien von Items.
DerWoWusste
DerWoWusste 28.08.2020 um 10:22:50 Uhr
Goto Top
Danke für den Tipp!