【发布时间】:2021-06-09 15:15:12
【问题描述】:
我正在编写一个在 Windows 上使用命名管道的 C++ 程序。我可以很好地创建和使用它们。唯一缺少的部分是检查管道是否存在的函数。
来自 Unix 世界,我最初尝试过 std::filesystem::exists("\\\\.\\pipe\\myPipe"),但这并不可靠,并且经常与 ERROR_PIPE_BUSY 出错。
在寻找检查管道是否存在的替代方法时,我偶然发现了 GitHub 上的this issue(Boost 进程),从那里我认为 Boos 进程通过使用特殊的命名方案和计数器来规避问题,并且然后在内部跟踪它(但似乎只适用于通过 Boost 进程创建的管道)。
此外,根据How can I get a list of all open named pipes in Windows?,似乎有办法列出现有的命名管道。这些解决方案虽然没有使用 C++,但我没有找到将其移植过来的方法。
在阅读了documentation of CreateNamedPipe 之后,我现在组装了以下解决方案来解决我的问题:
bool NamedPipe::exists(const std::filesystem::path &pipePath) {
if (pipePath.parent_path() != "\\\\.\\pipe") {
// This can't be a pipe, so it also can't exist
return false;
}
// Attempt to create a pipe with FILE_FLAG_FIRST_INSTANCE so that the creation will fail
// if the pipe already exists
HANDLE pipeHandle = CreateNamedPipe(pipePath.string().c_str(),
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_WAIT,
1, // # of allowed pipe instances
0, // Size of outbound buffer
0, // Size of inbound buffer
0, // Use default wait time
NULL // Use default security attributes
);
if (pipeHandle == INVALID_HANDLE_VALUE) {
// Creation has failed
// It has failed (most likely) due to there alredy existing a pipe with
// that name
return true;
} else {
// The creation has succeeded
if(!CloseHandle(pipeHandle)) {
throw PipeException< DWORD >(GetLastError(), "CheckExistance");
}
return false;
}
}
然而,试图创建一个命名管道只是为了检查是否已经存在一个具有该名称的管道似乎已经有很多不必要的开销。此外,我不确定此解决方案是否普遍适用,或者仅在测试的管道也是使用 FILE_FLAG_FIRST_PIPE_INSTANCE 创建时才有效。
因此我的问题是:有没有更好的方法来检查 Windows 中是否已经存在具有给定名称的命名管道?
【问题讨论】:
-
我没有理由想要拥有该功能。它提供的唯一东西是 TOCTTOU 比赛。强大的软件不需要。
-
@IInspectable 我想在我的单元测试中使用它来检查管道是否已创建,然后按照我的预期再次删除。我不打算在生产中使用它。
标签: c++ windows named-pipes