Named pipes: C# server, C++ client
-
I wrote 2 pairs of named pipe client/server programs: 1st pair in C# (.NET 4) 2nd pair in C++ (un-managed) All 4 test programs use the same pipe name
\\\\.\pipe\mypipe
The C# pair work fine with each other - I send a message from the client and it is received by the server. The C++ pair work also fine with each other. But... when I try to run the C# client with the C++ server, or the C++ client with the C# server - then it doesn't work. The client is unable to connect to the server. Is there something preventing the C++ client from working with the .NET server? Should it work? Thank you. -
I wrote 2 pairs of named pipe client/server programs: 1st pair in C# (.NET 4) 2nd pair in C++ (un-managed) All 4 test programs use the same pipe name
\\\\.\pipe\mypipe
The C# pair work fine with each other - I send a message from the client and it is received by the server. The C++ pair work also fine with each other. But... when I try to run the C# client with the C++ server, or the C++ client with the C# server - then it doesn't work. The client is unable to connect to the server. Is there something preventing the C++ client from working with the .NET server? Should it work? Thank you.Crazy Joe Devola wrote:
The client is unable to connect to the server.
When running the C++ client and it doesn't connect, check the error code:
GetLastError()
The difficult we do right away... ...the impossible takes slightly longer.
-
Crazy Joe Devola wrote:
The client is unable to connect to the server.
When running the C++ client and it doesn't connect, check the error code:
GetLastError()
The difficult we do right away... ...the impossible takes slightly longer.
it returns error code 2 - ERROR_FILE_NOT_FOUND
-
it returns error code 2 - ERROR_FILE_NOT_FOUND
You might want to try Sysinternals' Process Explorer. It can enumerate every kernel object (that includes pipes) that exists inside a process. This way you could be sure the pipe name is being created the way you intend.
The difficult we do right away... ...the impossible takes slightly longer.
-
You might want to try Sysinternals' Process Explorer. It can enumerate every kernel object (that includes pipes) that exists inside a process. This way you could be sure the pipe name is being created the way you intend.
The difficult we do right away... ...the impossible takes slightly longer.
thank you. I have Process Explorer but I don't know how to see list of objects for a process. I used the search option to search for "mypipe". It shows that the server has a handle to \Device\NamedPipe\pipe\mypipe . I tried to check the client to open "\\Device\\NamedPipe\\pipe\\mypipe" but that didn't help (I didn't expect it to work anyway).
-
thank you. I have Process Explorer but I don't know how to see list of objects for a process. I used the search option to search for "mypipe". It shows that the server has a handle to \Device\NamedPipe\pipe\mypipe . I tried to check the client to open "\\Device\\NamedPipe\\pipe\\mypipe" but that didn't help (I didn't expect it to work anyway).
This is how the client opens the pipe:
hPipe=CreateFile("\\\\.\\pipe\\mypipe",
GENERIC_WRITE,//GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL) ;if ( hPipe!=INVALID_HANDLE_VALUE)
{
return 0; //Success!!!
}err = GetLastError();
if(err!=ERROR_PIPE_BUSY)
{
printf("Could not open pipe, GetLastError=%u\n", err);
return -1 ;
}Create file returns an invalid handle. GetLastError() returns 2.
-
This is how the client opens the pipe:
hPipe=CreateFile("\\\\.\\pipe\\mypipe",
GENERIC_WRITE,//GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL) ;if ( hPipe!=INVALID_HANDLE_VALUE)
{
return 0; //Success!!!
}err = GetLastError();
if(err!=ERROR_PIPE_BUSY)
{
printf("Could not open pipe, GetLastError=%u\n", err);
return -1 ;
}Create file returns an invalid handle. GetLastError() returns 2.
You do know that backslashes need to be escaped in C++, right? It should be:
hPipe=CreateFile("\\\\.\\pipe\\mypipe",
GENERIC_WRITE,//GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL) ;The difficult we do right away... ...the impossible takes slightly longer.
-
You do know that backslashes need to be escaped in C++, right? It should be:
hPipe=CreateFile("\\\\.\\pipe\\mypipe",
GENERIC_WRITE,//GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL) ;The difficult we do right away... ...the impossible takes slightly longer.
Yes i do :-) for some reason the codeproject shows just 1 backslash. I do have it like this:
"\\\\.\\pipe\\mypipe"
-
Yes i do :-) for some reason the codeproject shows just 1 backslash. I do have it like this:
"\\\\.\\pipe\\mypipe"
Let's see the code that creates the pipes in both projects.
The difficult we do right away... ...the impossible takes slightly longer.
-
Let's see the code that creates the pipes in both projects.
The difficult we do right away... ...the impossible takes slightly longer.
Server: C# NamedPipeServerStream pipeServer = new NamedPipeServerStream("\\\\.\\pipe\\mypipe", PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); // Wait for a connection pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer); Client: C++
hPipe=CreateFile("\\\\\\\\\\\\\\\\.\\\\\\\\pipe\\\\\\\\mypipe", GENERIC\_READ | GENERIC\_WRITE, 0, NULL, OPEN\_EXISTING, 0, NULL) ; if ( hPipe!=INVALID\_HANDLE\_VALUE) { return 0; //Success!!! } err = GetLastError(); if(err!=ERROR\_PIPE\_BUSY) { printf("Could not open pipe, GetLastError=%u\\n", err); return -1 ; } printf("Could not open pipe, GetLastError=%u. WaitNamedPipe.\\n", err); if(! WaitNamedPipe(pipe\_name,2000)) { printf("Could not open pipe\\n"); return -1 ; }
again: C++ client with C++ server - works. C# client with C# server - works. C++ client with C# server - does not works. Thank you.
-
Server: C# NamedPipeServerStream pipeServer = new NamedPipeServerStream("\\\\.\\pipe\\mypipe", PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); // Wait for a connection pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer); Client: C++
hPipe=CreateFile("\\\\\\\\\\\\\\\\.\\\\\\\\pipe\\\\\\\\mypipe", GENERIC\_READ | GENERIC\_WRITE, 0, NULL, OPEN\_EXISTING, 0, NULL) ; if ( hPipe!=INVALID\_HANDLE\_VALUE) { return 0; //Success!!! } err = GetLastError(); if(err!=ERROR\_PIPE\_BUSY) { printf("Could not open pipe, GetLastError=%u\\n", err); return -1 ; } printf("Could not open pipe, GetLastError=%u. WaitNamedPipe.\\n", err); if(! WaitNamedPipe(pipe\_name,2000)) { printf("Could not open pipe\\n"); return -1 ; }
again: C++ client with C++ server - works. C# client with C# server - works. C++ client with C# server - does not works. Thank you.
This is just a guess, but could it be that since you have specified both GENERIC_READ and GENERIC_WRITE for the client, then you need to open the server as "InOut"?
The difficult we do right away... ...the impossible takes slightly longer.
-
This is just a guess, but could it be that since you have specified both GENERIC_READ and GENERIC_WRITE for the client, then you need to open the server as "InOut"?
The difficult we do right away... ...the impossible takes slightly longer.
I thought of that. I tried changing the server side to InOut - it did not help. i also tried changing the client to GENERIC_WRITE without GENERIC_READ - it didn't work either. Thank you for all the advise, tips and time you spent trying to help - much appreciated.
-
I wrote 2 pairs of named pipe client/server programs: 1st pair in C# (.NET 4) 2nd pair in C++ (un-managed) All 4 test programs use the same pipe name
\\\\.\pipe\mypipe
The C# pair work fine with each other - I send a message from the client and it is received by the server. The C++ pair work also fine with each other. But... when I try to run the C# client with the C++ server, or the C++ client with the C# server - then it doesn't work. The client is unable to connect to the server. Is there something preventing the C++ client from working with the .NET server? Should it work? Thank you.I think the problem was found.... On stackoverflow, someone posted this answer: C#'s NamedPipeClientStream, NamedPipeServerStream automatically append "\.\\pipe\" to the name I changed the C# code to open the pipe just as "mypipe" and now the connection is successful.
-
I think the problem was found.... On stackoverflow, someone posted this answer: C#'s NamedPipeClientStream, NamedPipeServerStream automatically append "\.\\pipe\" to the name I changed the C# code to open the pipe just as "mypipe" and now the connection is successful.
Glad you got it sorted. :)
The difficult we do right away... ...the impossible takes slightly longer.