反编译VB.. Net程序集产生具有无效成员变量名的代码;名称以$STATIC$开头



我正在为一个客户做工作,他已经丢失了其中一个VB的源代码。Net WinForms应用程序。他们拥有的集合一点也不模糊。我试图尽可能多地恢复c#源代码,并尝试了几种反编译程序集的工具,包括Reflector, ILSpy和JustDecompile(所有最新版本),但它们都产生了大量错误的代码。由于生成的代码中有大量错误,我将询问具体的错误(在不同的问题中),希望得到更直接的答案,并通过这种方式尝试阐明为什么所有工具都难以反编译此程序集。

这个问题与所有这些工具生成的代码总是有大量无效的成员变量(字段)有关,例如:

private short $STATIC$Report_Print$20211C1280B1$nHeight;
private ArrayList $STATIC$Report_Print$20211C1280B1$oColumnLefts;
private StaticLocalInitFlag $STATIC$Report_Print$20211C1280B1$oColumnLefts$Init;

有人能解释为什么生成的代码有这些无效的成员变量,我如何解决这些?

这些是VB生成的标识符。. NET编译器实现Static关键字。例如:

Class Example
    Public Sub test()
        Static lookhere As Integer = 42
    End Sub
End Class

生成这个IL:

.field private specialname int32 $STATIC$test$2001$lookhere
.field private specialname class [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag $STATIC$test$2001$lookhere$Init

通过在字段名中使用保留字母,编译器可以确保永远不会与其他字段发生意外冲突。c#语言中没有与Static直接等价的东西。您可以将它们保留为类中的私有字段,但必须注意初始化。$Init标志的目的和相当多的IL确保变量被正确初始化。您需要手动重命名它们

简而言之,在IL中有效的内容不一定与源语言中有效的内容相同。给编译器生成的(在某些圈子中称为合成)成员命名在语言中无效是相当常见的,因为它避免了任何可能的冲突。这些有时被称为不可说的名称,因为它们不能在源语言中"说"出来。例如,c#编译器通常在这些名称中包含<>

至于解决这个问题—一些反编译器会自动找出这些名称的来源,但通常您可以简单地在任何地方更改名称。你不会得到原始的源代码,但是如果你看看你做了什么结束,你可能能够更容易地找出原始源代码做了什么是什么样子的。

请注意,编译器可能生成的不仅仅是无效名称:例如,在c#中,迭代器块生成IL,在某些情况下,这些IL不能直接用"正常"c#本身表示。这对您来说可能不是问题,但值得注意。

这些不是变量,它们是字段(它们有访问修饰符)。

它们将是编译器生成的字段,将在许多不同的情况下生成。这些名称故意无效,以避免与"正常"字段冲突。

如果你能提供更多的上下文,聪明的人可能会弄清楚编译器发出这些字段的源代码最初是什么样子的。

最新更新