/// <summary> /// Named pipe server through P/Invoke-ing the native APIs /// </summary> static void PInvokeNativePipeServer() { ///////////////////////////////////////////////////////////////////// // Create a named pipe. // // Prepare the pipe name String strPipeName = String.Format(@"\\{0}\pipe\{1}", ".", // Server name "HelloWorld" // Pipe name ); // Prepare the security attributes IntPtr pSa = IntPtr.Zero; // NULL SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); SECURITY_DESCRIPTOR sd; SecurityNative.InitializeSecurityDescriptor(out sd, 1); // DACL is set as NULL to allow all access to the object. SecurityNative.SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false); sa.lpSecurityDescriptor = Marshal.AllocHGlobal(Marshal.SizeOf( typeof(SECURITY_DESCRIPTOR))); Marshal.StructureToPtr(sd, sa.lpSecurityDescriptor, false); sa.bInheritHandle = false; // Not inheritable sa.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)); pSa = Marshal.AllocHGlobal(sa.nLength); Marshal.StructureToPtr(sa, pSa, false); // Create the named pipe. IntPtr hPipe = PipeNative.CreateNamedPipe( strPipeName, // The unique pipe name. PipeOpenMode.PIPE_ACCESS_DUPLEX, // The pipe is bi-directional PipeMode.PIPE_TYPE_MESSAGE | // Message type pipe PipeMode.PIPE_READMODE_MESSAGE | // Message-read mode PipeMode.PIPE_WAIT, // Blocking mode is on PipeNative.PIPE_UNLIMITED_INSTANCES, // Max server instances BUFFER_SIZE, // Output buffer size BUFFER_SIZE, // Input buffer size PipeNative.NMPWAIT_USE_DEFAULT_WAIT, // Time-out interval pSa // Pipe security attributes ); if (hPipe.ToInt32() == PipeNative.INVALID_HANDLE_VALUE) { Console.WriteLine("Unable to create named pipe {0} w/err 0x{1:X}", strPipeName, PipeNative.GetLastError()); return; } Console.WriteLine("The named pipe, {0}, is created.", strPipeName); ///////////////////////////////////////////////////////////////////// // Wait for the client to connect. // Console.WriteLine("Waiting for the client's connection..."); bool bConnected = PipeNative.ConnectNamedPipe(hPipe, IntPtr.Zero) ? true : PipeNative.GetLastError() == PipeNative.ERROR_PIPE_CONNECTED; if (!bConnected) { Console.WriteLine( "Error occurred while connecting to the client: 0x{0:X}", PipeNative.GetLastError()); PipeNative.CloseHandle(hPipe); // Close the pipe handle. return; } ///////////////////////////////////////////////////////////////////// // Read client requests from the pipe and write the response. // // A byte buffer of BUFFER_SIZE bytes. The buffer should be big // enough for ONE request from a client. string strMessage; byte[] bRequest = new byte[BUFFER_SIZE];// Client -> Server uint cbBytesRead, cbRequestBytes; byte[] bReply; // Server -> Client uint cbBytesWritten, cbReplyBytes; bool bResult; while (true) { // Receive one message from the pipe. cbRequestBytes = BUFFER_SIZE; bResult = PipeNative.ReadFile( // Read from the pipe. hPipe, // Handle of the pipe bRequest, // Buffer to receive data cbRequestBytes, // Size of buffer in bytes out cbBytesRead, // Number of bytes read IntPtr.Zero); // Not overlapped I/O if (!bResult /*Failed*/ || cbBytesRead == 0 /*Finished*/) { break; } // Unicode-encode the byte array and trim all the '\0' chars at // the end. strMessage = Encoding.Unicode.GetString(bRequest).TrimEnd('\0'); Console.WriteLine("Receives {0} bytes; Message: \"{1}\"", cbBytesRead, strMessage); // Prepare the response. // '\0' is appended in the end because the client may be a native // C++ program. strMessage = "Default response from server\0"; bReply = Encoding.Unicode.GetBytes(strMessage); cbReplyBytes = (uint)bReply.Length; // Write the response to the pipe. bResult = PipeNative.WriteFile( // Write to the pipe. hPipe, // Handle of the pipe bReply, // Buffer to write to cbReplyBytes, // Number of bytes to write out cbBytesWritten, // Number of bytes written IntPtr.Zero); // Not overlapped I/O if (!bResult /*Failed*/ || cbReplyBytes != cbBytesWritten /*Failed*/) { Console.WriteLine("WriteFile failed w/err 0x{0:X}", PipeNative.GetLastError()); break; } Console.WriteLine("Replies {0} bytes; Message: \"{1}\"", cbBytesWritten, strMessage.TrimEnd('\0')); } ///////////////////////////////////////////////////////////////////// // Flush the pipe to allow the client to read the pipe's contents // before disconnecting. Then disconnect the pipe, and close the // handle to this pipe instance. // PipeNative.FlushFileBuffers(hPipe); PipeNative.DisconnectNamedPipe(hPipe); PipeNative.CloseHandle(hPipe); }
static void Main(string[] args) { ///////////////////////////////////////////////////////////////////// // Create the mailslot. // // Prepare the slot name String strMailslotName = String.Format(@"\\{0}\mailslot\{1}", ".", // Server name "HelloWorld" // Pipe name ); // Prepare the security attributes IntPtr pSa = IntPtr.Zero; // NULL SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); SECURITY_DESCRIPTOR sd; SecurityNative.InitializeSecurityDescriptor(out sd, 1); // ACL is set as NULL to allow all access to the object. SecurityNative.SetSecurityDescriptorDacl( ref sd, true, IntPtr.Zero, false); sa.lpSecurityDescriptor = Marshal.AllocHGlobal(Marshal.SizeOf( typeof(SECURITY_DESCRIPTOR))); Marshal.StructureToPtr(sd, sa.lpSecurityDescriptor, false); sa.bInheritHandle = false; // Not inheritable sa.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)); pSa = Marshal.AllocHGlobal(sa.nLength); Marshal.StructureToPtr(sa, pSa, false); // Create the mailslot. IntPtr hMailslot = MailslotNative.CreateMailslot( strMailslotName, // The name of the mailslot 0, // No maximum message size MailslotNative.MAILSLOT_WAIT_FOREVER, pSa); // Security attributes if (hMailslot.ToInt32() == MailslotNative.INVALID_HANDLE_VALUE) { Console.WriteLine("CreateMailslot failed w/err 0x{0:X}", Marshal.GetLastWin32Error()); return; } Console.WriteLine("Mailslot {0} created successfully.", strMailslotName); ///////////////////////////////////////////////////////////////////// // Check messages in the mailslot. // try { // In a loop, check for new messages every 5 seconds. while (true) { Console.WriteLine("Checking new messages..."); ReadMailslot(hMailslot); System.Threading.Thread.Sleep(5000); } } finally { ///////////////////////////////////////////////////////////////// // Close the handle of the mailslot instance. // MailslotNative.CloseHandle(hMailslot); } }