1. 程式人生 > >如何實現程式的重新啟動(windows環境下)

如何實現程式的重新啟動(windows環境下)

背景:

在遊戲程式的開發中,經常會碰到這樣的情況,運行遊戲更新程式後需要重新啟動更新程式,在遊戲內修改視訊等相關設定後需要重新啟動遊戲程式,這樣的操作該如何實現呢?

解決方案:

一種解決方案是通過等待來啟動新的程式,但是這樣的實現方式在極端情況下會出現問題,假設某遊戲程式每次在一個物理機上只允許啟動一個程序,如果關閉舊的程序因為一些原因而造成延遲,那麼啟動新的程序時會失敗,試想遊戲更新程式結束後,提示玩家遊戲將重啟,而遊戲並沒有重啟,這種體驗是相當糟糕的。

另一種解決方案,為了保證程式A關閉後與程式B再開啟,在windows環境下有一種很常用的方法——批處理,由於批處理中的方法都是順序執行的,關閉程式A開啟程式B的操作可以保證同步執行,將殺死程序與啟動程序的功能寫入批處理,在需要重啟的地方,呼叫API執行該批處理即可。

/*
author:	coffeecat
brief : All the code below has been tested.
date  :	2014/10/21
*/
#include "stdafx.h"
#include <iostream>

using namespace std;

void Restart()  
{  
	FILE* pf;
	::DeleteFile(L"restart.cmd");							//確保刪除上次遺留下的批處理檔案
	errno_t err = ::_wfopen_s(&pf, L"restart.cmd", L"w");	//“w”表示開啟一個空檔案以進行寫入。如果該檔案存在,其內容將被銷燬。
	if( err == 0 )											//restart.cmd不存在時,err == 0
	{  
		char szExeName[1024];  
		GetModuleFileNameA( NULL, szExeName, 1024);			//獲取程序的名稱
		fprintf( pf, "@echo off\n:a\n taskkill /f /im restart.exe \n start \"\" \"%s\" \ndel %%0", szExeName);  
                //restart.exe為需要重啟的程序名稱
		//taskkill /f(指定要強行終止的程序) /im( image name 可以理解為指定要終止的程序名名稱)
		//%%0在批處理中表示%0,del %%0(刪除批處理自身)
		fclose( pf );  
	}  
	else  
	{  
		cout << "can not open restart.cmd" << endl;  
	}  

	STARTUPINFO si;  
	PROCESS_INFORMATION pi;  
	ZeroMemory( &si, sizeof si );  
	ZeroMemory( &pi, sizeof pi );  
	si.cb = sizeof si;  
	si.dwFlags = STARTF_USESHOWWINDOW;  
	si.wShowWindow = SW_HIDE;  
	TCHAR winSysDir[1024];  
	ZeroMemory( winSysDir, sizeof winSysDir );  
	::GetSystemDirectory( winSysDir, 1024 );  
	std::wstring appName = winSysDir;  
	appName += L"\\cmd.exe";  
	BOOL bRet = CreateProcess(  
		appName.c_str(),  
		L"/c restart.cmd",					//執行字串指定的命令然後終斷
		NULL,  
		NULL,  
		FALSE,  
		0,  
		NULL,  
		NULL,  
		&si,  
		&pi);  

	if ( bRet == FALSE )  
	{  
		int err = GetLastError();  
		cout << "can not restart test, error code:" << err << endl;  
	}  
} 

int main()
{
	int input, curPid;
	curPid = GetCurrentProcessId();
	cout << "Current process Id:" << curPid << endl;
	cout << "Do you need to restart the program ? (input 1 for restart, else do not restart)" << endl;
	cin >> input;
	if (input == 1)
	{
		Restart();
	}
	system("pause");
	return 0;
}

執行上述程式碼,輸入1會關閉當前程序,重新開啟一個新的程序。

執行結果:

以下為程序A,待輸入1後會被關閉。

以下為程序B,程序A被關閉後,程序B將會被建立。

可以看到兩個程序的PID不同,符合預期。