前言
开发应用程序时,会遇到需要程序能够开机自启的需求。本文介绍两种方式,来实现这一目的。
一、注册表
一般来说,遇到这种需求,我们首先想到的就是将应用程序的路径写到注册表来实现:
void setAutoStart(bool enable) {
QString appName = QApplication::applicationName(); // 程序名称
QString appPath = QApplication::applicationFilePath().replace("/","\\"); // 程序路径
QSettings *reg = new QSettings("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
if (enable) {
QString val = reg->value(appName).toString(); // 如果此键不存在,则返回的是空字符串
if (val != appPath) {
reg->setValue(appName,appPath);
}
} else {
reg->remove(appName);
}
reg->deleteLater();
}
代码中实现了将应用程序路径写到注册表,同时也实现了从注册表删除该应用程序路径。如果程序是64位的,会写到:
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
若程序是32位的,则会被系统自动映射到:
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run
正常情况下,这样就实现了该应用程序的开机自启动。但是,如果应用程序是带有”盾牌“的(即UAC执行级别为requireAdministrator),如下图所示:
这时通过写注册表的方式,可能会出现开机没有自启动的问题。要解决这个问题,可以使用接下来要介绍的通过任务计划的方式。
二、任务计划
通过 Win+R 键,输入 taskschd.msc 可以打开任务计划界面:
只要我们实现将应用程序写到这里,即可实现开机自启。代码如下:
void setAutoStart(bool enable) {
QString appName = QApplication::applicationName(); // 程序名称
QString appPath = QApplication::applicationFilePath().replace("/","\\"); // 程序路径
appPath = "\"" + appPath + "\""; // 路径要加引号
QStringList arguments;
if (enable) {
arguments << "/create"
<< "/tn" << appName
<< "/tr" << appPath
<< "/sc" << "onlogon"
<< "/rl" << "highest"
<< "/f";
} else {
arguments << "/delete"
<< "/tn" << appName
<< "/f";
}
QProcess process;
process.start("schtasks", arguments);
process.waitForFinished();
if (process.exitCode() != 0) {
qDebug() << QString::fromLocal8Bit(process.readAllStandardError());
}
}
这样就能在任务计划程序库中看到我们的应用程序了。双击它可以看到属性相关信息:
看到其中这两项是默认勾选的:”如果任务运行时间超过以下时间,停止任务“和”如果请求后任务还在运行,强行将其停止“,我们要将这两项改成不勾选,所以最终的代码如下:
void setAutoStart(bool enable) {
QString appName = QApplication::applicationName(); // 程序名称
QString appPath = QApplication::applicationFilePath().replace("/","\\"); // 程序路径
appPath = "\"" + appPath + "\""; // 路径要加引号
QStringList arguments;
if (enable) {
arguments << "/create"
<< "/tn" << appName
<< "/tr" << appPath
<< "/sc" << "onlogon"
<< "/rl" << "highest"
<< "/f";
} else {
arguments << "/delete"
<< "/tn" << appName
<< "/f";
}
QProcess process;
process.start("schtasks", arguments);
process.waitForFinished();
if (process.exitCode() != 0) {
qDebug() << QString::fromLocal8Bit(process.readAllStandardError());
} else {
if (enable) {
// 配置计划任务的设置:1、禁用任务的执行时间限制 2、禁止系统强制终止任务
QString psCommand = R"(
$task = Get-ScheduledTask -TaskName ")" + appName + R"(";
$task.Settings.ExecutionTimeLimit = "PT0S";
$task.Settings.AllowHardTerminate = $false;
Set-ScheduledTask $task;)";
arguments.clear();
arguments << "-ErrorAction" << "Stop" << "-Command" << psCommand;
process.start("powershell", arguments);
process.waitForFinished();
if (process.exitCode() != 0) {
qDebug() << QString::fromLocal8Bit(process.readAllStandardError());
}
}
}
}
如果想要修改其他属性信息,也可以通过查阅相关资料来进行,这里不再赘述。