Открыть сервис

SendMessageTimeout

SendMessageTimeout — это функция Windows API, предназначенная для отправки указанного сообщения в очередь сообщений одного или нескольких окон, с возможностью задания временного ограничения на выполнение операции. Относится к классу функций синхронного межпроцессного взаимодействия (IPC) и является расширенной версией функции SendMessage, добавляющей параметры тайм-аута и флагов поведения.

Функциональное назначение

SendMessageTimeout используется для отправки сообщения окну (или нескольким окнам) и ожидания его обработки в течение заданного времени. В отличие от SendMessage, которая блокирует вызывающий поток до завершения обработки сообщения получателем (что может привести к зависанию приложения, если окно-получатель не отвечает), SendMessageTimeout позволяет задать максимальное время ожидания. Если по истечении этого времени сообщение не было обработано, функция возвращает управление вызывающему потоку, предотвращая бесконечную блокировку.

Прототип и параметры

Функция объявлена в заголовочном файле winuser.h и экспортируется из библиотеки user32.dll. Прототип на языке C:

``c LRESULT SendMessageTimeout( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD lpdwResult ); ``

Параметры:

  • hWnd — дескриптор окна-получателя. Если задан HWND_BROADCAST (0xFFFF), сообщение отправляется всем окнам верхнего уровня в системе.
  • Msg — идентификатор сообщения (например, WM_GETTEXT, WM_SETTEXT).
  • wParam, lParam — дополнительные параметры сообщения, зависят от типа сообщения.
  • fuFlags — комбинация флагов, определяющих режим отправки:
  • SMTO_NORMAL (0x0000) — обычная отправка без специальных опций.
  • SMTO_BLOCK (0x0001) — блокирует вызывающий поток до завершения обработки сообщения получателем (аналогично SendMessage, но с тайм-аутом).
  • SMTO_ABORTIFHUNG (0x0002) — прерывает отправку, если окно-получатель находится в состоянии «зависания» (не отвечает на сообщения в течение определённого времени).
  • SMTO_NOTIMEOUTIFNOTHUNG (0x0008) — игнорирует тайм-аут, если окно-получатель не зависло.
  • uTimeout — время ожидания в миллисекундах. Если значение равно нулю, функция немедленно возвращает управление.
  • lpdwResultуказатель на переменную, в которую записывается результат обработки сообщения получателем. Может быть NULL, если результат не требуется.

Возвращаемое значение:

  • В случае успеха возвращает ненулевое значение (истина), а результат обработки сообщения помещается в *lpdwResult.
  • В случае ошибки (например, тайм-аут, окно не найдено) возвращает 0 (ложь). Для получения расширенной информации об ошибке следует вызвать GetLastError.

Поведение и особенности

Отправка одному окну

При указании конкретного дескриптора окна функция отправляет сообщение в очередь сообщений этого окна и ожидает его обработки. Если окно не отвечает в течение uTimeout миллисекунд, функция возвращает 0. Если окно обрабатывает сообщение до истечения тайм-аута, возвращается результат обработки.

Широковещательная отправка (HWND_BROADCAST)

При использовании HWND_BROADCAST сообщение отправляется всем окнам верхнего уровня (top-level windows) в системе. Функция ожидает завершения обработки каждым окном, но не более uTimeout миллисекунд на каждое окно. Общее время ожидания может значительно превышать uTimeout, если в системе много окон. Флаг SMTO_ABORTIFHUNG позволяет пропускать зависшие окна, ускоряя операцию.

Взаимодействие с потоками

SendMessageTimeout может использоваться для межпотокового общения в пределах одного процесса, если окна принадлежат разным потокам. Однако для общения между потоками одного процесса чаще применяются другие механизмы (например, PostMessage или пользовательские сообщения).

Ограничения и безопасность

  • Функция не может отправлять сообщения окнам, принадлежащим процессам с более высоким уровнем целостности (UIPI — User Interface Privilege Isolation) в Windows Vista и новее. В таких случаях возвращается ошибка.
  • Широковещательная отправка может быть заблокирована системой для некоторых сообщений (например, WM_SETTEXT), чтобы предотвратить злонамеренное вмешательство в работу других приложений.
  • При использовании SMTO_BLOCK вызывающий поток блокируется, что может привести к взаимоблокировке (deadlock), если два потока одновременно отправляют друг другу сообщения с ожиданием.

Пример использования

Следующий код на C++ демонстрирует отправку сообщения WM_GETTEXT для получения текста заголовка окна:

```cpp

include <windows.h>

include <iostream>

int main() { HWND hWnd = FindWindow(NULL, L"Блокнот"); // дескриптор окна "Блокнот" if (!hWnd) { std::cerr << "Окно не найдено" << std::endl; return 1; }

wchar_t buffer[256]; DWORD result; LRESULT ret = SendMessageTimeout( hWnd, WM_GETTEXT, sizeof(buffer) / sizeof(wchar_t), (LPARAM)buffer, SMTO_ABORTIFHUNG | SMTO_NORMAL, 5000, // тайм-аут 5 секунд &result );

if (ret) { std::wcout << L"Текст заголовка: " << buffer << std::endl; } else { std::cerr << "Ошибка отправки сообщения (код: " << GetLastError() << ")" << std::endl; }

return 0; } ```

Сравнение с другими функциями

ФункцияБлокировкаТайм-аутШироковещаниеРезультат обработки
SendMessageДаНетДа (HWND_BROADCAST)Да
PostMessageНетНетДа (HWND_BROADCAST)Нет
SendMessageTimeoutДа (с тайм-аутом)ДаДаДа
SendNotifyMessageНетНетНетНет

История и версии

Функция появилась в Windows 95 и Windows NT 4.0. В последующих версиях Windows её поведение было уточнено, в частности, добавлены флаги SMTO_NOTIMEOUTIFNOTHUNG (Windows 2000) и улучшена обработка широковещательных сообщений. В Windows Vista и новее функция учитывает UIPI, что может влиять на возможность отправки сообщений окнам с более высоким уровнем целостности.

Применение

SendMessageTimeout используется в ситуациях, когда необходимо отправить сообщение окну, но нежелательно бесконечно ждать его обработки. Типичные сценарии:

  • Управление внешними окнами (например, закрытие, перемещение, изменение размера) с защитой от зависания.
  • Получение данных от окон других приложений (например, текста из полей ввода) с контролем времени ожидания.
  • Реализация тайм-аутов в пользовательских интерфейсах, где требуется синхронное взаимодействие с окнами, но без риска блокировки основного потока.

Критика и альтернативы

Основной недостаток SendMessageTimeout — потенциальная блокировка вызывающего потока, особенно при широковещательной отправке, когда функция ожидает ответа от каждого окна. В современных приложениях для межпроцессного взаимодействия часто предпочитают асинхронные механизмы (например, именованные каналы, сокеты, COM-интерфейсы), которые не блокируют поток и позволяют более гибко управлять временем ожидания. Для простого уведомления окон без ожидания ответа используется PostMessage.

Источники

  1. Microsoft Docs. "SendMessageTimeout function (winuser.h)".
  2. Рихтер Дж. "Windows via C/C++". 5-е издание, глава 10 "Механизмы синхронизации".
  3. Петцольд Ч. "Программирование для Windows 95". Глава 6 "Сообщения и обработка сообщений".
  4. MSDN Library. "User Interface Privilege Isolation (UIPI)".
  5. MSDN Magazine. "Windows API: SendMessage, PostMessage, and Related Functions".

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →