8

I'm trying to create a two-way communication channel between two programs (one in Python and another in C#)

When I create a named pipe between two C# programs or two Python programs, everything is OK, but when I try to (for example) connect to the C# server from Python code, it does not work:

C# code:

NamedPipeServerStream server = new NamedPipeServerStream(
    "Demo", PipeDirection.InOut, 100, PipeTransmissionMode.Byte,
    PipeOptions.None, 4096, 4096)

If I use win32pipe in Python, code blocks on ConnectNamedPipe (it never returns)

p = win32pipe.CreateNamedPipe(
    r'\\.\pipe\Demo',
    win32pipe.PIPE_ACCESS_DUPLEX,
    win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_WAIT,
    1, 65536, 65536,
    300,
    None)
win32pipe.ConnectNamedPipe(p)

If I use open function, it just establishes a connection, but nothing occurs:

open( '\\\\.\\pipe\\Demo', 'r+b' )

Now if I close the Python program, C# server receives just one data item from Python and a System.IO.IOException raises with "Pipe is broken" message

Am I doing anything wrong ?

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
Mehdi Asgari
  • 2,111
  • 3
  • 17
  • 18

3 Answers3

11

According to MS, ConnectNamedPipe is the "server-side function for accepting a connnection". That's why it never returns - it's waiting for a connection from a client. Here's some sample code showing C# as the server and python as the client:

C#:

using (var server = new NamedPipeServerStream("Demo"))
{
    server.WaitForConnection();

    using (var stream = new MemoryStream())
    using (var writer = new BinaryWriter(stream))
    {
        writer.Write("\"hello\"");
        server.Write(stream.ToArray(), 0, stream.ToArray().Length);
    }

    server.Disconnect();
}

python:

import win32file
fileHandle = win32file.CreateFile(
    "\\\\.\\pipe\\Demo", 
    win32file.GENERIC_READ | win32file.GENERIC_WRITE, 
    0, 
    None, 
    win32file.OPEN_EXISTING, 
    0, 
    None)
left, data = win32file.ReadFile(fileHandle, 4096)
print(data)  # "hello"
Pakman
  • 2,170
  • 3
  • 23
  • 41
  • 5
    This works like a charm :) Thanks for saving a lot of my time, 8 years later :) – Alex Sep 20 '18 at 12:44
  • Indeed, a very simple and working example! I would just add one minor thing which took me some time. In this example, both processes needs to run with same elevated rights, otherwise you will get ERROR_ACCESS_DENIED. – Tycho Mar 19 '23 at 08:57
1

OK, I fixed the problem. I should seek to position 0 of buffer.

My Python code:

    win32file.WriteFile(CLIENT_PIPE,"%d\r\n"%i ,None)
    win32file.FlushFileBuffers(CLIENT_PIPE)
    win32file.SetFilePointer(CLIENT_PIPE,0,win32file.FILE_BEGIN)
    i,s = win32file.ReadFile(CLIENT_PIPE,10,None)
Mehdi Asgari
  • 2,111
  • 3
  • 17
  • 18
0

I think you are meant to use win32pipe.popen, not open.

Also try: pipe.flush(), pipe.read(), and time.sleep(0.01). Sometimes IPC takes a while to sync up.

I don't really know, that's my experience with the subprocess pipes. win32pipe might be different.

wisty
  • 6,981
  • 1
  • 30
  • 29
  • I used win32pipe.popen. Nothing changed Have you managed to create a named pipe between Python and .NET ? I don't know why win32pipe.ConnectNamedPipe(p) never returns – Mehdi Asgari Nov 18 '09 at 08:57
  • I also used win32file, but now the connection establishes but WriteFile does not work (Yes, I've also flushed the buffer) – Mehdi Asgari Nov 18 '09 at 09:47