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-Key: 581219

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

Printed on: April 25, 2024 at 00:04 o'clock

Member: jrglndmnn
jrglndmnn Jun 22, 2020 at 13:18:35 (UTC)
Goto Top
Hallo,

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

Beste Grüße
Jörg
Member: DerWoWusste
DerWoWusste Jun 22, 2020 at 13:31:18 (UTC)
Goto Top
Hi.

Ja, vor allem deswegen.
Member: jrglndmnn
jrglndmnn Jun 22, 2020 updated at 13:47:09 (UTC)
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
Member: beidermachtvongreyscull
beidermachtvongreyscull Jun 22, 2020 at 14:51:54 (UTC)
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
Member: DerWoWusste
DerWoWusste Jun 22, 2020 at 15:08:48 (UTC)
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?
Member: colinardo
Solution colinardo Jun 22, 2020 updated at 17:07:18 (UTC)
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
Member: DerWoWusste
DerWoWusste Jun 22, 2020 updated at 17:58:25 (UTC)
Goto Top
Sehr cool. Das versuche mal einer zu ergooglen. Scheint entweder keiner zu wissen, oder keiner zu brauchen. Teste ich morgen, danke!
Member: beidermachtvongreyscull
beidermachtvongreyscull Jun 22, 2020 at 18:53:43 (UTC)
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.
Member: DerWoWusste
DerWoWusste Jun 23, 2020 at 06:54:29 (UTC)
Goto Top
Läuft hervorragend.
Das ist doch weitaus besser als vorher!

Vielen Dank!
Member: colinardo
colinardo Jun 23, 2020 at 06:57:10 (UTC)
Goto Top
👍
Member: DerWoWusste
DerWoWusste Aug 27, 2020 at 11:06:48 (UTC)
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
Member: colinardo
colinardo Aug 27, 2020 updated at 16:14:12 (UTC)
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  
Member: DerWoWusste
DerWoWusste Aug 27, 2020 at 16:07:41 (UTC)
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
Member: DerWoWusste
DerWoWusste Aug 28, 2020 updated at 07:01:59 (UTC)
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.
Member: colinardo
colinardo Aug 28, 2020 updated at 07:15:09 (UTC)
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.
Member: DerWoWusste
DerWoWusste Aug 28, 2020 at 08:22:50 (UTC)
Goto Top
Danke für den Tipp!