Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过Win32 API捕获全局(会话0)OutputDebugString消息时出现问题?_C#_.net_Winapi_Outputdebugstring - Fatal编程技术网

C# 通过Win32 API捕获全局(会话0)OutputDebugString消息时出现问题?

C# 通过Win32 API捕获全局(会话0)OutputDebugString消息时出现问题?,c#,.net,winapi,outputdebugstring,C#,.net,Winapi,Outputdebugstring,我目前正在开发一个简单的应用程序来捕获OutputDebugString消息(类似于或)。当从本地会话访问OutputDebugString消息时(即Local\DBWIN\u BUFFER\u READY、Local\DBWIN\u DATA\u READY和Local\DBWIN\u BUFFER)一切都正常工作 但是,当我尝试访问会话0的任何输出时(即,Global\DBWIN\u BUFFER\u READY等),我没有收到任何输出。基于DbgView的行为,我假设应用程序必须以某种级别

我目前正在开发一个简单的应用程序来捕获OutputDebugString消息(类似于或)。当从本地会话访问OutputDebugString消息时(即Local\DBWIN\u BUFFER\u READY、Local\DBWIN\u DATA\u READY和Local\DBWIN\u BUFFER)一切都正常工作

但是,当我尝试访问会话0的任何输出时(即,Global\DBWIN\u BUFFER\u READY等),我没有收到任何输出。基于DbgView的行为,我假设应用程序必须以某种级别的管理权限运行。我认为我配置的SecurityDescriptor不正确,或者我完全丢失了访问全局OutputDebugString消息的内容(读作…我现在对此有点不知所措)

我在下面突出显示了代码片段,但完整的源代码可以在

如果您对此事有任何帮助或见解,我们将不胜感激。提前谢谢

安全描述符配置

我尝试了一些不同的配置,但提交的代码目前看起来如下所示

[DllImport("advapi32.dll", SetLastError = true)]
private static extern Boolean InitializeSecurityDescriptor(ref SecurityDescriptor sd, UInt32 dwRevision);

[DllImport("advapi32.dll", SetLastError = true)]
private static extern Boolean SetSecurityDescriptorDacl(ref SecurityDescriptor sd, Boolean daclPresent, IntPtr dacl, Boolean daclDefaulted);

public SecurityDescriptor InitializeSecurityDescriptor()
{
  const Int32 securityDescriptorRevision = 1;
  var securityDescriptor = new SecurityDescriptor();

  // Initialize the security descriptor.
  if (!InitializeSecurityDescriptor(ref securityDescriptor, securityDescriptorRevision))
    throw new Win32Exception(Marshal.GetLastWin32Error());

  // Set information in a discretionary access control list
  if (!SetSecurityDescriptorDacl(ref securityDescriptor, true, IntPtr.Zero, false))
    throw new Win32Exception(Marshal.GetLastWin32Error());

  return securityDescriptor;
}
正如您所期望的,这段代码最终会在我的DbWinMessageSource类的设置中调用

_windowsApi.Advanced.InitializeSecurityDescriptor();
安全属性和事件

当前在CodePlex上提交的代码使用的是本地\**前缀,但唯一的区别应该是本地\**替换为全局\**据我所知?然而,这似乎并没有像预期的那样捕获输出。同样,相关的代码片段

  public const Int32 ErrorAlreadyExists = 183;

  [DllImport("kernel32.dll", SetLastError = true)]
  private static extern IntPtr CreateEvent(ref SecurityAttributes sa, Boolean bManualReset, Boolean bInitialState, String lpName);

  public Handle CreateLocalEvent(ref SecurityAttributes securityAttributes, String objectName)
    {
      Verify.NotWhitespace(objectName);
      return CreateEvent(ref securityAttributes, "Local", objectName);
    }

    public Handle CreateGlobalEvent(ref SecurityAttributes securityAttributes, String objectName)
    {
      Verify.NotWhitespace(objectName);
      return CreateEvent(ref securityAttributes, "Global", objectName);
    }

    private static Handle CreateEvent(ref SecurityAttributes securityAttributes, String objectNamePrefix, String objectName)
    {
      IntPtr handle = CreateEvent(ref securityAttributes, false, false, String.Format(@"{0}\{1}", objectNamePrefix, objectName));

      if(Marshal.GetLastWin32Error() == ErrorAlreadyExists)
        throw new Win32Exception(ErrorAlreadyExists);

      if (handle == IntPtr.Zero)
        throw new Win32Exception(Marshal.GetLastWin32Error());

      return new Handle(handle, CloseHandle);
    }
