返回首页
EN
H7 / SECURITY RESEARCH NOTES

通过COM组件ITaskService创建计划任务实现开机自启动

环境说明

IPHOSTNAMENOTE
N/AWin10测试机

相关脚本

内容下载
powershell脚本和exe可执行文件点击下载

实现逻辑

实现原理:

  • 使用Windows Shell编程实现创建任务计划,所以会涉及COM组件相关知识,整个程序的逻辑概括为 3 个部分,分别是:初始化操作、创建任务计划以及删除任务计划。

初始化操作

  • 初始化操作的目的就是获取 ITaskService 对象以及 ITaskFolder 对象,我们创建任务计划,主要是对这两个指针进行操作。具体流程是:
1.首先初始化COM接口环境,因为我们接下来会使用到COM组件
2.然后,创建 ITaskService 对象,并连接到任务服务上
3.接着,从 ITaskService 对象中获取 ITaskFolder 对象
  • 这样,初始化操作就完成了,接下来就是直接使用ITaskService对象以及 ITaskFolder 对象进行操作了。

创建任务计划

  • 现在,解析下任务计划的具体创建过程:
1.首先,从 ITaskService 对象中创建一个任务定义对象 ITaskDefinition,用来来创建任务
2.接着,就是开始对任务定义对象 ITaskDefinition进行设置:
	(1)设置注册信息,包括设置作者的信息
	(2)设置主体信息,包括登陆类型、运行权限
	(3)设置设置信息,包括设置在使用电池运行时是否停止、在使用电池是是否允许运行、是否允许手动运行、是否设置多个实例
	(4)设置操作信息,包括启动程序,并设置运行程序的路径和参数
	(5)设置触发器信息,包括用户登录时触发
3.最后,使用 ITaskFolder 对象根据任务定义对象 ITaskDefinition的设置,注册任务计划
  • 这样,任务计划创建的操作就完成了,只要满足设置的触发条件,那么就会启动指定程序。

删除任务计划

  • ITaskFolder 对象存储着已经注册成功的任务计划的信息,我们只需要将任务计划的名称传入其中,调用DeleteTask接口函数,就可以删除指定的任务计划了。

代码实现

创建任务计划的初始化

CMyTaskSchedule::CMyTaskSchedule(void)
{
    m_lpITS = NULL;
    m_lpRootFolder = NULL;
    // 初始化COM
    HRESULT hr = ::CoInitialize(NULL);
    if(FAILED(hr))
    {
        ShowError("CoInitialize", hr);
    }
    // 创建一个任务服务(Task Service)实例
    hr = ::CoCreateInstance(CLSID_TaskScheduler,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_ITaskService,
        (LPVOID *)(&m_lpITS));
    if(FAILED(hr))
    {
        ShowError("CoCreateInstance", hr);
    }
    // 连接到任务服务(Task Service)
    hr = m_lpITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    if(FAILED(hr))
    {
        ShowError("ITaskService::Connect", hr);
    }
    // 获取Root Task Folder的指针,这个指针指向的是新注册的任务
    hr = m_lpITS->GetFolder(_bstr_t("\\"), &m_lpRootFolder);
    if(FAILED(hr))
    {
        ShowError("ITaskService::GetFolder", hr);
    }
}

创建任务计划

