C# service fails to start - c#

I have created a C# Windows service but it fails to start. I get the following message when I attempt to start it:
The System Usage Monitor service on Local Computer started and then stopped. Some services stop automatically if they have no work to do, for example, the Performance Logs and Alerts service.
The following is my OnStart override ...
/// <summary>
/// OnStart(): Put startup code here
/// - Start threads, get inital data, etc.
/// </summary>
protected override void OnStart(string[] args)
{
base.OnStart(args);
broadcaster = new UdpBroadcaster(IP_Address, Port);
itm = new IdleTimeMonitor(1 * 1 * 3000, 1000);
aam = new ActiveApplicationMonitor(1000);
itm.IdleTimeExceeded += new IdleTimeExceededDelegate(itm_IdleTimeExceeded);
itm.IdleTimeReset += new IdleTimeResetDelegate(itm_IdleTimeReset);
itm.IdleTimeEvaluated += new IdleTimeEvaluatedDelegate(itm_IdleTimeEvaluated);
aam.StartedUsingApplication += new StartedUsingApplicationDelegate(aam_StartedUsingApplication);
aam.EndedUsingApplication += new EndedUsingApplicationDelegate(aam_EndedUsingApplication);
aam.ApplicationEvaluated += new ApplicationEvaluatedDelegate(aam_ApplicationEvaluated);
}
Do I need to block at the end of that function or something? Why wont my service start?

Did you kick off a thread?
If you don't have a thread that does something then the application will close so when onstart finishes there is no thread (unless you kick one off in UdpBrodacaster) so the service closes.
EDIT: Just declare a ManualResetEvent that isn't signalled and have the thread call WaitOne() on it. Then in your OnStop() signal the event (.Set()) to have the thread wake up and exit thus closing your service.

Take a look in the event log, if your service is starting then crashing for some reason there will be an exception event in the Application Log.

Put your code in the OnStart(string[]) in a try-catch-Block and log the exception to a log file (if one is raised). I think there is a problem on creating the instances.

Related

Correct way to timeout asynchronous namedpipes in C# .net environoment

I have a process that might have multiple instances running at anytime. Each instance should only run for several seconds at most. A process might have to pass data to an earlier started instance, or receive data from a latter started instance using named pipes. Each instance is aware of each other, but doesn't know for sure if it will attempt to pass or receive data. The process has a pipe server and client that each runs on its own thread. Since the process doesn't know before hand if the other process needs to send or receive data, I need the ability to attempt a connection but to time out and close the pipe if it hasn't connected in a few seconds. I'm using the asynch NamedPipeServer.BeginWaitForConnection() method. But I'm not sure if i'm using it correctly.
The process starts with Main() creating a thread with the
receiveServer() method.
receiveServer() starts a NamedPipeServer in a using block and starts the BeginWaitForConnection() method.
the AsychWaitHandle(3000) is used in the if condition so that if it successfully connects the readMessage(namedPipeServer) and a timeout timer is started. If the AsychWaitHandle(3000) expires then control goes to the else block where NamedPipeServer.Close() method is called.
The holdtimer runs as a safeguard while readMessage() method is running in case the pipeserver connects, and waits for data that never comes. When holdtimer expires it calls and event handler that calls the pipe server's close() method.
Being new to some of this, my main questions and concerns with my code are the fact that namedPipeServer.EndWaitForConnection(asynchResult) is only called int the event that the connection succeeds. According to the documentation EndWait must be called exacly once for each BeginWait. Testing the application, if no connection is made in 3 seconds the logic just falls through to the else block and then the pipe is closed, sometimes twice with out throwing any exception.
I'm also concerned about the way that I use the namedpipeserver.close() method in the timeout event when there is a hangup. That can call an exception readMessage() because the while loop tests while (!namedPipeServer.IsMessageComplete) which might be tested on a closed pipe.
I apologize for the lack of brevity, but I thought it would be a clearer question if I included all the relevant parts of the code.
Thanks in advance for the help.
public static void readMessage(NamedPipeServerStream namedPipeServer)
{
//While block continues while the Read() method has not complete,
// but once the Read() begins even if no data is available it blocks
//and the while block continues. Which is the reason for the
//timeout.
{
//Read from pipe to a global string variable
namedPipeServer.Read(messageBuffer, 0, messageBuffer.Length);
}
while (!namedPipeServer.IsMessageComplete);
}
public static void receiveServer()
{
try
{
using (NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("test-pipe", PipeDirection.InOut,
1, PipeTransmissionMode.Message, PipeOptions.Asynchronous))
{
var asynchResult = namedPipeServer.BeginWaitForConnection(null, null);
//Adds a delegate to a timer that explicitly closes the pipe server on timeout
holdtimer.Elapsed += new ElapsedEventHandler((sender, e) => clockExpired(sender, e, namedPipeServer));
holdtimer.AutoReset = true;
//If connection succeeds within 3 seconds
//then control goes to the "if block" where
//the read method is called. And the hold timer
//is started. If the connection doesn't succeed in 3
//seconds then the named pipe server Close() method is called.
if (asynchResult.AsyncWaitHandle.WaitOne(3000))
{
//
namedPipeServer.EndWaitForConnection(asynchResult);
//start timer before calling method
holdtimer.Start();
//Pass namedAPipeServer to readMessage
readMessage(namedPipeServer);
//stop timer after method completes
holdtimer.Stop();
}
else
{
Console.WriteLine("didn't get anything ----------");
}
//Explicately close the PipeServer.
namedPipeServer.Close();
}
}
catch (Exception ex)
{
//This is just for testing.
MessageBox.Show("Exception in receiveMessage :" + ex.Message);
}
}
static void Main(string[] args)
{
//assign clockExpired() delgate to holdtimer
Thread receiverThread = new Thread(receiveServer);
receiverThread.Start();
}

