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

Python与C++ WinRT UWP应用命名管道通信遇访问拒绝问题

命名管道跨Python与C++ WinRT UWP通信的权限问题解决

问题描述

尝试通过命名管道实现Python服务端向C++ WinRT UWP客户端发送消息,Python客户端测试正常,但C++端出现Access Denied错误,Python端提示The pipe is getting closed。已尝试以管理员模式运行双方程序,问题依然存在。

双方源码

Python服务端代码

import win32pipe
import win32file

# Define the name of the pipe
pipe_name = r'\\.\pipe\myPipe'

try:
    # Create the named pipe
    pipe = win32pipe.CreateNamedPipe(
        pipe_name,
        win32pipe.PIPE_ACCESS_DUPLEX,
        win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
        1,  # Number of instances
        65536,  # Out buffer size
        65536,  # In buffer size
        0,  # Timeout
        None  # Security attributes
    )

    print("Waiting for connection...")

    # Wait for a client to connect
    win32pipe.ConnectNamedPipe(pipe, None)

    print("Client connected!")
    message = "test"
    win32file.WriteFile(pipe, message.encode('utf-8'))
    win32file.FlushFileBuffers(pipe)
    print("Sent data")
    
    # Read the data
    #data_received, _ = win32file.ReadFile(pipe)
    #print(f"Received data: {data_received.decode('utf-8')}")

finally:
    # Close the pipe
    win32pipe.DisconnectNamedPipe(pipe)
    win32file.CloseHandle(pipe)

C++ WinRT UWP客户端代码

HANDLE hPipe;
LPTSTR lpvMessage = TEXT("Default message from client.");
TCHAR  chBuf[512];
BOOL   fSuccess = FALSE;
DWORD  cbRead, cbToWrite, cbWritten, dwMode;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\myPipe");

while (1)
{
    
    hPipe = CreateFile2(
        lpszPipename,   // pipe name 
        GENERIC_READ,
        0,              // no sharing 
        OPEN_EXISTING,  // opens existing pipe 
        NULL);          // no template file 

    // Break if the pipe handle is valid. 

    if (hPipe != INVALID_HANDLE_VALUE)
        break;

    // Exit if an error other than ERROR_PIPE_BUSY occurs. 

    if (GetLastError() != ERROR_PIPE_BUSY)
    {
        DWORD errorr = GetLastError();
        printf("Could not open pipe. GLE=%d\n", GetLastError());
        break;
    }

    // All pipe instances are busy, so wait for 20 seconds. 

    if (!WaitNamedPipe(lpszPipename, 20000))
    {
        printf("Could not open pipe: 20 second wait timed out.");
        break;
    }

}

问题原因

  1. UWP沙箱限制:UWP应用运行在受限的安全沙箱中,默认无法访问普通用户创建的命名管道,即使以管理员身份运行也无法突破沙箱的权限隔离。
  2. 管道安全属性缺失:Python创建管道时传入None作为安全属性,默认会应用当前用户的严格访问权限,拒绝沙箱内的UWP进程访问。
  3. 管道命名空间不兼容:UWP只能访问特定命名空间的管道,\\.\pipe\这种本地管道不在UWP的允许访问范围内。

解决方案

1. 修改管道名称为UWP兼容的命名空间

UWP仅允许访问以下命名空间的管道:

  • \\.\pipe\LOCAL\:适用于本地用户的管道(推荐)
  • \\.\pipe\LOCALLOW\:适用于低权限本地用户的管道
  • \\.\pipe\GLOBAL\:全局管道,需要管理员权限

修改双方的管道名称,例如改为:

# Python端
pipe_name = r'\\.\pipe\LOCAL\myPipe'
// C++端
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\LOCAL\\myPipe");

2. 为Python端管道设置开放的安全属性

构造允许所有用户(包括UWP沙箱进程)访问的安全描述符,替换原有的None参数:

修改后的Python代码:

import win32pipe
import win32file
import win32security
import ntsecuritycon as con

# Define the name of the pipe
pipe_name = r'\\.\pipe\LOCAL\myPipe'

try:
    # 创建安全描述符,允许所有用户读写管道
    sa = win32security.SECURITY_ATTRIBUTES()
    sd = win32security.SECURITY_DESCRIPTOR()
    sd.SetSecurityDescriptorDacl(1, None, 0)  # 启用DACL,并设置允许所有访问
    
    # 添加Everyone用户的完全访问权限
    everyone_sid = win32security.CreateWellKnownSid(win32security.WinWorldSid)
    ace = win32security.ACL()
    ace.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_ALL_ACCESS, everyone_sid)
    sd.SetSecurityDescriptorDacl(1, ace, 0)
    sa.SECURITY_DESCRIPTOR = sd

    # Create the named pipe
    pipe = win32pipe.CreateNamedPipe(
        pipe_name,
        win32pipe.PIPE_ACCESS_DUPLEX,
        win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
        1,  # Number of instances
        65536,  # Out buffer size
        65536,  # In buffer size
        0,  # Timeout
        sa  # 使用自定义安全属性
    )

    print("Waiting for connection...")

    # Wait for a client to connect
    win32pipe.ConnectNamedPipe(pipe, None)

    print("Client connected!")
    message = "test"
    win32file.WriteFile(pipe, message.encode('utf-8'))
    win32file.FlushFileBuffers(pipe)
    print("Sent data")
    
    # 可选:等待客户端响应(如果需要双向通信)
    # data_received, _ = win32file.ReadFile(pipe)
    # print(f"Received data: {data_received.decode('utf-8')}")

finally:
    # Close the pipe
    win32pipe.DisconnectNamedPipe(pipe)
    win32file.CloseHandle(pipe)

3. 确保UWP应用声明管道访问权限

在UWP应用的Package.appxmanifest中添加命名管道的功能声明:

<Capabilities>
    <Capability Name="internetClient" />
    <DeviceCapability Name="namedPipes" />
</Capabilities>

验证步骤

  1. 运行修改后的Python服务端
  2. 启动C++ WinRT UWP客户端
  3. 检查是否成功建立连接并接收消息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 22:28:10