Running Quartz.net on another server - c#

I have a Windows Forms application where users can define certain tasks to be scheduled, but I want to run them on another server. I was thinking that I could schedule the tasks using Quartz.NET with the AdoJob scheduler, so they will be in a database, and on the same server as the database I would have a Windows Service which could read the scheduled jobs and execute them. How should I do this in Quartz.NET? Or is this not the best approach for my problem?
Update: Here's what I'm trying.
Schedule a task from the app using the type name of the class which should be executed
I tried with Quartz.NET to schedule a job using the name and namespace of the class, but it doesn't work, instead of using a direct reference to it. If this would have worked, the next step would've been to start the windows service and see if I could run the job from there.
IJobDetail job = JobBuilder.Create(Type.GetType("SomeNamespace.IHelloJob"))
.WithIdentity("myJobRemote", "remote")
.StoreDurably()
.Build();
The exception message says "Job class cannot be null."
If I make the first step work, then I'll start the windows service and try to run the job inside of it

Related

c# : Create windows scheduled task as a different user

I'm creating Windows Scheduled Tasks dynamically from c# using the build-in TaskService and TaskDefinition libraries.
But for some of them, we need to create then to run as a different user (Local Service or Network Service). As the tasks are created and removed dynamically we cannot edit all of them manually to change the user. We need to do it via code.
Is is possible?
I've tried the following settings:
TaskDefinition.Principal.Id = "NETWORK SERVICE";
TaskDefinition.Principal.LogonType = TaskLogonType.ServiceAccount;
but this gives me the very descript error when creating the task:
System.Runtime.InteropServices.COMException: '(52,4):Task:'
Without those 2 lines, it works but creates them as the logged in user.
I've played around with the Task Scheduler stuff a bit and have replicated your problem. I believe I’ve found some things out, maybe they can help.
1. Firstly if your making Tasks in the debugger using Services Accounts, you'll want to ensure your Visual Studio or other IDE is launched as administrator to ensure you have the correct privileges to do this task.
2. I'm not sure if you do this later in your code but to make the task save and run as NETWORK SERVICE, I had to Identify Network Service as NT AUTHORITY\\NETWORKSERVICE in both the principle and on the RegisterTaskDefinition method:
TaskService tService = new TaskService();
TaskDefinition tDefinition = tService.NewTask();
tDefinition.Principal.Id = "NT AUTHORITY\\NETWORKSERVICE";
tDefinition.Principal.LogonType = TaskLogonType.ServiceAccount;
tDefinition.RegistrationInfo.Description = "Testing";
tDefinition.Triggers.Add(new DailyTrigger {DaysInterval = 2});
tDefinition.Actions.Add(new ExecAction("notepad.exe"));
tService.RootFolder.RegisterTaskDefinition(#"Test", tDefinition, TaskCreation.CreateOrUpdate,
"NT AUTHORITY\\NETWORKSERVICE", null,
TaskLogonType.ServiceAccount);
I used the above code to make a test Task that got successfully added to my scheduler as Network Service as shown below:
I'm guessing that one or both of the above points may have stopped the task from being added, hope that helps

Schedule a C# console application

I've given a task to create an email C# console application which targeted to run as batch. I'm very new to C# area and hence I have no idea about my direction. This C# console application will be deployed on a server and expect to run in certain time based on server time.
After some research, most of the suggestions are about using task scheduler or window services, but I'm wondering if this C# console application is somehow possible to run own its own? Maybe after execute it, it then register itself into the server and the server will handle it periodically?
If you want to manage the scheduler by code have a look at Quartz.NET: http://quartznet.sourceforge.net/
This library provides the creation of jobs and triggers.
e.g. (directly from: http://quartznet.sourceforge.net/tutorial/lesson_3.html):
// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();
// get a scheduler
IScheduler sched = schedFact.GetScheduler();
sched.Start();
// construct job info
JobDetail jobDetail = new JobDetail("myJob", null, typeof(DumbJob));
// fire every hour
Trigger trigger = TriggerUtils.MakeHourlyTrigger();
// start on the next even hour
trigger.StartTime = TriggerUtils.GetEvenHourDate(DateTime.UtcNow);
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger);
Now this means your console application should run continuously which makes it not really suitable for the job.
Option 1. Add a task via task scheduler (real easy) that executes your console application. See example task: http://www.sevenforums.com/tutorials/12444-task-scheduler-create-new-task.html
Option 2. Create a windows service (not to complicated) that uses a library like Quartz.NET or .NET's Timer class to scheduele jobs and executes a batch operation. See for creation of windows service http://msdn.microsoft.com/en-us/library/zt39148a.aspx
Option 3. Make your console application implement a scheduele library like Quartz.NET or /Net's Timer class and run it as a service (a bit more complex): Create Windows service from executable
As long as it requires no user input, it will be able to run on it's own. You can schedule the program to run in Windows Task Scheduler for example.

