管道读取异常:读取计数为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
相关产品推荐
相关产品推荐

