日期:2014-05-17  浏览次数:20803 次

如何实现Windows上只启动程序一次

问题描述:

我们的客户希望客户端程序在客户端上24小时在线,如果因为特殊的原因而崩溃或者退出,应该能自动的重启程序。

我们所想到的一个解决办法就是使用一个监控进程,这个进程一开机的时候就会自动尝试着启动程序;并且,每隔一段时间就检查程序是否还启动着,如果不是的话,则重新启动程序。


问题分析:

1、首先,是如何在Windows上启动一个程序,并定时的检查程序的运行状态,我们可以用如下的代码来做这些事情:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void _tmain( int argc, TCHAR *argv[] )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    if( argc != 2 )
    {
        printf("Usage: %s [cmdline]\n", argv[0]);
        return;
    }

    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        argv[1],        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}

2、然后需要定期的检测,并且在子进程退出的时候重新启动子进程即可。

3、为了确保同一时间只有一个子进程被启动着,需要确保程序只能启动一次,我们可以用如下的代码实现:

#ifndef LimitSingleInstance_H
#define LimitSingleInstance_H

#include <windows.h> 

//This code is from Q243953 in case you lose the article and wonder
//where this code came from.
class CLimitSingleInstance
{
protected:
  DWORD  m_dwLastError;
  HANDLE m_hMutex;

public:
  CLimitSingleInstance(TCHAR *strMutexName)
  {
    //Make sure that you use a name that is unique for this application otherwise
    //two apps may think they are the same if they are using same name for
    //3rd parm to CreateMutex
    m_hMutex = CreateMutex(NULL, FALSE, strMutexName); //do early
    m_dwLastError = GetLastError(); //save for use later...
  }
   
  ~CLimitSingleInstance() 
  {
    if (m_hMutex)  //Do not forget to close handles.
    {
       CloseHandle(m_hMutex); //Do as late as possible.
       m_hMutex = NULL; //Good habit to be in.
    }
  }

  BOOL IsAnotherInstanceRunning() 
  {
    return (ERROR_ALREADY_EXISTS == m_dwLastError);
  }
};
#endif

将上述内容保存为LimitSingleInstance.h,然后在程序的入口处创建其一个实例:

#include "LimitSingleInstance.H"

// The one and only CLimitSingleInstance object.
CLimitSingleInstance g_SingleInstanceObj(TEXT("Global\\{9DA0BEED-7248-450a-B27C-C0409BDC377D}"));

int main(int argc, char* argv[])
{
    if (g_SingleInstanceObj.IsAnotherInstanceRunning())
       return 0;
//Rest of code.
}


编程环境:

Qt 4.7 + Visual Studio 2008


参考资料:

1、 http://support.microsoft.com/kb/243953

2、 http://stackoverflow.com/questions/1591342/how-to-determine-if-a-windows-process-is-running

3、 http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx

4、 如何创建进程:http://msdn.microsoft.com/en-us/library/ms682512%28VS.85%29.aspx