【问题标题】:Running a Windows Scheduled Task from ASP.net从 ASP.net 运行 Windows 计划任务
【发布时间】:2013-04-27 23:25:36
【问题描述】:

我有一个 Windows 计划任务,它每小时运行一个数据库导入过程,但我希望用户能够通过点击 ASP.net 仪表板中的按钮(在 IIS6 中运行在 Windows Server 2003 上)。

以下内容在代码隐藏中完美运行...

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();

...但前提是应用程序池标识设置为本地系统(不理想!)。如果我将其保留为网络服务,则任务不会启动。所以大概是权限问题。

有没有办法 ASP.net 可以在不将应用程序作为本地系统运行的情况下在服务器上启动计划任务?如果没有,有什么好的选择?

更新:如果 SO 上没有人知道,我想这是不可能的,所以我会按照我的想法让我的 Web 应用程序将请求写入数据库表(兼作审计日志)和创建第二个任务来轮询该表并启动主要任务。

【问题讨论】:

  • 为什么你不调用这个任务将在你的 webapp 中调用的东西?为什么要运行任务,而不是任务的目标?
  • 好问题。 1 我需要以特定用户的身份运行该任务,以及 2 它不能与每小时计划的任务同时运行,如果手动启动了任务,Windows 计划程序就不会启动。不过,这不是我详细探讨过的选项。

标签: c# asp.net iis scheduled-tasks windows-server-2003


【解决方案1】:

您需要 Windows 中的管理员用户。此代码将帮助您调用任务:

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();

如果您的应用程序需要以系统帐户运行,您可以使用以下参数:

如果 /RU 用户名和 /RP 密码参数匹配当前 登录用户,任务将以交互方式运行(在 前景)。

对于系统账号,/RU用户名可以写成“”,“NT AUTHORITY\SYSTEM" 或 "SYSTEM",不需要密码。系统 帐户具有对本地计算机的完全访问权限,但没有权限 网络上的任何其他机器(或映射的驱动器)。

来源:http://ss64.com/nt/schtasks.html

【讨论】:

  • ProcessStartInfo.Password 是 SecureString 类型而不是字符串,因此此代码无法编译。
【解决方案2】:

您可以利用 ASP.NET 的缓存来运行计划任务。我个人使用它,它就像魅力一样。当然它有一些限制(准确性),但你可以调整/改变。

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

问候

【讨论】:

  • 这是一个黑客。更好的方法是使用调度服务,例如atrigger.com
【解决方案3】:

更新您的计划任务以触发特定事件。然后让您的网站在单击按钮时记录该事件 - 从而开始您的计划任务。

例如: 在我的安装程序中,我为我的程序创建了一个事件日志源,因为创建源需要管理权限 (you can also use the command line to create the source)

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

然后在我的应用程序中,单击按钮时创建一个事件日志条目。

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) 
    {
        ...   
    }
}

并且任务计划程序设置为在记录事件时打开 MyOtherApp。

【讨论】:

  • 他将“需要更改注册表”以获得正确的写入权限。
  • ?我的没有。如果你设置 log.source = ".NET Runtime" 你会没事的。虽然,我将它设置为我的应用程序名称,因为我设置我的安装程序将应用程序添加为事件日志源。如果你愿意,我会发布一些代码。
  • 是的,你是对的。我刚刚尝试过,它奏效了。但是我想知道如何创建一个新的源...发布一些代码。
【解决方案4】:

如果不能使用诸如Quartz.NET 之类的第三方调度程序服务,并且也不允许更改权限(无论如何都不是一个好主意),另一种可能性是编写一个辅助 Windows 服务作为两者之间的桥梁ASP.NET 应用程序和 Windows 调度程序。您可以将任务列表存储在数据库中,并且一系列事件将是这样的:

  1. 当您需要运行任务时,您可以从 ASP.NET GUI 在数据库中为该任务设置标志
  2. 帮助服务按计划运行,以给定的时间间隔检查数据库 - 查看标志、启动任务、重置标志。

哦,还有一些库(例如 http://taskscheduler.codeplex.com/ 和其他库)包装了 Window Task Scheduler,因此您不必直接执行它们,而是以一种很好的托管方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    相关资源
    最近更新 更多