/// <summary> /// Connects to a server named pipe. /// </summary> /// <param name="pipeName">The pipe name.</param> /// <param name="serverName">The server name.</param> /// <returns>The pipe handle, which also contains the pipe state.</returns> /// <remarks>This method is used by clients to establish a pipe connection with a server pipe.</remarks> #endregion public static PipeHandle ConnectToPipe(string pipeName, string serverName) { PipeHandle handle = new PipeHandle(); // Build the name of the pipe. string name = @"\\" + serverName + @"\pipe\" + pipeName; for (int i = 1; i <= ATTEMPTS; i++) { handle.State = InterProcessConnectionState.ConnectingToServer; // Try to connect to the server handle.Handle = NamedPipeNative.CreateFile(name, NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE, 0, null, NamedPipeNative.OPEN_EXISTING, 0, 0); if (handle.Handle.ToInt32() != NamedPipeNative.INVALID_HANDLE_VALUE) { // The client managed to connect to the server pipe handle.State = InterProcessConnectionState.ConnectedToServer; // Set the read mode of the pipe channel uint mode = NamedPipeNative.PIPE_READMODE_MESSAGE; if (NamedPipeNative.SetNamedPipeHandleState(handle.Handle, ref mode, IntPtr.Zero, IntPtr.Zero)) { break; } if (i >= ATTEMPTS) { handle.State = InterProcessConnectionState.Error; throw new NamedPipeIOException("Error setting read mode on pipe " + name + " . Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError()); } } if (i >= ATTEMPTS) { if (NamedPipeNative.GetLastError() != NamedPipeNative.ERROR_PIPE_BUSY) { handle.State = InterProcessConnectionState.Error; // After a certain number of unsuccessful attempt raise an exception throw new NamedPipeIOException("Error connecting to pipe " + name + " . Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError()); } else { handle.State = InterProcessConnectionState.Error; throw new NamedPipeIOException("Pipe " + name + " is too busy. Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError()); } } else { // The pipe is busy so lets wait for some time and try again if (NamedPipeNative.GetLastError() == NamedPipeNative.ERROR_PIPE_BUSY) { NamedPipeNative.WaitNamedPipe(name, WAIT_TIME); } } } return(handle); }
/// <summary> /// Tries to connect to a named pipe. /// </summary> /// <param name="pipeName">The name of the pipe.</param> /// <param name="serverName">The name of the server.</param> /// <param name="handle">The resulting pipe handle.</param> /// <returns>Return true if the attempt succeeds.</returns> /// <remarks>This method is used mainly when stopping the pipe server. It unblocks the existing pipes, which wait for client connection.</remarks> #endregion public static bool TryConnectToPipe(string pipeName, string serverName, out PipeHandle handle) { handle = new PipeHandle(); // Build the pipe name string string name = @"\\" + serverName + @"\pipe\" + pipeName; handle.State = InterProcessConnectionState.ConnectingToServer; // Try to connect to a server pipe handle.Handle = NamedPipeNative.CreateFile(name, NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE, 0, null, NamedPipeNative.OPEN_EXISTING, 0, 0); if (handle.Handle.ToInt32() != NamedPipeNative.INVALID_HANDLE_VALUE) { handle.State = InterProcessConnectionState.ConnectedToServer; return(true); } else { handle.State = InterProcessConnectionState.Error; return(false); } }