views:

60

answers:

3

I have created a windows service which allows communications via namedpipes.

This code worked fine when I wrote some unit tests to spin up the pipes and test the communication, but now I have installed the same code in my windows service I get the following error:

Exception Info: System.IO.IOException
Stack:
       at System.IO.__Error.WinIOError(Int32, System.String)
       at System.IO.Pipes.NamedPipeServerStream.Create(System.String, System.IO.Pipes.PipeDirection, Int32, System.IO.Pipes.PipeTransmissionMode, System.IO.Pipes.PipeOptions, Int32, Int32, System.IO.Pipes.PipeAccessRights, SECURITY_ATTRIBUTES)
       at System.IO.Pipes.NamedPipeServerStream..ctor(System.String, System.IO.Pipes.PipeDirection, Int32, System.IO.Pipes.PipeTransmissionMode, System.IO.Pipes.PipeOptions, Int32, Int32, System.IO.Pipes.PipeSecurity, System.IO.HandleInheritability, System.IO.Pipes.PipeAccessRights)
       at System.IO.Pipes.NamedPipeServerStream..ctor(System.String, System.IO.Pipes.PipeDirection, Int32, System.IO.Pipes.PipeTransmissionMode,     
System.IO.Pipes.PipeOptions, Int32, Int32, System.IO.Pipes.PipeSecurity)
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart(System.Object)

Now I did some googling and found this post in stackoverflow > POST But I implemented this (apart from the ps.AddAccessRule(pa); as that made no reference to was pa was) and I get the same error.

this is the code I have for the thread:

var pipeSecurity = new PipeSecurity();
pipeSecurity.AddAccessRule(new PipeAccessRule("Users", PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow));
pipeSecurity.AddAccessRule(new PipeAccessRule("CREATOR OWNER", PipeAccessRights.FullControl, AccessControlType.Allow));
pipeSecurity.AddAccessRule(new PipeAccessRule("SYSTEM", PipeAccessRights.FullControl, AccessControlType.Allow));

var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.InOut, numThreads, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 1024, 1024, pipeSecurity);    

pipeServer.WaitForConnection();

any help will be great.

Ok here is the code that is running the listener:

the windows service:

public static System.Timers.Timer Timer = new System.Timers.Timer();

public void Start()
{
    Timer.Elapsed += (HeartBeat);
    //Timer.Interval = 100; //Live
    Timer.Interval = 2000; //Debug
    Timer.Start();
}

public void Stop()
{
    Timer.Stop();
}

private static void HeartBeat(object sender, ElapsedEventArgs e)
{
    //listen for a message
    ListenForMessage();

}

the listener code:

private const String pipeName = "StackOVerFlowPipeCode";
private const int numThreads = 10;

public static void ListenForMessage()
{
    int i;
    var servers = new Thread[numThreads];

    for (i = 0; i < numThreads; i++)
    {
        servers[i] = new Thread(ServerThread);
        servers[i].Start();
    }

    Thread.Sleep(250);

    while (i > 0)
    {
        for (var j = 0; j < numThreads; j++)
        {
            if (servers[j] == null) continue;
            if (!servers[j].Join(250)) continue;

            servers[j] = null;

            i--;    // decrement the thread watch count
        }
    }
}

private static void ServerThread(object data)
{
    try
    {
        var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.InOut, numThreads);

        pipeServer.WaitForConnection();

        var ss = new StreamString(pipeServer);
        ss.WriteString(pipeName);

        var message = ss.ReadString();

        //DO STUFF HERE WITH MESSAGE

        pipeServer.Close();
    }
    catch (Exception ex)
    {
        //CRY LIKE A BABY WHO LOST HIS TEDDY
        throw ex;
    }
}

Exception message found: All pipe instances are busy.

A: 

You didn't include the exception.Message but According to the MSDN page for NamedPipeServerStream, the IOException is for "The maximum number of server instances has been exceeded." is this the exception you are getting?

If so, what is numThreads set to, and is it possible you have another instance of you app running? (e.g. the unit test you were experimenting with?)

Don R.
I did include the exception? the max num I have set is 10, and the pipe isnt even being created, it bombs out just after I start the service
JamesStuddart
Are you sure your test application is no longer running? And, You included the type (IOException) of the exception but not the Message.
Don R.
I have now added the code I am using, could it be that the heartbeat is spinning the listner up all the time?
JamesStuddart
A: 

Named Pipe names need to be in the format:

\\.\pipe\pipename

See CreatedNamedPipe Win32 API: http://msdn.microsoft.com/en-us/library/aa365150(VS.85).aspx


EDIT: On further examination (looking at the NamedPipeServerStream sample) this might not be the case. So need to see the full details of the exception: Message property and run time type.

Richard
+1  A: 

Turns out my whole implementation was flawed, I deleted a lot of code and rewrote it and it worked. I removed code from in ListenForMessage() and replaced it with the code from ServerThread() and then also changed how the service was calling this, to a thread from a timer. and it worked.

well sort of, the code after the message is received (shown as //Do Stuff in the above) does work, but at least this task is complete.

note: never just copy and past code and take it for granted always read it and understand it.

JamesStuddart
You should have made this an edit on your question unless you intend to post your actual code here and then mark this as the answer so other SO'ers know what you did differently so they can learn too. Just FYI.
drachenstern
The above comment explains how I did it, with EXACTLY the same code as in the original question, but thanks.
JamesStuddart