首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ Builder 程式自我重啟的簡潔實作方法

     編輯:關於C++

前言

應用程式有時需要自我重啟(如更新完成、設定變更需重載、異常恢復)。在 C++ Builder 中,利用 Windows API CreateProcess 啟動自身新執行個體,然後結束目前程序,即可實現乾淨的重啟。本文提供最小化、可直接套用的實作碼。

一、核心原理

  1. 主程式進入點(WinMain)結束前,檢查全域旗標 g_bIsRunAgain
  2. 若為真,呼叫 CreateProcess 啟動同一執行檔(Application->ExeName)
  3. 目前程序正常結束,新程序接管執行

二、完整程式碼實作

1. 專案主檔 (Project1.cpp)

#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
    try {
        Application->Initialize();
        Application->CreateForm(__classid(TfrmMain), &frmMain);
        Application->Run();
    }
    catch (Exception &exception) {
        Application->ShowException(&exception);
    }
    catch (...) {
        try { throw Exception(""); }
        catch (Exception &exception) {
            Application->ShowException(&exception);
        }
    }

    // === 自我重啟邏輯 ===
    if (g_bIsRunAgain) {
        AnsiString exePath = Application->ExeName;
        STARTUPINFO si = {0};
        PROCESS_INFORMATION pi = {0};
        si.cb = sizeof(STARTUPINFO);

        if (!::CreateProcess(
                exePath.c_str(),  // 應用程式名稱
                NULL,             // 命令列參數
                NULL, NULL,       // 程序/執行緒安全屬性
                FALSE,            // 不繼承控制代碼
                NORMAL_PRIORITY_CLASS,
                NULL, NULL,       // 環境區塊/當前目錄
                &si, &pi))        // 啟動資訊/程序資訊
        {
            return 0;  // 啟動失敗
        }
        // 可選:CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
    }
    return 0;
}

2. 主視窗標頭檔 (Unit1.h)

// 全域旗標宣告
extern bool g_bIsRunAgain;

class TfrmMain : public TForm {
    // ...
    void __fastcall btnCloseClick(TObject *Sender);
    void __fastcall btnReExecuteClick(TObject *Sender);
};

3. 主視窗實作檔 (Unit1.cpp)

#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;

// 全域旗標定義
bool g_bIsRunAgain = false;
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnCloseClick(TObject *Sender) {
    Close();  // 正常關閉
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnReExecuteClick(TObject *Sender) {
    g_bIsRunAgain = true;  // 設定重啟旗標
    Close();               // 觸發關閉流程,WinMain 會檢查旗標並重啟
}

三、關鍵細節說明

  • 全域旗標:g_bIsRunAgain 需在 WinMain 可見範圍,故置於 Unit1.cpp 並 extern 供標頭檔引用
  • CreateProcess 參數:
    • lpApplicationName:用 Application->ExeName 取得完整執行檔路徑
    • lpCommandLine:NULL 表示使用預設命令列(同原啟動參數)
    • bInheritHandles:FALSE 避免控制代碼洩漏
    • dwCreationFlags:NORMAL_PRIORITY_CLASS 一般優先權
  • 錯誤處理:CreateProcess 失敗時直接返回,不重啟
  • 資源清理:PROCESS_INFORMATION 中的控制代碼若不需等待新程序,應呼叫 CloseHandle 釋放

四、進階變體:帶參數重啟

若需重啟時傳遞參數(如 /restarted 標記):

AnsiString cmdLine = exePath + " /restarted";
if (!::CreateProcess(
        NULL,                   // 模組名稱設 NULL
        cmdLine.c_str(),        // 完整命令列
        NULL, NULL, FALSE,
        NORMAL_PRIORITY_CLASS,
        NULL, NULL, &si, &pi)) { ... }

新程序啟動時可解析 ParamStr(1) 判斷是否為重啟啟動。

五、適用場景

  • 線上更新完成需重載新版本
  • 語言/主題切換需完整重新初始化
  • 嚴重錯誤後嘗試自動恢復
  • 安裝/解除安裝後續操作
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved