2011-02-18 2 views
1

Я пытаюсь обновить dateTimeController в другом приложении с помощью DTM_SETSYSTEMTIME.Обновление dateTimePicker в другом процессе с помощью DTM_SETSYSTEMTIME

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.

Может ли кто-нибудь помочь мне исправить это?

ответ

1

Ваша информация действительно полезна для меня, чтобы исправить мою проблему. Ниже приведен код.

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

Да, не может работать. 4-й аргумент SendMessage - это указатель на SYSTEMTIME. Значение указателя действует только в вашем процессе, а не в том, что принадлежит элементу управления. Сбой целевого приложения с этим значением указателя вполне возможен. Вы должны

  • вызова OpenProcess() на целевом процессе, чтобы получить его хэндл
  • вызова VirtualAllocEx() для выделения памяти в целевом процессе
  • вызова WriteProcessMemory(), чтобы скопировать значение SYSTEMTIME из вашего процесс целевого процесса
  • вызов SendMessage, используя значение указателя вы получили от VirtualAllocEx
  • вызов VirtualFreeEx(), чтобы освободить память
  • вызова CloseHandle(), чтобы освободить процесс ч andle.

Много вещей, которые могут пойти не так, начиная с UAC, прекратить выполнение этих высокоприоритетных функций API. Функция называет google хорошо, вам не составит труда найти образец кода.