How to emulate cron jobs on a Windows Server? - asp.net

I'm running .NET on a windows box and I would like to have a function run every night at midnight. Of course since HTTP stateless and Windows doesn't have a "cron job" type function (that I know of), I will either have to visit my site myself every night at midnight or just wait for a user to visit the site to rely on it being updated.
Is there an alternative to this that I can create where something will automatically run at a certain time?

I'm pretty sure that Windows' task scheduler can do most things that cron can do. But I might be missing something.
Edit: Reached at Settings -> Control Panel -> Scheduled Tasks

If none of the other answers work for you, here's an option:
There are a bunch of server monitoring services out there that will make an http call to your site at regular intervals (every minute if you like). You can get 5 minute intervals for free on some of them.
Create a password protected page, that performs your function (if it hasn't been done yet today) and point that service at it.
At least this way you won't have to write anything additional, and you can rest easy knowing it doesn't rely on your home machine.

Jeff Attwood at some point in the podcast mentioned a dirty hack to use the Cache Expiration Callback to fake this.
He'd insert an item in .Net's Cache, with an expiration set to 2 hours, and a callback to get called once the item expired, and that was his cron.
I think this was the article:
http://www.codeproject.com/KB/aspnet/ASPNETService.aspx?display=Print
It sucks if you ask me, but for a shared hosting solution, I can't think of anything much better.
Also, there are external cron services that you give a URL to and they will "ping" it regularly, like: (these are not free)
http://webcron.org/
http://www.webbasedcron.com/

Here's a starting point to programmatically add/delete and manage tasks in the Task Scheduler.
http://www.codeproject.com/KB/system/taskscheduler.aspx

If you have command-line access you could try the "at" command, which is like an ultra-light cron:
http://support.microsoft.com/kb/313565

you can also take a look at Quartz .Net http://quartznet.sourceforge.net/ which is a scheduler

The windows equivalent of cron is At. If you have access to the machine.

Use the Timer class to create a timer that periodically calls a method to be executed.
A static timer can be started in the Application_Start event in the Global class. Because the timer uses an interval rather than an absolute time, you'll have to calculate the time interval until midnight and set the Interval property accordingly.

It looks like GoDaddy has provisions for this, but There Is More Than One Way To Do It:
When you install Drupal it needs you to set up a cron job, and I've found out that the project members have documented this step throughly. Go to http://drupal.org/cron for more information, and remember to read http://drupal.org/node/31506 for specific Windows information.
If everything else fails, google for "web cron job" and use a commercial "cron job" service. Choose carefully, don't get ripped off.

I'm also facing the same issue. I want to run ASP.NET with MSSQL at GoDaddy. But they don't have scheule task for windows hosting. After reading the post, I did my own google and found this free web cron job scheduler:
I just tried and it works perfectly...well almost. The job expires in 1 year.
http://www.setcronjob.com/
Hope it helps.

Searching for an answer to the same question, I found this post (quartz-net-with-asp-net) with setup instruction for Quartz.NET ("Enterprise Job Scheduler for .NET Platform", from their website) even from inside an ASP.NET application.
Added it here mainly for reference.

Why not install cygwin and use cron itself?
here is a pdf guide on setting it up:
http://csc.csudh.edu/kleyba/cygwin-cron.pdf

Related

In web/cloud applications, how can I have an automated task (based on date/time)?

My web site stores invoices.
I would like to process them every night at midnight.
I would also like to send out notices nightly at midnight.
But the web is stateless.
I do not have my own server.
Is there a way?
No, you need a Windows Service on a dedicated box, however the box can be virtual and in the cloud.
You do not own your own server, but your website must be hosted somewhere. You may want to see if you can install windows services on to that server. If you can, I would strongly recommend using a service to run any automated tasks. It is generally frowned upon to use IIS to run automated tasks simply because the process shuts down after periods of inactivity... and if IIS isn't running, neither will your automated task.
A similar question was asked a while back and I think the answers are still very relevant to your problem: Best way to run scheduled tasks
And even further, after google searching I found even more info which you might find helpful:
https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
http://www.codeproject.com/KB/aspnet/ASPNETService.aspx
If you absolutely cannot install a service, you could try something like creating a new thread on Application_Start() that checks the time and decides whether or not to run. Then, to keep IIS running during periods of inactivity, you could possibly try spawning a process or something every few minutes to send a request to your server and thus keep it from shutting down.

Running a script just from the server using asp.net

I have a site that I'm working on. Say I need something to run every... say... 30 minutes, how would I get just a simple thing to run like that?
EDIT
I'll be hosting this online with another company. This is why I am not making it as a separate scheduled program.
If you need a process to be run at pre-defined intervals you might be better off using the windows task scheduler, or to create a windows service with a timer. ASP.NET applications aren't ideal for doing this sort of thing, since they are vulnerable to restarts and so you can't guarantee that the process will run at the given interval.
Windows scheduled tasks and services are ideal for this but if you want to run database queries at specified times then I would suggest using SQL Server Agent if you have access to this.
I don't know of any way to reliably do this using ASP.NET. My understanding is: after a certain period of inactivity, IIS will unload your website/webspp from memory. If that happens, your periodic job very likely won't execute, regardless of what technique you used to configure it.
You could, of course, set up some kind of automated system on your own, which occasionally pings your site to keep it from being unloaded. But if you're doing that anyway, well you could just set it up to do the desired operation at the desired interval. :)

How should I perform a long-running task in ASP.NET 4?

I am building a website using .NET 4. There are lots of MSDN articles dating from 2003, about using Thread objects and 2007, using Asynchronous Pages in .NET 2, but that is all pretty stale. I know .NET 4 brought us the Task class and some people vaguely cautioning against its use for this purpose.
So I ask you, what is the "preferred" method circa 2011 for running background/asynchronous work under IIS in ASP.NET 4? What caveats are there about using Thread/Task directly? Is Async=true still in vogue?
EDIT: Ok, ok, from the answers it's clear the opinion is that I should make a service if I can. But the advantages to doing it inside the webapp are significant, especially easier deployment/redeployment. Assuming the process is safe-to-crash, then, if I were to do it inside IIS, what is the best way?
Preferentially, avoid having long tasks executing in such an environment.
Delegate long running tasks out to a stable system service via interoperability, leaving the web application responsive and only required for direct user requests.
Web applications have never been (and still aren't) considered reliable systems - anyone who has ever used a browser has encountered (at least) a time-out, to be sure; and such inconvenience (for both parties) is not limited to this scenario. Of course, any system can crash, but the circumstances surrounding such an event on a system built-to-be-persistent ought to completely exceptional.
Windows services are designed to be long running, and if something goes wrong you've generally got more to worry about than your individual service.
It's best to be avoided, but if you are forced to, consider Hanselman's thoughts at How to run Background Tasks in ASP.NET.
Among them, and for something quick and easy, I would suggest you look in particular at the QueueBackgroundWorkItem added in 4.5.2.
From personal experience, Task does not cut it. QueueBackgroundWorkItem is much better.
You can create a static ThreadPool like this http://www.dotnetperls.com/threadpool with limited threads number(for example only 2). and then queue tasks in it, but it's highly not recommended because web servers are not for such kind of tasks
My preferred method is the same as Robert Harvey proposes in his answer.
You can still use the Task Parallel Library, but spin the task up in a separate process outside of IIS (the reason being that IIS has a limited number of worker threads to hand out and imposes other limitations that can make long running tasks unpredictable).
This is a description of a 'once a day' scenario.
If you really want to avoid creating a service, you could start a timer with 1 minute intervals. Each time the timer delegate is invoked, you will have to run something like this (pseudo code):
lastInvokeDay = LoadLastInvokeDate();
If (lastInvokeDay < DateTime.Now.Date && timeOfDayToRun == DateTime.Now.Time)
{
try
{
today = DateTime.Now.Date;
runMyTask();
}
catch..
finally
{
lastInvokeDay = today;
SaveLastInvokeDay(lastInvokeDay);
}
}
Keep in mind that the lastInvokeDay should be persisted either in Database or on a file...
Now, If you want to enable immediate invocation of the task, you could simply call runMyTask() on demand.
If its important for you to keep the runMyTask from occuring more than once a day, you could create a syncronized block of code inside it (with a lock statement) and move the lastInvokeDay check inside.
Does this answer your question?
I could suggest a simple solution, which doesn't use Windows Services, yet is able to invoke a task to be executed outside of the IIS sandbox.
Also it could be easily adopted by any other language or mix of them, in my case that was Python
Create Event log and source on the IIS server (requires Administrative rights), executing from the PowerShell console:
[System.Diagnostics.EventLog]::CreateEventSource('Automations', 'Automations')
If you have no Administrative rights, skip this step. You will fallback to use Windows/Application log
Create a Task Scheduler task to be executed on event, for example, with ID = 2020, Log = 'Automations' and Source = 'Automations'. There you could invoke whatever you like with all necessary permissions
Prepare a code to send your event, while handling a web request. Giving you a Python example, but you could adopt it to your language:
import win32evtlog
app_name = "Automations"
event_id = 2020
event_category = 0
event_type = win32evtlog.EVENTLOG_INFORMATION_TYPE
messages = ['Starting automation']
# Logs event into the custom Automations log if it exists,
# otherwise logs event into Windows/Application log
handle = win32evtlog.OpenEventLog("localhost", app_name)
win32evtlog.ReportEvent(handle, event_type, event_category, event_id, None, messages, None)
Profit

How to automate database updates at webserver

I am developing the online bidding system using SP.NET where I need to close the auction if the auction time is get closed without any bid.
As on this website (archived link)
Any ideas on how to implement that?
I can think of 4 ways to do this:
1: A bit hackish, but you can try to use the "cache expiration technique" described here
In short, you rely on the ASP.NET cache expiration mechanism to run some code at a set time. In your case you could set this time to the expiration time of the auction the moment the auction gets created. However, this is unreliable, what if you get a server restart? You can say bye to your cache. But if you use a shared service where you don't have access to the server, this could be your solution.
2: A little better, you can write an .aspx page and call it from the Windows task scheduler every X minutes to run your code. The issue here is that you would have to execute a public page. Could be a security concern.
3: Much better, you can write a Windows Service. But this may be too much work if you lack the time.
4: Have a look at Quartz.NET, this is a .NET port of the industry-standard Java project of the same name. I haven't tried it but it looks promising.

Is there a way to run a process every day in a .Net web application without writing a windows service or SQL server jobs

We require that in a ASP.Net application, a .Net process should be invoked every day at a specified time automatically. This process needs to interact with the database (SQL Server 2005) and generate billing on a daily basis. We are using a shared hosting hence we are not able to create a windows service or create SQL Server jobs. How can this be achieved without user intervention?
You could try the technique described here, used at StackOverflow itself (or at least it was used here at one point). In a nutshell:
At startup, add an item to the HttpRuntime.Cache with a fixed
expiration.
When cache item expires, do your work, such as WebRequest or what have
you.
Re-add the item to the cache with a fixed expiration.
To get it to run at a specific time instead of an interval, you could lower the interval and simply modify your working method to check the time itself.
As the comments in the original article linked above note, this isn't a perfect solution, and no one should prefer it over a proper scheduling technique if one is available. See When Does Asp.Net Remove Expired Cache Items? for some additional qualifications.
Yes, use Windows Scheduler. Depending on how it's configured you might need to be logged in for the scheduler to run.
You could always schedule a task to run a webservice..
http://weblogs.asp.net/jgalloway/archive/2005/10/24/428303.aspx
The scheduler would run a VBS file with the following..
Set oServerXML = CreateObject("Msxml2.ServerXMLHTTP")
oServerXML.Open "GET","http://my.hostedservice.com/myService.asmx/myService?aParam=Value
oServerXML.setRequestHeader "Content-Type","application/x-www-form-urlencoded"
oServerXML.Send
Set oServerXML = nothing
Can't be done, unfortunately.
IIS only responds to requests, and SQL Server only wakes up for jobs.
The closest you'll be able to do is to put your routine in an ASPX page, not linked from the site and not with an obvious name, and trigger it by a request from some other machine out on the Internet.
The other machine could be a Windows, Linux, Mac, whatever you have available, and all of those platforms have ways of scheduling events (service, cron, etc.) that can make the request to trigger the update on the server.
There are ways to run "services" in .Net by using cache expiration to trigger the task.
More at CodeProject
You can use a Scheduled Task, but this might not work in a shared hosting environment either.
You could setup a webservice or page on your website to kickoff the process, then have a scheduled task on a desktop machine hit that page/service once daily to start the process. Hacky, but it might work.
Being .NET ignorant, I would imagine there's some kind of .NET based scheduler framework available for this (much like Quartz for Java).
Or you could simply fire off a long running thread that spends the bulk of its time sleeping, wake up every minute, check the time, check it's list of "things to do", fire off the ones that need to be done. Level of sophistication being as far as you want to take it, but the primary goal of keeping the primary scheduling thread "alive", "at all costs".
What i can think about now are:
Create a dll which contain the
schedule logic you want, and make
sure that this dll schedule function
will not stop and will loop for ever,
then you will need a page on that
server this page will fire this dll
functions. "you will need to call
this page at least once to start the
scheduler".
Create an application "holds schedule logic" on another machine, may be your Home PC, and make your pc application call the functions on the server through webservices or pages

Resources