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; } }
问题原因
- UWP沙箱限制:UWP应用运行在受限的安全沙箱中,默认无法访问普通用户创建的命名管道,即使以管理员身份运行也无法突破沙箱的权限隔离。
- 管道安全属性缺失:Python创建管道时传入
None作为安全属性,默认会应用当前用户的严格访问权限,拒绝沙箱内的UWP进程访问。 - 管道命名空间不兼容: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>
验证步骤
- 运行修改后的Python服务端
- 启动C++ WinRT UWP客户端
- 检查是否成功建立连接并接收消息
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

