只要我不学习,就不会遇到困难
本文介绍在Qt中通过QProcess灵活注册Windows定时任务,以注册每个星期的星期五、星期天下午六点创建文件夹为例.
一、准备工作
Windows上注册定时任务一般使用schtasks命令,可以参考官网文档:schtasks.exe,但是使用schtasks提供的语法不是一个很好的选择(组合太复杂,很难定制灵活的定时任务)。
取巧方式:schtasks.exe /create /tn [taskname] /xml [xmlpath]
,schtasks提供通过xml文本注册定时任务,只需要提前定义好xml文本,即可轻松注册定时任务。
二、定时任务XML
打开计算机管理(本地)-任务计划程序-任务计划程序库,可以查看本机的Windows定时任务,通过Windows提供的界面注册一个定时任务,然后将其导出成xml定时任务文件。以下是我导出的一个模板,触发器为每周执行的XML文件,大家可以根据需要自行导出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| <?xml version="1.0" encoding="UTF-16"?> <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Date></Date> <Author></Author> <Description></Description> <URI></URI> </RegistrationInfo> <Triggers> <CalendarTrigger> <StartBoundary></StartBoundary> <Enabled>true</Enabled> <ScheduleByWeek> <DaysOfWeek> <Sunday/> <Monday/> <Tuesday/> <Wednesday/> <Thursday/> <Friday/> <Saturday/> </DaysOfWeek> <WeeksInterval></WeeksInterval> </ScheduleByWeek> </CalendarTrigger> </Triggers> <Principals> <Principal id="Author"> <LogonType>InteractiveToken</LogonType> <RunLevel>LeastPrivilege</RunLevel> </Principal> </Principals> <Settings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <StartWhenAvailable>false</StartWhenAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <IdleSettings> <Duration>PT10M</Duration> <WaitTimeout>PT1H</WaitTimeout> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Enabled>true</Enabled> <Hidden>false</Hidden> <RunOnlyIfIdle>false</RunOnlyIfIdle> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>PT72H</ExecutionTimeLimit> <Priority>7</Priority> </Settings> <Actions Context="Author"> <Exec> <Command></Command> <Arguments></Arguments> </Exec> </Actions> </Task>
|
部分参数含义:
URI:任务名称
Description:任务描述
WeeksInterval:每隔多少星期执行
Command:bat或exe执行程序的绝对路径
Arguments:程序参数,多个参数逗号分隔
Date: 任务执行时间,格式:yyyy-MM-ddThh:mm:ss
Author:任务创建者,可通过QDir获取:QDir::home().dirName()
DaysOfWeek:定义星期几执行定时任务,比如定义星期一、三执行:<DaysOfWeek><Monday/><Wednesday/></DaysOfWeek>
UserId:计算机ID,这里我将其删掉了,是根据不同机器自行生成的,如果保留此模板就不能在其它机器上使用,算一个坑(已踩)
三、创建文件夹bat文件
bat文件接收外部传参,bat文件绝对路径对应Command,参数对应Arguments,这里以创建文件夹举例,大家可以根据需要自行定制bat文件.
1 2 3 4 5
| @echo off set dir=%1% set folder=%2% set datetime=%Date:~0,4%%Date:~5,2%%Date:~8,2%_%time:~0,2%%time:~3,2% md "%dir%/%folder%_%datetime%"
|
备注:bat文件常规最多接收9个外部传参,坑.
四、注册定时任务
使用Qt的QProcess,定时注册每个星期的星期五、星期日执行创建文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| QString strXmlPath = "F:/schtasks.xml"; QString strTempXml = "F:/schtasks_temp.xml"; QString strCommand = "F:/schtasks.bat"; QString strTaskName = "task"; QString strTargetTime = "2021-01-05T18:00:00"; QStringList arguments{"F:/", "ss"};
QString strXML; QFile file(strXmlPath); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QDomDocument doc; if (!doc.setContent(&file)) { file.close(); return; } strXML = doc.toString(); file.close(); }
strXML.remove("<Monday/>"); strXML.remove("<Tuesday/>"); strXML.remove("<Wednesday/>"); strXML.remove("<Thursday/>"); strXML.remove("<Saturday/>"); strXML.replace("<WeeksInterval/>", "<WeeksInterval>1</WeeksInterval>");
strXML.replace("<URI/>", "<URI>" + strTaskName + "</URI>"); strXML.replace("<Date/>", "<Date>" + strTargetTime + "</Date>"); strXML.replace("<Author/>", "<Author>" + QDir::home().dirName() + "</Author>"); strXML.replace("<StartBoundary/>", "<StartBoundary>" + strTargetTime + "</StartBoundary>");
strXML.replace("<Command/>", "<Command>" + strCommand + "</Command>"); strXML.replace("<Arguments/>", "<Arguments>" + arguments.join(",") + "</Arguments>");
QFile tempfile(strTempXml); if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { QString strUnicode = QTextCodec::codecForName("gbk")->toUnicode(strXML.toLocal8Bit().data()); QByteArray data = QTextCodec::codecForName("gbk")->fromUnicode(strUnicode); tempfile.write(data); tempfile.close(); }
QProcess process; process.setProgram("C://Windows//System32//schtasks.exe"); QStringList argument; argument << "/create" << "/tn" << strTaskName << "/xml" << strTempXml; process.setArguments(argument); process.start(); process.waitForStarted(); process.waitForFinished(); QString strRes = QString::fromLocal8Bit(process.readAllStandardOutput());
|
实际工作是针对MySQL、Oracle等数据源做定时任务管理,支持每天、每周、每月创建定时备份任务,业务代码没有这么粗糙. 大家可以根据这个例子,使用不同XML文件拓展定时任务,定制bat执行文件实现业务.
五、schtasks实用命令
以下均是cmd命令,可以使用QProcess实现程序调用,根据readAllStandardOutput获取返回值判断结果.
1.强制删除定时任务
1 2
| schtasks /delete /tn name /f
|
2.修改定时任务状态(可用、禁用)
1 2 3
| schtasks /change /tn name /enable schtasks /change /tn name /disable
|
3.查询定时任务是否已被注册,根据返回参数判断
1 2
| schtasks /query /tn name
|
4.查询某一个定时任务所有信息,以list形式返回
1 2
| schtasks /tn name /fo list /v
|
gitee工程地址: https://gitee.com/qiangutime/qt-project/tree/master/schtasks