I'm trying to get a C++ application to let a C# application know when a particular action happens. The way I'm trying to do this is via named pipes.
I've set up a named pipe server on the C++ app, which seems to be working (the named pipe gets created - it appears on the list retrieved by PipeList) and a named pipe client on the C# app, where it fails: First line of the C# client code gives "Pipe handle has not been set. Did your PipeStream implementation call InitializeHandle?" error, and line 2 throws "Access to the path is denied" exception.
Where am I going wrong?
C++ Server Code
CString namedPipeName = "\\\\.\\pipe\\TitleChangePipe";
HANDLE pipe = CreateNamedPipe(namedPipeName, PIPE_ACCESS_INBOUND , PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
if (pipe == INVALID_HANDLE_VALUE) {
MessageBox(NULL, "Pipe Could Not be Established.", "Error: TCM", MB_ICONERROR);
return -1;
}
char line[512]; DWORD numRead;
while (true)//just keep doing this
{
numRead = 1;
while ((numRead < 10 || numRead > 511) && numRead > 0)
{
if (!ReadFile(pipe, line, 512, &numRead, NULL) || numRead < 1) {//Blocking call
CloseHandle(pipe); //If something went wrong, reset pipe
pipe = CreateNamedPipe(namedPipeName, PIPE_ACCESS_INBOUND , PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
ConnectNamedPipe(pipe, NULL);
if (pipe == INVALID_HANDLE_VALUE) {
MessageBox(NULL, "Pipe Could Not be Established.", "Error: TCM", MB_ICONERROR);
return -1; }
numRead = 1;
}
}
line[numRead] = '\0'; //Terminate String
}
CloseHandle(pipe);
C# Client Code
var client = new NamedPipeClientStream(".", "TitleChangePipe", PipeDirection.InOut);
client.Connect();
var reader = new StreamReader(client);
var writer = new StreamWriter(client);
while (true)
{
var input = Console.ReadLine();
if (String.IsNullOrEmpty(input))
break;
writer.WriteLine(input);
writer.Flush();
Console.WriteLine(reader.ReadLine());
}
The named pipe creation doesn't have the right parameters.
First you want to read & write on the pipe, so the flag to use is : PIPE_ACCESS_DUPLEX
Then, here you are sending messages in synchronous mode. Use these flags : PIPE_WAIT | PIPE_TYPE_MESSAGE
Finally, you are allowing only one instance of this pipe on the machine. Obviously you need at least 2: One for the server one for the client. I would just use the unlimited flag: PIPE_UNLIMITED_INSTANCES
HANDLE pipe = CreateNamedPipe(namedPipeName, PIPE_ACCESS_DUPLEX, \
PIPE_WAIT | PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, \
1024, 1024, 120 * 1000, NULL);
After creating a pipe in the server you should wait against connections on this pipe before using it : https://msdn.microsoft.com/en-us/library/windows/desktop/aa365146(v=vs.85).aspx