2012-02-08 9 views
5

Ho un certo numero di file che vengono generati in una funzione definita come:Il file sembra essere tenuto aperto dopo essere stato inviato come allegato da SmtpClient. Come posso cancellare il file?

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 

Questi file vengono immediatamente stampate ed i file vengono automaticamente salvati in una directory; i file stessi non sono utilizzati dagli utenti effettivi del software. Timestamp i file per mantenerli identificati in modo univoco a fini di controllo.

Ora ho ricevuto l'obbligo di inviare alcuni di questi file esternamente all'azienda e qualcuno si è lamentato del fatto che i nomi file correnti non siano di facile utilizzo.

Così, ho provato a copiare il file generato in una directory temporanea, con un nome più amichevole, e-mail il file più amichevole, quindi eliminarlo, lasciando intatta la mia pista di controllo, in questo modo:

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 

Questo getta una System.IO.IOException sulla riga System.IO.File.Delete(friendlyFilePath) perché il file è ancora in uso, dopo che è stato inviato per e-mail.

Ho eliminato il codice e-mail, il che rende la copia e l'eliminazione funzionanti, quindi è apparentemente allegando il file all'e-mail che causa il problema.

Ho anche provato il breakpointing prima della riga di eliminazione, aspettando cinque minuti, confermando che l'e-mail è stata inviata, quindi facendo avanzare il codice, ma la stessa eccezione è ancora generata.

Qualcuno può suggerire come risolvere questo problema?

+0

Qualche possibilità che nella regione [Vasta quantità di codice] tu abbia un flusso di qualche tipo che non hai chiuso? –

risposta

7

SmtpClient non rilascia l'handle per un allegato. Dovrai gestirlo manualmente, o, cosa faccio, è prima di tutto copiare il contenuto del file in un MemoryStream. Il codice qui sotto dovrebbe funzionare pure.

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

Yup. Smaltimento manuale di tutti gli allegati del messaggio di posta elettronica dopo l'invio. Problema risolto. Grazie. – Frosty840

3

È necessario utilizzare l'istruzione Using durante l'accesso a File. Ciò smaltire l'oggetto e si dovrebbe essere in grado di chiamare il vostro System.IO.File.Delete()

vedere qui: http://msdn.microsoft.com/en-us/library/htd05whh(v=vs.80).aspx

+0

Questo è il risultato migliore ... a meno che tu non [per qualsiasi motivo] non utilizzi come 'using' (quindi usa la soluzione @ Nasir) –

0

hai chiuso il tuo file allegato dopo che hai creato?

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

Vedi this forum in cui una domanda simile è stato risposto. (E 'in C# con asp.net, ma dovrebbe fare il trucco quando convertito in vb.net)

+0

Il file che si sta eliminando viene creato usando 'System.IO.File.Copy', quindi il tuo la domanda non si applica. – Frosty840

11

dopo mailClient.Send(message); aggiungere message.Attachments.Dispose();

Questo rilascerà le risorse di attacco

1

Mentre mi rendo conto l'ultimo post su questo articolo è stato qualche anno fa ho pensato che valesse la pena aggiungere una piccola quantità di informazioni aggiuntive per chiunque non sia a conoscenza ...

Se si invia la tua e-mail in modo asincrono, non puoi usare "usare" o disporre di nulla fino a quando non viene attivato il callback, è necessario inviare l'istanza di MailMessage a s il parametro UserState di SendAsync(). In tal modo, quando viene attivato il callback, sarà possibile smaltire gli allegati e l'istanza di MailMessage. È inoltre possibile eliminare il client di posta in quanto sarà l'oggetto del mittente.

Problemi correlati