{
PROCESS_INFORMATION info
STARTUPINFO startup
char szPath[128]
char *szCmdLine
GetModuleFileName(AfxGetApp()->m_hInstance, szPath, sizeof(szPath))
szCmdLine = GetCommandLine()
GetStartupInfo(&startup)
BOOL bSucc = CreateProcess(szPath, szCmdLine, NULL, NULL,
FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &info)
if(bNormal && bSucc)
{
CWnd *pWnd = AfxGetMainWnd()
if(pWnd != NULL)
{
pWnd->PostMessage(WM_CLOSE, 0, 0)
}
else
ExitProcess(-1)
}
else
ExitProcess(-1)
}
VC实现程序重新启动
在很多情况下,我们需要将当前运行的程序重新运行;此时我们就必须在程序关闭后立即重新运行程序,形成新的进程;
实例代码:
1、重启按钮事件中添加代码:
g_bIsRunAgain=true//控制是否重新运行的变量
this->SendMessage(WM_CLOSE)
在MESSAGE_MAP中药添加 ON_WM_CLOSE
2、在OnClose()消息处理中加入代码:
if(g_bIsRunAgain)
{
char pBuf[MAX_PATH] //存放路径的变量
GetCurrentDirectory(MAX_PATH,pBuf) //获取程序的当前目录
strcat(pBuf,"\")
strcat(pBuf,AfxGetApp()->m_pszExeName)
strcat(pBuf,".exe")
CString strPath= (CString) pBuf
STARTUPINFO StartInfo
PROCESS_INFORMATION procStruct
memset(&StartInfo, 0, sizeof(STARTUPINFO))
StartInfo.cb = sizeof(STARTUPINFO)
::CreateProcess(
(LPCTSTR) strPath,
NULL,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&StartInfo,
&procStruct)
}
CDialog::OnClose()
通过查阅资料实现了对话框程序重新启动的功能,流程如下:
1ShowWindow(SW_HIDE)//隐藏本对话框
2WinExec(strPath, SW_SHOW)//启动strPath路径下的执行文件
3 OnOK()//退出当前执行对话框程序
另外在获取strPath是使用函数:GetModuleFileName(NULL,buf,sizeof(buf))获取当前程序的执行文件路径。
附源代码:
1void CF_RockClientDlg::OnBtnRestart()
2{
3// TODO: Add your control notification handler code here
4char buf[256]
5::GetModuleFileName(NULL,buf,sizeof(buf))
6CString strPath = buf
7ShowWindow(SW_HIDE)//隐藏本对话框
8WinExec(strPath, SW_SHOW)//启动strPath路径下的执行文件
9OnOK()//退出当前执行对话框程序
10}
vc 实现软件重启
一般要在一个事件里产生软件的自动重启 。
比如,我在一个对话框工程的子对话框中有一个单击按钮“确定”后d出一个是否重开软件的功能。
子对话框中:
if(MessageBox("更改了设置,需重启软件生效","Notice",MB_YESNO)==IDYES)
{
// WM_ONSETRESTART 消息是一个自定义的消息
//实现一个布尔变量的开关,以此评估 响应 wm_close 消息是不是由这个按钮触发(否则软件永远重启)
AfxGetMainWnd()->SendMessage(WM_ONSETRESTART)
AfxGetMainWnd()->SendMessage(WM_CLOSE)
}
在主对话框中的 OnClose 中:
void CTransFileDlg::OnClose()
{
char pBuf[MAX_PATH]
//获取应用程序完全路径,比 GetCurrentDirectory 好用多了
GetModuleFileName(NULL,pBuf,MAX_PATH)
STARTUPINFO startupinfo
PROCESS_INFORMATION proc_info
memset(&startupinfo,0,sizeof(STARTUPINFO))
startupinfo.cb=sizeof(STARTUPINFO)
// 最重要的地方
if(m_bSetRestart)
::CreateProcess(pBuf,NULL,NULL,NULL,FALSE,
NORMAL_PRIORITY_CLASS,NULL,NULL,&startupinfo,&proc_info)
CDialog::OnClose()
}
用ShellExecuteEx启动另外一个程序,传递一个reboot参数,然后在新启动的程序中接收这个参数,来判断自身是“重启”的结果,然后寻找之前的窗体,最后TerminateProcess之前的进程。
在App类里面定义一个未处理异常的回调函数。例如:
static LONG ApplicationCrashHandler(EXCEPTION_POINTERS* pException)然后在这个函数里面实现计算机重启的功能。代码你可以自己在网上查询。这里我把提权限和重启的参考代码附上:
OSVERSIONINFO osos.dwOSVersionInfoSize = sizeof(OSVERSIONINFO)
GetVersionEx(&os)
if (VER_PLATFORM_WIN32_NT == os.dwPlatformId)
{
HANDLE handle
TOKEN_PRIVILEGES tkp
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &handle)
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid)
tkp.PrivilegeCount = 1
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
AdjustTokenPrivileges(handle, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0)
if (GetLastError() != ERROR_SUCCESS)
{
MessageBox(NULL, TEXT("AdjustTokenPrivileges error"), TEXT("error"), MB_OK | MB_ICONERROR)
}
}
ExitWindowsEx(EWX_REBOOT, 0)
在App类的InitInstance成员函数的前面加上下列语句:
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)App)这个函数的功能是在整个进程出现了未处理异常的时候,就会把他交给ApplicationCrashHandler来处理,这个函数里面我们是做了重启 *** 作,因而能达到程序崩溃后能重启计算机的目的。
上面是在目标进程中来实现程序崩溃后重启计算机的,不需要另外单独写一个监控程序。如果需要单独写监控程序来做一个守护进程,可以用进程快照或者枚举进程来实现,这种做法缺点是用户更改了程序名就会出现问题,更好的做法是用内核对象来实现,在目标进程中申请一个内核对象,监控进程中打开这个内核对象,如果能打开就说明目标进程存在,否则表示不存在目标进程,就可以重启计算机了。这种做法记得在程序异常的时候关闭内核对象,否则当程序崩溃的时候,d出了标准的异常对话框,内核对象的生存周期还在,就无法达到程序崩溃的时候重启计算机了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)