Is there anyone skilled in windows services?

G

Giulio Petrucci

Hi everybody,

I've a big problem with a Windows Service I've created using C#. It's a
very simple service: it just starts a TcpListener listening for incoming
connections on a certain ports. First I compiled it on FW2.0, and run the
service without any problem. Some days ago I had to performe a sort of
"backporting" to FW1.1, I compiled the source code, installed the service
but as I try to start it I get a timeout and a system error. I know that if
the "OnStart()" method doesn't retunr in 30 seconds the OS generates an
exception but there's something I'm still missing:

1 - why the _same_code_ works if compiled on FW2.0 and not if on FW1.1?

2 - In the OnStart() method I just spawn a new thread, so the method should
return something to the OS suddenly... or not?

3) - I've filled my code with tracelines, using the
System.Diagnostic.DefaultTraceListener class, and I can see (using dbgview)
that the TcpListener actually starts... moreover if I send a request to the
service before the 30s period has elapsed, it works fine and my client gets
its right response (so the server is asctually workink but the OS seems
to don't know...).

Any suggestion?

Thanks in advance.
Kind regards,
Giulio - Italia
 
W

Willy Denoyette [MVP]

Please upload all of your code to a free download host, so we can take a
look at it.

Willy.



message | Hi everybody,
|
| I've a big problem with a Windows Service I've created using C#. It's a
| very simple service: it just starts a TcpListener listening for incoming
| connections on a certain ports. First I compiled it on FW2.0, and run the
| service without any problem. Some days ago I had to performe a sort of
| "backporting" to FW1.1, I compiled the source code, installed the service
| but as I try to start it I get a timeout and a system error. I know that
if
| the "OnStart()" method doesn't retunr in 30 seconds the OS generates an
| exception but there's something I'm still missing:
|
| 1 - why the _same_code_ works if compiled on FW2.0 and not if on FW1.1?
|
| 2 - In the OnStart() method I just spawn a new thread, so the method
should
| return something to the OS suddenly... or not?
|
| 3) - I've filled my code with tracelines, using the
| System.Diagnostic.DefaultTraceListener class, and I can see (using
dbgview)
| that the TcpListener actually starts... moreover if I send a request to
the
| service before the 30s period has elapsed, it works fine and my client
gets
| its right response (so the server is asctually workink but the OS seems
| to don't know...).
|
| Any suggestion?
|
| Thanks in advance.
| Kind regards,
| Giulio - Italia
 
K

Kevin Spencer

1 - why the _same_code_ works if compiled on FW2.0 and not if on FW1.1?

It has a bug in it.
2 - In the OnStart() method I just spawn a new thread, so the method
should return something to the OS suddenly... or not?

Should it?
3) - I've filled my code with tracelines, using the
System.Diagnostic.DefaultTraceListener class, and I can see (using
dbgview) that the TcpListener actually starts... moreover if I send a
request to the service before the 30s period has elapsed, it works fine
and my client gets its right response (so the server is asctually workink
but the OS seems to don't know...).

Do you have any error handling in your code? A tracelistener will give you
information, but it won't tell you where an exception occurred, details
about the exception, or a Stack trace when the exception occurs. Are you
using Try/Catch in your code, to document such information? Remember that
just because you catch an exception doesn't mean you can't rethrow it, if
that is something you desire.

Also, remember that a Service is a form of "user-less interface" for a
program. It provides a host for the application which presents no user
interface. One good method for developing a Service is to break it into a
Business layer and a Service layer. This way you can test the Business layer
separately in an application that has an interface you can *see*.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Chicken Salad Alchemist

A lifetime is made up of
Lots of short moments.
 
G

Giulio Petrucci

Hi Kevin, thanks four your reply,
Hi everybody,

Kevin Spencer ha scritto:
It has a bug in it.

Don't think so.
The version that I compiled for FW2.0 used to work greatly.
Should it?

Yes, it should.
The thread's spawned very suddenly, so that I can see it's activity logged
by the tracelines I left in the code. Moreover I set an unuseful (but
reassureing) "return" statement;
Do you have any error handling in your code? A tracelistener will give you
information, but it won't tell you where an exception occurred, details
about the exception, or a Stack trace when the exception occurs. Are you
using Try/Catch in your code, to document such information? Remember that
just because you catch an exception doesn't mean you can't rethrow it, if
that is something you desire.

I have try/catch blocks in my code but I get no exception while my
service's running.
Also, remember that a Service is a form of "user-less interface" for a
program. It provides a host for the application which presents no user
interface. One good method for developing a Service is to break it into a
Business layer and a Service layer. This way you can test the Business layer
separately in an application that has an interface you can *see*.

Already tested it.
I repeat: it works fine. The only issue is with the FW1.1 version: I start
the service and the OS wait for it to start... but it has already started
so that I can run my client and query the service. After 30 seconds the
system stops the service because it didn't get any response (it means that
the OnStart method hasn't return but it's not true...).

Thanks again,
Kind regards,
Giulio
 
G

Giulio Petrucci

Hi Willy and thanks for your reply,
Hi everybody,

Willy Denoyette [MVP] ha scritto:
Please upload all of your code
[cut]

I'll post my code here.
Please note that's been compiled on the FW1.1 (using MSBee) and that I used
c:\Windows\Microsoft.NET\Framework\v1.1.4322\InstallUtil.exe MyService.exe
to install it and then >sc start MyService to start it.

Thanks again,
Kind regards,
Giulio

--

//Service class
public class MyService : ServiceBase
{
private MyListener listener;
private DefaultTraceListener dtl;
public MyService()
{
dtl = new DefaultTraceListener();
dtl.WriteLine("creating a new listener...");
listener = new MyListener();
InitializeComponents();
}
private void InitializeComponents()
{
dtl.WriteLine("initializing service components...");
AutoLog = true;
CanPauseAndContinue = true;
CanShutdown = true;
CanStop = true;
ServiceName = "MyService";
if (!EventLog.SourceExists("MyService"))
EventLog.CreateEventSource("MyService", "MyService_Log");
}
protected override void OnStart(string[] args)
{
dtl.WriteLine("OnStart() --> starting listening...");
Thread startListening = new Thread(new
ThreadStart(listener.StartListening));
startListening.IsBackground = true;
startListening.Start();
return;
}
protected override void OnStop()
{
dtl.WriteLine("OnStop() --> stopping listening...");
listener.StopListening();
}
protected override void Dispose(bool disposing)
{
dtl.WriteLine("Dispose() --> stopping listening...");
listener.StopListening();
dtl.WriteLine("disposeing components...");
base.Dispose(disposing);
dtl.WriteLine("done");
}

static void Main(string[] args)
{
#if (!DEBUG)
//ServiceBase.Run(new ServiceBase[] { new MyService() });
System.ServiceProcess.ServiceBase.Run(new MyService());
#else
LicenseManagerService service = new LicenseManagerService();
service.OnStart(null);
Thread.Sleep(Timeout.Infinite);
#endif
}
}


//listener class;
public class LicenseManagerListener
{
private ManualResetEvent acceptDone; //a manual reset event
protected Thread listeningThread;
private System.Diagnostics.DefaultTraceListener dtl;

public LicenseManagerListener()
{
dtl = new System.Diagnostics.DefaultTraceListener();
dtl.WriteLine("-- creating a new listener...");
acceptDone = new ManualResetEvent(false);
}
public void StartListening()
{
dtl.WriteLine("starting the listening thread...");
listeningThread = new Thread(new ThreadStart(ListeningThread));
listeningThread.IsBackground = true;
listeningThread.Start();
}
public void StopListening()
{
dtl.WriteLine("stopping the listening thread...");
listeningThread.Abort();
}
private void ListeningThread()
{
dtl.WriteLine("listening thread");
dtl.WriteLine("creating endpoint...");
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 6677);
dtl.WriteLine("creating a new socket...");
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
dtl.WriteLine("binding socket to endopoint...");
listener.Bind(localEndPoint);
listener.Listen(10000);
dtl.WriteLine("socket :: start listening...");
while (true)
{
acceptDone.Reset();
dtl.WriteLine("acceptDone -- > reset");
dtl.WriteLine("waiting for a new connection...");
listener.BeginAccept(new
AsyncCallback(AcceptCallback), listener);
dtl.WriteLine("acceptDone --> wait one");
acceptDone.WaitOne();
}
}
catch (Exception e)
{
dtl.WriteLine("exception : \n " + e.Message);
Console.WriteLine(e.Message);
throw e;
}
}
/*
* the AcceptCallback method implements a callback to accepting
incoming connections;
*/
private void AcceptCallback(IAsyncResult ar)
{
dtl.WriteLine("accept callback...");
acceptDone.Set();
dtl.WriteLine("acceptD-one --> set");
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
dtl.WriteLine("finished");
}
}



//service installer
[RunInstaller(true)]
public class LicenseManagerServiceInstaller : Installer
{
private ServiceInstaller serviceInstaller;
private ServiceProcessInstaller serviceProcessInstaller;
private Container components;

public LicenseManagerServiceInstaller()
{
InitializeComponents();
}

private void InitializeComponents()
{
serviceProcessInstaller = new ServiceProcessInstaller();
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
serviceInstaller = new ServiceInstaller();
serviceInstaller.ServiceName = "SpeechDrawLicenseManager";
serviceInstaller.StartType = ServiceStartMode.Manual;
Installers.AddRange(new Installer[] { serviceInstaller,
serviceProcessInstaller });
Committed += new
InstallEventHandler(LicenseManagerServiceInstaller_Committed);
Committing += new
InstallEventHandler(LicenseManagerServiceInstaller_Committing);
}

void LicenseManagerServiceInstaller_Committing(object sender,
InstallEventArgs e)
{
Console.WriteLine("...committing event occurred...");
}

void LicenseManagerServiceInstaller_Committed(object sender,
InstallEventArgs e)
{
Console.WriteLine("...committed event occurred...");
}

public override void Install(System.Collections.IDictionary
stateSaver)
{
base.Install(stateSaver);
}

public override void Commit(System.Collections.IDictionary savedState)
{
base.Commit(savedState);
}

public override void Rollback(System.Collections.IDictionary
savedState)
{
base.Rollback(savedState);
}
}
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


Why are you calling Thread.Sleep?


Do this, remove all the code , and just do a simple echo program.
 
G

Giulio Petrucci

Hi Ignacio and thanks for your reply,
Hi everybody,

Ignacio Machin ( .NET/ C# MVP ) ha scritto:
Why are you calling Thread.Sleep?
Do this, remove all the code , and just do a simple echo program.

Do you mean in this snippet?

#if (!DEBUG)
//ServiceBase.Run(new ServiceBase[] { new MyService() });
System.ServiceProcess.ServiceBase.Run(new MyService());
#else
LicenseManagerService service = new LicenseManagerService();
service.OnStart(null);
Thread.Sleep(Timeout.Infinite);
#endif

the code concerning the #else instruction isn't executed because the
(!DEBUG) condition evaluates to true. It's useful to run the service within
the visual studio debugger. Anyway I'll remove it and test again.

Thanks again.
Kind regards,
Giulio - Italia
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top