How can I know when Kestrel has started listening?

I need to notify systemd that my service has started up successfully, and a task it needs to run after startup requires that the server is already listening on the target Unix domain socket.
I am using IWebHost::Run to start the server, and that is a blocking call. Additionally, I am unable to find any obvious way to set a delegate or callback event for successful initialization.
Anyone?
You may use Microsoft.AspNetCore.Hosting.IApplicationLifetime:
/// <summary>
/// Triggered when the application host has fully started and is about to wait
/// for a graceful shutdown.
/// </summary>
CancellationToken ApplicationStarted { get; }
Look into this SO post for the configuration example.
On .Net Core 1.x it is safe to just run IWebHost.Start() and assume that the server is initialized afterwards (instead of Run() that blocks the thread). Check the source.
var host = new WebHostBuilder()
.UseKestrel()
(...)
.Build();
host.Start();
If you are using .NET Core 2.0 Preview 1 (or later), the source is different, the synchronous method is not available anymore so you should await IWebHost.StartAsync() and assume everything is ready afterwards.
This is what I ended up going with, for now. Seems to be working fine:
host.Start();
Log.Information("Press Ctrl+C to shut down...");
Console.CancelKeyPress += OnConsoleCancelKeyPress;
var waitHandles = new WaitHandle[] {
CancelTokenSource.Token.WaitHandle
};
WaitHandle.WaitAll(waitHandles);
Log.Information("Shutting down...");
Then, in the Ctrl+C event handler:
private static void OnConsoleCancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Log.Debug("Got Ctrl+C from console.");
CancelTokenSource.Cancel();
}
This is what I did to overcome the issue.
1- I registered ApplicationStopped event. So that it brute force terminates the app by calling Kill() method of the current process.
public void Configure(IHostApplicationLifetime appLifetime) {
appLifetime.ApplicationStarted.Register(() => {
Console.WriteLine("Press Ctrl+C to shut down.");
});
appLifetime.ApplicationStopped.Register(() => {
Console.WriteLine("Terminating application...");
System.Diagnostics.Process.GetCurrentProcess().Kill();
});
}
See IHostApplicationLifetime docs
2- Don't forget to use the UseConsoleLifetime() while building the host.
Host.CreateDefaultBuilder(args).UseConsoleLifetime(opts => opts.SuppressStatusMessages = true);
See useconsolelifetime docs
A working sample from .NET Core 6:
In your Program.cs, you will have the following (with more or less embellishment, depending on the middleware):
var builder = WebApplication.CreateBuilder(args);
/* ... kestrel configuration, middleware setup ... */
var app = builder.Build();
app.Services.GetService<IHostApplicationLifetime>()!.ApplicationStarted.Register(() =>
{
/* any code you put here will execute
* after the host has started listening */
Console.WriteLine("Kestrel has started listening");
});
/* this is a blocking call.
* the start event occurs from "in there" */
app.Run();
Working principle: The event handler with the Console.WriteLine call will be called after app.Run() is already blocking the main thread, at the exact moment when the server is first ready and will accept requests.

