2

DTM_SETSYSTEMTIME を使用して、別のアプリケーションで dateTimeController を更新しようとしています。

bool retVal = false;
ushort GDT_VALID = 0;

SYSTEMTIME td = new SYSTEMTIME();
td.wYear = 1990;
td.wMonth = 4;
td.wDay = 2;
td.wDayOfWeek = 0;
td.wHour = 0;
td.wMilliseconds = 0;
td.wMinute = 0;
td.wSecond = 0;

int erc = SendMessage(handle, DTM_SETSYSTEMTIME, GDT_VALID, ref td);

残念ながら、試行は失敗しました。戻り値がゼロになるたびに、ピッカーは更新されません。重要なことは、dataTimePicker を持つアプリケーションは、SendMessage コマンドを実行した後、不正なメモリ アクセス例外というエラー メッセージを表示することがあります。

誰でもこれを修正するのを手伝ってもらえますか?

4

2 に答える 2

3

はい、動作しません。SendMessageの4番目の引数は、SYSTEMTIMEへのポインターです。ポインタ値はプロセスでのみ有効であり、コントロールを所有しているプロセスでは有効ではありません。そのポインター値でターゲットアプリをクラッシュさせる可能性は十分にあります。あなたはする必要があります

  • ターゲットプロセスでOpenProcess()を呼び出して、そのハンドルを取得します
  • VirtualAllocEx()を呼び出して、ターゲットプロセスにメモリを割り当てます
  • WriteProcessMemory()を呼び出して、SYSTEMTIME値をプロセスからターゲットプロセスにコピーします
  • VirtualAllocExから取得したポインタ値を使用してSendMessageを呼び出します
  • VirtualFreeEx()を呼び出して、メモリを解放します
  • CloseHandle()を呼び出して、プロセスハンドルを解放します。

ここで問題が発生する可能性のある多くのことがあります。UACから始めて、これらの高度な特権を持つAPI関数の実行を停止します。関数名はグーグルです。サンプルコードを見つけるのにほとんど問題はないはずです。

于 2011-02-18T03:47:24.483 に答える
2

あなたの情報は、私の問題を解決するのに非常に役立ちます。以下はコードです。

private static bool injectMemory(IntPtr windowHandle, byte[] buffer, out IntPtr hndProc, out IntPtr lpAddress)
    {
        hndProc = IntPtr.Zero;
        lpAddress = IntPtr.Zero;
        //open local process object
        Process mainWindowProcess = FindProcess(windowHandle);
        hndProc = OpenProcess(
            (0x2 | 0x8 | 0x10 | 0x20 | 0x400), //create thread, query info, operation 
            //write, and read 
            1,
            (uint)mainWindowProcess.Id);
        if (hndProc == (IntPtr)0)
        {
            Console.WriteLine("Unable to attach process");
            return false;
        }
        //allocate memory for process object
        lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (uint)buffer.Length,
             AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ExecuteReadWrite);
        if (lpAddress == (IntPtr)0)
        {
            Console.WriteLine("Unable to allocate memory to target proces");
            return false;
        }
        //wite data
        uint wrotelen = 0;
        WriteProcessMemory(hndProc, lpAddress, buffer, (uint)buffer.Length, out wrotelen);
        if (Marshal.GetLastWin32Error() != 0)
        {
            Console.WriteLine("Unable to write memory to process.");
            return false;
        }
        return true;
    }

メソッドは、

        int structMemLen =  Marshal.SizeOf(typeof(SYSTEMTIME));
        byte[] buffer = new byte[structMemLen];
        ushort GDT_VALID = 0;
        SYSTEMTIME sysTime = new SYSTEMTIME();
        //Assign the values as you prefer

        IntPtr dataPtr = Marshal.AllocHGlobal(structMemLen);
        Marshal.StructureToPtr(sysTime, dataPtr, true);
        Marshal.Copy(dataPtr, buffer, 0, structMemLen);
        Marshal.FreeHGlobal(dataPtr);

        IntPtr hndProc = IntPtr.Zero;
        IntPtr lpAddress = IntPtr.Zero;
        injectMemory(mainWindowHandle, buffer, out hndProc, out lpAddress); 
        SendMessage(handle, DTM_SETSYSTEMTIME, (IntPtr)GDT_VALID, lpAddress);
        CloseHandle(hndProc);
于 2011-02-19T09:40:02.217 に答える