vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Erstellen von dynamischen Kontextmen?s - wann immer Sie sie brauchen!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Ein- und Umsteiger
Outlook Mailitem schließen funktioniert nicht 
Autor: Volker Bunge
Datum: 05.12.18 07:56

Hallo zusammen,

ich will aus hunderten abgelegten Outlook 2007 Mails (MSG Dateien das Datum/Zeit und den Absender ermitteln (funktioniert soweit auch).

Anschließend soll die Datei das Erstellungsdatum der Mail bekommen und nicht wie jetzt das aktuelle Datum von gestern (da habe ich die Mails in Ordner abgelegt.

Hier mal mein bisheriger Code
Imports Microsoft.Office.Interop
 
Public Class Form1
 
    Const Dateipfad As String = "C:\tmp\Zur Info - Satzung.msg"
    Sub ändern(Dateipfad As String, neuesDatum As Date)
        Dim sFile As String = Dateipfad
 
        ' FileInfo-Objekt erstellen
        With New System.IO.FileInfo(sFile)
            ' Datums- und Zeitangaben auslesen 
            Debug.Print("Erstellungsdatum: " & .CreationTime)
            Debug.Print("Letzter Zugriff: " & .LastAccessTime)
            Debug.Print("Letzte Änderung: " & .LastWriteTime)
 
            ' Erstellungsdatum ändern
            Dim DatumTag As Integer
 
            'DatumTag = DateTime.Parse(neuesDatum.Day).DayOfWeek
            .CreationTime = New Date(neuesDatum.Year, neuesDatum.Month, _
              neuesDatum.Day, neuesDatum.Hour, neuesDatum.Minute, _
              neuesDatum.Second)
 
            ' Datumsangabe "Letzter Zugriff" ändern
            .LastAccessTime = neuesDatum ' New Date(2009, 5, 16, 13, 12, 11)
 
            ' Datum "Letzte Änderung" ändern
            .LastWriteTime = neuesDatum ' New Date(2009, 5, 17, 13, 12, 11)
        End With
    End Sub
 
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) _
      Handles Button1.Click
 
        Dim objOutlook As Outlook.Application
        Dim objOutlookItem As Outlook.MailItem
 
        Dim strPath As String
        Dim strFile As String
 
        Dim NeuesDatum As Date
 
        ' War auch mal ein Text, klappt unten aber auch nicht
        Dim ExterneAnwendung As New System.Diagnostics.Process()
        ExterneAnwendung.StartInfo.FileName = "OUTLOOK.EXE"
        '  ExterneAnwendung.Start() ' deaktiviert, da hier Outlook selbst _
          starten würde
        ' Erzeugen...
 
        objOutlook = New Outlook.Application
 
        ' Check...
 
        If Not objOutlook Is Nothing Then
 
            '   Ab hier könntest Du eine Schleife draus machen,
            '   um die Dateien alle einzulesen
            '
            '   Pfad und Datei...
 
            strPath = "E:\Temp"
            strFile = "TEST.msg"
 
            '   Mail öffnen...
            objOutlookItem = CType(objOutlook.Session.OpenSharedItem( _
              Dateipfad), Outlook.MailItem) 'strPath & "\" & strFile)
 
            '   Check...
            If Not objOutlookItem Is Nothing Then
 
                '     Auslesen...
                'MsgBox "Body: " & objOutlookItem.Body
                'MsgBox "CreationTime: " & objOutlookItem.CreationTime
                'MsgBox "DeferredDeliveryTime: " & 
                ' objOutlookItem.DeferredDeliveryTime
                MsgBox("ReceivedTime: " & objOutlookItem.ReceivedTime)
                'MsgBox "ReminderTime: " & objOutlookItem.ReminderTime
                MsgBox("SenderName: " & objOutlookItem.SenderName)
                MsgBox("SenderEmailAddress: " & _
                  objOutlookItem.SenderEmailAddress)
                MsgBox("Subject: " & objOutlookItem.Subject)
                NeuesDatum = objOutlookItem.ReceivedTime
 
                '     Schließen...
                ' Hie scheint es dran zu liegen
                objOutlookItem.Close(Outlook.OlInspectorClose.olDiscard) ' 
                ' Close(olDiscard) ' 1 = Discard = Verwerfen
                'Outlook.Application.close()
 
            End If
 
            '   Zurücksetzen...
            objOutlookItem = Nothing
 
            '
            '   Hier wäre das Ende der Schleife
            '
 
            '   Abschließen schließen...
            objOutlook.Quit()
 
        End If
 
        ' Aufräumen...
        objOutlook = Nothing
 
        ' ExterneAnwendung.kill() ' Findet hier keinen passenden Prozess. Liegt _
          wohl an der oben deaktivierten .Start() Anweisung
 
        Call ändern(Dateipfad, NeuesDatum)
    End Sub
End Class
Ich glaube, dass es an der Zeile

objOutlookItem.Close(Outlook.OlInspectorClose.olDiscard) ' Close(olDiscard) ' 1 = Discard = Verwerfen

liegt, denn Outlook ist als Task noch zu sehen. Beende ich Outlook manuell, dann funktioniert alles super.

(Die Massenabfertigung muss ich natürlich noch einbauen, und aufräumen sowieso).

Wäre echt super, wenn mir einer von Euch helfen könnte. Im Internet habe ich auch schon ein paar Stunden gestern gesucht aber immer nur das gleiche gefunden.

Vielen Dank

Volker
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Outlook Mailitem schließen funktioniert nicht 
Autor: Manfred X
Datum: 05.12.18 09:50

Hallo!

Schau mal hier:

https://blogs.msdn.microsoft.com/deva/2010/01/07/best-practices-how-to-quit-outlook-application-after-automation-from-visual-studio-net-client/
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Outlook Mailitem schließen funktioniert nicht 
Autor: Volker Bunge
Datum: 05.12.18 11:09

Hallo Manfred X,

vielen Dank erst einmal für den Link.

So, habe mal was ausprobiert:

1. Der neue Aufruf:

' Schließen...
' Hie scheint es dran zu liegen
' objOutlookItem.Close(Outlook.OlInspectorClose.olDiscard) ' Close(olDiscard) ' 1 = Discard = Verwerfen
' Outlook.Application.close()
ReleaseObj(objOutlookItem)

2. Neue Sub eingefügt

' Kamm bei der Übersetzung raus
Private Sub ReleaseObj(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
Catch
Finally
obj = Nothing
End Try
End Sub

Ergebnis: Funktioniert leider nicht.

Jetzt halt die Frage: Habe ich es bis hier her alles richtig gemacht? Wenn ja, woran liegt es dann bzw. welche Lösungen gibt es noch? Wenn nicht, wie müsste es richtig sein?

(P.S. Hatte beim ersten Versuch glaube ich kurz Erfolg, jetzt aber funktioniert es nicht, die OUTLOOK.EXE ist immer noch im Taskmanager sichtbar).

Hast Du bzw. ein anderer eine passende Lösung für mich?

Vielen Dank

Volker
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Outlook Mailitem schließen funktioniert nicht 
Autor: Manfred X
Datum: 05.12.18 20:41

Hallo!

Versuche folgendes:
Stelle sicher, daß Deine Anwendung Outlook nur einmal startet
(Taskmanager).
Stelle sicher, daß alle verwendeten Outlook-Objekte im Code auch
wieder freigegeben werden
Rufe die Outlook.Quit-Methode beim Release des Outlook-Objekts
Setze den Automatisierungscode in eine eigene Klasse
und implementiere dort die Dispose-Schnittstelle, um sicher zu stellen
daß der Garbage-Collektor für das freigegebene Objekt zum Einsatz kommt.
Entferne den Code für den Prozeß "externe Anwendung".

Beitrag wurde zuletzt am 05.12.18 um 20:47:02 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Outlook Mailitem schließen funktioniert nicht 
Autor: Volker Bunge
Datum: 11.12.18 09:41

Hallo Manfred,

sorry, dass ich mich erst jetzt melde.

Zu Deiner Antwort bzw. Vorgehensweise habe ich noch so ein paar Verständnisfragen

Zuerst einmal was habe ich geändert:

1. "externe Anwendung" entfernt
2. Ein paar Kleinigkeiten gelöscht (bspw. die alte Pfadangabe)
3. Den Automatisierungscode ( Public Sub ReleaseObj(ByVal obj As Object) in eine cls_Outlook Klasse gepackt

Was ich aber noch nicht verstehe bzw. nicht weiss, ob das richtig ist ist folgendes

1. Stelle sicher, daß alle verwendeten Outlook-Objekte im Code auch wieder freigegeben werden

Also die Variablen objOutlookItem und objOutlook werden ja durch = Nothing gelöscht. Oder meinst Du was anderes?

2. Rufe die Outlook.Quit-Methode beim Release des Outlook-Objekts

Habe ich mal eingefügt (siehe Code). Es wird zumindestens kein offensichtlicher Fehler angezeigt.

3. und implementiere dort die Dispose-Schnittstelle, um sicher zu stellen daß der Garbage-Collektor für das freigegebene Objekt zum Einsatz kommt

Hier habe ich mal gegoogelt und folgenden Link gefunden und das erste Beispiel mal übersetzen lassen

https://docs.microsoft.com/de-de/dotnet/standard/garbage-collection/implementing-dispose

Habe dann den vb.net Code in die Klasse kopiert. Dort ist aber schon die 5. Zeile "Implements IDisposable" wellig unterstrichen.
(Fehlermeldung: Class "cls_Outlook" muss "Sub Dispose" für die System.IDispoable-Schnittstelle implementieren.)

Aber erlich gesagt: Ich verstehe hier auf der Seite nur noch Bahnhof.

Daher füge ich nun hier noch einmal den gesamten Code ein und hoffe, dass Du (oder ein anderer) mir weiterhelfen kann bzw. mal kurz erklären kann, was die Dispose-Sache eigentlich bedeutet.

Vielen Dank schon einmal im Voraus.

Volker
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Outlook Mailitem schließen funktioniert nicht 
Autor: Volker Bunge
Datum: 11.12.18 09:41

Hier nun der Code für das Formular

Imports Microsoft.Office.Interop
 
Public Class Form1
 
    Const Dateipfad As String = "C:\tmp\Test.msg"
 
    Sub ändern(Dateipfad As String, neuesDatum As Date)
        Dim sFile As String = Dateipfad
 
        ' FileInfo-Objekt erstellen
        With New System.IO.FileInfo(sFile)
            ' Datums- und Zeitangaben auslesen 
            Debug.Print("Erstellungsdatum: " & .CreationTime)
            Debug.Print("Letzter Zugriff: " & .LastAccessTime)
            Debug.Print("Letzte Änderung: " & .LastWriteTime)
 
            ' Erstellungsdatum ändern
            Dim DatumTag As Integer
 
            'DatumTag = DateTime.Parse(neuesDatum.Day).DayOfWeek
            .CreationTime = New Date(neuesDatum.Year, neuesDatum.Month, _
              neuesDatum.Day, neuesDatum.Hour, neuesDatum.Minute, _
              neuesDatum.Second)
 
            ' Datumsangabe "Letzter Zugriff" ändern
            .LastAccessTime = neuesDatum ' New Date(2009, 5, 16, 13, 12, 11)
 
            ' Datum "Letzte Änderung" ändern
            .LastWriteTime = neuesDatum ' New Date(2009, 5, 17, 13, 12, 11)
        End With
    End Sub
 
    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) _
      Handles Button2.Click
        Dim objOutlook As Outlook.Application
        Dim objOutlookItem As Outlook.MailItem
 
        Dim NeuesDatum As Date
 
          ' Erzeugen...
 
        objOutlook = New Outlook.Application
 
        ' Check...
 
        If Not objOutlook Is Nothing Then
 
            '   Ab hier könntest Du eine Schleife draus machen,
            '   um die Dateien alle einzulesen
            '
            '   Mail öffnen...
            objOutlookItem = CType(objOutlook.Session.OpenSharedItem( _
              Dateipfad), Outlook.MailItem) 'strPath & "\" & strFile)
 
            '   Check...
            If Not objOutlookItem Is Nothing Then
 
                '     Auslesen...
                'MsgBox "Body: " & objOutlookItem.Body
                'MsgBox "CreationTime: " & objOutlookItem.CreationTime
                'MsgBox "DeferredDeliveryTime: " & 
                ' objOutlookItem.DeferredDeliveryTime
                MsgBox("ReceivedTime: " & objOutlookItem.ReceivedTime)
                'MsgBox "ReminderTime: " & objOutlookItem.ReminderTime
                MsgBox("SenderName: " & objOutlookItem.SenderName)
                MsgBox("SenderEmailAddress: " & _
                  objOutlookItem.SenderEmailAddress)
                MsgBox("Subject: " & objOutlookItem.Subject)
                NeuesDatum = objOutlookItem.ReceivedTime
 
                '     Schließen...
                ' Hie scheint es dran zu liegen
                'objOutlookItem.Close(Outlook.OlInspectorClose.olDiscard) ' _
                  Close(olDiscard) ' 1 = Discard = Verwerfen
                'Outlook.Application.close()
                releaseObj(objOutlookItem)
 
            End If
 
            '   Zurücksetzen...
            objOutlookItem = Nothing
 
            '
            '   Hier wäre das Ende der Schleife
            '
 
            '   Abschließen schließen...
            objOutlook.Quit()
 
        End If
 
        ' Aufräumen...
        objOutlook = Nothing
 
 
        Try
 
        Catch ex As Exception
 
        End Try
 
        Call ändern(Dateipfad, NeuesDatum)
    End Sub
 
    Private Sub releaseObj(objOutlookItem As Outlook.MailItem)
        Throw New NotImplementedException
    End Sub
 
End Class
Für die Klasse cls_Outlook

Imports Microsoft.Win32.SafeHandles
Imports System
Imports System.Runtime.InteropServices
Class cls_Outlook
    Implements IDisposable
 
    Private disposed As Boolean = False
    Private handle As SafeHandle = New SafeFileHandle(IntPtr.Zero, True)
 
    Public Sub Dispose()
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
 
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If disposed Then Return
 
        If disposing Then
            handle.Dispose()
        End If
 
        disposed = True
    End Sub
    Public Sub ReleaseObj(ByVal obj As Object)
        Try
 
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
        Catch
        Finally
            obj = Nothing
        End Try
    End Sub
End Class
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Outlook Mailitem schließen funktioniert nicht 
Autor: Manfred X
Datum: 12.12.18 10:22

Hallo!

Wo ich mich diese Tage aufhalte, ist MS-Outlook nicht in Gebrauch.
Insofern kann ich nur eingeschränkt hilfreich sein.

Schnittstelle ...
Eine Schnittstelle ist eine Liste von Eigenschaften, Methoden usw
OHNE darin enthaltenen Code!
Eine Klasse kann eine Schnittstelle implementieren und muß dann alle
Methoden und Eigenschaften der Schnittstelle mit passendem Code
zur Verfügung stellen.
Schnittstellen erlauben es, im Programm an einer Stelle Instanzen
unterschiedlicher Klassen, die alle diese Schnittstelle impl., zu nutzen,
wenn man sich darauf beschränkt, diese Schnittstellen-Methoden zu verwenden.

IDisposable-Schnittstelle ...
In Net gibt es verwaltete und nicht-verwaltete Objekte.
Verwaltete Objekte werden innerhalb der Net-Umgebung erstellt, verwendet und
freigegeben.
Nicht-verwaltete Objekte erstellen intern weitere Objekte oder Ressourcen und
nutzen diese. Net kennt diese unverwalteten "Speicherinhalte" nicht und kann sie
weder direkt verwenden noch freigeben.
Es macht keinen Sinn, Zugriffsvariablen für nicht-verwaltete Objekte auf
Nothing zu setzen. Eine völlige Freigaben kann Net nicht durchführen.

Die IDisposable-Schnittstelle implementiert die Dispose-Methode.
In dieser Methode ist der Code einzutragen, durch den nicht-verwaltete
Bestandteile (Handles, Prozesse, ...) explizit "released" werden.
In Deinem Fall wäre das die Freigabe und das Quit von verwendeten
Outlook-Klassen.
Falls vorhanden, ruft Net bei Freigabe einer Instanz diese Methode auf.
Wenn sie korrekt für eine Klasse programmiert worden ist, ermöglicht dies
die vollständige Entfernung des Objekts aus dem Speicher.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Outlook Mailitem schließen funktioniert nicht 
Autor: Volker Bunge
Datum: 22.12.18 10:49

Hallo ManfredX,

leider verstehe ich Deine "allgemeine" Erklärung nicht bzw. habe keine Ahnung, wie ich diese erfolgreich umsetzen könnte.

Daher meine Frage bzw. Bitte: Könntest Du mir (wenn Du wieder an einem Rechner mit Outlook bist), mir dies anhand eines Codebeispiels verdeutlichen?

Eigentlich kann es doch nicht so schwer sein, eine Anwendung zu öffnen und eine Verarbeitung zu vollziehen und diese dann wieder ordnungsgemäß zu beenden.

Wenn Du, oder natürlich jemand anderes, eine passende Lösung hätte, wäre ich sehr glücklich darüber.

Vielen Dank schon einmal an alle und ein frohes Fest Euch allen.

Gruß

Volker
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel