Как я могу получить OutputDebugString от службы?
Я пытаюсь поймать все сообщения OutputDebugString (в том числе из служб), используя следующий код. Он работал нормально, пока я не перешел на Windows 7.
Проблема заключается в том, что поскольку службы Windows Vista работают на низкоуровневом сеансе № 0, некоторые люди говорят, что их невозможно поймать, а некоторые нет. Как вы думаете?
Можно ли изменить следующий код, увеличив некоторые права, чтобы иметь возможность получать сообщения OutputDebugString из сеанса № 0? Другими словами; Можно ли поделиться DBWIN_BUFFER в сеансе № 0 с сеансом № 1?
Я бы сказал, что это должно быть возможно, потому что, например, DebugView может сделать это, и я не вижу ни одного сервисного помощника, который бы отправлял эти сообщения (например, через именованные каналы) из Session #0 в Session #1, где работает GUI.
Проблема будет ИМО в настройках безопасности. Кто-нибудь может подсказать, как их изменить?
type
TODSThread = class(TThread)
protected
procedure Execute; override;
end;
...
procedure TODSThread.Execute;
var SharedMem: Pointer;
SharedFile: THandle;
WaitingResult: DWORD;
SharedMessage: string;
DataReadyEvent: THandle;
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, 'DBWIN_BUFFER_READY');
if BufferReadyEvent = 0 then
Exit;
DataReadyEvent := CreateEvent(@SecurityAttributes, False, False, 'DBWIN_DATA_READY');
if DataReadyEvent = 0 then
Exit;
SharedFile := CreateFileMapping(THandle(-1), @SecurityAttributes, PAGE_READWRITE, 0, 4096, 'DBWIN_BUFFER');
if SharedFile = 0 then
Exit;
SharedMem := MapViewOfFile(SharedFile, FILE_MAP_READ, 0, 0, 512);
if not Assigned(SharedMem) then
Exit;
while (not Terminated) and (not Application.Terminated) do
begin
SetEvent(BufferReadyEvent);
WaitingResult := WaitForSingleObject(DataReadyEvent, INFINITE);
case WaitingResult of
WAIT_TIMEOUT: Continue;
WAIT_OBJECT_0:
begin
SharedMessage := String(PAnsiChar(SharedMem) + SizeOf(DWORD));
// here I have what I need and process it in the main thread
end;
WAIT_FAILED: Continue;
end;
end;
UnmapViewOfFile(SharedMem);
CloseHandle(SharedFile);
end;
Я добавил тег C#, даже если код находится на Delphi, потому что атрибуты безопасности являются общими для всего API Windows, и у C# есть много последователей:)
1 ответ
Кто-то говорил об этой же проблеме на форумах SysInternals. Их решение состояло в том, чтобы добавить "Global" к названным объектам.
Так что используйте следующее
CreateEvent(@SecurityAttributes, False, True, 'Global\DBWIN_BUFFER_READY');
CreateEvent(@SecurityAttributes, False, False, 'Global\DBWIN_DATA_READY');
CreateFileMapping(THandle(-1), @SecurityAttributes, PAGE_READWRITE, 0, 4096, 'Global\DBWIN_BUFFER');