.NET (C #) Процессы и Adobe Acrobat - PullRequest
2 голосов
/ 09 января 2010

Хорошо, вот сделка ...

У меня есть программа Windows (XP) в .NET 2.0 (C #), которая позволяет пользователям переименовывать данный файл .pdf. (Имя файла является «структурно описательным», так как оно выдает простую информацию о том, что находится в самом файле.) В единственной форме программы есть объект LinkLabel, который позволяет пользователю открывать сам файл .pdf, чтобы они могли видеть что они переименовывают.

Хитрость в том, что, когда пользователь вносит соответствующие изменения и нажимает кнопку «Сохранить», я хочу, чтобы окно Acrobat, показывающее .pdf, закрывалось, выполняемое сохранение, «следующий» файл извлекался и откроется новое окно для немедленно , отображающее следующий файл.

Вот соответствующие фрагменты кода:

    private void OpenViewer()
    {
        // NOTE: pdfView is of type Process, in case you're not familiar with
        // Process.Start().
        pdfView = System.Diagnostics.Process.Start(lnkFile.Links[0].LinkData.ToString());
    }

    private bool KillViewer()
    {
        bool result = (pdfView != null);

        if (pdfView != null)
        {
            pdfView.CloseMainWindow();
            pdfView.Close();
            pdfView.Dispose();
            pdfView = null;
            GC.Collect();

            // Verify that the lock is available before you return, as returning basically says:
            // "Yup, the file's available."
            bool locked = false;
            StreamWriter sw = null;
            do
            {
                try
                {
                    sw = new StreamWriter(new FileStream(lnkFile.Links[0].LinkData.ToString(), FileMode.Open));
                    locked = false;
                }
                catch (Exception)
                {
                    locked = true;
                }
            } while (locked);

            sw.Dispose();
        }

        return result;
    }

    private void SomeButtonEvent
    {
        // Record whether a viewer was open in the first place.
        bool viewerActive = KillViewer(); 

        PerformFileLockingMethod();
        GetNextFile()

        if(viewerActive)
        {
            OpenViewer();
        }
    }

Обратите внимание, что в KillViewer () в основном есть цикл захвата блокировки, чтобы убедиться, что программа не пытается переименовать рабочий файл до тех пор, пока программа просмотра PDF не снимет блокировку полностью.

Проблема заключается в следующем: иногда все это работает прекрасно, а иногда KillViewer прерывается при вызове CloseMainWindow () с исключением InvalidOperationException, details = "Процесс завершен, поэтому запрашиваемая информация недоступна". Это было бы довольно просто, если бы не две вещи ...

1: pdfView.HasExited = true

И

2: Проклятый просмотрщик PDF-файлов ЕЩЕ ОТКРЫТ !!!

Как в мире это возможно? Есть ли какая-нибудь команда процесса, которую я должен использовать, чтобы закрыть окно? К вашему сведению, программа не ссылается ни на что, кроме пространств имен System. * Или внутреннего класса, который в конечном итоге также ссылается только на System. *.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 11 января 2010

После дальнейшего расследования, я думаю, я определил, что происходит.

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

  1. Нажмите на ссылку несколько раз, а затем нажмите Сохранить.
  2. Нажмите на ссылку, закройте окно просмотра и нажмите «Сохранить».

В каждом из этих случаев проблема сводилась к тому, что процесс, на который указывает pdfViewer, не синхронизировался с тем, что делал пользователь.

  1. Если ссылка была нажата несколько раз, то активный зритель находился в процессе, не связанном с процессом pdfViewer, следовательно, на первый взгляд невозможная ситуация описана выше.

  2. Если щелкнуть ссылку и закрыть окно, переменная pdfViewer останется, оставив процесс с HasExited = true.

Извлеките урок из всего этого следующим образом: если вы запускаете отдельный процесс от основного пользовательского интерфейса, убедитесь, что вы АБСОЛЮТНО УБЕДИТЕСЬ, что вы охватили все возможные ситуации, которые могут возникнуть с внешним процессом.

Для справки, Ник Геррера заслуживает очков за то, что указал мне на идентификаторы процессов. Это в конечном счете решило это.

0 голосов
/ 09 января 2010

Попробуйте вместо этого ..

pdfView.Kill();
pdfView.WaitForExit();
...