我借助CLR(启动.NET 4.0.30319)将托管类库注入非托管进程[将单人游戏变为多人游戏]。
ICLRMetaHost *pMetaHost;
ICLRRuntimeInfo *pRuntimeInfo;
ICLRRuntimeHost *pClrRuntimeHost;
DWORD result;
CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&pRuntimeInfo);
pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pClrRuntimeHost);
pClrRuntimeHost->Start();
// execute the method "Int32 Program.Main(String arg)"
pClrRuntimeHost->ExecuteInDefaultAppDomain(L"UnmanagedAssembly.dll", L"Program", L"Main", L"Argument", &result);
要从目标进程调用我自己的非托管方法,我使用了以下方法:
HRESULT ExecuteInDefaultAppDomain (
[in] LPCWSTR pwzAssemblyPath,
[in] LPCWSTR pwzTypeName,
[in] LPCWSTR pwzMethodName,
[in] LPCWSTR pwzArgument,
[out] DWORD *pReturnValue
);
https://msdn.microsoft.com/en-gb/library/ms164411(v=vs.110).aspx
哪个工作正常,但由于它只接受字符串作为参数我试图用这个方法做同样的事情,这似乎更方便:
HRESULT ExecuteInAppDomain(
[in] DWORD AppDomainId,
[in] FExecuteInDomainCallback pCallback,
[in] void* cookie
);
https://msdn.microsoft.com/de-de/library/ms164410(v=vs.110).aspx
我使用第一个方法使用的相同AppDomain,调用我的.NET回调,并且cookie参数传输正常。
但是,如果我尝试访问由ExecuteInAppDomain启动的托管回调中的文件,请执行此操作。
File.Create("wat.txt");
流程直接崩溃,没有例外。使用“ExecuteInDefaultAppDomain”-Method我没有遇到这个问题。调试崩溃转储为我提供了以下信息:
> KERNELBASE.dll!_RaiseException@16()
[Transition from managed to native]
mscorlib.dll!Microsoft.Win32.Win32Native.SafeCreateFile(string lpFileName, int dwDesiredAccess, System.IO.FileShare dwShareMode, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition, int dwFlagsAndAttributes, System.IntPtr hTemplateFile)
mscorlib.dll!System.IO.FileStream.Init(string path, System.IO.FileMode mode, System.IO.FileAccess access = ReadWrite, int rights, bool useRights = false, System.IO.FileShare share, int bufferSize = 4096, System.IO.FileOptions options, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs, string msgPath = "wat.txt", bool bFromProxy, bool useLongPath, bool checkHost)
mscorlib.dll!System.IO.FileStream.FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, int bufferSize)
mscorlib.dll!System.IO.File.Create(string path)
Error module name: KERNELBASE.dll
Error module version: 6.3.9600.18202
Exception code: e0434352
Exception offset: 00015b68
互联网上没有任何内容可以帮助解决这个KernelBase错误,但似乎它只是一个症状。是否缺少某些权限? 我有点无奈该做什么。显然“ExecuteInDefaultAppDomain”的做法与“ExecuteInAppDomain”不同,尽管我使用两种方法调用相同的AppDomain,这两种方法都是具有不受限制权限的默认AppDomain。
此外,如果我使用pinvoke
[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi, SetLastError=true)]
public static extern IntPtr fopen(String filename, String mode);
在我的托管代码中读/写文件,它工作得很好。
编辑:
什么在起作用:
Managed Code:
pClrRuntimeHost->ExecuteInDefaultAppDomain(L"D:/UnmanagedLib.dll", L"Unmanaged.Program", L"Main", L"Argument", &result);
Unmanaged Code:
namespace Unmanaged
{
public static class Program
{
public static int Main(string message)
{
File.Create("D:\\test.txt");
AnotherClass.CreateFile();
return 0;
}
}
public static class AnotherClass
{
public static void CreateFile()
{
File.Create("D:\\test2.txt");
}
}
}
和
Managed Code:
pClrRuntimeHost->ExecuteInDefaultAppDomain(L"D:/UnmanagedLib.dll", L"Unmanaged.Program", L"Main", L"Argument", &result);
pClrRuntimeHost->ExecuteInAppDomain(1, (ExecuteInAppDomainCallback)result, (void*)1234);
Unmanaged Code:
namespace Unmanaged
{
public static class Program
{
public delegate void Callback(int arg);
public static int Main(string message)
{
return Marshal.GetFunctionPointerForDelegate((Callback)MyCallback).ToInt32();
}
public static void MyCallback(int argument)
{
File.Create("D:\\test.txt");
}
}
}
什么不起作用:
Managed Code:
pClrRuntimeHost->ExecuteInDefaultAppDomain(L"D:/UnmanagedLib.dll", L"Unmanaged.Program", L"Main", L"Argument", &result);
pClrRuntimeHost->ExecuteInAppDomain(1, (ExecuteInAppDomainCallback)result, (void*)1234);
Unmanaged Code:
namespace Unmanaged
{
public static class Program
{
public delegate void Callback(int arg);
public static int Main(string message)
{
return Marshal.GetFunctionPointerForDelegate((Callback)MyCallback).ToInt32();
}
public static void MyCallback(int argument)
{
AnotherClass.CreateFile();
}
}
public static class AnotherClass
{
public static void CreateFile()
{
File.Create("D:\\test.txt"); // crashes here
}
}
}
和
Managed Code:
pClrRuntimeHost->ExecuteInDefaultAppDomain(L"D:/UnmanagedLib.dll", L"Unmanaged.Program", L"Main", L"Argument", &result);
pClrRuntimeHost->ExecuteInAppDomain(1, (ExecuteInAppDomainCallback)result, (void*)1234);
Unmanaged Code:
namespace Unmanaged
{
public static class Program
{
public delegate void Callback(int arg);
public static int Main(string message)
{
return Marshal.GetFunctionPointerForDelegate((Callback)AnotherClass.MyCallback).ToInt32();
}
}
public static class AnotherClass
{
public static void MyCallback(int argument)
{
File.Create("D:\\test.txt"); // crashes here
}
}
}