Вызов управляемой библиотеки C# с помощью P/invoke без Assembly.Load или аналогичного

Я уже несколько дней искал это, но все, что я нашел, - это как вызвать неуправляемые библиотеки из C# с помощью P/Invoke. Мне нужно сделать это по-другому: я хочу использовать P / Invoke для вызова управляемой сборки из другой (или использовать что-то еще, избегая вызова Assembly.Load, Assembly.LoadFromи т. д.) в основном из-за ограничения CoreRT/NativeAOT (см. здесь).

По сути, идея использования CoreRT/NativeAOT связана с генерацией собственных исполняемых файлов, что немного улучшит безопасность моего приложения, поскольку обычные декомпиляторы не будут работать с ним (кроме IDA и умного разработчика со знаниями ASM, но они сложнее проходить мимо). Учитывая, что CoreRT/NativeAOT не может (может, но команда.NET прямо сейчас не хочет...) загружать внешние сборки с помощью любого из методов.NET Interop (Assembly.Load, Assembly.LoadFromи т. д.), но он может использовать DllImport, Я хотел бы вызвать внешнюю сборку, которая меня не особо заботит, декомпилирована она или нет, без использования любого из этих методов загрузки сборки.

Да, я знаю, что могу написать оболочку или что-то еще с самим CoreRT, чтобы создать собственную библиотеку и вызвать ее с помощью P / Invoke из приложения, но в случае Entity Framework, которая не компилируется из-за Reflection.Emit, это невозможно.

Идеальным решением здесь было бы знать, как вызвать любую сборку.NET (DLL) из другого приложения / сборки C# БЕЗ использования Assembly.Load/LoadFrom/LoadFromStream/ и т. Д. используя другие методы, будь то P/Invoke (не так ли?), либо другие.

1 ответ

РЕШЕНИЕ

Спасибо @ChristianHeld за его предложение использовать собственный экспорт.NET 5.0 (плюс также спасибо Аарону Робинсону за его код. У меня это работает следующим образом:

.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    ADD THIS -> <EnableDynamicLoading>true</EnableDynamicLoading>
    ADD THIS -> <DnneAddGeneratedBinaryToProject>true</DnneAddGeneratedBinaryToProject>
  </PropertyGroup>

  <ItemGroup>
    ADD THIS -> <PackageReference Include="DNNE" Version="1.*" />
  </ItemGroup>

</Project>

Код библиотеки.NET (вырезанный):

[UnmanagedCallersOnlyAttribute]
public static void Init()
{
    // ... Some code here...
}

Код.NET вызывающего абонента (образец):

class Program
{
    const string LIBNAME = @"LibraryNE.dll";
    [DllImport(LIBNAME)] public static extern void Init();

    static void Main(string[] args)
    {
        Init();
    }
}

ВАЖНО: при работе с VSCode (F5) он может сказать что-то вроде этого:

Failed to initialize context for config: C:\Project\Library.runtimeconfig.json. Error code: 0x80008092

Не обращайте на это внимания, потому что VSCode отлаживает приложение с помощью dotnet.exe, игнорируя runtimeconfig.json каждой сборки (каким-то образом он выдает LibHostInvalidArgs. Понятия не имею почему).

Если вы запустите файл.EXE вашего приложения напрямую, оно будет работать (просто использовало его с двоичным файлом, созданным CoreRT/NativeAOT). Решение этой проблемы - отредактировать ваш launch.json файл и изменить .dll с участием .exe в configurations -> program.

Кроме того, не забудьте скопировать DLL-файл.NET. Кажется, что при публикации копируется только собственная библиотека (с суффиксом NE), но она не будет работать сама по себе, поскольку это просто оболочка. В этой же папке должна находиться настоящая DLL.NET.

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

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