How to run long-lasting process asynchronously under asp.net?

.net 4.5, asp.net mvc: What is the best way to run long-lasting process (1-2 minutes) from ASP.NET application giving it should be run in a single-threaded environment, I mean the process is initiated for one user at a time only, executions for all other users have to wait till the current execution is done? The scenario is the following: user clicks button that run some sort of long-lasting calculations, http response returned to the user immediately, then user has to request status of the calculations with separate request manually. Asp.net http session abortion should not lead to the process termination, it should keep going. The process might be run on the same or separate server.
I'll show you how to perform this task with http://hangfire.io – incredibly easy way to perform fire-and-forget, delayed and recurring tasks inside ASP.NET applications. No Windows Service required.
First, install the package through NuGet. If you have any problems, please see the Quick Start guide in the official documentation.
PM> Install-Package Hangfire
Open your OWIN Startup class and add the following lines:
public void Configure(IAppBuilder app)
{
GlobalConfiguration.Configuration.UseSqlServerStorage("connection_string");
app.UseHangfireDashboard();
app.UseHangfireServer();
}
Then write the method that will do the long-running work (I applied attribute to perform only one method at a time):
[DisableConcurrentExecution]
public void LongRunning()
{
// Some processing stuff
}
And then call a method in background as fire-and-forget to respond user immediately:
public ActionResult Perform()
{
BackgroundJob.Enqueue(() => LongRunning());
return View();
}
If you want to notify a user about job completion, consider using SignalR and append the LongRunning method correspondingly.
.Net 4.5.2 adds QueueBackgroundWorkItem that you can use to schedule a task. If you don't control the server (when it's rebooted), the 90 second default delay of appPool shut down won't work (unless you can detect the task didn't complete and run it on another server). For more details see "QueueBackgroundWorkItem to reliably schedule and run background processes in ASP.NET"
I would suggest using a product such as NServiceBus to offload the processing and run it in single threaded mode. The advantage to this is that all requests will be processed in order and the processing can be offloaded from the web server as you don't really want long running processes to happen on a web server.
If you control the server, and need more simplicity that a full framework like Hangfire, you can make a console app (.exe), and make any thing..., then you can call the .exe with Process.Start Method, you can call the .exe from SQL Server to, service, etc.

Scheduler doesn't execute job, doesn't appear to even register it

I've created the following:
A windows service
A quartz scheduler class
A single IJob implementation called Worker, which contains a set of tasks that I intend to execute via the Quartz scheduler.
The windows service overrides OnStart to call the scheduling/setup class, which attempts to create a single scheduled task within Quartz that I want to run at a given time frame (At the moment, this is simply once per 30 seconds for example, to test the process)
I've used identical code to one of the samples for creating a job and trigger - the trigger containing a chain of code to start immediately and repeat every 30 seconds, forever.
I then call Schedule() and eventually call Start() on the scheduler object.
I use installutil.exe to shove the Service into the services list, I start the service and see my internal logging framework showing me that the service is starting, the scheduler is being created and the job scheduled (logging output line by line since I've been having issues...) The problem is that the task doesn't run once and doesn't ever repeat. The service sits there running happily, but never spins up to execute anything.
If I use the Exists method, passing in the JobKey - it always says false. The count of Jobs is zero, both tested immediately after scheduling and starting the scheduler.
I am setting up the IJobDetail using this approach:
IJobDetail job = JobBuilder.Create<Worker>()
.WithIdentity("job1", "group1")
.Build();
and creating the Trigger with:
TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.ForJob(job)
.StartAt(DateTime.Now)
.WithSimpleSchedule(x => x.WithIntervalInSeconds(30).WithRepeatCount(10))
.Build();
and then to hook it up:
sched.ScheduleJob(job, trigger);
sched.Start();
I am at a loss as to why this is happening, there is nothing in the event log and nothing wrong with the service and the code appears to run through without any problems as I've shoved logging statements (output to txtfile within /bin/debug) after every line & there's plenty of exception handling.
Any ideas? Is the Build() on the generic Create going to tell the scheduler that the type I've defined is where the Execute() method resides?
Edit
Configuration sections I nabbed from this post on SO (#jadenedge's answer) and placed within app.config for the Windows Service. Possibility here of 1.0/2.0 mismatch?
I want the configuration within app.config, ideally, and have no other configuration elsewhere.
Are you starting a thread that keeps the process running? After the service is started, is your process still in memory?
I had this problem and oh boy it drove me absolutely crazy. As it happened I had a spike project that I could always get to run, but my main projects would not run!
The problem: The namespace of my project had dots/periods in it e.g.MyProject.UpdateService where as my spike was simply named QuartzTest.
Debugging through line by line found that when I set my Windows service name to MyProjectUpdateService the Quartz job then registered.
TL/DR:
Ensure your Windows service doesn't have dots in the name.
Update: I've done some more testing and it looks like the maximum length of the service name for a Windows service running Quartz is 25 characters. It doesn't error - it just won't start.

How to schedule tasks using Quartz.Net inside a Windows Service?

I have created a windows service project in VS and in it I configure Quartz.Net to run a task immediately. The code that registers the task runs with no exception, but the task is never executed as far as my debugging can tell.
I can't be sure because debugging a Windows Service is very different. The way I do it is to programatically launching the debugger from my code. Quartz.Net runs jobs on a separate threads, but I'm not sure if VS2010 can see other running threads when debugging a Windows Service.
Has anyone done what I'm trying before? Any tips are appreciated.
PS. I don't want to use Quartz.Net's own Service.
One of the most common reasons a job doesn't execute, is because you need to call the Start() method on the scheduler instance.
http://quartznet.sourceforge.net/faq.html#whytriggerisntfiring
But it's hard to say what the problem is if we don't have some sort of snippet of the code that does the scheduler creation and job registration.
I see that this is a bit dated, but it came up many times in various searches!
Definitely check out this article, which uses an XML config when the scheduler is instantiated.
http://miscellaneousrecipesfordotnet.blogspot.com/2012/09/quick-sample-to-schedule-tasks-using.html
In case you would rather not use XML (dynamically created tasks and such), replace the "Run" procedure from the article above with something like this:
public void Run()
{
// construct a scheduler factory
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
_scheduler = schedulerFactory.GetScheduler();
IJobDetail job = JobBuilder.Create<TaskOne>()
.WithIdentity("TaskOne", "TaskOneGroup")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("TaskOne", "TaskOneGroup")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(20).RepeatForever())
.Build();
_scheduler.ScheduleJob(job, trigger);
_scheduler.TriggerJob(job.Key);
_scheduler.Start();
}
Note - Using Quartz .NET 2.1.2, .NET 4
Cheers!
I have successfully used Quart.NET before in a Windows service. When the service starts-up I create the Scheduler Factory and then get the Scheduler. I then start the scheduler which implicitly reads in the configuration XML I have specified in the App.config of the service.
Quartz.NET basic setup: http://quartznet.sourceforge.net/tutorial/lesson_1.html
App.config Setup Question: http://groups.google.com/group/quartznet/browse_thread/thread/abbfbc1b65e20d63/b1c55cf5dabd3acd?lnk=gst&q=%3Cquartz%3E#b1c55cf5dabd3acd

Categories

Resources