.net SmtpClient将文件作为附件发送后,文件似乎保持打开状态。如何删除该文件?

.net SmtpClient将文件作为附件发送后,文件似乎保持打开状态。如何删除该文件?,.net,vb.net,email,smtpclient,.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 Gen

我有许多文件是在函数中生成的,定义为:

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.File.Delete(friendlyFilePath)
行上抛出
System.IO.IOException
,因为该文件在通过电子邮件发送后仍在使用中

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

我还尝试在删除行之前中断,等待五分钟,确认电子邮件已发送,然后推进代码,但仍然引发相同的异常


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

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);
}

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


请参见此处:

创建附件文件后是否关闭了它

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

查看类似问题的答案。(它是用asp.net编写的C#,但在转换为vb.net时应该能做到这一点)

mailClient.Send(message)之后
add
message.Attachments.Dispose()


这将释放附件资源

,而我意识到这篇文章的最后一篇文章是几年前发布的,我认为值得为任何不知道的人添加少量附加信息


如果您以异步方式发送电子邮件,则在回调触发之前,您不能使用“using”或处理任何内容,而是应将MailMessage实例作为SendAsync()的UserState参数发送。这样,当调用回调时,您将能够处理任何附件和MailMessage实例。您还可以处置邮件客户端,因为它将是发件人对象。

在[海量代码]区域中,您是否有某种尚未关闭的流?要删除的文件是使用
System.IO.file.Copy
创建的,因此您的问题不适用。是的。发送邮件后,手动处理邮件的所有附件。解决了这个问题。谢谢。这是更好的结果……除非你[出于任何原因]不使用as“using”(然后使用@Nasir的解决方案)