Приложение
У меня есть приложение, написанное на C ++.
Оно живет в C:\app\app.exe
Плагины
Приложение может быть расширено с помощью плагинов. Плагины - это библиотеки DLL, написанные на C ++. У меня нет доступа к исходному коду для app.exe
Плагины живут в C:\app\plugins
app.exe
используют Windows функции LoadLibraryExW
и GetProcAddress
для загрузки функций в библиотеки DLL плагина (библиотеки DLL плагина и имена функций указываются пользователем во время выполнения).
Generi c Plugin
Существует общий c плагин, который может запускать плагины, написанные на C#. Этот общий c плагин имеет такую структуру:
- Класс C ++ под названием GenericPlugin. -> создает
GenericPlugin.dll
(неуправляемую DLL) - Класс C ++ / CLI с именем PluginLoader -> создает
PluginLoader.dll
- A C# класс с именем Tools -> создает
Tools.dll
(управляемый DLL)
GenericPlugin вызывает PluginLoader, который вызывает Tools.
Tools использует System.Reflection.Assembly.LoadFrom
и Reflection (для поиска всех DLL (например, SomeDotNetPlugin.dll
) с классами stati c с методами с настраиваемым атрибутом. Я не могу выполнить код C ++ / CLI или C#.
Итак, структура папок / файлов выглядит так
C:\app\app.exe
C:\app\plugins\GenereicPlugin.dll
C:\app\plugins\PluginLoader.dll
C:\app\plugins\Tools.dll
C:\app\plugins\SomeDotNetPlugin.dll
Проблема
Когда я запускаю app.exe
, приложение вылетает.
Использование Windows Process Monitor ,
- Я вижу, что
app.exe
может найти GenereicPlugin.dll
и PluginLoader.dll
в папке плагинов. - Но
app.exe
не удается найти. NET Tools.dll
. Согласно Process Monitor, app.exe
ищет только C:\app
для Tools.dll
, но не C:\app\plugins
. В качестве теста я поместил Tools.dll
и SomeDotNetPlugin.dll
в C:\apps
. Теперь DLL найдена, но app.exe
по-прежнему не работает. Монитор процессов не сообщает мне, что не так.
Вопросы
- Как диагностировать эту проблему?
- Почему
app.exe
не заглядывать в папку плагинов, чтобы найти. NET C# управляемую DLL?
Код Здесь очень кратко вызовы, используемые в app.exe и плагинах.
app.exe
LoadLibraryExA( libName, NULL, 0);
...
static_cast< void * >( ::GetProcAddress( library_, symbolName ) );
...
GenericPlugin.dll
auto functionList = PluginLoader::listNetFunctions();
PluginLoader.dll
auto functions = Tools::listFunctions();
Tools.dll
string DirPath = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var di = new System.IO.DirectoryInfo(DirPath);
var fi = di.GetFiles("plugins\\*.dll");
foreach (var f in fi) {
var a = System.Reflection.Assembly.LoadFrom(f.FullName);
var types = a.GetTypes();
var dm = buildDelegateMap();
foreach (var t in types) {
foreach (var m in t.GetMembers()) {
var ea = m.GetCustomAttribute<CustomFunctionAttribute>();
var mi = m as MethodInfo;
string methodSignature = getMethodSignatureString(mi);
Delegate d = Delegate.CreateDelegate(dm[getMethodSignatureString(mi)], mi);
var fp = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(d);
...
//store fp in dictionary ea.Name -> fp
...