HowTo: Get an attachment size in Outlook 2000 – 2010, part 1
The new Size property of the Attachment object was introduced in the Outlook 2007 Object Model. There exist at least two methods of getting the attachment size in older Outlook versions, that is in Outlook 2003, XP and 2000.
The first method is as follows: you store each attachment in a temporary file, then query the file size, and after that delete that temporary file. The other, and probably a smarter way, is getting the attachment size via the PR_ATTACH_SIZE Extended MAPI property. It is that second method that we are going to scrutinize today.
The DoGetAttachmentSize method is quite simple, the code below processes the Attachments collection:
Private Sub DoGetAttachmentSize(ByRef mail As Outlook._MailItem) Dim attachments As Outlook.Attachments = mail.Attachments If attachments IsNot Nothing Then Try If attachments.Count > 0 Then Dim Output As String = String.Empty For i As Integer = 1 To attachments.Count Dim attach As Outlook.Attachment = attachments.Item(i) If attach IsNot Nothing Then Try Dim size As Long = GetMAPIProp( _ attach.MAPIOBJECT, _ MAPI.PR_ATTACH_SIZE) Output += "#" + i.ToString() + _ ": " + attach.FileName + _ " " + size.ToString() + _ Environment.NewLine Finally Marshal.ReleaseComObject(attach) End Try End If Next i If Output <> String.Empty Then MessageBox.Show(Output) End If Finally Marshal.ReleaseComObject(attachments) End Try End If End Sub
In the GetMAPIProp method, you dig for the needed PR_ATTACH_SIZE property. Initialize Extended MAPI, query the right interface, get the SPropValue structure and receive the wanted value. Pay attention here to the two calls of QueryInterface. The point is that Outlook 2003, 2007 and Outlook 2010 return only the IMAPIProp interface, while Outlook 2000 and Outlook XP return the IAttach interface only. What kind of interface will be implemented in Outlook 2010 is unclear so far, that is why I am leaving the code as is, with 2 QueryInterface calls:
Private Function GetMAPIProp( _ ByVal oMAPIObject As Object, _ ByVal uiPropertyTag As UInteger) 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) Dim guidMAPIProp As Guid = New Guid(MAPI.IID_IMAPIProp) Dim res = Marshal.QueryInterface(IUnk, guidMAPIProp, IProperty) If (res <> MAPI.S_OK) Then Dim guidMAPIAttach As Guid = New Guid(MAPI.IID_IAttachment) Marshal.QueryInterface(IUnk, guidMAPIAttach, IProperty) If (res <> MAPI.S_OK) Then Return 0 End If Try MAPI.HrGetOneProp(IProperty, uiPropertyTag, pPropValue) If (pPropValue = IntPtr.Zero) Then Return 0 Dim propValue As SPropValue propValue = _ Marshal.PtrToStructure(pPropValue, propValue.GetType()) result = propValue.Value And UInt32.MaxValue Catch ex As System.Exception Throw ex End Try 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
Have a nice weekend. I hope the weather will finally get better here and I will go fishing to enjoy peace and tranquility, at last!