Process.WaitForExit не ждет, a Process.Kill не убивает - удаление файла после завершения процесса

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

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

Примерный код. SimpleForm.exe здесь примитивная программа с одним окном, создаваемая студией по умолчанию для соответствующего типа проекта. При желании протестировать разные промежутки времени в нее можно добавить таймер, закрывающий приложение через пару секунд. Более сложные варианты могут включать в себя поиск существующего процесса по имени или коду.

            using System.Diagnostics;
            using System.IO;
            // какой-то код
            string directory = Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().Location );
            string path = directory  + "\\SimpleForm.exe";
            ProcessStartInfo processStartInfo = new ProcessStartInfo();
            processStartInfo.FileName = path;

            Process process = Process.Start(processStartInfo);
            process.Kill();
            //process.WaitForExit(2000);

            try
            {
                File.Delete(path);
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }


Для начала мы можем столкнуться с тем, что Process.WaitForExit банально ни фига не ждет. Чтобы он начал это делать надо выставить свойство процесса EnableRaisingEvents в true. Теперь метод заработает, но ошибка никуда не исчезнет.

Причина проста - после завершения работы процесса системе требуется некоторое время на уничтожение его объектов в памяти и снятие блокировок с файлов. Отследить это стандартными средствами невозможно, так что придется пойти обходным путем, смысл которого понятен из примера кода - пытаться удалять файл через небольшие промежутки времени.

                bool deleted = !File.Exists(newFilePath);
                while (!deleted)
                {
                    try
                    {
                        File.Delete(newFilePath);
                        deleted = true;
                    }
                    catch (UnauthorizedAccessException)
                    {
                        deleted = false;
                    }
                    // чтобы не ждать 100 миллисекунд если файл уже свободен
                    if (!deleted)
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                }

Process.WaitForExit() doesn't actually wait for the process to completely exit?
Process.WaitForExit not waiting
Why does Process.WaitForExit block even though I have it in a separate thread?
Thread Class


Комментарии

Process.WaitForExit не ждет, a Process.Kill не убивает - удаление файла после завершения процесса — 1 комментарий

  1. Есть такое дело, у меня подобный код, но самое интересное, что после удаления exe файла даже через паузу как тут описано, у меня идет копирование другого exe на его место, так вот, копирование тоже пришлось делать через паузу, несмотря на то, что файл удалил))) Да, на копировании реже вылетает чем на удаление, но вылетает!))) Причем чем сильнее загружены CPU и память, тем чаще.

Добавить комментарий для Игорь Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *


*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>