Создан неверный код IL

Я пытаюсь объединить два метода вместе (один метод из моего проекта, один из DLL) и записать их в DLL. Исходный код выглядит так:

 .method public hidebysig static class Storage.DataMap 
    Create() cil managed 
  {
    .maxstack 8

    // [22 7 - 22 70]
    IL_0000: call         unmanaged stdcall native int Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
    IL_0005: newobj       instance void Storage.DataMap::.ctor(native int)
    IL_000a: ret          

  } // end of method DataMap::Create

Я хочу добавить простой Console.WriteLine к этому коду, в итоге я получаю следующее: (из декомпилятора)

  .method public hidebysig static class Storage.DataMap 
    Create() cil managed 
  {
    .maxstack 8

    // [22 7 - 22 44]
    IL_0000: ldstr        "Hello World"
    IL_0005: call         void [mscorlib]System.Console::WriteLine(string)

    // [23 7 - 23 70]
    IL_000a: call         unmanaged stdcall native int Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
    IL_000f: newobj       instance void Storage.DataMap::.ctor(native int)
    IL_0014: ret          

  } // end of method DataMap::Create

Мой декомпилятор не может декомпилировать это (dotPeek), поэтому я предполагаю, что сгенерированный мной IL недействителен. Тем не менее, я не уверен, что не так с моим сгенерированным IL.

я использую dnlib с помощью C# для получения кода IL обоих методов, а затем Concat обоих блоков кода вместе (я удалил nop а также ret заявления (за исключением последнего)). Для перекомпиляции кода я использую ModuleDef#Write(String) функция, у меня был успех с этим при написании моих собственных операторов IL, но не при объединении уже существующих операторов.

(Следующий IL напечатан с консоли, а не с декомпилятора)
Оригинальная часть 1 ИЛ:

IL_0000: nop
IL_0001: ldstr "Hello World"
IL_0006: call System.Void System.Console::WriteLine(System.String)
IL_000B: nop
IL_000C: ret

Оригинальная часть 2 ИЛ:

IL_0000: call System.IntPtr Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
IL_0005: newobj System.Void Storage.DataMap::.ctor(System.IntPtr)
IL_000A: ret

Слитый ИЛ:

IL_0001: ldstr "Hello World"
IL_0006: call System.Void System.Console::WriteLine(System.String)
IL_0000: call System.IntPtr Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
IL_0005: newobj System.Void Storage.DataMap::.ctor(System.IntPtr)
IL_000A: ret

1 ответ

Решение

Я исправил свою проблему. Как несколько человек правильно указали в комментариях, IL является правильным. Проблема связана не с моим кодом или сгенерированным IL, а с декомпилятором dotPeek.

Произошло следующее: я впервые сгенерировал DLL, но IL был неправильным (у него было 2 оператора return), декомпилировал его с помощью dotPeek и увидел, что IL был искажен. Я сделал это снова, но с правильным IL (только 1 оператор возврата) и удалил старую DLL, переименовал новую DLL в старую, удалил одну. Однако DotPeek это не понравилось, он показал бы мне обновленный IL, но не обновленный код.

После многих перезапусков и удаления / повторного добавления сборки я обнаружил, что это так. dnSpy, кажется, работает намного лучше, чем dotPeek, поэтому я буду использовать это в будущем.

Другие вопросы по тегам