How to use Named Pipes? lazarus / 34-Windows ---------------------------------------------------------------------- Aidex · 2019-02-12 07:08 Hello! I want to use Named Pipes to communicate between two programs. With the Windows function I manage to create a named pipe, but unfortunately I fail to write into the pipe. What am I doing wrong? uses Windows; function Server_createPipe(): THandle; var    SD: SECURITY_DESCRIPTOR;    SA: SECURITY_ATTRIBUTES; const    PIPE_UNLIMITED_INSTANCES = 255; begin    InitializeSecurityDescriptor(@SD, SECURITY_DESCRIPTOR_REVISION);    SetSecurityDescriptorDacl(@SD, true, nil{ACL}, false);    SA.lpSecurityDescriptor := @SD;    SA.nLength := SizeOf(SA);    SA.bInheritHandle := true;    Result := CreateNamedPipe(PChar('\\.\pipe\Test'),                              PIPE_ACCESS_DUPLEX or FILE_FLAG_WRITE_THROUGH,                              PIPE_TYPE_BYTE or PIPE_NOWAIT, // others: PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE                              PIPE_UNLIMITED_INSTANCES,                              1024,                              1024,                              50,                             @SA); end;  function writeToPipe(Pipe: THandle; const s: String): Boolean; var written: DWord; begin   if s='' then Exit(true);   Result := WriteFile(Pipe, s[1], Length(s), {out}written, nil); end; The handle seems to be correct (value 252), but WriteFile always returns false. ---------------------------------------------------------------------- Aidex · 2019-02-12 07:23 By the way, is there a cross-operating system solution for Named Pipes? Unfortunately, the Lazarus unit Pipes only provides functions for Anonymous Pipes. ---------------------------------------------------------------------- Remy Lebeau · 2019-02-12 18:52 Quote from: Aidex on February 12, 2019, 08:08:12 amCode: [Select]SA.bInheritHandle := true; Why are you creating the server pipe as inheritable? Quote from: Aidex on February 12, 2019, 08:08:12 amCode: [Select]Result := CreateNamedPipe(PChar('\\.\pipe\Test'),                           PIPE_ACCESS_DUPLEX or FILE_FLAG_WRITE_THROUGH,                           PIPE_TYPE_BYTE or PIPE_NOWAIT, // others: PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE                           PIPE_UNLIMITED_INSTANCES,                           1024,                           1024,                           50,                           @SA); Did you check to make sure that CreateNamedPipe() is not returning INVALID_HANDLE_VALUE on failure? Quote from: Aidex on February 12, 2019, 08:08:12 amCode: [Select]Result := WriteFile(Pipe, s[1], Length(s), {out}written, nil); Note that this code assumes that String is AnsiString.  I would suggest encoding the String to a byte array first, using whatever charset you want to use (like UTF-8) and then send the bytes. Quote from: Aidex on February 12, 2019, 08:08:12 amThe handle seems to be correct (value 252), but WriteFile always returns false. Did you check with GetLastError() to find out WHY WriteFile() is returning false? Note that you are creating the pipe with the PIPE_NOWAIT flag: QuotePIPE_NOWAIT Nonblocking mode is enabled. In this mode, ReadFile, WriteFile, and ConnectNamedPipe always return immediately. When WriteFile() is used asynchronously, it always returns false, so you MUST check with GetLastError() afterwards to see if it returns ERROR_IO_PENDING indicating the write operation has actually been started in the background and did not really fail. Note, however: QuoteNote that nonblocking mode is supported for compatibility with Microsoft LAN Manager version 2.0 and should not be used to achieve asynchronous I/O with named pipes. if you want asynchronous I/O - use FILE_FLAG_OVERLAPPED You should replace the PIPE_NOWAIT flag with FILE_FLAG_OVERLAPPED when calling CreateNamedPipe(), and then pass OVERLAPPED structs to ConnectNamedPipe(), ReadFile(), and WriteFile() so you can track the status of I/O operations that are running in the background. See the following articles on MSDN: Named Pipe Type, Read, and Wait ModesSynchronous and Overlapped Pipe I/ONamed Pipe Server Using Overlapped I/O ---------------------------------------------------------------------- Aidex · 2019-02-13 21:33 Thank you very much for your detailed answer. The idea with GetLastError() really could have come to me. After WriteFile() GetLastError() returns the value 536 (ERROR_PIPE_LISTENING) = "Waiting for a process to open the other end of the pipe." After the other process has also opened the pipe, WriteFile() works now!  Thank you very much! ---------------------------------------------------------------------- Remy Lebeau · 2019-02-13 22:21 Quote from: Aidex on February 13, 2019, 10:33:25 pmThe idea with GetLastError() really could have come to me. Next time, please read the documentation more carefully. Quote from: Aidex on February 13, 2019, 10:33:25 pmAfter WriteFile() GetLastError() returns the value 536 (ERROR_PIPE_LISTENING) = "Waiting for a process to open the other end of the pipe." That means you are calling WriteFile() too soon, you are not waiting for a client to connect to the pipe first.  Call ConnectNamedPipe() and wait for it to report a successfully connected client before trying to read/write to it: QuoteEnables a named pipe server process to wait for a client process to connect to an instance of a named pipe. A client process connects by calling either the CreateFile or CallNamedPipe function. And don't forget to disconnect the pipe when done.