Estoy tratando de atrapar todos los mensajes OutputDebugString (incluidos los de los servicios) utilizando el siguiente código. Funcionó bien hasta que migré a Windows 7.¿Cómo puedo recibir OutputDebugString desde un servicio?
El problema es que debido a que los servicios de Windows Vista se ejecutan en el bajo nivel Session # 0, algunas personas dicen que it's impossible para atraparlos y algunos que sí lo están. ¿Qué piensas?
¿Es posible modificar el siguiente código aumentando algunos derechos para poder recibir mensajes OutputDebugString de la sesión # 0? En otras palabras; ¿es posible compartir DBWIN_BUFFER en la sesión # 0 con Session # 1?
Yo diría que debería ser posible porque, p. DebugView puede hacer eso, y no puedo ver ningún ayudante de servicio que envíe esos mensajes (por ejemplo, a través de las canalizaciones con nombre) de la sesión # 0 a la sesión # 1, donde se ejecuta la GUI.
El problema será IMO en la configuración de seguridad. ¿Alguien puede sugerirme cómo modificarlos?
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;
He añadido la etiqueta C#, incluso si el código está en Delphi porque los atributos de seguridad son comunes para toda la API de Windows y C# tiene muchos seguidores :)
+1 y aceptar. Gracias; funciona perfectamente. Añadiré la solución específica a tu respuesta con excusa. –