文件似乎在被SmtpClient作为附件发送后保持打开状态。我该如何删除文件?

时间:2012-02-08 15:24:46

标签: .net vb.net email smtpclient

我有一些在定义为:

的函数中生成的文件
Public Function GeneratePDF(exportFileName As String) As String
    Dim GeneratePath As String = FileSystem.CombinePath(standardDirectory, exportFileName  & DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") & ".pdf")
    If GenerateFile(GeneratePath) Then
        Return GeneratePath
    End If
    Return String.Empty
End Function

立即打印这些文件,文件自动保存到目录中;文件本身不供实际软件用户使用。我为文件添加时间戳,以便将它们唯一标识用于审计目的。

我现在已收到要求将其中一些文件通过电子邮件发送到公司,并且有人抱怨当前的文件名不是用户友好的。

所以,我尝试将生成的文件复制到临时目录,使用更友好的名称,通过电子邮件发送友好文件,然后删除它,保持审计跟踪完整,如下所示:

Public Function GeneratePDF(exportFileName As String) As String
    Dim GeneratePath As String = FileSystem.CombinePath(standardDirectory, exportFileName  & DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") & ".pdf")
    If GenerateFile(GeneratePath) Then

        Dim friendlyFilePath As String = FileSystem.CombinePath(standardDirectory, GetFriendlyFileName(GeneratePath))
        System.IO.File.Copy(GeneratePath, friendlyFilePath)

        Dim mailMsg As New System.Net.Mail.MailMessage
        Dim smtp As New System.Net.Mail.SmtpClient
        [Vast amount of code, which attaches friendlyFilePath to the email, then sends it]

        System.IO.File.Delete(friendlyFilePath)

        Return GeneratePath
    End If
    Return String.Empty
End Function

这会在System.IO.IOException行引发System.IO.File.Delete(friendlyFilePath)因为该文件在通过电子邮件发送后仍在使用中。

我已经取出了电子邮件代码,这使得复制和删除工作正常,因此显然将文件附加到导致问题的电子邮件中。

我还尝试在删除行之前进行断点操作,等待五分钟,确认电子邮件已发送,然后推进代码,但仍然抛出同样的异常。

有人可以建议如何解决这个问题吗?

5 个答案:

答案 0 :(得分:13)

mailClient.Send(message);添加message.Attachments.Dispose();

之后

这将释放附件资源

答案 1 :(得分:7)

SmtpClient不会释放附件的句柄。您必须手动处理,或者我所做的是首先将文件内容复制到MemoryStream。下面的代码也可以使用。

using (MailMessage message = new MailMessage(from, to, subject, body))
using (Attachment attachment = new Attachment(fileName))
{
   message.Attachments.Add(attachment);
   mailClient.UseDefaultCredentials = true;
   mailClient.Send(message);
}

答案 2 :(得分:3)

访问文件时应使用Using语句。这将处理您的对象,您应该能够调用您的System.IO.File.Delete()

见这里:http://msdn.microsoft.com/en-us/library/htd05whh(v=vs.80).aspx

答案 3 :(得分:1)

虽然我意识到这篇文章的最后一篇文章是在几年前我认为值得为那些不知道的人添加少量额外信息...

如果您异步发送电子邮件,则在回调触发之前不能使用“使用”或处置任何内容,而应将SendMessage实例作为SendAsync()的UserState参数发送。这样,当回调触发时,您将能够处置任何附件和MailMessage实例。您也可以将Mail Client作为发件人对象进行处置。

答案 4 :(得分:0)

创建附件后,您是否关闭了附件?

System.IO.FileStream afile = System.IO.File.Create(@"c:\test\astream.csv");
afile.Close();
afile = null;

请参阅this forum,其中回答了类似的问题。 (它使用的是带有asp.net的C#,但是在转换为vb.net时应该可以做到这一点)