- 介绍
应用程序需要进行守护,又不想另外运行一个软件去实时监测应用程序是否退出了,退出就重启。在Windows上可以利用任务计划程序,达到守护进程的作用。
- 创建任务计划
在nsis脚本中可以直接使用schtasks命令来创建任务计划,以下是每分钟检测一次的脚本。
nsExec::ExecToLog 'schtasks /create /tn "${PRODUCT_NAME}" /tr "\"$INSTDIR\ILink.exe\" -schtasks" /sc MINUTE /mo 1 /f' ;创建计划任务
- 问题
使用schtasks命令行创建的任务计划,会在笔记本电脑未接通电源的情况下失效。失效原因为,任务计划中的条件项中的电源条件导致了失效
- 解决方案
schtasks命令无法修改电源选项,故使用C++制作了一个小程序由nsis脚本中调用来关闭电源条件。
以下是C++实现代码部分:
// SQTool.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _WIN32_DCOM
#include <iostream>
#include<comdef.h>
#include<wincred.h>
#include<taskschd.h>
#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsupp.lib")
#pragma comment(lib, "credui.lib")
using namespace std;
int wmain(int argc, WCHAR** argv)
{
if (argc <= 1)
{
std::cout << "请输入正确的参数" << std::endl;
return 1;
}
WCHAR* taskName = argv[1];
std::wcout << L"任务名称为:" << taskName << std::endl;
std::cout << "开始修改条件->电源-[只有在计算机使用交流电时才启动此任务]-[如果计算机改用电池电源,则停止]" << std::endl;
std::cout << "设置->如果任务运行时间超过以下时间,停止任务" << std::endl;
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr))
{
std::cout << "CoInitializeEx failed:" << hr << std::endl;
return 1;
}
hr = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
0,
NULL);
if (FAILED(hr))
{
std::cout << "CoInitializeSecurity failed:" << hr << std::endl;
return 1;
}
LPCWSTR wszTaskName = taskName;
ITaskService* pService = nullptr;
hr = CoCreateInstance(CLSID_TaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskService,
(void**)&pService);
if (FAILED(hr))
{
std::cout << "Failed to create an instance of ITaskService:" << hr << std::endl;
return 1;
}
hr = pService->Connect(_variant_t(), _variant_t(),
_variant_t(), _variant_t());
if (FAILED(hr))
{
std::cout << "ITaskService:Connect failed:" << hr << std::endl;
pService->Release();
CoUninitialize();
return 1;
}
ITaskFolder* pRootFolder = nullptr;
hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
if (FAILED(hr))
{
std::cout << "Canot get root folder pointer:" << hr << std::endl;
pService->Release();
CoUninitialize();
return 1;
}
IRegisteredTask* pRegisteredTask = nullptr;
hr = pRootFolder->GetTask(taskName, &pRegisteredTask);
if (FAILED(hr))
{
std::cout << "GetTask fail:" << hr << std::endl;
return 1;
}
ITaskDefinition* pTaskDefinition = nullptr;
hr = pRegisteredTask->get_Definition(&pTaskDefinition);
if (FAILED(hr))
{
std::cout << "get_Definition fail:" << hr << std::endl;
return 1;
}
ITaskSettings* pTaskSettings = nullptr;
hr = pTaskDefinition->get_Settings(&pTaskSettings);
if (FAILED(hr))
{
std::cout << "get_Settings fail:" << hr << std::endl;
return 1;
}
pTaskSettings->put_DisallowStartIfOnBatteries(false);
pTaskSettings->put_StopIfGoingOnBatteries(false);
pTaskSettings->put_ExecutionTimeLimit(_bstr_t(L"PT0H"));
hr = pRootFolder->RegisterTaskDefinition(
_bstr_t(wszTaskName),
pTaskDefinition,
TASK_CREATE_OR_UPDATE,
_variant_t(),
_variant_t(),
TASK_LOGON_INTERACTIVE_TOKEN,
_variant_t(L""),
&pRegisteredTask);
if (FAILED(hr))
{
std::cout << "RegisterTaskDefinition fail:" << hr << std::endl;
return 1;
}
pTaskSettings->Release();
pTaskDefinition->Release();
pRegisteredTask->Release();
pRootFolder->Release();
pService->Release();
std::cout << "设置结束" << std::endl;
}
- 参考文档
文档