1

当我们的 C# 应用程序缺少依赖项时,它会报告此“找不到模块”错误对话框。不幸的是,这个对话框不包括它找不到的文件的名称。在这种情况下,缺少的依赖项是 DirectX dll D3DCompiler_43.dll。如果客户报告“找不到模块”这不是很有帮助,但如果他们报告找不到文件的名称,它至少给了我们一个线索。

我们能否捕获此异常并生成一个错误对话框,其中包含未找到的文件的名称?由于它发生在应用程序启动的早期(我相信在 main 之前)我们怎么能做到这一点?

错误对话框

4

5 回答 5

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 方法中使用,否则不会触发事件。它必须在您的代码中以单独的方法进一步调用,如上面的代码示例所示。

于 2012-12-03T23:31:13.250 回答
2

如果可以修改代码并重新部署:

  • 创建一个新的启动类(一个带有 Main() 的),确保在项目属性中选择该类
  • 确保系统外部的启动类没有“使用”和外部引用
  • 尝试/捕获对您以前的启动类的 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 太多,请从异常消息中复制所有内容并排除 - 加载的内容不是问题

于 2012-12-04T21:02:22.933 回答
1

有一个“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\

确保在文件夹名称后包含反斜杠并且该文件夹存在。

于 2012-12-06T18:29:36.310 回答
1

我认为您不能以编程方式执行此操作。但是,如果您可以访问机器,则可以打开“全局标志”以显示所谓的“加载程序快照”(显示加载程序快照(Windows 调试器)),至少可以识别问题。

这是一篇关于它的文章,解释了如何做到这一点:Debugging LoadLibrary Failures

于 2012-12-03T09:03:25.407 回答
1

让您的客户在您的 exe 上运行depends.exe,将结果保存到文件中并将此文件发送给您。

于 2012-11-21T12:11:36.057 回答