I am writing a C++ program that makes use of named pipes on Windows. I can create and work with them quite fine. The only piece missing to the puzzle is a function to check for a pipe's existence.
Coming from the Unix world I originally tried std::filesystem::exists("\\\\.\\pipe\\myPipe")
but this is not reliable and often errors with ERROR_PIPE_BUSY
.
While searching for an alternative way to check for a pipe's existence, I stumbled upon this issue on GitHub (Boost process) and from there I take it that Boos process circumvents the problem by using a special naming scheme and a counter and then keeping track of that internally (only seems to work for pipes created via Boost process though).
Furthermore according to How can I get a list of all open named pipes in Windows? it seems that there are ways to list the existing named pipes. These solutions are not using C++ though and I did not find a way to port that over.
After having read the documentation of CreateNamedPipe, I now assembled the following solution to my problem:
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;
}
}
However attempting to create a named pipe only to check whether there already exists one with that name already seems like a lot of unnecessary overhead. Furthermore I am unsure of whether this solution is universally applicable or only works if the pipe tested for was also created with FILE_FLAG_FIRST_PIPE_INSTANCE
.
Therefore my question is: Is there a better way to check whether a named pipe with the given name already exists in Windows?