You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何NamedPipes在64位环境下无法正常工作?

64位构建下NamedPipe原生API调用返回无效句柄(错误码6)

我正在开发一个C#项目,通过原生C函数调用实现NamedPipes,完成主应用与Windows服务的进程间通信。32位构建下运行正常,但切换到64位构建后,客户端读取管道时GetLastError()始终返回错误码6(无效句柄)。

服务端核心代码

public const uint PIPE_ACCESS_DUPLEX = 0x00000003;
public const uint FILE_FLAG_OVERLAPPED = 0x40000000;
public const uint PIPE_WAIT = 0x00000000;
public const uint PIPE_READMODE_MESSAGE = 0x00000002;
public const uint PIPE_TYPE_MESSAGE = 0x00000004;
public const uint PIPE_UNLIMITED_INSTANCES = 255;
public const uint NMPWAIT_WAIT_FOREVER = 0xffffffff;
public const uint GENERIC_READ = (0x80000000);
public const uint GENERIC_WRITE = (0x40000000);
public const uint OPEN_EXISTING = 3;
public const uint WAIT_OBJECT_0 = 0x00000000;
public const uint ERROR_BROKEN_PIPE = 109;
public const uint ERROR_MORE_DATA = 234;
public const uint ERROR_PIPE_CONNECTED = 535;
public const uint ERROR_IO_PENDING = 997;
public const Int32 INVALID_HANDLE_VALUE = -1;

public const uint OUTPUT_BUFFER_SIZE_IN_BYTES = 32000;
public const uint INPUT_BUFFER_SIZE_IN_BYTES = 32000;
public const Int32 MAX_MESSAGE_SIZE_IN_BYTES = 1000000;

base.handle = CreateNamedPipe(@"\\.\pipe\" + name,
                      NamedPipe.PIPE_ACCESS_DUPLEX | NamedPipe.FILE_FLAG_OVERLAPPED,
                      NamedPipe.PIPE_TYPE_MESSAGE | NamedPipe.PIPE_READMODE_MESSAGE | NamedPipe.PIPE_WAIT,
                      NamedPipe.PIPE_UNLIMITED_INSTANCES,
                      NamedPipe.OUTPUT_BUFFER_SIZE_IN_BYTES,
                      NamedPipe.INPUT_BUFFER_SIZE_IN_BYTES,
                      NamedPipe.NMPWAIT_WAIT_FOREVER,
                      secAttr);

客户端核心代码

base.handle = CreateFile(@"\\.\pipe\" + name, NamedPipe.GENERIC_READ | NamedPipe.GENERIC_WRITE, 0, null, NamedPipe.OPEN_EXISTING, 0, 0);

错误信息

客户端读取管道时,调用GetLastError()返回错误码6:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetLastError();

ERROR: Invalid Handle Specified (错误6:无效句柄)

已确认kernel32.dll会自动路由到对应位数版本,排除这个因素。


问题原因与解决方法

核心原因:句柄类型的位数不匹配

64位系统中,Windows API返回的句柄是8字节的指针类型,代码中大概率存在以下问题:

  • base.handle类型错误:如果定义为Int32(32位整数),在64位环境下存储8字节句柄会被截断,直接导致无效句柄。
  • DllImport函数签名错误:CreateNamedPipe和CreateFile的返回值必须是IntPtr(适配32/64位的指针类型),而非固定位数的int或uint。

具体修复步骤

  1. 修正句柄类型:将base.handle的类型改为IntPtr,避免位数截断。
  2. 修正API函数签名:
    • CreateNamedPipe的正确签名:
      [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
      public static extern IntPtr CreateNamedPipe(
          string pipeName,
          uint dwOpenMode,
          uint dwPipeMode,
          uint nMaxInstances,
          uint nOutBufferSize,
          uint nInBufferSize,
          uint nDefaultTimeOut,
          IntPtr lpSecurityAttributes);
      
    • CreateFile的正确签名:
      [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
      public static extern IntPtr CreateFile(
          string fileName,
          uint desiredAccess,
          uint shareMode,
          IntPtr securityAttributes,
          uint creationDisposition,
          uint flagsAndAttributes,
          IntPtr templateFile);
      
  3. 修正无效句柄判断:将INVALID_HANDLE_VALUE替换为new IntPtr(-1),64位环境下只有IntPtr类型的-1才是标准的无效句柄值。

额外注意事项

  • 所有涉及句柄传递的API调用(如ReadFile、WriteFile),参数中的句柄必须统一使用IntPtr类型。
  • 64位环境下禁止将IntPtr强制转换为int或uint,避免数据截断。

内容的提问来源于stack exchange,提问作者Spiky05

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 20:52:47