Похоже, что файл остается открытым после отправки SmtpClient в качестве вложения.Как я могу удалить файл? - PullRequest
7 голосов
/ 08 февраля 2012

У меня есть ряд файлов, которые создаются в функции, определенной как:

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 ]

13 голосов
/ 01 августа 2012

после mailClient.Send(message); добавить message.Attachments.Dispose();

Это освободит ресурсы вложения

7 голосов
/ 08 февраля 2012

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);
}
3 голосов
/ 08 февраля 2012

Вы должны использовать оператор Using при доступе к файлам.Это избавит вас от вашего объекта, и вы сможете вызвать ваш System.IO.File.Delete ()

, см. Здесь: http://msdn.microsoft.com/en-us/library/htd05whh(v=vs.80).aspx

1 голос
/ 31 октября 2016

Хотя я понимаю, что последний пост этой статьи был несколько лет назад, я подумал, что стоит добавить небольшое количество дополнительной информации для тех, кто не знает ...

Если вы отправляете свою электронную почту асинхронно, тогда выне может использовать «использование» или распоряжаться чем-либо до тех пор, пока не сработает обратный вызов, вместо этого вы должны отправить свой экземпляр MailMessage в качестве параметра UserState функции SendAsync ().Таким образом, когда обратный вызов сработает, вы сможете избавиться от любых вложений и экземпляра MailMessage.Вы также можете утилизировать почтовый клиент, поскольку он будет объектом отправителя.

0 голосов
/ 08 февраля 2012

Вы закрыли свой файл вложения после того, как создали его?

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

См. этот форум , на который был дан ответ на похожий вопрос.(Это в C # с asp.net, но это должно сработать при преобразовании в vb.net)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...