Проблема с CLR / it не работает с runtime v4.0.30319
У меня есть библиотека dll C++, которая вызывает мой код C# после инъекции с помощью CLR.
Итак, это мой код C++ (dll) :
#include "stdafx.h" #include <iostream> #include <metahost.h> #include <atlbase.h> #include <atlcom.h> #pragma comment(lib, "mscoree.lib") #define IfFailRet(expr) { hr = (expr); if(FAILED(hr)) return (hr); } #define IfNullFail(expr) { if (!expr) return (E_FAIL); } extern "C" int __declspec(dllexport) CALLBACK CallClrMethod( const WCHAR *AssemblyName, const WCHAR *TypeName, const WCHAR *MethodName, const WCHAR *args, LPDWORD pdwResult ) { int hr = S_OK; CComPtr<ICLRMetaHost> spHost; hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&spHost)); CComPtr<ICLRRuntimeInfo> spRuntimeInfo; CComPtr<IEnumUnknown> pRunTimes; IfFailRet(spHost->EnumerateInstalledRuntimes(&pRunTimes)); CComPtr<IUnknown> pUnkRuntime; while (S_OK == pRunTimes->Next(1, &pUnkRuntime, 0)) { CComQIPtr<ICLRRuntimeInfo> pp(pUnkRuntime); if (pUnkRuntime != nullptr) { spRuntimeInfo = pp; break; } } IfNullFail(spRuntimeInfo); BOOL bStarted; DWORD dwStartupFlags; hr = spRuntimeInfo->IsStarted(&bStarted, &dwStartupFlags); if (hr != S_OK) // sometimes 0x80004001 not implemented { spRuntimeInfo = nullptr; //v4.0.30319 //v2.0.50727 hr = spHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&spRuntimeInfo)); bStarted = false; } CComPtr<ICLRRuntimeHost> spRuntimeHost; IfFailRet(spRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&spRuntimeHost))); if (!bStarted) { hr = spRuntimeHost->Start(); } hr = spRuntimeHost->ExecuteInDefaultAppDomain( AssemblyName, TypeName, MethodName, args, pdwResult); return hr; } int _tmain(int argc, _TCHAR* argv[]) { DWORD dwResult; HRESULT hr = CallClrMethod( L"D:\\Dev\\CSharpDll\\CSharpDll\\bin\\x64\\Debug\\CSharpDll.dll", L"CSharpDll.MainClass", L"EntryPoint", L"Im successfully called from a C++ dll", &dwResult); return 0; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)_tmain, hModule, NULL, NULL); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; }
А это мой код C# (dll) :
using System.Windows.Forms; namespace CSharpDll { public class MainClass { public static int EntryPoint(string MessageFromCppDll) { MessageBox.Show(MessageFromCppDll); Form form = new MainForm(); form.ShowDialog(); return 0; } } }
Так что это очень хорошо работает для большинства программ и игр, но не совсем. На некоторых программах ничего не происходит. Введенная библиотека dll c++ пытается запустить код c#, но ничего не происходит. Моя теория заключается в том, что библиотека DLL c++ не создаст ни одного экземпляра библиотеки dll c#.
Но есть один вариант исправить это: если я изменю среду выполнения с v4.0.30319 на v2.0.50727, она будет работать нормально.
Это не работает:
hr = spHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&spRuntimeInfo));
Это работает:
hr = spHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&spRuntimeInfo));
А теперь мы подходим к моей "главной" проблеме: я должен уменьшить свою .Чистая версия от 4+ до 3.5, потому что CLR V2 поддерживает только .NET 2 - 3.5. и это приносит проблемы с моим кодом C# (dll).
Итак, теперь я перехожу к своему вопросу(ам):
Почему это не работает на всех программах и играх? (Я имею в виду время выполнения v4.0.30319). С CLR RunTimeHost v2.0.50727 это работает.
И как я могу это исправить или изменить что-то в своем коде, чтобы запустить его?
Если у вас, ребята, есть какие-то идеи или примеры кода, я был бы очень благодарен.
Что я уже пробовал:
Я пытался выяснить, почему это работает не на всех программах, но не могу распознать закономерность.
Mehdi Gholam
Вполне возможно, что у вас есть 32/64-битные проблемы.
Dave Kreskowiak
Это также процессы, в которые вы вводите свой код .NET apps, соответствующие требованиям .NET 2.0, 3.0 или 3.5? Если так, то у вас есть проблема. .NET CLR 2.x не поддерживает несколько версий среды выполнения в одном процессе.
Member 13911570
Я знаю свою ошибку, я забыл нажать кнопку "Использовать CLR" в настройках, теперь она работает. (С CLR v4)