VC++创建计划任务的若干方式

1. 创建计划任务的两种方式

计划任务是windows操作系统提供的定时执行程序的方式,可在指定时间、指定时机(开机或用户登录)周期性执行指定程序或命令。

创建计划任务需要管理员权限(过UAC),同时计划任务也将在管理员权限下被执行。

1.1 利用CMD命令行创建计划任务

CMD命令行下有两个命令可以创建计划任务,一个是at 另一个是schtasks

  • at 命令仅在Win7及以下系统有效,支持指定任务的执行时间,支持远程创建计划任务,但不能指定任务在系统启动或用户登录时启动。与schtasks命令相比,其优势是创建计划任务所需的命令比较简单。
  • schtasks支持Windows全系列系统,与at命令相比,可设置的选项更加丰富,能适应更多的应用场景,同时还允许指定任务在系统启动、用户登录甚至是系统闲置时间启动。

1.2 利用COM组件的API编程创建计划任务

本小节内容来自于 https://docs.microsoft.com/en-us/windows/desktop/TaskSchd/tasks

: 通过COM组件创建的计划任务会在C:\windows\Tasks目录下生成一个.OBJ格式的文件,且该计划任务无法通过schtasks命令查询。

1.2.1 几个基本概念
  1. Task对象。一个Task对象就是一个计划任务,Task对象又包括多个组件,具体如下图所示。Task对象至少包含一个Trigger对象和一个Actions对象。
    在这里插入图片描述

  2. Trigger对象定义的是计划任务执行的触发器,详细描述了计划任务的启动时机。

  3. Action对象定义的是计划任务需要执行的具体操作。

  4. Principal定义了执行计划任务需要的安全上下文(Security Context) ,比如指定可执行计划任务的用户。

  5. Setting可以定义计划任务执行时的进程优先级、是否支持一个计划任务有多个实例同时运行等。

  6. Registration Infomation保存的时该计划任务的相关管理信息,例如计划任务的创建者、创建时间等。

  7. Data 计划任务的创建者可以在这里保存计划任务执行所需的额外数据,例如一个XML帮助文档。

1.2.2 Task API

windows提供两个版本的API接口用于创建计划任务,分别是Task Scheduler 1.0Task Scheduler 2.0。以下是两套API的区别。

API 版本系统需求
Task Scheduler 1.0Windows全系列
Task Scheduler 2.0Windows Vista 及以上系统

:Task Scheduler 2.0 允许在远程XP计算机上创建计划任务,但需要将Compatibility属性设置为TASK_COMPATIBILITY_V1。

2. 使用Task Scheduler 1.0 管理计划任务

Task Scheduler 1.0 需要使用ITaskScheduler接口,相关示例代码参见:https://docs.microsoft.com/en-us/windows/desktop/TaskSchd/task-scheduler-1-0-examples

使用Task Scheduler 1.0 的几个注意点:

  1. 必须确保 Task Scheduler service 正在运行。
  2. 当通过接口获取字符串后,必须使用 CoTaskMemFree 进行释放。
  3. 创建和修改计划任务后,必须使用 IPersistFile::Save 对结果进行保存。
  4. 当API使用结束后,需要调用IUnknown::Release 释放所有 IUnknown对象。
  5. 在Task Scheduler 1.0中,每个IScheduledWorkItem类的对象就是一个计划任务;Action直接由IScheduledWorkItem对象的SetApplicationName、和SetParameters函数定义。

2.1 创建计划任务

本小节内容来自于:https://docs.microsoft.com/en-us/windows/desktop/TaskSchd/creating-a-task-using-newworkitem-example

注1:创建计划任务需要管理员权限;

注2:同时需要为计划任务指定一个唯一的名称,如果指定的名称已被使用,则会导致任务创建失败。

注3:通过该方式创建的计划任务会在C:\windows\Tasks目录下创建一个同名的JOB文件。

