Удаление файлов завершается неудачно в соответствии с существующим процессом - PullRequest
2 голосов
/ 25 июня 2009

У меня проблемы с небольшим количеством кода, который я пишу на C #.

Я отправляю документ с использованием компонентов MailMessage и SMTP. Я копирую файлы, которые хочу отправить, во временный каталог, например, c: \ temp, перебираю документы и прикрепляю их к электронному письму.

Письмо отправляется нормально, однако, когда я пытаюсь удалить файлы из временного каталога, я получаю следующую ошибку:

Процесс не может получить доступ к файлу, поскольку он используется другим процессом

Я не могу понять, почему это происходит. Ниже приведен код, который обрабатывает документы

public void sendDocument(String email, string barcode, int requestid)
    {

        string tempDir = @"c:\temp";

        //first we get the document information from the database.
        Database db = new Database(dbServer, dbName, dbUser, dbPwd);

        List<Document> documents = db.getDocumentByID(barcode);
        int count = 0;
        foreach (Document doc in documents)
        {
            string tempPath = tempDir + "\\" + doc.getBarcode() + ".pdf";
            string sourcePath = doc.getMachineName() + "\\" + doc.getFilePath() + "\\" + doc.getFileName();

            //we now copy the file from the source location to the new target location
            try
            {
                //this copies the file to the folder
                File.Copy(sourcePath, tempPath, false);

            }
            catch (IOException ioe)
            {
                count++; 

                //the file has failed to copy so we add a number to the file to make it unique and try
                //to copy it again.
                tempPath = tempDir + "\\" + doc.getBarcode() + "-" + count + ".pdf";
                File.Copy(sourcePath, tempPath, false);

            }

            //we now need to update the filename in the to match the new location
            doc.setFileName(doc.getBarcode() + ".pdf");                

        }

        //we now email the document to the user.
        this.sendEmail(documents, email, null);

        updateSentDocuments(documents, email);

        //now we update the request table/
        db.updateRequestTable(requestid);


        //now we clean up the documents from the temp folder.
        foreach (Document doc in documents)
        {
            string path = @"c:\temp\" + doc.getFileName();
            File.Delete(path);
        }

    }

Я бы подумал, что метод this.sendEmail () отправил бы электронное письмо перед возвратом в метод sendDocument, так как я думаю, что именно объект smtp вызывает сбой при удалении.

Это метод sendEmail:

public void sendEmail(List<Document> documents, String email, string division)
    {
        String SMTPServer = null;
        String SMTPUser = null;
        String SMTPPwd = null;
        String sender = "";
        String emailMessage = "";

        //first we get all the app setting used to send the email to the users
        Database db = new Database(dbServer, dbName, dbUser, dbPwd);

        SMTPServer = db.getAppSetting("smtp_server");
        SMTPUser = db.getAppSetting("smtp_user");
        SMTPPwd = db.getAppSetting("smtp_password");
        sender = db.getAppSetting("sender");
        emailMessage = db.getAppSetting("bulkmail_message");

        DateTime date = DateTime.Now;

        MailMessage emailMsg = new MailMessage();

        emailMsg.To.Add(email);

        if (division == null)
        {
            emailMsg.Subject = "Document(s) Request - " + date.ToString("dd-MM-yyyy");
        }
        else
        {
            emailMsg.Subject = division + " Document Request - " + date.ToString("dd-MM-yyyy");
        }

        emailMsg.From = new MailAddress(sender);
        emailMsg.Body = emailMessage;

        bool hasAttachements = false;

        foreach (Document doc in documents)
        {

            String filepath = @"c:\temp\" + doc.getFileName();

            Attachment data = new Attachment(filepath);
            emailMsg.Attachments.Add(data);

            hasAttachements = true;


        }

        SmtpClient smtp = new SmtpClient(SMTPServer);

        //we try and send the email and throw an exception if it all goes tits.
        try
        {
            if (hasAttachements)
            {
                smtp.Send(emailMsg);
            }
        }
        catch (Exception ex)
        {
            throw new Exception("EmailFailure");
        }


    }

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

Я могу удалить файл (ы) после завершения работы приложения.

Ответы [ 3 ]

6 голосов
/ 25 июня 2009

Ваше сообщение электронной почты не удаляется, попробуйте удалить его после отправки:

 try
 {
      if (hasAttachements)
      {
          smtp.Send(emailMsg);         
      }
 }  
 catch ...
 finally
 {
      emailMsg.Dispose();
 }
1 голос
/ 25 июня 2009

Первый шаг - выяснить, какой процесс задерживает данный файл. Я бы взял инструментарий SysInternals и использовал команду handle.exe, чтобы определить, какой процесс удерживает файл.

Не зная, в каком процессе открыт файл, решить эту проблему невозможно.

Sysinternals Link: http://technet.microsoft.com/en-us/sysinternals/default.aspx

0 голосов
/ 09 июня 2010

Вот трюк, который я только что обнаружил, который, надеюсь, пригодится другим людям? Прежде чем добавлять вложения в сообщение, создайте вложение с помощью оболочки. Это обеспечивает правильную утилизацию, позволяя успешно удалить файл. Я не уверен, что отправка также должна быть в этом цикле; (когда я тестировал, сначала письма не проходили, потом через полчаса я был залит, поэтому решил оставить тестирование на время, когда сеть стала немного спокойнее)

using (Attachment attachment = new Attachment(filename))
{
    message.Attachments.Add(attachment);
    client.SendAsync(message, string.Empty);
}
File.Delete(filename);

У меня все равно работает нормально:)

Удачи,

JB

...