返璞归真:使用Fusion Log Viewer调试模糊的加载程序错误

戴靖
2023-12-01

UPDATE: There is a new modern open source alternative to Fusion Log Viewer called Fusion you should check out!

更新: Fusion Log Viewer有一个新的现代开源替代品,名为Fusion,您应该签出!

It's time to remind people about Fusion. Mostly because I don't see as many people using it as should. I mentioned it as long as six (!) years ago and it's still useful. I used it just this week with .NET 4.

现在该提醒人们有关融合的知识了。 主要是因为我没有看到太多使用它的人。 我早在六(!)年前就提到了它,但它仍然很有用。 我刚刚在.NET 4中使用了它。

Sometimes when an assembly doesn't load, there's still a sense/feeling that "something in the black box has broken." For some folks, the black box is larger and obscures more, than for others. My point is, if you know where to look, there is no box at all.

有时,当装配体不加载时,仍然会感觉到“黑匣子中的某物已损坏”。 对于某些人来说,黑匣子比其他人更大,并且遮盖得更多。 我的意思是,如果您知道要看哪里,根本就没有盒子。

When it comes to assemblies there's three "times" to know about:

当涉及到装配时,需要了解三个“时间”:

  • Binding before it happens - What do you want?

    绑定之前发生-您想要什么?

    • ILDASM or Reflector will tell you what your assembly wants (what it was compiled against)

      ILDASM或Reflector会告诉您程序集需要什么(针对其进行了编译)

    Binding before it happens - What do you want?

    绑定之前发生-您想要什么?

  • Binding as it happens - Where does it look?

    发生绑定-看起来在哪里?

    • Fusion (the Assembly Binding Log Viewer) will show you all assembly binds if you set the HKLM\Software\Microsoft\Fusion\ForceLog registry value to 1

      如果将HKLM \ Software \ Microsoft \ Fusion \ ForceLog注册表值设置为1, Fusion(程序集绑定日志查看器)将显示所有程序集绑定

    Binding as it happens - Where does it look?

    发生绑定-看起来在哪里?

  • Binding after it happens - What did you get?

    绑定发生后-您得到了什么?

    • Process Explorer will tell you what DLL (assembly) is loaded in memory and from where it came.

      Process Explorer将告诉您内存中加载了哪些DLL(程序集)以及它从何处加载

    Binding after it happens - What did you get?

    绑定发生后-您得到了什么?

Here's an example of how a tiny bit of digging saved me hours of confusion recently when I hit an unusual edge case. I was doing a build of sample that was showing C# interop-ing with IronPython, but I was using a daily build of .NET 4 and a random build of IronPython.

这是一个示例,说明当我遇到异常情况时,最近的一点点挖掘如何使我避免了数小时的混乱。 我正在构建一个示例,该示例显示了与IronPython进行C#互操作,但是我使用的是.NET 4的每日版本和IronPython的随机版本。

I made a mistake and had some really old DLLs floating around that I shouldn't have had. My symptom was a FileNotFoundException for the file "System.Dynamic.dll." I KNEW it was in the GAC (Global Assembly Cache) and I could SEE it as a reference DLL in my directory. Can't find the file? Dude, it's right there!

我犯了一个错误,周围有一些我本不应该拥有的非常老的DLL。 我的症状是文件“ System.Dynamic.dll”的FileNotFoundException。 我知道它在GAC(全局程序集缓存)中,可以将其作为目录中的参考DLL看到。 找不到文件? 杜德,就在那!

开启Fusion Logging (Turning on Fusion Logging)

You probably have a tool to help on your development system already. Type "Fusion" in the Start Menu. The Assembly Binding Log Viewer, or "Fusion Log Viewer" will tell the CLR to load assembling binding/loading activities to a folder, then let you see them.

您可能已经有了可以帮助您开发系统的工具。 在“开始”菜单中键入“融合”。 程序集绑定日志查看器或“融合日志查看器”将告诉CLR将组装绑定/加载活动加载到文件夹,然后让您查看它们。

Be sure to run it as Administrator if you want to change the Settings, otherwise they'll be grayed out.

如果要更改设置,请确保以管理员身份运行它,否则它们将显示为灰色。

Alternatively, just set the Registry keys your self. (I just memorized them, as I set them all the time.) Set HKLM\Software\Microsoft\Fusion\ForceLog registry value to 1 and HKLM\Software\Microsoft\Fusion\LogPath registry value to C:\FusionLogs or some path that exists.