同样,在DbWinMessageSource的设置中最终调用,如下所示:

  _dbwinBufferReadyEvent = _windowsApi.Basic.CreateGlobalEvent(ref securityAttributes, "DBWIN_BUFFER_READY");
  _dbwinDataReadyEvent = _windowsApi.Basic.CreateGlobalEvent(ref securityAttributes, "DBWIN_DATA_READY");
  _dbwinBufferFile = _windowsApi.Basic.CreateGlobalFileMapping(ref securityAttributes, "DBWIN_BUFFER");
  using (var identity = WindowsIdentity.GetCurrent())
  {
    if (identity == null)
      return;

    TokenPrivilege tp;

    tp.Count = 1;
    tp.Luid = 0;
    tp.Attr = SE_PRIVILEGE_ENABLED;
    if (!LookupPrivilegeValue(null, SE_CREATE_GLOBAL_NAME, ref tp.Luid))
      throw new Win32Exception(Marshal.GetLastWin32Error());

    if (!AdjustTokenPrivileges(identity.Token, false, ref tp, Marshal.SizeOf(tp), IntPtr.Zero, IntPtr.Zero))
      throw new Win32Exception(Marshal.GetLastWin32Error());
  }
我正在使用一个配置了OutputDebugString追加器的Log4Net简单web应用程序进行测试。当我通过VisualStudio运行应用程序时,我会按预期捕获所有本地输出。当我将应用程序移入IIS并配置代码以捕获全局会话中的任何内容时;我什么也得不到。我已经确认DbgView正在捕获来自IIS的输出,正如我所期望的那样(因此这肯定是我做错的事情)

希望这是足够的背景,但如果需要更多的信息或细节;让我知道

注意:在Windows7 Professional上开发,如果这样做有区别的话

编辑

正如泰兰德(和卢克)所指出的,所需要的只是管理员权限,以及创建全局名称。我又运行了一些测试,上面的代码设置实际上捕获了一些全局消息(例如,在IISRESET期间);但是,当应用程序在IIS内部运行时(在VS会话期间通过本地\**路由),上述代码不会从Log4Net OutputDebutString appender捕获任何数据。所有Win32 api调用都已成功返回,调用
Marshal.GetLastWin32Error()时也未返回任何错误。
为了更好地衡量,我添加了一些代码以确保当前Windows令牌具有SE\u CREATE\u GLOBAL\u名称。粗略的代码如下所示:

  _dbwinBufferReadyEvent = _windowsApi.Basic.CreateGlobalEvent(ref securityAttributes, "DBWIN_BUFFER_READY");
  _dbwinDataReadyEvent = _windowsApi.Basic.CreateGlobalEvent(ref securityAttributes, "DBWIN_DATA_READY");
  _dbwinBufferFile = _windowsApi.Basic.CreateGlobalFileMapping(ref securityAttributes, "DBWIN_BUFFER");
  using (var identity = WindowsIdentity.GetCurrent())
  {
    if (identity == null)
      return;

    TokenPrivilege tp;

    tp.Count = 1;
    tp.Luid = 0;
    tp.Attr = SE_PRIVILEGE_ENABLED;
    if (!LookupPrivilegeValue(null, SE_CREATE_GLOBAL_NAME, ref tp.Luid))
      throw new Win32Exception(Marshal.GetLastWin32Error());

    if (!AdjustTokenPrivileges(identity.Token, false, ref tp, Marshal.SizeOf(tp), IntPtr.Zero, IntPtr.Zero))
      throw new Win32Exception(Marshal.GetLastWin32Error());
  }

如果您对此有进一步的了解,我们将不胜感激。

您确定要创建节/文件映射对象吗?是的,您需要是管理员才能这样做,因为在全局命名空间中创建文件映射需要在您的令牌中使用SeCreateGlobalPrivilege。现在,您可能需要在调用CreateFileMapping之前启用该功能,但我已经有一段时间没有使用该功能了,而且手头没有代码


哦,你真的不应该指定一个空DACL,它在很多级别上都是错误的,我知道dbgview会这样做,但它只是懒惰,而且当完整性级别涉及到vista+时,它可能会崩溃。

有趣。。。我将探索设置SeCreateGlobalPrivilege,看看这是否能让我达到我想要的目标。我还将重新访问空DACL;我想让基本功能到位,然后我可以在一切都好的时候锁定所有东西。+1为我指明了正确的方向,但仍然不太清楚。。。在IIS中运行时,我没有像预期的那样捕获OutputDebugString追加器信息(DbgView正在查看所有内容)。我用一个代码片段更新了上面的代码,以确保设置了SE_CREATE_GLOBAL_NAME,但还需要一些其他东西。没有抛出任何错误,就所有Win32 API调用而言;一切都表明它是成功的。接受作为答案,因为这确实捕获了我最初的一些全球会话捕获问题;这个悬而未决的问题需要一个内核钩子(),从技术上讲,它与我最初发布的内容是不同的。最终我走上了另一条路。到底是什么不起作用?对象是否已成功创建?某些特定的函数失败了吗?我使用本机代码测试了它,它对我来说运行良好。唯一需要注意的是1)必须以管理员身份运行,2)必须启用SeCreateGlobalPrivilege。@卢克,正如泰兰德在下面指出的,我认为我缺少的是SeCreateGlobalPrivilege。我发现了以下链接,我认为它将为我指明正确的方向,但我还没有机会测试它: