Процесс считывателя Adobe сбое не работает при запуске второго экземпляра

StackOverflow https://stackoverflow.com/questions/4496373

Вопрос

В нашем приложении C# Winforms мы генерируем файлы PDF и запускаем Adobe Reader (или какой бы то ни было системой по умолчанию. Process учебный класс. Поскольку наши файлы PDF могут быть большими (около 200 тысяч), мы обрабатываем Exited Событие, чтобы затем очистить временный файл впоследствии.

Система работает по мере необходимости, когда файл открывается, а затем снова закрыта. Однако, когда открывается второй файл (перед закрытием Adobe Reader), второй процесс немедленно выходит (поскольку читатель теперь использует свои полномочия MDI) и в нашем Exited Обработчик нашего файла. Delete Call должен сбой, потому что он заблокирован теперь присоединенным процессом Adobe. Однако в читателе мы вместо этого получаем:

Была ошибка, открывающая этот документ. Этот файл не может быть найден.

Необычная вещь заключается в том, что если я помесчу точку останова отладчика перед удалением файла и позволит ему попытаться (и терпеть неудачу) удаление, то система ведет себя так, как и ожидалось!

Я уверен, что файл существует и довольно положительно, что все потоки файлов/файлов к файлу закрыты перед запуском процесса.

Мы запускаем следующий код:

// Open the file for viewing/printing (if the default program supports it) 
var pdfProcess = new Process();
pdfProcess.StartInfo.FileName = tempFileName;
if (pdfProcess.StartInfo.Verbs.Contains("open", StringComparer.InvariantCultureIgnoreCase))
{
    var verb = pdfProcess.StartInfo.Verbs.First(v => v.Equals("open", StringComparison.InvariantCultureIgnoreCase));
    pdfProcess.StartInfo.Verb = verb;
}
pdfProcess.StartInfo.Arguments = "/N"; // Specifies a new window will be used! (But not definitely...)
pdfProcess.SynchronizingObject = this;
pdfProcess.EnableRaisingEvents = true;
pdfProcess.Exited += new EventHandler(pdfProcess_Exited);

_pdfProcessDictionary.Add(pdfProcess, tempFileName);

pdfProcess.Start();

Примечание: мы используем _pdfProcessDictionary Чтобы хранить ссылки на объекты процесса, чтобы они оставались в сфере действия, чтобы можно было успешно поднять выходящее событие.

Наше мероприятие по очистке/выходу:

void pdfProcess_Exited(object sender, EventArgs e)
{
    Debug.Assert(!InvokeRequired);
    var p = sender as Process;
    try
    {
        if (_pdfProcessDictionary.ContainsKey(p))
        {
            var tempFileName = _pdfProcessDictionary[p];
            if (File.Exists(tempFileName)) // How else can I check if I can delete it!!??
            {
                // NOTE: Will fail if the Adobe Reader application instance has been re-used!
                File.Delete(tempFileName);
                _pdfProcessDictionary.Remove(p);
            }

            CleanOtherFiles(); // This function will clean up files for any other previously exited processes in our dictionary
        }
    }
    catch (IOException ex)
    {
        // Just swallow it up, we will deal with trying to delete it at another point
    }
}

Возможные решения:

  • Обнаружение, что файл все еще открыт в другом процессе
  • Обнаружение того, что второй процесс не был полностью вышел полностью и что файл открыт в первом процессе вместо этого
Это было полезно?

Решение

я просто Работал с этим пару дней назад.

Когда уже нет экземпляра, уже открыт, документ открывается непосредственно в новом экземпляре.

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

Я «решил» это, не сразу не удаляя файлы, а отслеживая пути в списке, а затем покинув все из них, когда программа выходит (оберните каждое удаление в попытке/поймать пустым блоком улова на случай, если файл исчез в то же время).

Другие советы

Я бы предложил следующему подходу:

  1. Создать файлы в каталоге пользователя (Temp (Path.gettemppath) Вы можете создать немного подразделения под ним.
  2. Попытайтесь удалить файлы только тогда, когда выйдет последний экземпляр процесса (то есть вам нужно подсчитать количество процессов, которые вы запустили, на выходе, уменьшите количество и когда он становится нулевым, попытаться удалить (все) файлы, которые открыты до сих пор )
  3. Попробуйте очистить созданный подраздел (в рамках каталога Temp), запуская и заканчивая приложение. Вы даже можете попытаться периодической очистки с помощью таймера.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top