timer in console application

I am creating a device application using .NET compact framework 2.0. There is a system.threading.timer in my application which executes some code. It works fine. My problem is when I am running the app by double clicking on the exe in the bin folder, the timer starts and execute all it works but it never stops. It runs in the background even after closing the app by clicking the X-button or from the file menu close button. I don't understand how and where I stop or dispose of the timer so that it doesn't run after closing the app. May be something like a form_closing event in window form application. I had searched a lot in Google but did't find any proper answer.
The application is use to generate digital output for a device
here is some code of timer event:
public static void Main()
{
// Some code related to the device like open device etc
// Then the timer
System.Threading.Timer stt =
new System.Threading.Timer(new TimerCallback(TimerProc), null, 1, 5000);
Thread.CurrentThread.Join();
}
static void TimerProc(Object stateInfo)
{
// It is my local method which will execute in time interval,
// uses to write value to the device
writeDigital(1, 0);
GC.Collect();
}
It is working fine when I run the code in debug mode, timer stops when I stop the program. But not working when I run the exe.
You could create and dispose it in Main() and pass it to any methods that require it?
private static void Main()
{
using (var timer = new System.Threading.Timer(TimerProc))
{
// Rest of code here...
}
}
More importantly, this line of code:
Thread.CurrentThread.Join();
will never return, because you are asking the current thread to wait for the current thread to terminate. Think about that for a moment... ;)
So your solution is probably to just remove that line of code.
All about GC.Collect();
Your stt object is used once and after that is pointed out to being removed and its memory reclaimed.
If you don't belive call stt.ToString(); at the end of main function, it will extend the stt live till the end of main function.
Solution(s)?
You can define the stt object as a static - it guarantees that it will be alive till the end of live of you program
recommended solution is to use GC.KeepAlive(stt); which you can call at the end of main function which will keep the stt away from destroying process.

Unusual WCF Client behaviour

