当我们的 C# 应用程序缺少依赖项时,它会报告此“找不到模块”错误对话框。不幸的是,这个对话框不包括它找不到的文件的名称。在这种情况下,缺少的依赖项是 DirectX dll D3DCompiler_43.dll。如果客户报告“找不到模块”这不是很有帮助,但如果他们报告找不到文件的名称,它至少给了我们一个线索。
我们能否捕获此异常并生成一个错误对话框,其中包含未找到的文件的名称?由于它发生在应用程序启动的早期(我相信在 main 之前)我们怎么能做到这一点?
尝试订阅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 方法中使用,否则不会触发事件。它必须在您的代码中以单独的方法进一步调用,如上面的代码示例所示。
如果可以修改代码并重新部署:
在消息框(或调试日志)中打印出异常和所有内部异常
公共类 MyNewEntryClass{
公共静态无效 Main(){
try{
MyPreviousEntryClass.Main();
} catch (Exception x){
Exception ix = x;
while (ix!=null){
MessageBox.Show("Exception: "+ix);
ix=ix.InnerException;
}
}
} }
编辑:我看到您的异常来自消息处理程序。上述代码编辑可以(并且应该)应用于所有入口方法,其中包括处理来自代码外部的事件的所有事件处理程序。上面的崩溃屏幕可能会显示各种处理程序中的异常,异步执行的代码。例如,带有异步调用的按钮处理程序应该有两个 try/catch 以防止崩溃窗口出现:
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){
}
}
上面的语句也适用于 Windows 消息处理——它只是外部事件的另一个事件处理程序
如果您无法修改代码并重新部署使用 Sysinternals Process Monitor: http ://technet.microsoft.com/en-us/sysinternals/bb896645 将其配置为监控您的应用程序并突出显示文件未找到事件(有关详细信息,请参阅他们的文档)
如果 ProcessMonitor 太多,请从异常消息中复制所有内容并排除 - 加载的内容不是问题
有一个“Fuison Log”,可以通过设置几个注册表项来打开。它有助于识别任何类型的程序集加载问题。您所需要的只是来自客户 PC 的日志文件。
有关详细信息,请参阅https://stackoverflow.com/a/1527249/1288776。
如果链接不可用:
将以下值添加到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion
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\
确保在文件夹名称后包含反斜杠并且该文件夹存在。
我认为您不能以编程方式执行此操作。但是,如果您可以访问机器,则可以打开“全局标志”以显示所谓的“加载程序快照”(显示加载程序快照(Windows 调试器)),至少可以识别问题。
这是一篇关于它的文章,解释了如何做到这一点:Debugging LoadLibrary Failures
让您的客户在您的 exe 上运行depends.exe,将结果保存到文件中并将此文件发送给您。