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

管道读取异常:读取计数为368字节但缓冲区仅返回1字节

管道读取异常:bytes_read显示读取368字节但缓冲区仅返回1字节

已成功打开管道并完成写入操作,但读取时出现异常:无报错信息,bytes_read对象显示读取了368字节,而缓冲区仅包含1字节。参考Python中该函数的其他示例并尝试多种修改后仍无法解决问题。程序运行流程为:先调用open_file,再调用write_file发送握手消息,之后在循环中调用read_all_file_contents。

相关代码

import ctypes as ct
from ctypes.wintypes import *
from .exceptions import WinapiException


__all__ = (
    "open_file", "read_file", "write_file", "read_all_file_contents",
)


# Winapi constants

GENERIC_READ = -0x80000000
GENERIC_WRITE = 0x40000000
OPEN_EXISTING = 0x3
INVALID_HANDLE_VALUE = -0x1
ERROR_IO_PENDING = 0x3E5


# Winapi structures

class SecurityAttributes(ct.Structure):
    _fields_ = (
        ("nLength", DWORD),
        ("lpSecurityDescriptor", LPVOID),
        ("bInheritHandle", BOOL)
    )


class OverlappedUnionStruct(ct.Structure):
    _fields_ = (
        ("Offset", DWORD),
        ("OffsetHigh", DWORD)
    )


class OverlappedUnion(ct.Union):
    _fields_ = (
        ("Offset", OverlappedUnionStruct),
        ("Pointer", LPVOID)
    )


class Overlapped(ct.Structure):
    _fields_ = (
        ("Internal", PULONG),
        ("InternalHigh", PULONG),
        ("Data", OverlappedUnion),
        ("hEvent", HANDLE)
    )


# Winapi functions

k32 = ct.WinDLL("kernel32")
GetLastError = k32.GetLastError
GetLastError.restype = DWORD
CreateFile = k32.CreateFileA
CreateFile.argtypes = LPCSTR, DWORD, DWORD, SecurityAttributes, DWORD, DWORD, HANDLE
CreateFile.restype = HANDLE
ReadFile = k32.ReadFile
ReadFile.argtypes = HANDLE, LPVOID, DWORD, LPDWORD, ct.POINTER(Overlapped)
ReadFile.restype = BOOL
WriteFile = k32.WriteFile
WriteFile.argtypes = HANDLE, LPCVOID, DWORD, LPDWORD, ct.POINTER(Overlapped)
WriteFile.restype = BOOL
PeekNamedPipe = k32.PeekNamedPipe
PeekNamedPipe.argtypes = HANDLE, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD
PeekNamedPipe.restype = BOOL


# Wrapper functions


def _peek_pipe(handle):
    bytes_available = ct.c_ulong()
    if not PeekNamedPipe(handle, None, 0, None, ct.byref(bytes_available), None):
        raise WinapiException(f"PeekNamedPipe failed with error code {GetLastError()}")
    print(f"Bytes available {bytes_available.value}")
    return bytes_available.value


def open_file(file_name, access=GENERIC_READ | GENERIC_WRITE, share_mode=0, security_attribute=None,
              creation_disposition=OPEN_EXISTING, flags=0, template_file=None):
    file_name = ct.c_char_p(file_name.encode())
    if security_attribute is None:
        security_attribute = SecurityAttributes()
    handle = CreateFile(file_name, access, share_mode, security_attribute, creation_disposition,
                        flags, template_file)
    if handle == INVALID_HANDLE_VALUE:
        raise WinapiException(f"CreateFile failed with error code {GetLastError()}")
    return handle


def read_file(handle, size):
    buf = (ct.c_char * size)()
    bytes_read = DWORD(0)
    print(f"reading {size}")
    if ReadFile(handle, ct.byref(buf), size, ct.byref(bytes_read), None):
        print(f"return data read {bytes_read.value}")
        return bytes_read.value, buf.value
    elif error_code := GetLastError() != ERROR_IO_PENDING:
        raise WinapiException(f"ReadFile failed with error code {error_code}")


def read_all_file_contents(handle):
    data = bytes()
    total_bytes_read = 0
    while bytes_available := _peek_pipe(handle):
        print("calling read_file")
        result = read_file(handle, bytes_available)
        if result is None:
            break
        print(result)
        total_bytes_read += result[0]
        data += result[1]
    return total_bytes_read, data


def write_file(handle, data):
    bytes_written = ct.c_ulong()
    print("writing time")
    if WriteFile(handle, data, len(data), ct.byref(bytes_written), Overlapped()):
        print("return bytes read")
        return bytes_written.value
    else:
        raise WinapiException(f"WriteFile failed with error code {GetLastError()}")

程序运行输出

Bytes available 0
...
Bytes available 368
calling read_file
reading 368
return data read 368
(368, b'\x01')
Bytes available 0
[Error from the main loop caused by only one byte being returned]

复现步骤(需打开Discord)

from winapi import open_file, read_all_file_contents, write_file
import json
import struct


def payload_to_bytes(opcode, payload):
    payload_bytes = json.dumps(payload).encode()
    header = struct.pack("BL", opcode, len(payload_bytes))
    return header + payload_bytes


handle = open_file("\\\\?\\pipe\\discord-ipc-0")

# handshake
write_file(handle, payload_to_bytes(0, {
    "v": 1,
    "client_id": "1032756213445836801"
}))


while True:
    bytes_read, raw = read_all_file_contents(handle)
    if bytes_read == 0:
        continue
    opcode, length, _ = struct.unpack_from("BLh", raw, 0)
    payload = json.loads(raw[8:8 + length].decode())
    print(payload)
    break

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 01:35:26