Running a Windows Scheduled Task from ASP.net
Asked Answered
E

4

8

I have a Windows scheduled task that runs a database import process every hour, but I'd like users to be able to kick it off out-of-schedule by hitting a button in an ASP.net dashboard (running in IIS6 on Windows Server 2003).

The following works perfectly in code-behind ...

var proc = new Process
            {
                StartInfo =
                    {
                        UseShellExecute = false,
                        FileName = @"C:\Windows\System32\schtasks.exe",
                        Arguments = "/run /tn Loader",
                        RedirectStandardError = true,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true
                    }
            };
proc.Start();
proc.WaitForExit();

... but only if the application pool identity is set to Local System (not ideal!). If I leave it as Network Service, the task does not start. So it is presumably a permissions issue.

Is there a way ASP.net can kick off a scheduled task on the server without running the application as Local System? If not, what good alternatives are there?

Update: if nobody on SO knows, I guess it is not possible so I will go with my idea of having my web application write requests to a database table (doubling as an audit log) and creating a second task to poll that table and kick off the main task.

Extrusion answered 3/5, 2013 at 14:10 Comment(2)
Why you are not calling what this task will call in your webapp? Why you want to run the task, not the target of the task?Lansing
Good question. 1 I need the task to run as a specific user, and 2 It must not run at the same time as the hourly scheduled task, which Windows Scheduler conveniently does not start if the task has been manually kicked off. This isn't an option I've explored in much detail, though.Extrusion
A
6

Update your schedule task to trigger off a specific event. Then have your website log that event when the button is clicked - thus starting your scheduled task.

Ex: In my installer I create an event log source for my program, since creating the source requires administrative privileges (you can also use the command line to create the source)

  if (EventLog.SourceExists("MyApp"))
  {
      EventLog.CreateEventSource("MyApp", "Application");
  }

Then in my application, I create an event log entry when the button is clicked.

private void btnOpenOtherApp_Click (object sender, EventArgs e) 
{
    try 
    {
        var log = new EventLog
        {
            Source = "MyApp"
        };
        log.WriteEntry("Start MyOtherApp", EventLogEntryType.Information, 1337);
    } 
    catch (Exception ex) 
    {
        ...   
    }
}

And the task scheduler set to open MyOtherApp when the event is logged. Event viewer

Algiers answered 6/11, 2013 at 16:16 Comment(3)
his would "require registry change" for proper write permissions.Pierides
? Mine doesn't. If you set the log.source = ".NET Runtime" you'll be fine. Although, I set it to my application name, because I setup my installer to add the application as an Event Log source. I'll post some code, if you want.Algiers
yes you are right.I just tried it and it worked. However I would like to know how to create a new source...do post some code.Pierides
L
1

You need an administrator user in windows. This code will help you to call the task:

var securePass = new System.Security.SecureString();
foreach (char c in "my_password")
{
    pass.AppendChar(c);
}

var proc = new Process
{
    StartInfo =
    {
        UseShellExecute = false,
        FileName = @"C:\Windows\System32\schtasks.exe",
        Arguments = "/run /tn Loader",
        UserName = "myAdminUser", //NEW
        Password = securePass, //NEW
        RedirectStandardError = true,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    }
};
proc.Start();
proc.WaitForExit();

If your application needs to run as SYSTEM Account you can use this arguments:

If the /RU username and /RP Password parameters match the currently logged-in user, the task will run interactively (visible in the foreground).

For the system account, /RU username can be written as "", "NT AUTHORITY\SYSTEM" or "SYSTEM", a Password is not required. The system account has full access to the local machine but has no permissions on any other machines (or mapped drives) across the Network.

Source: http://ss64.com/nt/schtasks.html

Lansing answered 27/8, 2013 at 11:1 Comment(1)
ProcessStartInfo.Password is a SecureString Type and not a string, therefore this code doesn't compile.Merce
W
0

You can utilize the cache of ASP.NET to run schedule tasks. I personally used this and it worked like charm. Ofcourse it has some limitation (Accuracy) but you can adjust/change.

https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/

Regards

Whitechapel answered 27/8, 2013 at 11:16 Comment(1)
It's a hack. The better way is to use scheduling services such as atrigger.comLansing
E
0

If using a 3rd party scheduler service such as Quartz.NET is not an option, and changing permissions is not allowed either (not a good idea in any case) another possibility is to to write a helper Windows service as a bridge between ASP.NET application and Windows scheduler. You would store list of tasks in a DB and a sequence of events would be something like this:

  1. When you need to run a task, from ASP.NET GUI you set flag in the DB for that task
  2. Helper service runs on schedule to check the DB at given intervals - sees the flag, starts the task, reset the flag.

Oh and there're libraries out there (e.g. http://taskscheduler.codeplex.com/ and others) that wrap Window Task Scheduler, so you don't have to execute them directly, but rather in a nice managed way.

Encratia answered 6/11, 2013 at 16:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.