如何从服务接收OutputDebugString? [英] How can I receive OutputDebugString from a service?

查看:315
本文介绍了如何从服务接收OutputDebugString?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试捕获所有使用以下代码的OutputDebugString 消息(包括来自服务的消息).在我迁移到Windows 7之前,它运行良好.

I'm trying to catch all OutputDebugString messages (including those from services) using the following code. It worked fine until I migrated to Windows 7.

问题在于,由于Windows Vista服务在低级会话#0中运行,因此有人说

The problem is that since Windows Vista services are running in the low level Session #0, some people say that it's impossible to catch them and some that it is. What do you think?

是否可以通过增加一些权限来修改以下代码,以便能够接收

Is it possible to modify the following code by increasing some rights to be able to receive OutputDebugString messages from the Session #0? In other words; is it possible to share DBWIN_BUFFER in the session #0 with Session #1?

我说这应该是可能的,因为DebugView可以做到这一点,而且我看不到任何服务助手会(例如通过命名管道)将这些消息从会话#0发送到运行GUI的会话#1.

I would say it should be possible because e.g. DebugView can do that, and I can't see any service helper which would send those messages (e.g. through the named pipes) from the Session #0 to Session #1, where the GUI's running.

问题将出在IMO的安全设置中.谁能建议我如何修改它们?

The problem will be IMO in the security settings. Can anyone suggest me how to modify them?

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;

即使代码位于Delphi中,我也添加了C#标记,因为安全属性对于整个Windows API都是通用的,并且C#具有许多关注者:)

推荐答案

有人在将"Global \"添加到命名对象

Someone talked about the same issue in the SysInternals forums. Their solution was to add "Global\" to the named objects.

因此请使用以下内容

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

这篇关于如何从服务接收OutputDebugString?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