2012-11-20 17 views
1

當我們的C#應用​​程序缺少依賴項時,它會報告此「無法找到模塊」錯誤對話框。不幸的是,這個對話框不包括它找不到的文件的名稱。在這種情況下,缺失的依賴項是DirectX dll D3DCompiler_43.dll。如果客戶報告「無法找到模塊」,這不是很有用,但如果他們報告沒有找到文件的名稱,它至少會給我們提供線索。如何獲取「無法找到模塊」錯誤對話框的文件名

我們可以捕捉到這個異常併產生一個錯誤對話框,其中包含未找到的文件的名稱?由於它發生在應用程序啓動的早期(在我相信主要之前),我們該怎麼做呢?

Error Dialog

+0

我希望有一種方法來安裝處理程序來捕獲此異常,然後報告包含未找到文件的名稱的錯誤消息。該應用程序加載100多個dll,因此如果沒有指示缺少的內容就會得到「缺少某些內容」的錯誤是超級無用的。 – Philip

+0

我說它發生得早,主要之前。這是不正確的,我可以在錯誤發生之前通過主罰。當我跨過發生錯誤時的Application.Run。 – Philip

+0

我實際上可以用[ThreadExceptionEventHandler](http://www.csharp-examples.net/catching-unhandled-exceptions/)捕獲這個異常。但是我看不到它正在查找的DLL的名稱,只是「找不到指定的模塊」,因此沒有任何幫助。 – Philip

回答

1

我不認爲你可以以編程方式做到這一點。但是,如果您有權訪問機器,則可以打開一個「全局標誌」來顯示所謂的「Loader Snaps」(至少用於識別問題)(Show loader snaps (Windows Debuggers))。

下面是關於它的文章,解釋如何做到這一點:Debugging LoadLibrary Failures

+0

這看起來像一個偉大的調試技術。但是,它並不能解決如何讓應用程序在未修改的機器上報告丟失文件的問題。但絕對很好知道,謝謝。 – Philip

+0

接受這一個,因爲它說你不能這樣做,你不能以編程方式獲取缺少的DLL的名稱。沒有嘗試加載程序捕捉部分,我使用Process Monitor來找出DLL的名稱作爲一次性的事情。但真的想讓EXE直接向用戶報告缺少的DLL的名稱。在我看來,這似乎不可能。 – Philip

1

讓你的客戶對你的EXE運行depends.exe,將結果保存到一個文件,這文件發送給您。

+0

好主意,但是DirectX DLL不依賴於依賴項。也許是因爲雖然它是一個C#應用程序,但我們鏈接到引入DirectX的C++庫。 – Philip

+0

嘗試Depends4Net,http://www.codeproject.com/Articles/246858/Depends4Net-Part-1 – Flot2011

2

嘗試訂閱當應用程序無法找到所需的組件,其觸發的事件AssemblyResolve。在此事件的處理程序中,您可以提供您自己的消息框,其中包含程序集的名稱以及任何其他您喜歡的信息。

public static void Main() 
{    
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyNotFoundEventHandler); 

    InvokeExternalType(); 
} 

private static Assembly ResolveEventHandler(object sender, ResolveEventArgs args) 
{ 
    MessageBox.Show("Error, can't find assembly: " + args.Name, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error); 
    return null; 
} 

private static void InvokeExternalType() 
{ 
    MyClass doc = ... // from an external assembly. 
} 

有一個掛鉤,其中外部類型(即可能屬於失蹤組裝)不得在main方法中使用,否則該事件不會被解僱。必須在代碼中以上述代碼示例中所示的單獨方法進一步調用它。

+0

聽起來很有前途,但我嘗試過。在我們的情況下不會發射。也許是因爲所討論的DLL是純粹的C++,它實際上並不是一個Assembly?因爲我們有一個C#應用程序,它鏈接到引用系統(directx)DLL的C++代碼。這個ResolveEventHandler似乎不會觸發,如果directx DLL是mising。 – Philip

2

如果你可以修改代碼和重新部署:

  • 創建一個新的啓動類(一個主()),請確保您選擇在項目屬性該類
  • 確保沒有「使用「從你的啓動類系統
  • 外面和外部參考
  • 把一個try/catch圍繞一個電話到以前的啓動類的主要
  • 打印出異常,並在消息框中的所有內部異常(或調試日誌)

    公共類MyNewEntryClass {

    公共靜態無效的主要(){

    try{ 
         MyPreviousEntryClass.Main(); 
        } catch (Exception x){ 
        Exception ix = x; 
        while (ix!=null){ 
         MessageBox.Show("Exception: "+ix); 
         ix=ix.InnerException; 
        } 
        } 
    

    }}

編輯:我看到你的異常是從一個消息處理程序來。上面的代碼編輯可以(也應該)應用於所有的入口方法,其中包括處理代碼之外事件的所有事件處理程序。上面的崩潰屏幕可能會顯示各種處理程序中的異常,即異步執行的代碼。例如 - 異步調用一個按鈕處理程序應該有兩個試/漁獲量,以防止碰撞窗從顯示出來:

private void Button_Clicked(object sender, EventArgs arg){ 
    try{ 
     Action<string> asyncCall = (s)=>{ 
      try{ 
       //...exception here will cause crash 
       // as it's not handled in Button_Clicked 
      } catch (Exception xOnAsyncThread){ 
      } 
     }; 
     asyncCall.BeginInvoke("outahere",null,null); 
    } catch (Exception xOnUIThread){ 
    } 
} 

上面的語句是用於處理以及窗口消息真的 - 它只是一個之外的另一個事件處理程序事件

如果您不能修改代碼並重新部署使用的Sysinternals的Process Monitor: http://technet.microsoft.com/en-us/sysinternals/bb896645 配置它來監控你的應用程序和亮點文件未找到事件(見他們的文檔獲取詳細信息)

如果是的ProcessMonitor太多從異常消息複製所有內容,並通過去排斥 - 已加載的那些都不是問題

+0

嘗試了第一個片段。聰明的主意有第二主力,但在這種情況下沒有幫助。看起來像這樣會有助於如果在輸入原始主體之前發生異常情況。但我的例外情況是在主進入後發射。我已經在原始主體周圍試過了。這並沒有捕捉到這個例外,在這個「外部」主要也沒有。 – Philip

+0

第二個片段我不清楚該放哪裏。這是在應用程序啓動時沒有點擊按鈕或類似的處理程序。我在WndProc上放了一個斷點,在FileNotFoundException發生之前它不會被調用,所以我不知道它爲什麼在堆棧中。 – Philip

+0

第二個片段說明__any__事件處理程序,如WndProc或Button_Clicked。 如果你的WndProc沒有被擊中,那麼嘗試通過一個包裝來調用它 - 應用與上述Main相同的邏輯到你的WndProc;這意味着一個沒有引用的新類,只是靜態的WndProc方法,它會調用原始的方法。此外 - 訂閱AppDomain.CurrentDomain.AssemblyResolve和AppDomain.CurrentDomain.UnhandledException事件,並在消息框中顯示您從中獲得的信息 –

1

有一個「Fuison日誌」,它可以通過設置來開啓幾個註冊表項。它有助於識別任何類型的裝配加載問題。您需要的只是客戶PC上的日誌文件。
詳情請參閱https://stackoverflow.com/a/1527249/1288776
如果該鏈接不可用:
添加下列值HKEY_LOCAL_MACHINE \ SOFTWARE \微軟\融合

DWORD ForceLog set value to 1 
DWORD LogFailures set value to 1 
DWORD LogResourceBinds set value to 1 
String LogPath set value to folder for logs ie) C:\FusionLog\ 

確保您包括文件夾名後,該文件夾存在反斜槓。

+0

這很好理解,但我們真正想要的是在未修改的PC上運行的EXE,它可以報告缺少的dll的名稱。但是,謝謝,這很有用。 – Philip

+0

我能夠打開這個日誌,但它沒有任何有關缺少DLL的信息。看起來像這是所有IL /組裝的東西,純粹的C/C + + DLL的不包括在內。也許我錯過了一些東西,但是我通過所有日誌產品爲我們缺少的DLL以及一般DLL的grepped,並沒有看到正常的系統DLL。 – Philip