2

好吧,这就是交易...

我在 .NET 2.0 (C#) 中有一个 Windows (XP) 程序,它允许用户重命名给定的 .pdf 文件。(文件名是“结构描述性的”,因为它列出了有关文件本身内容的简单信息。)在程序的唯一形式上,有一个 LinkLabel 对象允许用户打开 .pdf 本身,以便他们可以看到他们正在重命名什么。

诀窍是,当用户进行适当的更改并单击“保存”按钮时,我希望显示 .pdf 的 Acrobat 窗口关闭,执行保存,检索“下一个”文件,以及新窗口立即打开显示下一个文件。

以下是相关的代码片段:

    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 = "Process has exited, so the requested information is not available."。如果不是因为两件事,这将是相当简单的......

1: pdfView.HasExited = true

2:该死的 pdf 查看器仍然打开!

这怎么可能?是否有我应该使用的进程命令来确保窗口关闭?仅供参考,该程序不引用 System.* 命名空间之外的任何内容,或者最终也仅引用 System.* 的内部构建类。

谢谢。

4

2 回答 2

0

试试这个。。

pdfView.Kill();
pdfView.WaitForExit();
于 2010-01-09T20:47:35.430 回答
0

经过进一步调查,我想我已经确定了发生了什么。

我没有详细说明工作流程细节,因为我无法可靠地复制这种情况。经过进一步尝试,我发现了两种可靠的情况......

  1. 多次单击该链接,然后单击保存。
  2. 单击链接,关闭查看器窗口,然后单击保存。

在每种情况下,问题都归结为 pdfViewer 指向的进程与用户正在执行的操作不同步。

  1. 如果多次单击该链接,则活动查看器位于与 pdfViewer 进程未连接的进程上,因此上面详述的看似不可能的情况。

  2. 如果单击链接并关闭窗口,则 pdfViewer 变量将保留,留下一个 HasExited = true 的进程。

所有这一切的带回家的教训如下:如果您从主用户界面运行一个单独的进程,请绝对确保您涵盖了外部进程可能发生的所有可能情况。

作为记录,Nick Guerrera 将我引向进程 ID 值得加分。这最终解决了它。

于 2010-01-11T18:22:47.347 回答