none
Outlook öffnen mit MAPI RRS feed

  • Frage

  • Hallo zusammen

    Ich habe ein VB .NET Programm, welches MAPI32.DLL benutzt um ein Mail Fenster zu öffnen oder Mails mit Dateianhängen vorzubereiten. Ich habe diese Version gewählt, weil nicht bei allen Outlook installiert ist. Einige benutzen noch immer Thunderbird oder sogar noch Windows Live Mail. Mit diesen 3 Programmen klappt es eigentlich auch. Ein Problem hat nur Office 325, bzw. Outlook davon. Outlook von Office 365 bleibt nämlich hängen, wenn man das geöffnete Mail Fenster wieder schliesst. Outlook wird geschlossen steht. Dabei bleibt ein grauses Outlook Symbol in der Taskliste zurück mit eben dem genannten Text. Auch im Taskmanager ist dieses Symbol noch zu sehen. Der PC lässt sich nicht mehr ordnungsgemäss herunterfahren, weil ja noch Outlook hängt. Nur in Outlook von Office 365 hatte ich bisher das Phänomen. Mit Outlook 2007 geht es hingegen einwandfrei. Ebenfalls funktioniert es mit Outlook von Office 365 wenn Outlook schon gestartet ist. Der Fehler Passiert also nur, wenn Outlook noch nicht gestartet ist. Dies geht aber mit anderen Outlook Versionen einwandfrei.

    Ich rufe dies wie folgt auf:

     Dim mapi As New MAPI
    
     mapi.SendMailPopup(String.Empty, String.Empty)
    

    Natürlich kann ich auch einen Betreff und einen Mailinhalt mitgeben. Auch dies funktioniert mit dem beschriebenen Fehler. Nun hänge ich noch die ganze Klasse MAPI an, mit der Hoffnung jemand kann mir helfen.

    Imports System
    Imports System.Collections.Generic
    Imports System.IO
    Imports System.Runtime.InteropServices
    Imports System.Windows.Forms
    
    Namespace SendFileTo
        Public Class MAPI
    
    #Region "Import"
            <DllImport("MAPI32.DLL")>
            Private Shared Function MAPISendMail(sess As IntPtr, hwnd As IntPtr, message As MapiMessage,
                                                 flg As Integer, rsv As Integer) As Integer
            End Function
    #End Region
    
    #Region "Variablen"
            Private ReadOnly errors() As String = New String() {"OK [0]", "User abort [1]", "General MAPI failure [2]", "MAPI login failure [3]",
                                                                "Disk full [4]", "Insufficient memory [5]", "Access denied [6]",
                                                                "-unknown- [7]", "Too many sessions [8]",
                                                                "Too many files were specified [9]",
                                                                "Too many recipients were specified [10]",
                                                                "A specified attachment was not found [11]",
                                                                "Attachment open failure [12]", "Attachment write failure [13]",
                                                                "Unknown recipient [14]", "Bad recipient type [15]",
                                                                "No messages [16]", "Invalid message [17]", "Text too large [18]",
                                                                "Invalid session [19]", "Type not supported [20]",
                                                                "A recipient was specified ambiguously [21]",
                                                                "Message in use [22]", "Network failure [23]",
                                                                "Invalid edit fields [24]", "Invalid recipients [25]",
                                                                "Not supported [26]"}
    
            Private ReadOnly m_recipients As New List(Of MapiRecipDesc)
            Private ReadOnly m_attachments As New List(Of String)
            Private m_lastError As Integer = 0
    
            Private Const MAPI_LOGON_UI As Integer = &H1
            Private Const MAPI_DIALOG As Integer = &H8
            Private Const maxAttachments As Integer = 20
    #End Region
    
    #Region "Enums"
            Public Enum howTo
                MAPI_ORIG = 0
                MAPI_TO
                MAPI_CC
                MAPI_BCC
            End Enum
    
    #End Region
    
    #Region "Public Funktionen"
            Public Function AddRecipientTo(email As String) As Boolean
                Return AddRecipient(email, howTo.MAPI_TO)
            End Function
    
            Public Function AddRecipientCC(email As String) As Boolean
                Return AddRecipient(email, howTo.MAPI_TO)
            End Function
    
            Public Function AddRecipientBCC(email As String) As Boolean
                Return AddRecipient(email, howTo.MAPI_TO)
            End Function
    
            Public Sub AddAttachment(strAttachmentFileName As String)
                m_attachments.Add(strAttachmentFileName)
            End Sub
    
            Public Function SendMailPopup(strSubject As String, strBody As String) As Integer
                Return SendMail(strSubject, strBody, MAPI_LOGON_UI Or MAPI_DIALOG)
            End Function
    
            Public Function SendMailDirect(strSubject As String, strBody As String) As Integer
                Return SendMail(strSubject, strBody, MAPI_LOGON_UI)
            End Function
    #End Region
    
    #Region "Private Funktionen"
            Private Function SendMail(strSubject As String, strBody As String, how As Integer) As Integer
                Dim msg As New MapiMessage With {.subject = strSubject, .noteText = strBody}
    
                msg.recips = GetRecipients(msg.recipCount)
                msg.files = GetAttachments(msg.fileCount)
    
                m_lastError = MAPISendMail(New IntPtr(0), New IntPtr(0), msg, how, 0)
    
                If m_lastError > 1 Then
                    MessageBox.Show("MAPISendMail failed! " + GetLastError(), "MAPISendMail")
                End If
    
                Cleanup(msg)
    
                Return m_lastError
            End Function
    
            Private Function AddRecipient(email As String, howTo As howTo) As Boolean
                Dim recipient As MapiRecipDesc = New MapiRecipDesc With {.recipClass = CType(howTo, Integer), .name = email}
    
                m_recipients.Add(recipient)
    
                Return True
            End Function
    
            Private Function GetRecipients(ByRef recipCount As Integer) As IntPtr
                recipCount = 0
    
                If m_recipients.Count = 0 Then
                    Return CType(0, IntPtr)
                End If
    
                Dim size As Integer = Marshal.SizeOf(GetType(MapiRecipDesc))
                Dim intPtr As IntPtr = Marshal.AllocHGlobal(m_recipients.Count * size)
                Dim ptr As Integer = CType(intPtr, Integer)
                Dim mapiDesc As MapiRecipDesc
    
                For Each mapiDesc In m_recipients
                    Marshal.StructureToPtr(mapiDesc, CType(ptr, IntPtr), False)
                    ptr += size
                Next
    
                recipCount = m_recipients.Count
                Return intPtr
            End Function
    
            Private Function GetAttachments(ByRef fileCount As Integer) As IntPtr
                fileCount = 0
                If m_attachments Is Nothing Then
                    Return CType(0, IntPtr)
                End If
    
                If (m_attachments.Count <= 0) Or (m_attachments.Count >
                    maxAttachments) Then
                    Return CType(0, IntPtr)
                End If
    
                Dim size As Integer = Marshal.SizeOf(GetType(MapiFileDesc))
                Dim intPtr As IntPtr = Marshal.AllocHGlobal(m_attachments.Count * size)
    
                Dim mapiFileDesc As MapiFileDesc = New MapiFileDesc With {.position = -1}
                Dim ptr As Integer = CType(intPtr, Integer)
    
                For Each strAttachment As String In m_attachments
                    mapiFileDesc.name = Path.GetFileName(strAttachment)
                    mapiFileDesc.path = strAttachment
                    Marshal.StructureToPtr(mapiFileDesc, CType(ptr, IntPtr), False)
                    ptr += size
                Next
    
                fileCount = m_attachments.Count
                Return intPtr
            End Function
    
            Public Function GetLastError() As String
                If m_lastError <= 26 Then
                    Return errors(m_lastError)
                Else
                    Return "MAPI error [" & m_lastError.ToString() & "]"
                End If
            End Function
    #End Region
    
    #Region "Private Methoden"
            Private Sub Cleanup(ByRef msg As MapiMessage)
                Dim size As Integer = Marshal.SizeOf(GetType(MapiRecipDesc))
                Dim ptr As Integer
    
                If msg.recips <> IntPtr.Zero Then
                    ptr = CType(msg.recips, Integer)
                    For i As Integer = 0 To msg.recipCount - 1
                        Marshal.DestroyStructure(CType(ptr, IntPtr), GetType(MapiRecipDesc))
                        ptr += size
                    Next
                    Marshal.FreeHGlobal(msg.recips)
                End If
    
                If msg.files <> IntPtr.Zero Then
                    size = Marshal.SizeOf(GetType(MapiFileDesc))
                    ptr = CType(msg.files, Integer)
                    For i As Integer = 0 To msg.fileCount - 1
                        Marshal.DestroyStructure(CType(ptr, IntPtr), GetType(MapiFileDesc))
                        ptr += size
                    Next
                    Marshal.FreeHGlobal(msg.files)
                End If
    
                m_recipients.Clear()
                m_attachments.Clear()
                m_lastError = 0
            End Sub
    #End Region
    
        End Class
    
        <StructLayout(LayoutKind.Sequential)>
        Public Class MapiMessage
            Public reserved As Integer
            Public subject As String
            Public noteText As String
            Public messageType As String
            Public dateReceived As String
            Public conversationID As String
            Public flags As Integer
            Public originator As IntPtr
            Public recipCount As Integer
            Public recips As IntPtr
            Public fileCount As Integer
            Public files As IntPtr
        End Class
    
        <StructLayout(LayoutKind.Sequential)>
        Public Class MapiFileDesc
            Public reserved As Integer
            Public flags As Integer
            Public position As Integer
            Public path As String
            Public name As String
            Public type As IntPtr
        End Class
    
        <StructLayout(LayoutKind.Sequential)>
        Public Class MapiRecipDesc
            Public reserved As Integer
            Public recipClass As Integer
            Public name As String
            Public address As String
            Public eIDSize As Integer
            Public enTryID As IntPtr
        End Class
    
    End Namespace

    Meine Frage nun: Wie kriege ich es hin, dass Outlook in jedem Fall beim Schliessen des Mail Fensters richtig geschlossen wird und nicht hängen bleibt.

    Gruss Marcel und danke an alle Beiträge.

    Dienstag, 28. Juli 2020 09:56

Antworten

  • Hallo Marcel,

        Public Function SendMailPopup(strSubject As String, strBody As String) As Integer
                Return SendMail(strSubject, strBody, MAPI_LOGON_UI Or MAPI_DIALOG)
        End Function

    Würdest Du es mit dem zusätzlichen Flag MAPI_DIALOG_MODELESS versuchen?

         Return SendMail(strSubject, strBody, MAPI_LOGON_UI Or MAPI_DIALOG Or MAPI_DIALOG_MODELESS)

    In folgendem Thread wurde bekanntgemacht, dass neuere Versionen von Outlook mithilfe von diesen drei, als Parameter zu übergebenden Flags nicht mehr hängenbleiben:
    With Outlook 2016 : MAPISendMail call hangs calling application

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Mittwoch, 29. Juli 2020 09:06
    Moderator

Alle Antworten

  • Hallo Marcel,

        Public Function SendMailPopup(strSubject As String, strBody As String) As Integer
                Return SendMail(strSubject, strBody, MAPI_LOGON_UI Or MAPI_DIALOG)
        End Function

    Würdest Du es mit dem zusätzlichen Flag MAPI_DIALOG_MODELESS versuchen?

         Return SendMail(strSubject, strBody, MAPI_LOGON_UI Or MAPI_DIALOG Or MAPI_DIALOG_MODELESS)

    In folgendem Thread wurde bekanntgemacht, dass neuere Versionen von Outlook mithilfe von diesen drei, als Parameter zu übergebenden Flags nicht mehr hängenbleiben:
    With Outlook 2016 : MAPISendMail call hangs calling application

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Mittwoch, 29. Juli 2020 09:06
    Moderator
  • Hallo Dimitar

    Vielen Dank für Deine Antwort. Dank Deiner einfachen Lösung funktioniert dies nun einwandfrei. Outlook wird so IMMER richtig geschlossen.

    Ergänzt habe ich also die Variable:

    Private Const MAPI_DIALOG_MODELESS As Integer = &H4

    Der Aufruf habe ich dann so gemacht wie Du vorgeschlagen hast.

    Gruss Marcel

     
    Mittwoch, 29. Juli 2020 09:55