标题有点说明了一切。如果没有名称,常用的 SOS 命令 !bpmd 并没有多大用处。
我的一些想法:
- 转储每个方法,然后在找到相应的 MethodDesc 时使用 !bpmd -md
- 据我所知,在现实世界中并不实用。即使我编写了一个宏来将转储限制为匿名类型/方法,也没有明显的方法来区分它们。
- 使用 Reflector 转储 MSIL 名称
- 在处理动态程序集和/或 Reflection.Emit 时没有帮助。 Visual Studio 无法在这种情况下读取本地变量是我首先转向 Windbg 的全部原因......
- 在VS中设置断点,等待断点,然后change to Windbg using the noninvasive trick
- 尝试与 VS 分离会导致它挂起(与应用程序一起挂起)。我认为这是因为托管调试器是一个 "soft" debugger via thread injection。而不是标准的“硬”调试器。或者它可能只是 Silverlight 特有的 VS 错误(几乎不会是第一个 I've encountered )。
- 在已知调用匿名方法的其他位置设置断点,然后单步执行
- 我的备用计划,但如果此问答揭示了更好的方法,我宁愿不求助于它
最佳答案
匿名方法并不是真正的匿名。它只是隐藏在编译器生成的名称后面。
考虑这个小例子:
Func<int, int> a = (x) => x + 1;
Console.WriteLine(a.Invoke(1));
要找到返回值,我们需要找到方法实现的名称。为此,我们需要找到周围方法的 MethodDesc。在这个例子中它是 Main()
,所以:
0:000> !name2ee * TestBench.Program.Main
Module: 6db11000 (mscorlib.dll)
--------------------------------------
Module: 00162c5c (TestBench.exe)
Token: 0x06000001
MethodDesc: 00163010
Name: TestBench.Program.Main()
JITTED Code Address: 001e0070
通过 MethodDesc 我们可以为 Main()
转储 IL
0:000> !dumpil 00163010
ilAddr = 003f2068
IL_0000: nop
IL_0001: ldstr "press enter"
IL_0006: call System.Console::WriteLine
IL_000b: nop
IL_000c: call System.Console::ReadLine
IL_0011: pop
IL_0012: ldsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1
IL_0017: brtrue.s IL_002c
IL_0019: ldnull
IL_001a: ldftn TestBench.Program::<Main>b__0
IL_0020: newobj class [System.Core]System.Func`2<int32,int32>::.ctor
IL_0025: stsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1
IL_002a: br.s IL_002c
IL_002c: ldsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1
IL_0031: stloc.0
IL_0032: ldloc.0
IL_0033: ldc.i4.1
IL_0034: callvirt class [System.Core]System.Func`2<int32,int32>::Invoke
IL_0039: call System.Console::WriteLine
IL_003e: nop
IL_003f: ret
注意那些看起来很滑稽的名字。它们是生成委托(delegate)类型和实际方法的名称。该方法称为 <Main>b__0
.我们来看看方法:
0:000> !name2ee * TestBench.Program.<Main>b__0
Module: 6db11000 (mscorlib.dll)
--------------------------------------
Module: 00152c5c (TestBench.exe)
Token: 0x06000003
MethodDesc: 00153024
Name: TestBench.Program.<Main>b__0(Int32)
Not JITTED yet. Use !bpmd -md 00153024 to break on run.
给你。 MethodDesc 是 00153024,正如评论所说,您可以使用 !bpmd 使用 MethodDesc 设置断点。
关于c# - 如何以匿名方式破解 WinDbg?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2430933/