概述: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、注意事项

  1. 数据保存:重启前确保保存所有未保存的数据
  2. 资源释放:正确关闭文件、网络连接等资源
  3. 状态恢复:考虑保存应用状态,重启后恢复
  4. 权限检查:管理员权限重启可能触发 UAC 提示

更新时间: 2026-03-27