概述:Qt 实现应用程序重启的多种方法。
0x01、应用内重启
方法一:使用 QProcess::startDetached
#include <QApplication>
#include <QProcess>
#include <QDir>
void restartApplication()
{
QString program = QApplication::applicationFilePath();
QStringList arguments = QApplication::arguments();
QString workingDirectory = QDir::currentPath();
QProcess::startDetached(program, arguments, workingDirectory);
QApplication::exit();
}方法二:使用 QCoreApplication
void restartApp()
{
qApp->quit();
QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
}方法三:带延迟重启
#include <QTimer>
void restartWithDelay(int delayMs = 1000)
{
QTimer::singleShot(delayMs, []() {
QProcess::startDetached(QApplication::applicationFilePath());
QApplication::exit();
});
}0x02、重启并提权
请求管理员权限重启(Windows)
#include <windows.h>
#include <shellapi.h>
void restartAsAdmin()
{
QString program = QApplication::applicationFilePath();
SHELLEXECUTEINFOW sei;
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.lpVerb = L"runas"; // 请求管理员权限
sei.lpFile = reinterpret_cast<const WCHAR*>(program.utf16());
sei.nShow = SW_SHOWNORMAL;
if (ShellExecuteExW(&sei)) {
QApplication::exit();
}
}0x03、系统重启
重启计算机(需要管理员权限)
#include <windows.h>
bool rebootComputer()
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// 获取当前进程令牌
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
return false;
}
// 获取关机特权
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// 启用特权
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
// 重启系统
if (!ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0)) {
CloseHandle(hToken);
return false;
}
CloseHandle(hToken);
return true;
}0x04、完整的重启管理器
// restartmanager.h
#ifndef RESTARTMANAGER_H
#define RESTARTMANAGER_H
#include <QObject>
#include <QProcess>
class RestartManager : public QObject
{
Q_OBJECT
public:
enum RestartType {
NormalRestart, // 普通重启
AdminRestart, // 管理员权限重启
SystemReboot // 系统重启
};
static RestartManager* instance();
void restart(RestartType type = NormalRestart, int delayMs = 0);
void scheduleRestart(int seconds);
void cancelScheduledRestart();
private:
explicit RestartManager(QObject *parent = nullptr);
signals:
void restartRequested(RestartType type);
private:
static RestartManager *m_instance;
};
#endif
// restartmanager.cpp
#include "restartmanager.h"
#include <QTimer>
#include <QApplication>
#include <QDir>
RestartManager *RestartManager::m_instance = nullptr;
RestartManager::RestartManager(QObject *parent) : QObject(parent)
{
}
RestartManager* RestartManager::instance()
{
if (!m_instance) {
m_instance = new RestartManager();
}
return m_instance;
}
void RestartManager::restart(RestartType type, int delayMs)
{
auto doRestart = [this, type]() {
emit restartRequested(type);
switch (type) {
case NormalRestart:
{
QString program = QApplication::applicationFilePath();
QStringList args = QApplication::arguments();
args.removeFirst(); // 移除程序名
QProcess::startDetached(program, args, QDir::currentPath());
QApplication::exit();
}
break;
case AdminRestart:
#ifdef Q_OS_WIN
{
QString program = QApplication::applicationFilePath();
SHELLEXECUTEINFOW sei;
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.lpVerb = L"runas";
sei.lpFile = reinterpret_cast<const WCHAR*>(program.utf16());
sei.nShow = SW_SHOWNORMAL;
if (ShellExecuteExW(&sei)) {
QApplication::exit();
}
}
#endif
break;
case SystemReboot:
#ifdef Q_OS_WIN
rebootComputer();
#endif
break;
}
};
if (delayMs > 0) {
QTimer::singleShot(delayMs, doRestart);
} else {
doRestart();
}
}
void RestartManager::scheduleRestart(int seconds)
{
QTimer::singleShot(seconds * 1000, [this]() {
restart(NormalRestart);
});
}
void RestartManager::cancelScheduledRestart()
{
// 取消所有待处理的定时器
// 实际实现需要保存 QTimer 指针
}0x05、使用示例
#include "restartmanager.h"
// 普通重启
void MainWindow::onRestartClicked()
{
RestartManager::instance()->restart(RestartManager::NormalRestart);
}
// 以管理员权限重启
void MainWindow::onAdminRestartClicked()
{
RestartManager::instance()->restart(RestartManager::AdminRestart);
}
// 延迟重启
void MainWindow::onDelayedRestartClicked()
{
RestartManager::instance()->restart(RestartManager::NormalRestart, 3000); // 3秒后重启
}
// 定时重启
void MainWindow::onScheduleRestartClicked()
{
RestartManager::instance()->scheduleRestart(60); // 60秒后重启
}0x06、注意事项
- 数据保存:重启前确保保存所有未保存的数据
- 资源释放:正确关闭文件、网络连接等资源
- 状态恢复:考虑保存应用状态,重启后恢复
- 权限检查:管理员权限重启可能触发 UAC 提示
更新时间: 2026-03-27