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);

不幸的是尝试失败,选择器没有更新,每次返回值为零。重要的是,在我执行 SendMessage 命令后,具有 dataTimePicker 的应用程序有时会给出错误消息,指出非法内存访问异常。

有人可以帮我解决这个问题吗?

4

2 回答 2

3

是的,不能工作。SendMessage 的第四个参数是指向 SYSTEMTIME 的指针。指针值仅在您的进程中有效,而不是拥有控件的进程。使用该指针值使目标应用程序崩溃是很有可能的。您将需要

  • 在目标进程上调用 OpenProcess() 以获取其句柄
  • 调用 VirtualAllocEx() 在目标进程中分配内存
  • 调用 WriteProcessMemory() 将 SYSTEMTIME 值从您的进程复制到目标进程
  • 使用从 VirtualAllocEx 获得的指针值调用 SendMessage
  • 调用 VirtualFreeEx() 释放内存
  • 调用 CloseHandle() 释放进程句柄。

这里有很多可能出错的地方,首先是 UAC 会阻止您执行这些高权限的 API 函数。函数名称 google 很好,您应该可以轻松找到示例代码。

于 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 回答