Click here to Skip to main content
15,904,287 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi,

I'm writing a service that will occasionally receive commands from a Windows Client telling it what actions to perform. I've attached a Timer with an elapse time of 1 second to check to see if anyone has connected to the NamedPipe and if so, what's the action requested.

The Service creates the ServerNamedPipe in the OnStart method and the Client connects to the pipe. What I'm seeing happening, is the client successfully connects to the Pipe ("Pipe Connected" message in the trace. I verified the pipe connection through ProcessExplorer, however the Server never shows the pipe being connected. This is proven by the lack of the message "Client is connected" in the trace and nothing that follows is taking place either. I verified the firing of the timer even by adding a Trace.WriteLine before the check for IsConnected and those trace messages appear.

I've been wracking my brain for hours trying to figure this one out. Anyone see what I've done wrong, it's not obvious to me.

PS - Everything is in a try/catch block and I'm not seeing any exceptions written either.

Thank you for your time and help!

Regards,
Glenn

C#
// -------------
// Service Code:
// -------------

// ---------------------------------------------
// Global Variables specified at the Class Level
// ---------------------------------------------
NamedPipeServerStream pipeServer = null;
internal const string ServerName = ".";
internal const string PipeName = "CmdCollector";
internal const string FullPipeName = @"\\" + ServerName + @"\pipe\" + PipeName;
internal const int BufferSize = 1024;

// -----------------------
// From the OnStart method
// -----------------------

PipeSecurity pipeSecurity = new PipeSecurity();

// Allow Everyone read and write access to the pipe. 
pipeSecurity.SetAccessRule(new PipeAccessRule("Authenticated Users",
                           PipeAccessRights.ReadWrite, AccessControlType.Allow));

// Allow the Administrators group full access to the pipe. 
pipeSecurity.SetAccessRule(new PipeAccessRule("Administrators",
                           PipeAccessRights.FullControl, AccessControlType.Allow));

if (pipeServer == null)
{
    pipeServer = new NamedPipeServerStream(
                     FullPipeName,                   // The unique pipe name. 
                     PipeDirection.InOut,            // The pipe is duplex 
                     NamedPipeServerStream.MaxAllowedServerInstances,
                     PipeTransmissionMode.Message,   // Message-based communication 
                     PipeOptions.None,               // No additional parameters 
                     BufferSize,                     // Input buffer size 
                     BufferSize,                     // Output buffer size 
                     pipeSecurity,                   // Pipe security attributes 
                     HandleInheritability.None       // Not inheritable 
                     );
    work = string.Format("{0} {1} - OnStart Pipe Created", 
                         ProductName, DateTime.Now);
    Trace.WriteLine(work);
}

// ------------------------------
//    In the Timer Event Handler:
// ------------------------------

if (pipeServer.IsConnected == false)
   return;

work = string.Format("{0} {1} - Client is connected", 
                     ProductName, DateTime.Now);
Trace.WriteLine(work);
Trace.Flush();

// --------------------------------
// Client Code
// --------------------------------

// ----------------
// Global Variables
// ----------------
internal const string ServerName = ".";
internal const string PipeName = "CmdCollector";
internal const string FullPipeName = @"\pipe\" + PipeName;
internal const int BufferSize = 1024;

// ------------------
// Request Collection
// ------------------
work = string.Format("{0} {1} - sendRunCollection - Run Collection Entry",  
                     Application.ProductName, DateTime.Now);
Trace.WriteLine(work);

pipeClient = new NamedPipeClientStream(
                 ServerName,                     // Server Name 
                 FullPipeName,                   // Pipe Name 
                 PipeDirection.InOut,            // Bi-Directional
                 PipeOptions.None);              // No additional parameters 

pipeClient.Connect(5000);

if (pipeClient.IsConnected == false)
{
    work = string.Format("{0} {1} - sendRunCollection - Pipe failed to connect",  
                         Application.ProductName, DateTime.Now);
    Trace.WriteLine(work);
    MessageBox.Show("Pipe failed to connect", "Cmd Controller",
                     MessageBoxButtons.OK, MessageBoxIcon.Error);
    return;
}
else
{
    work = string.Format("{0} {1} - sendRunCollection - Pipe connected", 
                         Application.ProductName, DateTime.Now);
    Trace.WriteLine(work);
}
Posted
Comments
Sergey Alexandrovich Kryukov 14-Feb-14 14:18pm    
What, no platform, no language? Please tag whatever is applicable. Nobody likes unnecessary guesswork. I answered just because one your critical mistake is apparent from the very beginning.
—SA

1 solution

Starting from the point "I've attached a Timer", everything goes wrong. Don't do such things. To communicate via named pipes, use a separate thread for a communication channel. (By the way, pretty much any activity on the Service need to be a separate thread.) A pipe read operation is blocking, your thread will be put a wait state until awaken by next command. It won't waste and CPU time, by the way, while having minimum latency. You timing is just a waste of time. This is call "polling" is a very bad thing. Throw it out and switch to threads. Before you do it, there is nothing to discuss.

For some background, please read:
http://en.wikipedia.org/wiki/Pull_technology[^],
http://en.wikipedia.org/wiki/Push_technology[^].

Also, if you are using .NET, you don't need to use named pipes on low level. They are included as a channel type called "IPC" in both "classical" remoting or WCF (self-hosted by your service). I don't even think that low-level pipe interface worth bothering. I did it only because I had to create an interface with non-.NET 3rd-party software, in collaboration with developers of that party.

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900