试图在 Windows 10 中打开一个现有的命名管道 - errno 22,无效的参数,但为什么呢?

Spo*_*are 5 python ipc pipe named-pipes python-3.x

我正在编写/试验需要连接到 Windows 10 中现有命名管道的 python 脚本。我使用的是 Python 3.8。

命名管道

具体来说,我试图连接到一个名为的管道SendPipe1并向其写入 14 个 ascii 编码的字符。

管道是由其他一些软件(驱动程序?)为连接到我的 PC 的设备创建的。我正在连接它以尝试以与制造商提供的软件相同的方式与设备交互。制造商提供的软件连接到同一管道并向其发送编码消息,命令设备执行某些操作。这就是我想做的。

通过运行 PipeList 实用程序,我知道管道已经存在:

PipeList v1.02 - Lists open named pipes
Copyright (C) 2005-2016 Mark Russinovich
Sysinternals - www.sysinternals.com

Pipe Name                                    Instances       Max Instances
---------                                    ---------       -------------
[...]
chrome.blah.foo                                   1                1
SendPipe1                                         1               -1
ReceivePipe1                                      1               -1
chrome.blah.bar                                   1                1
[...]
Run Code Online (Sandbox Code Playgroud)

编码

这是我现在所拥有的:

ACTIVE_DISP_ID = 1
msg = f'6;16;100;{ACTIVE_DISP_ID};1\r\n'
pipe_path = f'\\\\.\\PIPE\\SendPipe{ACTIVE_DISP_ID}'

try:
    f = open(pipe_path, 'wb+', buffering=0)
    f.write(msg.encode(encoding='ascii'))
except OSError as e:
    raise
Run Code Online (Sandbox Code Playgroud)

这给了我

错误

Traceback (most recent call last):
  File "C:/Users/Spooqi/PycharmProjects/Spooqi/radiant/pipe-test.py", line 7, in <module>
    f = open(pipe_path, 'wb+', buffering=0)
OSError: [Errno 22] Invalid argument: '\\\\.\\PIPE\\SendPipe1'
Run Code Online (Sandbox Code Playgroud)

我相当确定路径'\\\\.\\PIPE\\SendPipe1'是正确的,因为如果我将其更改为类似'\\\\.\\PIPE\\FooPipeBar',则会得到不同的异常:

FileNotFoundError: [Errno 2] No such file or directory: '\\\\.\\PIPE\\FooPipeBar'
Run Code Online (Sandbox Code Playgroud)

如果我写入一个(还)不存在相对路径的常规文件,foobar它通常只会生成一个带有该消息的文本文件。

问题

在这种情况下,errno 22 是什么意思?为什么这个论点无效?为什么我不能连接到这个管道并写入它?

是否有其他进程已连接到管道?我将如何检查?如果有,我怎样才能同时通过管道连接到设备?

nij*_*ave 0

我没有这方面的来源,但是从 Python 在 Windows 上打开管道时出现 errno 22 似乎表明该管道已被另一个进程使用。

例如:

  • Hyper-V 打开\\.\pipe\pipe1以作为 VM-A 的 ComPort 进行写入
  • Hyper-V 也无法\\.\pipe\pipe1作为 VM-B 的 ComPort 打开进行写入

或者:

  • Hyper-V 打开 ComPort\\.\pipe\pipe1进行写入
  • 程序-A 打开 ComPort\\.\pipe\pipe1进行读取
  • Program-B 也无法打开\\.\pipe\pipe1读取

根据管道的类型,可能还有其他警告,但这是我在将单个读取器/写入器命名管道与 Hyper-V 结合使用时对错误 22 的观察

使用 Powershell 时,您会看到此错误

PS C:\> $pipe = new-object System.IO.Pipes.NamedPipeClientStream \\.\pipe\pipe1
PS C:\> $pipe.Connect(1)
Exception calling "Connect" with "1" argument(s): "The semaphore timeout period has expired.
"
At line:1 char:1
+ $pipe.Connect(1)
+ ~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : IOException

Run Code Online (Sandbox Code Playgroud)