Best Practice: Converting an application to a service with a schedule - c#

I'm a bit of a beginner as far as programming is concerned. And looking at stack overflow I haven't found anything that quite answers my question.
I have created a C# console application that is used to push an XML file to a web service that I don't control. It does this by creating an http webrequest. The service will probably be running on windows server 2008, or a win 7 varient. Development is done in VS 2010.
My end goal is to run this program twice a day with little user involement. And I was told that services were the best way to do this. I know that services do not take user input and that outputs are usually to a log file. My console app dosn't take user input but must have the ability to C.R.U.D. files. Beacuse it creates and then reads an XMl file into the web request. If needed I should have no problems having it write any errors to a log file, but at current though it creates/sends an error report via email.
I have 2 questions:
Question 1:
I would like this service to call the application every 12 hours, Is it more reliable/better practice to use a service to determine when to run the application? Or use windows' built in scheduler, or a .net solution like quark? I'm looking for reliability and also, little user involvement. Kind of a set and forget deal.
Question 2:
What would the suggested best practice be for converting my program?
INFO: I have previously created a empty windows service that I would like to fold my application into. (This was done via tutorial, the service contains all that is needed to for a service but it dosn't do anything... yet! OnStart, OnStop, installer etc.) What would be the best way to do it? Should I call my application inside the service's OnStart() method? Our should I add the application as a dll to the service. It's not that I don't think I could do it. It's just my searches on the matter seem to point out that it would be better to just start from a service and add some code to that. My goal would be to minimise the code needed to convert this application.
Thanks for all your help,
Chris

I like standalone programs run by the scheduler because they are easier to write and test.
Services would be more appropriate when they have to be running all the time...say to monitor something.

Question 1: Personally running twice a day seems like a scheduled task type of operation
Question 2: I'd describe it as: more or less put the body of static void Main(string[] args) into the OnStart method. Then also create a timer in OnStart which will call the trigger function in your class. But then I've only stumbled my way through writing windows services so I'm not 100% certain on this advice...
One consideration might be whats the risk of anything failing in the process? If there is a chance of an unhandled exception, the service will die and either would need special settings to restart it or complete error handling to be coded. Where a scheduled task will always automatically retry at the next trigger interval.

Related

Process.Start Notepad++ an application which is started by Windows Service [duplicate]

I have done a lot of searching to find a way to start a GUI application from a windows service on Windows 7. Most of what I have found is that with Windows 7 services now run in a separate user session and can not display any graphical interface to the current user. I'm wondering is there is any kind of workaround or different way of accomplishing something like this? Can the service start a process in a different user session?
This change was made for a reason and not simply to annoy developers. The correct approach is to put your UI in a different program and communicate with the session through a pipe, or some other IPC mechanism. The recommendation that services do not present UI is more than 10 years old now.
You should really try to follow these rules, even though it may seem inconvenient to begin with. On the plus side you will enjoy the benefit of keeping your service logic and UI logic separate
If your services runs under the LOCALSYSTEM account then you can check "Allow service to interact with desktop", for the benefit of legacy services that would fail if they could not show UI. But it won't help you anyway because the UI will show in session 0 where it is never seen!
I recommend you take a read of the official Microsoft document describing session 0 isolation.
There is a way to do this.
If you need to show a simple message box you can use the WTSSendMessage Routine.
If you need a complex UI elements you can put it in a separate program and you need to use CreateProcessAsUser Routine.
In this sample provided by microsoft you can see the process.
http://blogs.msdn.com/b/codefx/archive/2010/11/26/all-in-one-windows-service-code-samples.aspx
Windows 7 introduced what is called "Session 0 isolation" that in practice means that every service (except system services) run in a separate non-interactive session. For this reason you cannot directly create a GUI from within the service, except if you run in legacy mode by flagging the Interact With Destop option, which is not good if you plan to run your service for some years in the future.
As David Heffernan said, the best is to use a client-server architecture. WCF makes it easy to communicate with named pipes.
This page is a good starting point to read about Session 0 Isolation and this white paper is also very good.

How to have periodical events in a C# MVC web app?

I have a web app that I'm writing right now that is supposed to have "periodical events". For instance, at midnight, the web app should calculate "scores" for all users. I want this done only once during the day.
Is there a way that I can automate this, so it runs automatically at midnight (or whatever hour I choose)?
I don't like the idea of creating a separate script (VBS) to do this, as the calculation would depend on a lot of business logic of the app. I was thinking to put it into a separate Class Library, so it can use the web app logic (which is also in a class library), but is this the best way to go about it?
I also don't like the idea of using the Session_Start() event in the Global.asax to trigger the event by checking the hour manually. There must be some easier way - especially because down the road I expect there will be a lot more of periodical events - some may have to be triggered every fifteen minutes, for example ...
Thanks a lot for any help you can give me.
You should not do this in the web app itself. You are correct to put the business logic in a separate library. Once you have done this, you can use the business logic from anywhere, and therefore, a good solution would be to create a console application that does the nightly jobs, and invoke the console application from Windows Task Scheduler. IIS is not suitable as a host for periodical events.
I guess you are missing the point of separation of concern. Whatever you are asking is a job of a service. You need to develop a separate application as Windows Service that will do all your calculation and to be triggered by any scheduler even Windows Task Scheduler would do. This is what basically done on large scale applications.
Yeah... again awesome "change your architecture and hosting environment so that my answer can be relevant" responses.
Doing what you ask is actually quite easy, take a look at this article: http://www.codeproject.com/Articles/12117/Simulate-a-Windows-Service-using-ASP-NET-to-run-sc
This is a job for a windows service or scheduled task. A web application responds to HTTP requests. Essentially the service's job would be to wake up, run the appropriate calculations and write back to the database. Once in the database, your web application can use the newly calculated values.
Here is some information on windows services: http://msdn.microsoft.com/en-us/library/d56de412.aspx

Best way to find out what error terminated a c# windows service?

My c# windows service is dying due to an unknown error deep down in one of the worker threads that it creates.
Is there any way to find out the exception that causes the service to be terminated?
(Without writing in a dozen try / catch / log the error codes).
Just a simple one-time report on the error that caused the service to shut down.
It is simple, implement an event handler for AppDomain.CurrentDomain.UnhandledException and log the value of e.ExceptionObject.ToString().
I'd say that it might be useful to add the dozen try catch so that the next time something goes wrong, you'll have a log of the error (especially useful if you later find an issue that only occurs sometimes in unclear circumstances so difficult to reproduce while debugging).
However, other than that, you can attach Visual Studio to a running process as shown in this MSDN article. To avoid having to do that I usually add some code to the startup of the service so that if the exe is started with a -c command line parameter, it'll run as a normal process which can be started from Visual Studio. This Code Project article shows something similar to this.
There's a couple of things that you can do. First, check the Windows error logs if you haven't already - I know this is probably obvious, and they can be a bit light on information, but it's always worth a look, because occasionally it will help.
The second approach is just a little bit more involved, and I know you've asked for something really quick and one-time, but to be honest I'm about to recommend the best way to develop Windows services, and once you've done it, you will never go back... and it will save you hours of pain, so I'll give you the advice anyway:
Extract the core of your service to be run independently in a simple console app host. This approach means that you can fully run and debug it in Visual Studio running as a plain old executable, or even on your test server with a remote debugging session attached. For the real "live" windows service, your service code is a thin wrapper around your testable, debuggable service core. This has worked for me time and time again.
Your core service will expose Start() and Stop() methods that can be called by your Windows Service host in production. That's it.
There's a really good OSS project called Topshelf that provides a full-featured and well-tested version of the wrapper I've described and you can read a developer's example of it in use it here.
The easy way is transferring the errors from VS to windows error log and checking there. You have to use some third party tools if you prefer to get error log list as a report instead.
Logger in c#
if you prefer go for a simpler/cheaper one try the above code. Its is very easy and simpler than u thought

What would be the best approach is my application had to pull information from a website every day at 2am

I'm making a small application that is supposed to download info from the web every day at 2am. It will download the information and write the strings to an XML file of my choosing.
Using .NET and C#.
My initial approach was to install a service on the users computer and have that run, but I'm not so sure. I've not even used it so much in the past, only once.
Which is the best (read: time tested :P ) approach to this very common problem.
You can either build your application as a Windows Service, as you mentioned.
Or else it would probably be a better idea to create a normal console application, and launch it automatically at 2.00am with the Windows Task Scheduler.
You can consider both methods as popular and "time-tested".
I would suggest having a console app, which calls data fetching algo in a separate public class (not the main method).
Like Daniel mentioned, run it via Windows Task Scheduler which itself will take care of most scheduling requirements.
This allows the solution to be scaled in the future if need be. E.g. convert into Windows Service, full GUI Winform or even SQL server scheduled tasks etc.

What could cause a Windows Service to hang when a Console App doing the exact same thing using the exact same base libraries doesn't?

I hate asking questions like this - they're so undefined... and undefinable, but here goes.
Background:
I've got a DLL that is the guts of an application that is a timed process. My timer receives a configuration for the interval at which it runs and a delegate that should be run when the interval elapses. I've got another DLL that contains the process that I inject.
I created two applications, one Windows Service and one Console Application. Each of the applications read their own configuration file and load the same libraries pushing the configured timer interval and delegate into my timed process class.
Problem:
Yesterday and for the last n weeks, everything was working fine in our production environment using the Windows Service. Today, the Windows Service will run for a period of around 20-30 minutes and hangs (with a timer interval of 30 secods), but the console application runs without issue and has for the past 4 hours. Detailed logging doesn't indicate any failure. It's as if the Windows Service just...dies quietly - without stopping.
Given that my Windows Service and Console Applications are doing the exact same thing, I can only think that there is something that is causing the Windows Service process to hang - but I have no idea what could be causing that. I've checked the configuration files, and they're both identical - I even copied and pasted the contents of one into the other just to be sure. No dice.
Can anyone make suggestions as to what might cause a Windows Service to hang, when a counterpart Console Application using the same base libraries doesn't; or can anyone point me in the direction of tools that would allow me to diagnose what could be causing this issue?
Thanks for everyone's help - still digging.
You need to figure out what changed on the production server. At first, the IT guys responsible will swear that nothing changed but you have to be persistent. i've seen this happen to often i've lost count. Software doesn't spoil. Period. The change must have been to the environment.
Difference in execution: You have two apps running the same code. The most likely difference (and culprit) is that the service is running with a different set of security credentials than your console app and might fall victim to security vagaries. Check on that first. Which Windows account is running the service? What is its role and scope? Is there any 3rd party security software running on the server and perhaps Killing errant apps? Do you have to register your service with a 3rd party security service? Is your .Net assembly properly signed? Are your .Net assemblies properly registered and configured on the server? Last but not least, don't forget that a debugger user, which you most likely are, gets away with a lot more stuff than many other account types.
Another thought: Since timing seems to be part of the issues, check the scheduled tasks on the machine. Perhaps there's a process that is set to go off every 30 minutes that is interfering with your own.
You can debug a Windows service by running it interactively within Visual Studio. This may help you to isolate the problem by setting (perhaps conditional) breakpoints.
Alternatively, you can use the Visual Studio "Attach to process" dialog window to find the service process and attach to it with the "Debug CLR" option enabled. Again this allows you to set breakpoints as needed.
Are you using any assertions? If an assertion fires without being re-directed to write to a log file, your service will hang. If the code throws an unhandled exception, perhaps because of a memory leak, then your service process will crash. If you set the Service Control Manager (SCM) to restart your process in the event of a crash, you should be able to see that the service has been restarted. As you have identical code running in both environments, these two situations don't seem likely. But remember that your service is being hosted by the SCM, which means a very different environment to the one in which your console app is running.
I often use a "heartbeat", where each active thread in the service sends a regular (say every 30 seconds) message to a local MSMQ. This enables manual or automated monitoring, and should give you some clues when these heartbeat messages stop arriving.
Annother possibility is some sort of permissions problem, because the service is probably running with a different local/domain user to the console.
After the hang, can you use the SCM to stop the service? If you can't, then there is probably some sort of thread deadlock problem. After the service appears to hang, you can go to a command-line and type sc queryex servicename. This should give you the current STATE of the service.
I would probably put in some file logging just to see how far the program is getting. It may give you a better idea of what is looping/hanging/deadlocked/crashing.
You can try these techniques
Logging start logging the flow of the code in the service. Have this parameter based so you dont have a deluge after you are done. You should log all function names, parameters, timestamps.
Attach Debugger Locally or Remotely attach a debugger with the code to the running service, set appropriate breakpoints (can be based on the data gathered from logging)
PerfMon Run this utility and gather information about the machine that the service is running on for any additional clues (high CPU spikes, IO spikes, excessive paging, etc)
Microsoft provides a good resource on debugging a Windows Service. That essentially sounds like what you'd have to do given that your question is so generic. With that said, has any changes been made to the system over the last few days that could aversely affect the service? Have you made any updates to the code that change the way the service might possibly work?
Again, I think you're going to have to do some serious debugging to find your problem.
What type of timer are you using in the windows service? I've seen numberous people on SO have problems with timers and windows services. Here is a good tutorial just to make sure you are setting it up correctly and using the right type of timer. Hope that helps.
Another potential problem in reference to psasik's answer is if your application is relying on something only available when being run in User Mode.
Running in service mode runs in (is it desktop0?) which can cause some issues in my experience if you are trying to determine states of something that can only be seen in user mode.
Smells like a threading issue to me. Is there any threading or async work being done at all? One crucial question is "does the service hang on the same line of code or same method every time?" Use your logging to find out the last thing that happens before a hang, and if so, post the problem code.
One other tool you may consider is a good profiler. If it is .NET code, I believe RedGate ANTS can monitor it and give you a good picture of any threadlock scenarios.

Categories

Resources