I'm new to windows service and I'm facing a problem I need to call a function on my services on start method but its not working. When I'm starts the service the following error occures
"The MIM service on local Computer started and then stopped.Some
service stop automatically if they are not in use by other services or
programs"
and my current code is given below
public CHK()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Logger.Message("ChkUser", "Service Start", "");
CheckUser();
}
protected override void OnStop()
{
Logger.Message("MChkUser", "Service Stop", "");
}
public void CheckUser()
{
//actions
}
and If I didnt call the CheckUser() method then the service works without any problem. What will be the reason behind this???
Most likely the reason is that your CheckUser() method throws an uncaught exception ...
To see what the exception is try simply putting the call to the method inside a try-catch block :
protected override void OnStart(string[] args)
{
Logger.Message("ChkUser", "Service Start", "");
try {
CheckUser();
} catch (Exception e) {
Logger.Message("ChkUser", e.Message, "");
}
}
Related
How do I use "StartService" Task with ThreadStart?
Is it possible?
public partial class MyService : ServiceBase
{
public MyService()
{
InitializeComponent();
LocalInit();
}
internal void LocalInit()
{
//place here any local checks
}
protected override void OnStart(string[] args)
{
if (Something.ConfigOK())
{
ThreadStart threadDelegate = Something.StartService; // Expected a method with void StartService signature
var newThread = new Thread(threadDelegate);
newThread.Start();
}
else
{
//log error
throw new Exception("MyService : Config failed");
}
}
}
public static partial class Something
{
public static async Task StartService()
{
await DoJob();
}
}
Errors
Error CS0407 'Task Something.StartService()' has the wrong return type
Expected a method with void StartService signature
Have you tried this?
protected override void OnStart(string[] args)
{
if (Something.ConfigOK())
{
Something.StartService();
}
else
{
//log error
throw new Exception("MyService : Config failed");
}
}
If DoJob os truly asynchronous or:
protected override void OnStart(string[] args)
{
if (Something.ConfigOK())
{
Task.Run(Something.StartService);
}
else
{
//log error
throw new Exception("MyService : Config failed");
}
}
if it isn't (blocking).
There's no need to explicitly create a thread.
Beware of exception handling!
But, since you mention ASP.NET Core (???) I would recomend using a Worker template.
It is possible, but I would suggest you to go with Background tasks with hosted services.
Here is some implementation
Or use hangfire queues.
As I mentioned, this is a suggestion not a answer for your question.
So I am just messing around here nothing production just proof of concept with my first ever Windows Service.
I am trying to essentially create a windows service that sits as the listener for a signalr connection. In essence, I will have a windows application and a windows service. The win service will handle connecting to the signalr hub and on signalr calls fire an event. The windows application will listen for these events and perform actions based on them.
Currently I cannot get this to work. I have never worked with events, or windows services before. In my windows application my events never hit their break points, as well I log an error of null reference exception from the
ConnectToHub()
Alright if I comment out the OnConnected() method call I log a successful connection to the hub. I have never worked with events before so is my mistake with the events?
I debated that this approach was a bit overkill. However, for me it was a proof of concept that I could find a use for a long running windows service, and adding some events into the mix.
Code for service:
public delegate void MessageRecievedEventHanlder(object sender, MessageRecievedArgs e);
public delegate void ConnectedToHubEventHandler(object sender, ConnectedArgs e);
public partial class SignalRService : ServiceBase
{
IHubProxy _hub;
HubConnection connection;
string url = #"http://localhost:8080/";
private Message LastMessage;
public static event MessageRecievedEventHanlder NewMessage;
protected virtual void OnNewMessage(MessageRecievedArgs e)
{
NewMessage(null, e);
}
public static event ConnectedToHubEventHandler Connected;
protected virtual void OnConnected(ConnectedArgs e) {
System.IO.File.WriteAllText(#"C:\Users\Bailey Miller\Desktop\FTP\Logg.txt", "Hit OnConnected " + e.Success +" " + Connected != null ? "Isn't null" : "Null event");
Connected(null, e);
}
public SignalRService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
ConnectToHub().Wait();
}
private async Task ConnectToHub()
{
try
{
//Connecting
if (connection == null)
{
connection = new HubConnection(url);
}
if (_hub == null)
{
_hub = connection.CreateHubProxy("ChatHub");
}
await connection.Start();
//Connected
//Configure all the incoming options
_hub.On<Message>("RecieveMessage", IncomingMessage);
System.IO.File.WriteAllText(#"C:\Users\Bailey Miller\Desktop\FTP\Succes.txt", "Connected");
OnConnected(new ConnectedArgs(true));
}
catch (Exception ex)
{
//Failed
//OnConnected(new ConnectedArgs(false));
System.IO.File.WriteAllText(#"C:\Users\Bailey Miller\Desktop\FTP\Fail.txt", "Failed to connect " + ex.Message.ToString());
}
}
private void IncomingMessage(Message state)
{
DateTime? lmt;
//Determine if has lastmessagetime
if (LastMessage == null) {
lmt = null;
}
else {
lmt = LastMessage.RecievedAt;
}
LastMessage = state;
//New Message
//OnNewMessage(new MessageRecievedArgs(state, lmt));
}
protected override void OnStop()
{
}
}
public class MessageRecievedArgs : EventArgs
{
public Message NewMessage { get; }
public DateTime? LastMessageTime { get; }
public MessageRecievedArgs(Message msg, DateTime? lmt) {
this.NewMessage = msg;
this.LastMessageTime = lmt;
}
}
public class ConnectedArgs : EventArgs {
public bool Success { get; }
public ConnectedArgs(bool suc) {
this.Success = suc;
}
}
My windows application as of now:
public MainWindow()
{
InitializeComponent();
SignalRService.SignalRService.NewMessage += SignalRService_NewMessage;
SignalRService.SignalRService.Connected += SignalRService_Connected;
}
private void SignalRService_Connected(object sender, SignalRService.ConnectedArgs e)
{
throw new NotImplementedException();
}
private void SignalRService_NewMessage(object sender, SignalRService.MessageRecievedArgs e)
{
throw new NotImplementedException();
}
Your question is a bit broad- you don't describe exactly what isn't working, so I am guessing that when you start your service, it says "starting..." for a long while and eventually windows service manager gives you an error saying your service didn't start in a timely fashion. The issue is that OnStart() is expected to return- you can't block the thread there with the Wait() call. My suggestion would be to spawn a new background thread here to perform the waiting, then exit. That should get you past the first hurdle.
As another aside... You can add a regular main method to a windows service project, change the project type to Console Application, and run it that way to reduce your debugging cycle time. Then when you are sure it basically works, change the project type back to Windows Service and install it.
EDIT: Now that you have a better error description, I see the real problem. The issue is that you are raising an event without checking for null first. Event fields are null until you attach a listener. So change your code as follows:
protected virtual void OnConnected(ConnectedArgs e) {
System.IO.File.WriteAllText(#"C:\Users\Bailey Miller\Desktop\FTP\Logg.txt", "Hit OnConnected " + e.Success +" " + Connected != null ? "Isn't null" : "Null event");
ConnectedToHubEventHandler connectedEvent = Connected;
if (connectedEvent != null) // This event might be null, so check first
connectedEvent(null, e);
}
I created a C# windows service and installed it successfully on my local developer machine (it works well).
Now I'm trying to install the service on a different machine.
I copied the "Release" folder to the new machine and installed the service.
When I start the service on the new machine I get the following error:
"service on Local Computer started and then stopped. Some services stop automatically if they are not in use by other services or programs."
I don't get any message to the Application event log, I even added debug message as the first line of the program, but i see nothing in the Event Viewer (as if the code doesn't start at all). :/
What have i done wrong?
"started and then stopped" message usually appears when your server throws an exception during start up. Which could be for many reasons, including invalid paths and inability to write to the Application Event Log due to missing source or insufficient privileges.
I usually include an option to run my service as a console app.
Which allows me to display any exceptions using Console.WriteLine.
Following assumes your service extends from System.ServiceProcess.ServiceBase.
partial class MyService : ServiceBase
{
private static void Main(string[] args)
{
MyService svc = new MyService();
if (Environment.UserInteractive)
RunConsole(args, svc);
else
Run(svc);
}
public MyService()
{
InitializeComponent();
}
protected static bool KeepRunning { get; set; }
protected override void OnStart(string[] args)
{
StartServiceHost();
}
protected override void OnStop()
{
StopServiceHost();
}
protected override void OnShutdown()
{
StopServiceHost();
base.OnShutdown();
}
private static void RunConsole(string[] args, ConverterService svc)
{
// need to hold on to Ctrl+C, otherwise StopServiceHost() never gets called
Console.CancelKeyPress += (sender, e) => ShutDown(svc);
KeepRunning = true;
svc.OnStart(args);
Console.WriteLine("Press <Ctrl+C> to exit.");
while (KeepRunning)
{
Console.ReadLine();
}
}
private void StartServiceHost()
{
// start your service
}
private void StopServiceHost()
{
// stop your service
}
private static void ShutDown(MyService svc)
{
Console.WriteLine("exiting...");
svc.OnStop();
KeepRunning = false;
}
}
Well, I've found the problem:
I used password decryption with DataProctionScope.LocalMachine.
So when I changed the machine- the decryption failed.
I had to re-encrypt the passwords on the local machine and then the decryption worked fine.
Thank you for your responds!
*The eventlog debugging didn't work because of my fault.
I am new To windows service. I need a windows service that reads an entry from a table from database. I have a CONSOLE APP where I add new project WINDOWS SERVICE. I already have a method that access the database, and other methods. I can put a thread on start that reads the database. Where do I put the thread? ( how can I do that). Where on WINDOWS SERVICE I add those methods? I have the Windows Service like this:
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
do
{
thread.start();
bool variab = readFromDatabase (Database table);
}
}
protected override void OnStop()
{
}
I suggest that you create a class in which you do everything you need and create in in the service:
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
YourClass cl = new YourClass();
cl.DoWhatYouNeed(...);
}
protected override void OnStop()
{
}
This gives you opportunity to run and test your class separate from service, maybe during debug release.
With windows services usually a method is created to execute the main loop of the service, in a separated thread. Otherwise the service could become unresponsive. For example, you can have a method called MainLoop to execute the service logic. Use the OnStart method only to do the initializing tasks, such as read configuration values or start the threads of the service. And use the OnStop to executing cleaning tasks, stopping threads, etc...
Thread _workerThread;
bool _shouldStop;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try{
_workerThread = new Thread(new ThreadStart(MainLoop));
_shouldStop = false;
_workerThread.Start();
}
catch{}
}
private void MainLoop()
{
while (!_shouldStop)
{
try{
//your logic here
}
catch{}
}
}
protected override void OnStop()
{
_shouldStop = true;
}
You must put your code or class, which contain data access logic in OnStart method
This is what I got:
protected override void OnStart(string[] args)
{
if (SomeApp.Initialize())
{
SomeApp.StartMonitorAndWork();
base.OnStart(args);
}
}
protected override void OnStop()
{
SomeApp.TearDown();
base.OnStop();
}
Here Initialize reads a config file and if it's wrong there's nothing to do so service should STOP! If config is ok StartMonitorAndWork starts:
Timer(new TimerCallback(DoWork), null, startTime, loopTime);
and DoWork polls database periodically.
If Initialize fails (i check log file) and I try to stop service from Administrative Tools->Services i get:
Could not stop the SomeService on Local Computer. The service did not return an error.
This could be internal Windows error or an internal service error.
If the problem persists, contact system administrator.
The question is:
"Is exiting OnStart without doing nothing enough if Initialize returns false?
OR should there be something like this:
private void ExitService()
{
this.OnStop();
System.Environment.Exit(1);
}
protected override void OnStart(string[] args)
{
if (ObjectFolderApp.Initialize())
{
SomeApp.StartMonitorAndWork();
base.OnStart(args);
}
else
{
ExitService();
}
}
Thanks & BR - Matti
EDIT:
I came up with something like this:
protected override void OnStart(string[] args)
{
try
{
if (SomeApp.Initialize())
{
SomeApp.StartMonitorAndWork();
base.OnStart(args);
}
else
{
Stop();
}
}
catch
{
Stop();
}
}
protected override void OnStop()
{
try
{
SomeApp.TearDown();
base.OnStop();
}
catch
{
base.OnStop();
}
}
after testing all the approaches I personally prefer calling
Environment.FailFast("Configuration is wrong.");
Main goal is that the fail explanation is written in Event Log and FailFast affects on Recovery settings of your service. So if you configure recovery and configuration gets correct your service will start automatically.
I know it's not pretty but throwing an exception in OnStart also works.
If your service is setup to "Autolog" this will also write a your exception message to the EventLog automatically.
protected override void OnStart(string[] args)
{
if (ObjectFolderApp.Initialize())
{
SomeApp.StartMonitorAndWork();
base.OnStart(args);
}
else
{
throw new Exception("What went wrong");
}
}
I would log an error to the eventlog if Initialize() returns false with some sensible message saying while it fails, and you should like you suggest call OnStop() if it fails. It's good practice to ensure proper shutdown of the service.
Also see this related SO question, and dev newsgroup thread.
I recommend you something like this:
protected override void OnStop()
{
try
{
EventLog.WriteEntry("MyService", "Service is going to stop because of ...", EventLogEntryType.Information);
// Dispose all your objects here
}
catch (Exception ex)
{
EventLog.WriteEntry("MyService", "Exception : " + ex.ToString(), EventLogEntryType.Error);
}
finally
{
GC.Collect();
base.OnStop();
}
}