Перехват сообщений OutputDebugString в Windows: проблемы и решения
Переход на Windows 7 может вызвать ряд проблем, в том числе и в работе с системными утилитами и механизмами. Одной из таких проблем является неспособность перехватить сообщения OutputDebugString от сервисов, работающих в сессии №0, что было возможно в предыдущих версиях операционной системы. В Windows Vista и более новых версиях сервисы работают в изолированном режиме сессии №0, что затрудняет обмен данными с пользовательскими приложениями, запущенными в сессии №1.
Проблема
Автор вопроса столкнулся с трудностями при попытке перехвата сообщений OutputDebugString от сервисов после обновления до Windows 7. В Windows Vista и выше, сервисы запускаются в сессии №0, что, по мнению некоторых, делает невозможным их перехват. Однако, существуют инструменты, такие как DebugView, которые успешно справляются с этой задачей.
Решение
Ключевым моментом в решении проблемы является изменение настроек безопасности. В частности, было предложено добавить префикс "Global\" к именам объектов, что позволяет объектам быть доступными в любой сессии.
Пример кода
Вот пример кода на Object Pascal (Delphi), который демонстрирует изменение настроек безопасности для создания событий и файла обмена памятью:
procedure TODSThread.Execute;
var
SharedMem: Pointer;
SharedFile: THandle;
WaitingResult: DWORD;
SharedMessage: string;
DataReadyEvent, BufferReadyEvent: THandle;
SecurityAttributes: SECURITY_ATTRIBUTES;
SecurityDescriptor: SECURITY_DESCRIPTOR;
begin
// Инициализация структур безопасности
SecurityAttributes.nLength := SizeOf(SECURITY_ATTRIBUTES);
SecurityAttributes.bInheritHandle := True;
SecurityAttributes.lpSecurityDescriptor := @SecurityDescriptor;
// Инициализация дескриптора безопасности
if not InitializeSecurityDescriptor(@SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION) then
Exit;
// Установка доступа к дескриптору
if not SetSecurityDescriptorDacl(@SecurityDescriptor, True, nil, False) then
Exit;
// Создание событий с глобальными именами
BufferReadyEvent := CreateEvent(@SecurityAttributes, False, True, 'Global\DBWIN_BUFFER_READY');
if BufferReadyEvent = 0 then
Exit;
DataReadyEvent := CreateEvent(@SecurityAttributes, False, False, 'Global\DBWIN_DATA_READY');
if DataReadyEvent = 0 then
Exit;
// Создание файла обмена памятью с глобальным именем
SharedFile := CreateFileMapping(THandle(-1), @SecurityAttributes, PAGE_READWRITE, 0, 4096, 'Global\DBWIN_BUFFER');
if SharedFile = 0 then
Exit;
// Дальнейшие действия...
end;
Выводы
Изменение настроек безопасности, в частности, использование глобальных имен для объектов, позволяет перехватывать сообщения OutputDebugString от сервисов, работающих в сессии №0, даже в операционных системах Windows Vista и выше. Это решение позволяет разработчикам продолжить использование механизма OutputDebugString для отладки приложений, работающих в сервисах.
Переход на Windows 7 усложнил перехват сообщений `OutputDebugString` из-за изоляции сервисов в сессии №0, но это можно обойти, изменив настройки безопасности и используя глобальные имена для объектов.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.