HowTo: Get an attachment size in Outlook 2000 – 2007, part 2

In the previous sample, I showed how to get the PR_ATTACH_SIZE Extended MAPI property that returns the size of an Attachment object. To be more precise, it returns the size of the attached file plus the size of some internal info.

In most cases that makeweight does not matter at all since it is very small (about 100-200 bytes), but sometimes it may be excess. In order to get the exact size of the attached file, you need to use the PR_ATTACH_DATA_BIN binary property:


Private Function GetAttachSizeMAPI(ByVal oMAPIObject As Object) As Long

    If (oMAPIObject Is Nothing) Then Return 0

    Dim result As String = 0
    Dim pPropValue As IntPtr = IntPtr.Zero
    Dim IUnk As IntPtr = IntPtr.Zero
    Dim IProperty As IntPtr = IntPtr.Zero
    Try
        MAPI.MAPIInitialize(IntPtr.Zero)
        IUnk = Marshal.GetIUnknownForObject(oMAPIObject)
        ' Outlook 2003 and 2007 ( IMAPIProp )
        Dim res = Marshal.QueryInterface(IUnk, MAPI.guidMAPIProp, IProperty)
        If res = MAPI.S_OK Then
            Dim oMapiProp As Object = Marshal.GetObjectForIUnknown(IProperty)
            Dim iMapiProp As IMAPIProp = TryCast(oMapiProp, IMAPIProp)
            If iMapiProp IsNot Nothing Then
                Try
                    Dim stream As ComTypes.IStream
                    Dim IStream As IntPtr = IntPtr.Zero
                    iMapiProp.OpenProperty( _
                        MAPI.PR_ATTACH_DATA_BIN, _
                        MAPI.guidIStream, 0, 0, _
                        IStream)
                    If IStream <> IntPtr.Zero Then
                        Try
                            stream = TryCast( _
                                Marshal.GetObjectForIUnknown(IStream), _
                                ComTypes.IStream)
                            If stream IsNot Nothing Then
                                Try
                                    Dim stat As ComTypes.STATSTG = Nothing
                                    stream.Stat(stat, STATFLAG.STATFLAG_NONAME)
                                    result = stat.cbSize
                                    Return result
                                Finally
                                    Marshal.ReleaseComObject(stream)
                                End Try
                            End If
                        Finally
                            Marshal.Release(IStream)
                        End Try
                    End If
                Finally
                    Marshal.ReleaseComObject(oMapiProp)
                End Try
            End If
        End If
        ' Outlook 2000 and XP ( IAttach )
        res = Marshal.QueryInterface(IUnk, MAPI.guidMAPIAttach, IProperty)
        If res = MAPI.S_OK Then
            Dim oMapiProp As Object = Marshal.GetObjectForIUnknown(IProperty)
            Dim iMapiProp As IAttach = TryCast(oMapiProp, IAttach)
            If iMapiProp IsNot Nothing Then
                Try
                    Dim stream As ComTypes.IStream
                    Dim IStream As IntPtr = IntPtr.Zero
                    iMapiProp.OpenProperty( _
                        MAPI.PR_ATTACH_DATA_BIN, _
                        MAPI.guidIStream, 0, 0, _
                        IStream)
                    If IStream <> IntPtr.Zero Then
                        Try
                            stream = TryCast( _
                                Marshal.GetObjectForIUnknown(IStream), _
                                ComTypes.IStream)
                            If stream IsNot Nothing Then
                                Try
                                    Dim stat As ComTypes.STATSTG = Nothing
                                    stream.Stat(stat, STATFLAG.STATFLAG_NONAME)
                                    result = stat.cbSize
                                    Return result
                                Finally
                                    Marshal.ReleaseComObject(stream)
                                End Try
                            End If
                        Finally
                            Marshal.Release(IStream)
                        End Try
                    End If
                Finally
                    Marshal.ReleaseComObject(oMapiProp)
                End Try
            End If
        End If
    Finally
        If (pPropValue <> IntPtr.Zero) Then
            MAPI.MAPIFreeBuffer(pPropValue)
        End If
        If (IProperty <> IntPtr.Zero) Then
            Marshal.Release(IProperty)
        End If
        If (IUnk <> IntPtr.Zero) Then
            Marshal.Release(IUnk)
        End If
    End Try
    Return result
End Function

Personal thanks to François-Denis for his contribution to the PR_ATTACH_SIZE vs. PR_ATTACH_DATA_BIN properties discussion on our forum.

You may also be interested in:

How to program an Outlook COM add-in: ribbon tabs, command bars, task panes
Advanced features for Outlook plug-in development
How to develop custom Outlook forms

Available downloads:

This sample add-in was developed using Add-in Express 2009 for Microsoft Office and .net
C# sample Outlook add-in for VS 2005
VB.NET sample Outlook add-in for VS 2005

Post a comment

Have any questions? Ask us right now!