具体步骤如下:

  1. Call CoInitialize to initialize the COM library and CoCreateInstance to get a Task Scheduler object. (This example assumes that the Task Scheduler service is running.)

  2. Call ITaskScheduler::NewWorkItem to create a new task. (This method returns a pointer to an ITask interface.)

  3. Save the new task to disk by calling IPersistFile::Save. (The IPersistFile interface is a standard COM interface supported by the ITask interface.)

  4. Call ITask::Release to release all resources. (Note that Release is an IUnknown method inherited by ITask.

示例代码:

#include <windows.h>
#include <initguid.h>
#include <ole2.h>
#include <mstask.h>
#include <msterr.h>
#include <objidl.h>
#include <wchar.h>
#include <stdio.h>


int main(int argc, char **argv)
{
  HRESULT hr = S_OK;
  ITaskScheduler *pITS;
  
  
  /
  // Call CoInitialize to initialize the COM library and then 
  // call CoCreateInstance to get the Task Scheduler object. 
  /
  hr = CoInitialize(NULL);
  if (SUCCEEDED(hr))
  {
     hr = CoCreateInstance(CLSID_CTaskScheduler,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_ITaskScheduler,
                           (void **) &pITS);
     if (FAILED(hr))
     {
        CoUninitialize();
        return 1;
     }
  }
  else
  {
     return 1;
  }
  
  
  /
  // Call ITaskScheduler::NewWorkItem to create new task.
  /
  LPCWSTR pwszTaskName;
  ITask *pITask;
  IPersistFile *pIPersistFile;
  pwszTaskName = L"Test Task";
  
  hr = pITS->NewWorkItem(pwszTaskName,         // Name of task
                         CLSID_CTask,          // Class identifier 
                         IID_ITask,            // Interface identifier
                         (IUnknown**)&pITask); // Address of task 
                                                                                                                                                                                            //  interface
  
  
  pITS->Release();                               // Release object
  if (FAILED(hr))
  {
     CoUninitialize();
     fprintf(stderr, "Failed calling NewWorkItem, error = 0x%x\n",hr);
     return 1;
  }
  
  
  /
  // Call IUnknown::QueryInterface to get a pointer to 
  // IPersistFile and IPersistFile::Save to save 
  // the new task to disk.
  /
  
  hr = pITask->QueryInterface(IID_IPersistFile,
                              (void **)&pIPersistFile);
  
  pITask->Release();
  if (FAILED(hr))
  {
     CoUninitialize();
     fprintf(stderr, "Failed calling QueryInterface, error = 0x%x\n",hr);
     return 1;
  }
  
  
  hr = pIPersistFile->Save(NULL,
                           TRUE);
  pIPersistFile->Release();
  if (FAILED(hr))
  {
     CoUninitialize();
     fprintf(stderr, "Failed calling Save, error = 0x%x\n",hr);
     return 1;
  }
  
  
  CoUninitialize();
  printf("Created task.\n");
  return 0;
}

2.2 枚举计划任务

具体步骤:

  1. Call CoInitialize to initialize the COM library and CoCreateInstance to get a Task Scheduler object. (This example assumes that the Task Scheduler service is running.)
  2. Call ITaskScheduler::Enum to get an enumeration object.
  3. Call IEnumWorkItems::Next to retrieve the tasks. (This example tries to retrieve five tasks with each call.)
  4. Process the tasks returned. (This example simply prints the name of each task to the screen.
  5. Release resources. Call CoTaskMemFree to free the memory used for names.

示例代码:

#include <windows.h>
#include <initguid.h>
#include <ole2.h>
#include <mstask.h>
#include <msterr.h>
#include <wchar.h>

#define TASKS_TO_RETRIEVE          5


int main(int argc, char **argv)
{
  HRESULT hr = S_OK;
  ITaskScheduler *pITS;
  
  
  /
  // Call CoInitialize to initialize the COM library and 
  // then call CoCreateInstance to get the Task Scheduler object. 
  /
  hr = CoInitialize(NULL);
  if (SUCCEEDED(hr))
  {
    hr = CoCreateInstance(CLSID_CTaskScheduler,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_ITaskScheduler,
                          (void **) &pITS);
    if (FAILED(hr))
    {
      CoUninitialize();
      return hr;
    }
  }
  else
  {
    return hr;
  }
  
  /
  // Call ITaskScheduler::Enum to get an enumeration object.
  /
  IEnumWorkItems *pIEnum;
  hr = pITS->Enum(&pIEnum);
  pITS->Release();
  if (FAILED(hr))
  {
    CoUninitialize();
    return hr;
  }
  
  /
  // Call IEnumWorkItems::Next to retrieve tasks. Note that 
  // this example tries to retrieve five tasks for each call.
  /
  LPWSTR *lpwszNames;
  DWORD dwFetchedTasks = 0;
  while (SUCCEEDED(pIEnum->Next(TASKS_TO_RETRIEVE,
                                &lpwszNames,
                                &dwFetchedTasks))
                  && (dwFetchedTasks != 0))
  {
    ///
    // Process each task. Note that this example prints the 
    // name of each task to the screen.
    //
    while (dwFetchedTasks)
    {
       wprintf(L"%s\n", lpwszNames[--dwFetchedTasks]);
       CoTaskMemFree(lpwszNames[dwFetchedTasks]);
    }
    CoTaskMemFree(lpwszNames);
  }
  
  pIEnum->Release();
  CoUninitialize();
  return S_OK;
}

2.3 删除计划任务

通过调用接口ITaskScheduler::Delete可以删除指定名称的任务。

2.4 触发器结构体 TASK_TRIGGER

本小节内容来自于https://docs.microsoft.com/en-us/windows/desktop/TaskSchd/trigger-structures

Task Scheduler 1.0使用一个结构体来描述触发器,其结构如下图所示。

在这里插入图片描述

其中,成员TriggerTypeTASK_TRIGGER_TYPE 的枚举类型,而成员Type则是一个TASK_TRIGGER_UNION 类型的结构体。枚举类型TASK_TRIGGER_TYPE用于指定触发器的类型,而根据TriggerType取值的不同,Type的取值可以是 DAILY, WEEKLY, MONTHLYDATE (day of month), and MONTHLYDOW (day of week) 这几种类型之一,Type用于指定触发器何时被触发。

如果TriggerType定义的触发器类型为one-time time-based trigger 或 event-based trigger,那么Type的取值将被忽略。

以下是Type取值与 TRIGGER_TYPE_UNION 所取的结构体类型之间的对应关系图。

在这里插入图片描述

2.5 创建触发器

本小节内容来自于 https://docs.microsoft.com/en-us/windows/desktop/TaskSchd/creating-a-new-trigger

To create a trigger you must use three interfaces. IScheduledWorkItem provides the IScheduledWorkItem::CreateTrigger method for creating the trigger object, ITaskTrigger provides the ITaskTrigger::SetTrigger method for setting the criteria for the trigger, and the COM interface IPersistFile provides a Save method for saving the new trigger to disk.

具体步骤如下

  1. Call CoInitialize to initialize the COM library and CoCreateInstance to get a Task Scheduler object. (This example assumes that the Task Scheduler service is running.)
  2. Call ITaskScheduler::Activate to get the ITask interface of the task object. (Note that this example gets the “Test Task” task.)
  3. Call CreateTrigger to create a trigger object. (Note that CreateTrigger is inherited from IScheduledWorkItem.)
  4. Define a TASK_TRIGGER structure. Note that wBeginDay, wBeginMonth, and wBeginYear members of TASK_TRIGGER must be set to a valid day, month, and year respectively.
  5. Call ITaskTrigger::SetTrigger to set the trigger criteria.
  6. Save the task with the new trigger to disk using IPersistFile::Save. (The IPersistFile interface is a standard COM interface supported by the ITask interface.)
  7. Call Release to release all resources. (Note that Release is an IUnknown method inherited by ITask.)

示例代码如下

#include <windows.h>
#include <winbase.h>
#include <initguid.h>
#include <ole2.h>
#include <mstask.h>
#include <msterr.h>
#include <wchar.h>


int main(int argc, char **argv)
{
  HRESULT hr = S_OK;
  ITaskScheduler *pITS;
  
  
  ///
  // Call CoInitialize to initialize the COM library and then
  // call CoCreateInstance to get the Task Scheduler object.
  ///
  hr = CoInitialize(NULL);
  if (SUCCEEDED(hr))
  {
    hr = CoCreateInstance(CLSID_CTaskScheduler,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_ITaskScheduler,
                          (void **) &pITS);
    if (FAILED(hr))
    {
      CoUninitialize();
      return 1;
    }
  }
  else
  {
     return 1;
  }
  
  
  ///
  // Call ITaskScheduler::Activate to get the Task object.
  ///
  
  ITask *pITask;
  LPCWSTR lpcwszTaskName;
  lpcwszTaskName = L"Test Task";
  hr = pITS->Activate(lpcwszTaskName,
                      IID_ITask,
                      (IUnknown**) &pITask);
  pITS->Release();

  if (FAILED(hr))
  {
     wprintf(L"Failed calling ITaskScheduler::Activate: ");
     wprintf(L"error = 0x%x\n",hr);
     CoUninitialize();
     return 1;
  }
    
  
  
  ///
  // Call ITask::CreateTrigger to create new trigger.
  ///
  
  ITaskTrigger *pITaskTrigger;
  WORD piNewTrigger;
  hr = pITask->CreateTrigger(&piNewTrigger,
                             &pITaskTrigger);
  if (FAILED(hr))
  {
    wprintf(L"Failed calling ITask::CreatTrigger: ");
    wprintf(L"error = 0x%x\n",hr);
    pITask->Release();
    CoUninitialize();
    return 1;
  }
  
  
  //
  // Define TASK_TRIGGER structure. Note that wBeginDay,
  // wBeginMonth, and wBeginYear must be set to a valid 
  // day, month, and year respectively.
  //
  
  TASK_TRIGGER pTrigger;
  ZeroMemory(&pTrigger, sizeof (TASK_TRIGGER));
  
  // Add code to set trigger structure?
  pTrigger.wBeginDay =1;                  // Required
  pTrigger.wBeginMonth =1;                // Required
  pTrigger.wBeginYear =1999;              // Required
  pTrigger.cbTriggerSize = sizeof (TASK_TRIGGER); 
  pTrigger.wStartHour = 13;
  pTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY;
  pTrigger.Type.Daily.DaysInterval = 1;
  
  
  ///
  // Call ITaskTrigger::SetTrigger to set trigger criteria.
  ///
  
  hr = pITaskTrigger->SetTrigger (&pTrigger);
  if (FAILED(hr))
  {
    wprintf(L"Failed calling ITaskTrigger::SetTrigger: ");
    wprintf(L"error = 0x%x\n",hr);
    pITask->Release();
    pITaskTrigger->Release();
    CoUninitialize();
    return 1;
  }
  
  
  ///
  // Call IPersistFile::Save to save trigger to disk.
  ///
  
  IPersistFile *pIPersistFile;
  hr = pITask->QueryInterface(IID_IPersistFile,
                              (void **)&pIPersistFile);
  hr = pIPersistFile->Save(NULL,
                           TRUE);

  if (FAILED(hr))
  {
    wprintf(L"Failed calling IPersistFile::Save: ");
    wprintf(L"error = 0x%x\n",hr);
    pITask->Release();
    pITaskTrigger->Release();
    pIPersistFile->Release();
    CoUninitialize();
    return 1;
  }
  
  wprintf(L"The trigger was created and IPersistFile::Save was \n");
  wprintf(L"called to save the new trigger to disk.\n"); 
  
  
  ///
  // Release resources.
  ///
  
  pITask->Release();
  pITaskTrigger->Release();
  pIPersistFile->Release();
  CoUninitialize();
  return 0;
}

2.6 立刻执行计划任务、中止计划任务执行

参见 https://docs.microsoft.com/en-us/windows/desktop/TaskSchd/task-scheduler-1-0-examples

3. 使用Task Scheduler 2.0 管理计划任务

Be coming soon.

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值