如何实现程序的重新启动(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后会被关闭。

如何实现程序的重新启动(windows环境下)

以下为进程B,进程A被关闭后,进程B将会被创建。

如何实现程序的重新启动(windows环境下)

可以看到两个进程的PID不同,符合预期。

如何实现程序的重新启动(windows环境下)

上一篇:ubuntu配置wine


下一篇:装饰类——wpf