或者,只需将注册表项设置为您自己。 (我一直记住它们,因为我一直在设置它们。)将HKLM \ Software \ Microsoft \ Fusion \ ForceLog注册表值设置为1,并将HKLM \ Software \ Microsoft \ Fusion \ LogPath注册表值设置为C:\ FusionLogs或存在。

Personally, I leave this on all the time on my dev machines (there's a small speed hit) and just clean the folder out every once in a while.

就个人而言,我一直将它一直留在我的开发机器上(速度影响不大),只是不时清理一下文件夹。

解决我的绑定问题 (Solving My Binding Problem)

Once I turned on Fusion Logging I could immediately see a failure in my folder:

打开融合日志记录后,我可以立即在文件夹中看到故障:

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.xxxxx\clr.dll
Running under executable C:\Users\Scott\Desktop\TechEd09\FX4\Demo 5 - DLR\Two.IronPythonInterop\bin\Debug\Two.IronPythonInterop.exe
--- A detailed error log follows.

=== Pre-bind state information ===
LOG: User = HANSELMAN-DEV10\Scott
LOG: DisplayName = System.Dynamic, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
LOG: Appbase = file:///C:/Users/Scott/Desktop/TechEd09/FX4/Demo 5 - DLR/Two.IronPythonInterop/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = Two.IronPythonInterop.exe
Calling assembly : IronPython, Version=2.6.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.xxxxx\config\machine.config.
LOG: Post-policy reference: System.Dynamic, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Users/Scott/Desktop/TechEd09/FX4/Demo 5 - DLR/Two.IronPythonInterop/bin/Debug/System.Dynamic.DLL.
LOG: Attempting download of new URL file:///C:/Users/Scott/Desktop/TechEd09/FX4/Demo 5 - DLR/Two.IronPythonInterop/bin/Debug/System.Dynamic/System.Dynamic.DLL.
LOG: Attempting download of new URL file:///C:/Users/Scott/Desktop/TechEd09/FX4/Demo 5 - DLR/Two.IronPythonInterop/bin/Debug/System.Dynamic.EXE.
LOG: Attempting download of new URL file:///C:/Users/Scott/Desktop/TechEd09/FX4/Demo 5 - DLR/Two.IronPythonInterop/bin/Debug/System.Dynamic/System.Dynamic.EXE.
LOG: All probing URLs attempted and failed.

You can see that it's looking all over for the file, first in the GAC< then all over the local folders before it gives up. Hm. Why isn't this working? I can see the file sitting right there.

您会看到它一直在寻找文件,首先是在GAC <中,然后是整个本地文件夹,然后再放弃。 嗯为什么这不起作用? 我可以看到文件就在那里。

Well, what's the public key token for this signed assembly? I can run "sn -T" on the file:

那么,此签名程序集的公钥令牌是什么? 我可以在文件上运行“ sn -T”:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0>
sn -T System.Dynamic.dll

Microsoft (R) .NET Framework Strong Name Utility Version 4.0.xxxxx.1
Copyright (c) Microsoft Corporation. All rights reserved.

Public key token is b03f5f7f11d50a3a

Wha? What's b03whatever? That's not b77whatever like the one my app is looking for! Looks like my sample app had reference not only an old version of System.Dynamic, but one with a completely different public key. That's what I get for not cleaning out my obj directories between daily builds.

ha? 什么是b03 ? 那不是b77,就像我的应用程序正在寻找的那种! 看起来我的示例应用程序不仅引用了System.Dynamic的旧版本,而且引用了完全不同的公钥。 这就是我在日常构建之间不清理我的obj目录所得到的。

This could have been just by setting the registry keys and watching the c:\fusionlogs folder, but the Fusion Log Viewer makes the process more user-friendly.

这可能只是通过设置注册表项并查看c:\ fusionlogs文件夹,但Fusion Log Viewer使该过程更加用户友好。

If you're debugging version number mismatches or strong-name mismatches, Fusion will ALWAYS tell you what's really going on. There is no Black Box.

如果您要调试版本号不匹配或强名称不匹配,Fusion始终会告诉您实际情况。 没有黑匣子。

Related Links

相关链接

翻译自: https://www.hanselman.com/blog/back-to-basics-using-fusion-log-viewer-to-debug-obscure-loader-errors

 类似资料: