我需要在聊天程序中创建一个richedit控件(我正在尝试创建一个音乐机器人)。 我不知道如何在c / c ++中编码,但我能够使用c ++使用CLR Hosting将托管代码注入聊天程序。但是会出现夫妻问题。希望我能从这里得到一些帮助。
有人能指出我这样做的正确方法吗?或者甚至可以在托管代码中执行此操作?
由于
答案 0 :(得分:1)
这种东西取决于很多因素,很难开始。你能提供更多细节吗?
在一般级别,1:如果您使用ICLRRuntimeHost::ExecuteInDefaultAppDomain(pwzAssemblyPath, pwzTypeName, pwzMethodName, pwzArgument)
来执行托管代码,那么只要pwzMethodName
表示的方法完成,托管执行就会停止。如果你有其他任务要坚持不懈,并且不想在此期间暂停此调用,那么最好的办法就是让pwzMethodName
在另一个线程上启动一些程序循环函数。
对于2,如果您将代码注入目标进程并与控件进行交互,则线程安全性可能是一个巨大的问题。我个人没有使用过SetWindowLong api,但它可能与从非调度程序线程修改控件有关。
答案 1 :(得分:0)
这是我的C#
public class Class1
{
[DllImport("kernel32", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc,IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "GetWindowLong", SetLastError = true)]
public static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", SetLastError = true)]
public static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
public static extern int SetWindowLong32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
public static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
{
if (IntPtr.Size == 8)
return GetWindowLongPtr64(hWnd, nIndex);
else
return GetWindowLongPtr32(hWnd, nIndex);
}
public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
{
if (IntPtr.Size == 8)
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
else
return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong));
}
public delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
public const int GWL_WNDPROC = -4;
public const int HWND_MESSAGE = -3;
public const int WM_LBUTTONDOWN = 513;
public static int Test(String pwzArgument)
{
f = new Form1();
f.Show();
Process p = Process.GetCurrentProcess();
string s = "Name: " + p.ProcessName + "\nTitle: " + p.MainWindowTitle + "\nHandle: " + p.MainWindowHandle.ToString();
Show(s);
Show("Started");
Subclasshwnd(p.MainWindowHandle);
//For i = 0 To 100000000
//' Show("Loop", "")
//Threading.Thread.CurrentThread.Sleep("10000")
//Next
return 1;
}
public static void Show(string input)
{
MessageBox.Show(input);
f.Settext(input + "\n");
}
public static WndProcDelegate _WndProc;
public static IntPtr _OldWndProc;
public static IntPtr _hWnd;
public static Form1 f;
public static void Subclasshwnd(IntPtr hWnd)
{
_WndProc = new WndProcDelegate(WndProc);
// _OldWndProc = GetWindowLongPtr(hWnd, GWL_WNDPROC);
_OldWndProc= SetWindowLongPtr(hWnd, GWL_WNDPROC,Marshal.GetFunctionPointerForDelegate(_WndProc));
// Show(_OldWndProc.ToString());
}
// this is the new wndproc, just show a messagebox on left button down:
public static IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam,IntPtr lParam)
{
System.Diagnostics.Debug.WriteLine(msg);
Show(msg.ToString());
return CallWindowProc(_OldWndProc, hWnd, msg, wParam, lParam);
}
}
这是我的C ++代码
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(0, L"Dll Injection Successful! ", L"Dll Injector", MB_ICONEXCLAMATION | MB_OK);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&StartTheDotNetRuntime, 0, 0, NULL);
break;
case DLL_THREAD_ATTACH: break;
case DLL_THREAD_DETACH: break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
void StartTheDotNetRuntime()
{
ICLRRuntimeHost *pClrHost = NULL;
HRESULT hr = CorBindToRuntimeEx(NULL, L"wks", 0, CLSID_CLRRuntimeHost,IID_ICLRRuntimeHost, (PVOID*)&pClrHost);
hr = pClrHost->Start();
DWORD dwRet = 0;
hr = pClrHost->ExecuteInDefaultAppDomain(L"ClassLibrary2.dll",L"ClassLibrary2.Class1", L"Test", L"MyParameter", &dwRet);
hr = pClrHost->Stop();
pClrHost->Release();
}
答案 2 :(得分:0)
另一种“更动态”的方法是在Managed C ++中编写可以注入的库。
托管C ++库可以导出本机函数以用于将其加载到另一个进程中。
只在该Managed C ++库中编写一些允许您加载额外库的代码。
该库可以重复用于注入未来的对象......
请参阅:http://www.vbib.be/index.php?name=PNphpBB2&file=viewtopic&p=38982