Декомпиляция сборки VB.Net создает код с недопустимыми именами переменных-членов;имена, начинающиеся с $ STATIC $ - PullRequest
3 голосов
/ 05 сентября 2011

Я делаю работу для клиента, который потерял исходный код для одного из своих приложений 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;

Может кто-нибудь объяснить, почемув сгенерированном коде есть эти недопустимые переменные-члены и как я могу их разрешить?

Ответы [ 3 ]

10 голосов
/ 05 сентября 2011

Это идентификаторы, сгенерированные компилятором 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, обеспечивающих правильную инициализацию переменной. Вам нужно будет переименовать их вручную.

9 голосов
/ 05 сентября 2011

Короче говоря, то, что действительно в IL, не обязательно совпадает с тем, что действует в исходном языке.Довольно часто дают сгенерированные компилятором (иначе называемые синтетические в некоторых кругах) имена членов, которые являются недопустимыми в языке, поскольку это позволяет избежать любых возможных конфликтов.Их иногда называют невыразимыми именами , так как они не могут быть «произнесены» на языке оригинала.Например, компилятор C # обычно включает <> в такие имена.

Что касается решения проблемы - некоторые декомпиляторы будут определять, откуда такие имена пришли автоматически, но обычно вы можете просто изменить имя везде.Вы не получите в конечном итоге исходный код, но если вы посмотрите на то, чем в итоге вы делаете , вы сможете легче разобраться с тем, что сделал исходный * 1011.* выглядит так.

Обратите внимание, что компилятор может генерировать больше, чем просто недопустимые имена: например, в C # блоки итераторов генерируют IL, который в некоторых случаях не может быть выражен непосредственно в самом "нормальном" C #.Возможно, это не проблема для вас, но об этом стоит знать.

2 голосов
/ 05 сентября 2011

Это не переменные , это поля (они имеют модификаторы доступа).

Это будут поля, сгенерированные компилятором, которые будут сгенерированы в ряде различных обстоятельств. Имена намеренно недопустимы, чтобы избежать конфликтов с «обычными» полями.

Если вы можете предоставить немного больше контекста, то кто-нибудь умный, возможно, сможет выяснить, как исходный код выглядел для компилятора, испускающего эти поля.

...