簡體   English   中英

啟動第二個實例時,Adobe Reader進程失敗

[英]Adobe Reader process fails when starting second instance

在我們的C#WinForms應用程序中,我們通過Process類生成PDF文件並啟動Adobe Reader(或任何默認系統.pdf處理程序)。 由於我們的PDF文件可能很大(大約200K),我們處理Exited事件然后清理臨時文件。

打開文件然后再次關閉時,系統將根據需要運行。 但是,當打開第二個文件時(關閉Adobe Reader之前),第二個進程立即退出(因為Reader現在正在使用它的MDI權限)並且在我們的Exited處理程序中,我們的File.Delete調用應該失敗,因為它被現在加入的Adobe進程鎖定。 但是,在Reader中,我們得到:

打開此文檔時出錯。 找不到此文件。

不尋常的是,如果我在刪除文件之前放置一個調試器斷點並允許它嘗試(並失敗)刪除,那么系統就會按預期運行!

我很肯定該文件存在並且相當肯定,在啟動進程之前,文件的所有句柄/文件流都已關閉。

我們將使用以下代碼啟動:

// 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來存儲對Process對象的引用,以便它們保持在范圍內,以便可以成功引發Exited事件。

我們的清理/退出活動是:

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
    }
}

可能的解決方案:

  • 檢測到文件在另一個進程中仍處於打開狀態
  • 檢測到第二個進程尚未完全退出,而是在第一個進程中打開該文件

剛剛在幾天前處理過這個問題。

當沒有實例打開時,文檔將直接在新實例中打開。

當一個實例已經打開時,我相信該實例會產生一個你實際上沒有得到句柄的新實例。 發生的是控制立即返回到您的函數,然后在新實例有機會讀取文件之前刪除文件 - 因此它似乎不在那里。

我通過不立即刪除文件來“解決”這個問題,但是跟蹤列表中的路徑,然后在程序退出時對所有文件進行核對(在try / catch中使用空catch塊包裝每個刪除以防文件在此期間已經消失了)。

我建議采用以下方法:

  1. 在用戶的臨時目錄( Path.GetTempPath )中創建文件。 您可以在其下創建一些子文件夾。
  2. 嘗試僅在最后一個進程實例退出時刪除文件(即,您需要計算已啟動的進程數,退出時,減少計數以及何時變為零,嘗試刪除目前為止打開的(所有)文件)
  3. 嘗試在啟動和結束應用程序時清理創建的子文件夾(在臨時目錄下)。 您甚至可以嘗試使用計時器進行定期清理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM