0

チャット プログラムでリッチエディット コントロールをサブクラス化する必要があります (ミュージックボットを作成しようとしています)。私は c/c++ でコーディングする方法を知りませんが、c++ を使用して、CLR ホスティングを使用してマネージ コードをチャット プログラムに挿入することができました。しかし、カップルの問題が発生します。うまくいけば、ここから助けを得ることができます。

  1. マネージド コードは、スレッドの終了後に終了していました。私はそれを実行し続ける必要があります
  2. SetWindowLong api と GWL_WNDPROC を使用してリッチエディット コントロールをサブクラス化しようとすると、チャット プログラムがフリーズしました。

誰かがこれを行う正しい方法を教えてもらえますか? または、マネージド コードでこれを行うことさえ可能ですか?

ありがとう

4

3 に答える 3

1

この種のものは、多くの要因に依存し、実行するのが難しい場合があります. 詳細を教えていただけますか?

一般的なレベルでは、1 の場合: を使用ICLRRuntimeHost::ExecuteInDefaultAppDomain(pwzAssemblyPath, pwzTypeName, pwzMethodName, pwzArgument)してマネージド コードを実行している場合、 で示されるメソッドがpwzMethodName終了するとすぐにマネージド実行が停止します。永続的に実行したい他のタスクがあり、その間にこの呼び出しをハングさせたくない場合は、pwzMethodName別のスレッドでプログラム ループ関数を起動することをお勧めします。

2 に関しては、ターゲット プロセスにコードを挿入してコントロールを操作する場合、スレッド セーフが大きな問題になる可能性があります。私は個人的に SetWindowLong api を使用していませんが、非ディスパッチャー スレッドからコントロールを変更することに関係している可能性があります。

于 2010-02-01T04:56:37.050 に答える
0

もう1つの「より動的な」方法は、注入可能なマネージC++でライブラリを作成することです。

マネージC++ライブラリは、ネイティブ関数をエクスポートして、別のプロセスにロードするために使用できます。

追加のライブラリをロードできるようにするコードは、そのマネージC++ライブラリにのみ記述してください。

そのライブラリは、将来のオブジェクトを注入するために再利用できます...

参照:http ://www.vbib.be/index.php?name = PNphpBB2&file = viewtopic&p = 38982

于 2011-06-16T16:16:22.147 に答える
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();
}
于 2010-02-02T05:55:26.357 に答える