BOOL CMyTaskSchedule::NewTask(char *lpszTaskName, char *lpszProgramPath, char *lpszParameters, char *lpszAuthor)
{
    if(NULL == m_lpRootFolder)
    {
        return FALSE;
    }
    // 如果存在相同的计划任务,则删除
    Delete(lpszTaskName);
    // 创建任务定义对象来创建任务
    ITaskDefinition *pTaskDefinition = NULL;
    HRESULT hr = m_lpITS->NewTask(0, &pTaskDefinition);
    if(FAILED(hr))
    {
        ShowError("ITaskService::NewTask", hr);
        return FALSE;
    }
    /* 设置注册信息 */
    IRegistrationInfo *pRegInfo = NULL;
    CComVariant variantAuthor(NULL);
    variantAuthor = lpszAuthor;
    hr = pTaskDefinition->get_RegistrationInfo(&pRegInfo);
    if(FAILED(hr))
    {
        ShowError("pTaskDefinition::get_RegistrationInfo", hr);
        return FALSE;
    }
    // 设置作者信息
    hr = pRegInfo->put_Author(variantAuthor.bstrVal);
    pRegInfo->Release();
    /* 设置登录类型和运行权限 */
    IPrincipal *pPrincipal = NULL;
    hr = pTaskDefinition->get_Principal(&pPrincipal);
    if(FAILED(hr))
    {
        ShowError("pTaskDefinition::get_Principal", hr);
        return FALSE;
    }
    // 设置登录类型
    hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
    // 设置运行权限
    // 最高权限
    hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);  
    pPrincipal->Release();
    /* 设置其他信息 */
    ITaskSettings *pSettting = NULL;
    hr = pTaskDefinition->get_Settings(&pSettting);
    if(FAILED(hr))
    {
        ShowError("pTaskDefinition::get_Settings", hr);
        return FALSE;
    }
    // 设置其他信息
    hr = pSettting->put_StopIfGoingOnBatteries(VARIANT_FALSE);
    hr = pSettting->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
    hr = pSettting->put_AllowDemandStart(VARIANT_TRUE);
    hr = pSettting->put_StartWhenAvailable(VARIANT_FALSE);
    hr = pSettting->put_MultipleInstances(TASK_INSTANCES_PARALLEL);
    pSettting->Release();
    /* 创建执行动作 */
    IActionCollection *pActionCollect = NULL;
    hr = pTaskDefinition->get_Actions(&pActionCollect);
    if(FAILED(hr))
    {
        ShowError("pTaskDefinition::get_Actions", hr);
        return FALSE;
    }
    IAction *pAction = NULL;
    // 创建执行操作
    hr = pActionCollect->Create(TASK_ACTION_EXEC, &pAction);
    pActionCollect->Release();
    /* 设置执行程序路径和参数 */
    CComVariant variantProgramPath(NULL);
    CComVariant variantParameters(NULL);
    IExecAction *pExecAction = NULL;
    hr = pAction->QueryInterface(IID_IExecAction, (PVOID *)(&pExecAction));
    if(FAILED(hr))
    {
        pAction->Release();
        ShowError("IAction::QueryInterface", hr);
        return FALSE;
    }
    pAction->Release();
    // 设置程序路径和参数
    variantProgramPath = lpszProgramPath;
    variantParameters = lpszParameters;
    pExecAction->put_Path(variantProgramPath.bstrVal);
    pExecAction->put_Arguments(variantParameters.bstrVal);
    pExecAction->Release();
    /* 创建触发器,实现用户登陆自启动 */
    ITriggerCollection *pTriggers = NULL;
    hr = pTaskDefinition->get_Triggers(&pTriggers);
    if (FAILED(hr))
    {
        ShowError("pTaskDefinition::get_Triggers", hr);
        return FALSE;
    }
    // 创建触发器
    ITrigger *pTrigger = NULL;
    hr = pTriggers->Create(TASK_TRIGGER_LOGON, &pTrigger);
    if (FAILED(hr))
    {
        ShowError("ITriggerCollection::Create", hr);
        return FALSE;
    }
    /* 注册任务计划  */
    IRegisteredTask *pRegisteredTask = NULL;
    CComVariant variantTaskName(NULL);
    variantTaskName = lpszTaskName;
    hr = m_lpRootFolder->RegisterTaskDefinition(variantTaskName.bstrVal,
        pTaskDefinition,
        TASK_CREATE_OR_UPDATE,
        _variant_t(),
        _variant_t(),
        TASK_LOGON_INTERACTIVE_TOKEN,
        _variant_t(""),
        &pRegisteredTask);
    if(FAILED(hr))
    {
        pTaskDefinition->Release();
        ShowError("ITaskFolder::RegisterTaskDefinition", hr);
        return FALSE;
    }
    pTaskDefinition->Release();
    pRegisteredTask->Release();
    return TRUE;
}

删除任务计划

BOOL CMyTaskSchedule::Delete(char *lpszTaskName)
{
    if(NULL == m_lpRootFolder)
    {
        return FALSE;
    }
    CComVariant variantTaskName(NULL);
    variantTaskName = lpszTaskName;
    HRESULT hr = m_lpRootFolder->DeleteTask(variantTaskName.bstrVal, 0);
    if(FAILED(hr))
    {
        return FALSE;
    }
    return TRUE;
}

测试程序

  • main 函数中调用上述封装好的函数,进行测试。main 函数为:
int _tmain(int argc, _TCHAR* argv[])
{
	CMyTaskSchedule task;
	BOOL bRet = FALSE;

	bRet = task.NewTask("520", "C:\\520.exe", "", "");
	if (FALSE == bRet)
	{
		printf("Create Task Schedule Error!\n");
	}

	printf("Create Task Schedule OK!\n");
	system("pause");

	bRet = task.Delete("520");
	if (FALSE == bRet)
	{
		printf("Delete Task Schedule Error!\n");
	}

	printf("Delete Task Schedule OK!\n");
	system("pause");
	return 0;
}
  • 运行程序,提示任务计划创建成功。

  • 打开任务计划列表查看,发现”520“任务计划成功创建。