I have an SOA application that uses a duplex WCF service hosted within a Windows Service. The client itself is a WPF application.
I'm seeing unusual behaviour on closing and restarting the client application. If I start a new instance after closing one, nothing visibly appears to happen. However, checking task manager shows the new instance is running as a background process. If I try to start another new instance of the client application, it will display the error screen I've written - stating an error with the service. Investigation has shown that the client cannot create a new instance of the service callback channel because another application has already registered the URL. This is a System.ServiceModel.AddressAlreadyInUseException.
If I then end the background client task in task manager, my client displaying the error message is then able to connect to the service and run as normal. I have also noticed that if I close the background task before starting a new instance, the new instance will also not appear.
My concern here is that this is not useable and feels like a real hassle for users. What could be going wrong? It seems as if something is not cleaning up unmanaged resource but I've used ANTS and can't identify it. The client is created as:
IServiceCallback callback = new Callback();
_context = new InstanceContext(callback);
_channelFactory = new DuplexChannelFactory<IMyService>(_context, binding, endpoint);
_proxy =
_channelFactory.CreateChannel();
((ICommunicationObject)_proxy).Open(TimeSpan.FromSeconds(5));
The Service's constructor uses the following code:
_callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
commObject.Faulted += ChannelFaulted;
commObject.Closing += ChannelClosing;
commObject.Closed += ChannelClosed;
}
OperationContext.Current.Channel.Faulted += ChannelFaulted;
OperationContext.Current.Channel.Closed += ChannelFaulted;
Before closing, the client calls the service's Disconnect method, which does:
var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
commObject.Faulted -= ChannelFaulted;
commObject.Closing -= ChannelClosing;
commObject.Closed -= ChannelClosed;
}
OperationContext.Current.Channel.Faulted -= ChannelFaulted;
OperationContext.Current.Channel.Closed -= ChannelFaulted;
Finally, the client closes the channels like this:
foreach (var incomingChannel in _context.IncomingChannels.ToArray())
{
incomingChannel.Close();
}
try
{
var proxy = _proxy as IChannel;
if (proxy != null)
{
proxy.Close();
}
}
catch (Exception)
{
_channelFactory.Abort();
}
Why am I seeing this unusual behaviour? Is there something I'm missing to close the channel or something I'm doing wrong to create it? Or is it likely that there must be an issue elsewhere in my code that keeps the channel or session alive?
**UPDATE: ** I have been trying a few things and found out that if I start a client instance, close it, then leave it for an hour, I can start another instance with no issue. I've also discovered that if I restart the Windows Service after creating and closing an instance of the client application then I'm also able to create another in those circumstances.
**UPDATE 2: ** Stepping through, I can see that the incomingChannel.Close() does not complete and does not throw an error. I've removed that section and also find proxy.Close() does not complete and does not throw an exception. I've tried using the overloads and added a timeout, but no timeout exception is being thrown. The Service's Dispose() method is not hit at all.
Try closing your channel factory too.
proxy.ChannelFactory.Close();
proxy.Close();

Logic for Windows Services & Getting Updates

I developed a Windows service using vb.net which does the following using OnStart Even...
Grabs all Entries from a SQL Table
Creates Schedules from returned rows
it works fine, schedules fire on their time and stuff.
Problem: Whenever I have to ADD a new row to my Table, I have to restart the Service, So it can Grab the Newly created rows. This is causing problems for me...there could be a task which is running already and restarting service might break the system.
So what is the best way to handle this? Can the new rows be loaded into Service without a restart?
Thanks
Use the concept of Polling into the Database. Use the System.Threading.Timer class, set some interval after which a callback method will be invoked and that will be responsible to Poll the Database for new entries.
This OnStart was provided here by Marc Gravell:
public void OnStart(string[] args) // should this be override?
{
var worker = new Thread(DoWork);
worker.Name = "MyWorker";
worker.IsBackground = false;
worker.Start();
}
void DoWork()
{
// do long-running stuff
}
Note that OnStart can launch multiple threads or the first thread started may be used to start additional threads as needed. This allows you to set up either database polling or a thread that waits on a message queue for data.
A useful tip:
Adding a Main to your service allows you to run it as a console application in Visual Studio. This greatly simplifies debugging.
static void Main(string[] args)
{
ServiceTemplate service = new ServiceTemplate();
if (Environment.UserInteractive)
{
// The application is running from a console window, perhaps creating by Visual Studio.
try
{
if (Console.WindowHeight < 10)
Console.WindowHeight = 10;
if (Console.WindowWidth < 240) // Maximum supported width.
Console.WindowWidth = 240;
}
catch (Exception)
{
// We couldn't resize the console window. So it goes.
}
service.OnStart(args);
Console.Write("Press any key to stop program: ");
Console.ReadKey();
Console.Write("\r\nInvoking OnStop() ...");
service.OnStop();
Console.Write("Press any key to exit: ");
Console.ReadKey();
}
else
{
// The application is running as a service.
// Misnomer. The following registers the services with the Service Control Manager (SCM). It doesn't run anything.
ServiceBase.Run(service);
}
}

Categories

Resources