Windows任务计划程序,是否在.NET中处理应用程序的停止请求



在.NET中,当您对windows服务进行编程时,您可以处理外部请求以停止,这样您就可以推迟并完成一些处理,而不是直接终止进程。

当计划任务试图停止控制台应用程序时,是否有类似的情况?任务调度器中的设置具有";如果运行中的任务在被请求时没有停止,则强制其停止";"设置"选项卡下的选项。对我来说,这意味着它首先请求停止进程,并在终止它之前给它一个机会。我确实看到一些内容引用了任务调度程序,如果应用程序在3分钟后没有完成,它就会终止它。

如果.NET中没有内置的功能来处理停止请求,那么我们是否可以利用Windows API外部功能,如Windows消息等?

根据此处的描述:https://learn.microsoft.com/en-us/windows/win32/api/taskschd/nf-taskschd-itasksettings-get_allowhardterminate

获取或设置一个布尔值,该值指示任务计划程序服务可以使用TerminateProcess终止任务。服务将尝试通过发送WM_close通知来关闭正在运行的任务,如果任务没有响应,则只有当此属性设置为true时,任务才会终止。

Task Scheduler将首先向程序的主窗口发送一条WM_CLOSE消息。如果这不起作用;"硬终止";,则该过程将使用CCD_ 2来终止。

对于控制台程序,任务调度程序将尝试关闭其控制台窗口。默认情况下,当控制台窗口关闭时,或者当按下Ctrl+C或Ctrl+Break时,控制台程序将立即终止。如果要处理这些事件,可以使用SetConsoleCtrlHandler添加一个处理程序函数。

.NET有Console.CancelKeyPress事件,它可以处理Ctrl+C和Ctrl+Break按下,并且它实际上在后台使用了SetConsoleCtrlHandler。但是,它只处理CTRL_C_EVENTCTRL_BREAK_EVENT,因此关闭控制台窗口等事件仍然不被处理。

下面是我的示例,它使用SetConsoleCtrlHandler来处理控制台应用程序中的退出事件。

using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace TestConsoleExit
{
internal class Program
{
enum CtrlType : int
{
CtrlCEvent,
CtrlBreakEvent,
CtrlCloseEvent,
CtrlLogoffEvent,
CtrlShutdownEvent
}
delegate bool HandlerRoutine(CtrlType dwCtrlType);
[DllImport("kernel32")]
static extern bool SetConsoleCtrlHandler(HandlerRoutine HandlerRoutine, bool Add);
static void Main(string[] args)
{
SetConsoleCtrlHandler(ExitHandler, true);
for (; ; )
{
Console.ReadLine();
}
}
static bool ExitHandler(CtrlType ctrlType)
{
Console.WriteLine();
Console.WriteLine(ctrlType);
if (ctrlType == CtrlType.CtrlCEvent || ctrlType == CtrlType.CtrlBreakEvent)
{
// you can return true to cancel exiting when handling Ctrl+C and Ctrl+Break
return true;
}
else
{
// you cannot cancel exiting in other events, but you can delay it for a few seconds
Thread.Sleep(3000);
return false;
}
}
}
}

请注意,任务调度器只给程序大约一秒钟的时间来完成对WM_CLOSECTRL_CLOSE_EVENT的处理。一秒钟后,您的程序将终止。

最新更新