Question Difficulty in Releasing CDO.message object in error handling

dhirendra

Member
Joined
Jan 26, 2011
Messages
9
Programming Experience
1-3
Hi,
i am having trouble in releasing the cdo.message object when there is a error. i have a mailing subroutine with file location of the attachment to be sent as a parameter.
After sending the mail the file which was sent as attachment has to be deleted from the file system. even if the mailing sub fails i still want to delete the attachment file from the file system, hence in error handler i again included the release cdo lines. so that when the mailing sub ends the main sub can delete this file
below is the code sample.
VB.NET:
sub mainn()
  Send_Email_Using_CDO(attachment)  'location of the attachment is passed 
  kill(attachment) - delete the original file from the filesystem
end sub

Private Sub Send_Email_Using_CDO(ByVal location As String)

On Error GoTo ErrorHandler
Dim objmessage As Object
objmessage = CreateObject("CDO.Message")
objmessage.AddAttachment(wblocation)
...
objmessage.configuration.fields.Item _
        ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = _
        abc.gef.com   ' a inactive smtp address is given to check the error handler
objmessage.send() ---> deliberate error introduced; wrong smtp address given

  objmessage = nothing
   ErrorHandler:
        If Err.Number <> 0 Then
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            GC.WaitForPendingFinalizers()
            Marshal.FinalReleaseComObject(objmessage)
            objmessage = Nothing
end sub

with proper settings and working smtp the mailing sub works properly.
then in the main sub the attachment file gets deleted as well
but when i keep any invalid smtp address, the error handler is not serving the purpose of releasing CDO object. because the next instruction in main which is kill(attachment) doesnt seem to be doing anything when i step through the code.
there is just no error shown when i step through kill(attachement) line.
which means that the file is still locked some where in the cdo object. :mad:
Also earlier i had the same thing VBA excel. there it didnt give me issues with releasing cdo reference to the attachment. its only in VB.net

Thanks!!! in advance if some one can really help me through it
 
Last edited:
CDO was actually the underlying messaging object for the .Net tools in System.Web.Mail namespace, but that was obsolete long time ago. Today you can use the .Net tools in System.Net.Mail namespace for sending mails. I usually prefer MSDN library for any reference and article lookups, but in this case there happen to be a fairly good site dedicated to this namespace here: System.Net.Mail, OH MY!

When coming from VBA you have to realize the only inherently available tool it has, apart from the basic language, is the office object library, while in VB.Net you have the tools from the huge .Net Framework class library available. So the consequence is that you in most cases should look for what tools .Net provides for a solution rather than converting old code that predates .Net.
 
Thanks John!!!!!!!,
you are my hero for the link which you gave me on System.net.mail. i had earlier tried using system.net.mail, i was doing silly mistakes such as directly assigning mail.to, mail.bcc, mail.cc , mail.from. and it was simply failing in smtp.send(mail)
it works totally different way in system.net.mail as compared to CDO.message.
Just Awsome FAQ ever made. couldnt get much help with google.
Thanks again John :D:)
 
i have same trouble in using System.net.mail as well. here is the code which i am using

VB.NET:
Private Sub send_mail_using_system_net_mail(ByVal [B][I]wblocation[/I][/B] As String, ByVal _  reparray As Object(,), ByVal rownum As Integer, ByVal repdate As String)
        On Error GoTo errorhandler
        Dim to_names As String
        Dim from_names As String
        Dim subject As String
        Dim body As String

        email = New MailMessage()

        to_names = reparray(rownum, 2).ToString
        email.to.add(to_names)
        from_names = reparray(rownum, 3).ToString
        email.from = New MailAddress(from_names)
        email.subject = "subject"
        email.body = "body"

        smtp_dtl = New SmtpClient
        attach_file = New Attachment(wblocation)
        smtp_dtl.Host = My.Settings.smtpmain.ToString
        smtp_dtl.Port = 25
        smtp_dtl.EnableSsl = False
        smtp_dtl.Timeout = 60
        smtp_dtl.UseDefaultCredentials = True
        email.attachments.add(attach_file)
        'smtp_dtl.send(email)
        Dispose(True)
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.WaitForPendingFinalizers()
        'Marshal.FinalReleaseComObject(email)
        'Marshal.FinalReleaseComObject(smtp_dtl)
        attach_file= nothing
        email = Nothing
        smtp_dtl = Nothing


errorhandler:
        If Err.Number <> 0 Then Call errorhandling()
    End Sub

by using this code i am successfully able to send mails. Again problem is when the control is returned back to main subroutine. there seems to be some file lock happening to the attachment file whose location i am passing to the mailing sub.
in the main sub i want to delete this file from the system. but i get below error
55 The process cannot access the file
'L:\macro\bin\Release\ 02-01-2011 11-32-40 AM\t1 02-01-2011 11-32-40 AM.xls' because it is being used by another process.

so when i am not calling the send mail sub routine then the code doesn't have any issue in deleting these excels.

also marshal.finalreleasecomobject() seems to throw an error on the mailmessage object and smtpclient object. so i commented it in the mailing sub
5 The object's type must be __ComObject or derived from __ComObject.
Parameter name: o


i need to know if there is a way i can wait for the lock to be removed from the attachment file after the mail has been sent. the aim is to clear all the files which are to be sent from the file system.
 
On Error... that is error ignoring, not error handling.
GC... generally don't call it.
Setting a variable to Nothing does nothing but dereference the variable, for local variables that is pointless at the end of their scope. Now, you are not using local variables in some cases here, why not? Still the object in memory remains until perhaps several GC steps later.

Both MailMessage class and Attachment (by AttachmentBase) class implements IDisposable interface, which means when you create an object of this type you must call Dispose method when done. This takes care of any cleanup the class instance needs to do before last reference can be released. My guess is that the Attachment class will lock the file until disposed.
email.to.
Since in several places your code does not have proper casing (like in above quote) I will guess that you are using untyped variables and late-binding with Option Strict off, I recommend you turn on Option Strict. It will make your life much easier. :)
 
hi John,
i am making use of using block to release all the used resources.
VB.NET:
        Using email As New System.Net.Mail.MailMessage()
            Dim smtp_dtl As New System.Net.Mail.SmtpClient
            Dim attach_file As New System.Net.Mail.Attachment(wblocation)
            Dim email_from As New System.Net.Mail.MailAddress(from_names)
            email.Attachments.Add(attach_file)
            email.To.Add(to_names)
            email.From = email_from
            email.Subject = subject
            body = "Hi," & _
            vbCrLf & _
            "Please find attached " & reparray(rownum, 1).ToString & _
            " refreshed on " & repdate & vbCrLf & _
             vbCrLf & reparray(rownum, 6).ToString
            email.Body = body
            smtp_dtl.Host = My.Settings.smtpmain.ToString
            smtp_dtl.Port = 25
            smtp_dtl.EnableSsl = False
            smtp_dtl.Timeout = 60
            smtp_dtl.UseDefaultCredentials = True
            smtp_dtl.Send(email)
        End Using
 
While I can't find that it's explicitly stated in the documentation, I found that when disposing the MailMessage like you do there the internal code also disposes the attached views and attachments. So you should be good by that.
 
Back
Top