Случайно выброшенные исключения ввода-вывода в C # - PullRequest
3 голосов
/ 26 июля 2010

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

После того, как все это сделано, она удаляет исходные файлы иместные копии.Время от времени программа выдает ошибки, потому что она не может удалить локальные копии с моего компьютера.Это не ошибка каждой другой папки, которую он архивирует.Я выдам ошибку после выполнения 300 из них или после 5. Он выдаст одну из 3 следующих ошибок: «Каталог не пуст», «Файл используется другим процессом» или «Доступ к файлу запрещен».Я попытался установить атрибуты файла в нормальное состояние, используя принудительную сборку мусора и завершить процесс winzip вручную.

Я действительно не понимаю, почему он делает это только иногда.Я администратор на моем компьютере, и он должен иметь возможность удалять файлы.Я подумал, что что-то еще должно использовать его, но на моем компьютере не должно быть ничего другого, кроме программы в Visual Studio.Спасибо.

Ниже приведен метод очистки, при котором файлы не удаляются, а также метод архивации файлов.

[MethodImplAttribute(MethodImplOptions.NoInlining)]
    static void CleanUp(SqlConnection Connection, string jNumber, DirectoryInfo dir, bool error, string prefix)
    {
        if (!error | (!error & emptyFolder))
        {
            try
            {
                SqlCommand updateJob = new SqlCommand(string.Format("update job set archived = 1 where job = {0}", jNumber), sdiConnection);
                updateJob.ExecuteNonQuery();
            }
            catch
            {
                WriteToLog("SQL Error: " + jNumber, "There was an error changing the archive bit to 1 after the job has been archived");
            }

            try
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            catch
            {
                WriteToLog("Error cleaning up after processing job", "There was an error garbage collecting.");
            }


            try
            {
                //path of the temporary folder created by the program
                string tempDir = Path.Combine(Path.Combine(System.Environment.CurrentDirectory, "Temp"), jNumber);
                //path of the destination folder
                string destDir = Path.Combine(dir.ToString(), jNumber);
                //SetFileAttributes(tempDir);


                try
                {
                    File.Delete(tempDir + ".zip");
                }
                catch (System.IO.IOException)
                {
                    File.Delete(tempDir + ".zip");
                }
                try
                {
                    Directory.Delete(destDir, true);
                }
                catch (System.IO.IOException)
                {
                    Directory.Delete(destDir, true);
                }
                try
                {
                    Directory.Delete(tempDir, true);
                }
                catch (System.IO.IOException)
                {
                    Directory.Delete(tempDir, true);
                }

            }
            catch
            {

                WriteToLog("File Error: " + jNumber, "There was an error removing files and/or folders after the job has been archived. Please check the source server and destination server to make sure everything copied correctly. The archive bit for this job was set.");
                Directory.Delete(Path.Combine(System.Environment.CurrentDirectory, "Temp"), true);
                Directory.CreateDirectory(Path.Combine(System.Environment.CurrentDirectory, "Temp"));
            }
        }


static bool ZipJobFolder(string jNumber, string jPath)
    {
        try
        {
            string CommandStr = @"L:\ZipFiles\winzip32.exe";
            string parameters = "-min -a -r \"" + jNumber + "\" \"" + jPath + "\"";

            ProcessStartInfo starter = new ProcessStartInfo(CommandStr, parameters);
            starter.CreateNoWindow = true;
            starter.RedirectStandardOutput = false;
            starter.UseShellExecute = false;

            Process process = new Process();
            process.StartInfo = starter;
            Console.WriteLine("Creating .zip file");
            process.Start();
            process.WaitForExit();

            Process[] processes;
            string procName = "winzip32.exe";
            processes = Process.GetProcessesByName(procName);
            foreach (Process proc in processes)
            {
                Console.WriteLine("Closing WinZip Process...");
                proc.Kill();
            }

        }
        catch
        {
            WriteToLog(jNumber, "There was error zipping the files of this job");
            return false;
        }
        return true;
    }

Ответы [ 4 ]

1 голос
/ 27 июля 2010

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

Несколько способов справиться с этим: 1) В случае сбоя, поспите несколько секунд и попробуйте снова.2) Я бы, вероятно, не использовал WinZip и вместо этого использовал ZipStorer (http://zipstorer.codeplex.com/).. В процессе архивируется файл, и вам не придется выполнять шаг уничтожения, и у вас будет гораздо более детальный контроль.делайте молнии параллельно, раскручивая несколько потоков.

1 голос
/ 27 июля 2010

Я заметил такое поведение с помощью проводника Windows, при удалении больших папок с большим количеством файлов и подпапок.Но после небольшого ожидания, а затем повторного удаления, все работает нормально.

Из-за этого я всегда предполагал, что это было некорректное поведение операционной системы.

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

Если ошибки исчезнут, это может показаться связаннымв какой-то момент времени.Я сам хотел бы знать источник проблемы, хотя.

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

Вам просто нужно быть осторожным, чтобы не попасть в состояние бесконечной гонки.

Редактировать: Есть связанный вопрос о Как лучше всего дождаться освобождения блокировки файла проверить его на наличие идей.

Edit2: Вот еще одно возможное решение Подождите, пока файл не будет разблокирован в .Net

0 голосов
/ 27 июля 2010

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

0 голосов
/ 27 июля 2010

Одна вещь, которую я обнаружил, помогает мне не пытаться создавать временные файлы и каталоги за один вызов File.Move или File.Copy.Скорее, вручную создайте родительские каталоги, начиная с самого высокого уровня и работая вниз.Наконец, когда все родительские каталоги существуют, переместите или скопируйте файл.

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