CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Mar 2002
    Location
    Philadelphia
    Posts
    150

    how can single instance app restart itself?

    Is there any way for a "single instance" app to restart itself via CreateProcess()?

    I have an app that uses a Mutex as it must ensure only one instance of itself is allowed to run. It is an MFC MDI single document app that "reinitializes" then "restarts" itself after its user reconfigures its database path. It does this by closing its main document and reloading it, but, unfortunately, it does not reinitialize all of itself. The app fails to reinitialize Crystal Reports which in turn uses an ODBC DSN to show database reports. Even though the database pointer changes in the text of the DSN file, there seems to be no way to tell Crystal Reports to reload its DSN.

    The app works fine if the user exits the app and then restarts it.
    I read the FAQ "How can I start a process" though it is unclear to me how to start a process from a process that uses a mutex to ensure only one copy of itself runs. Any ideas?
    Sincerely,
    - Ron

  2. #2
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,867
    Perhaps you could start a second process that would shut down the mutex app, start it up again and then close itself?
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  3. #3
    Join Date
    Feb 2000
    Location
    San Diego, CA
    Posts
    10,354

    Re: how can single instance app restart itself?

    Originally posted by RNEELY
    Is there any way for a "single instance" app to restart itself via CreateProcess()?
    I think this is not really required. If you do this, I think it is going to be only a workaround for the issue.

    It does this by closing its main document and reloading it, but, unfortunately, it does not reinitialize all of itself. The app fails to reinitialize Crystal Reports which in turn uses an ODBC DSN to show database reports. Even though the database pointer changes in the text of the DSN file, there seems to be no way to tell Crystal Reports to reload its DSN.
    There may be some bug here. You may want to investigate that first. It is kinda ugly to kill the app and relaunch it just for the heck of it.

    The app works fine if the user exits the app and then restarts it.
    I read the FAQ "How can I start a process" though it is unclear to me how to start a process from a process that uses a mutex to ensure only one copy of itself runs. Any ideas?
    I would still encourage you to find the exact problem instead

  4. #4
    Join Date
    Jun 2002
    Posts
    395
    If you are using a mutex, just delete it (CloseHandle() iirc) before you call CreateProcess().

    That way the second one won't find the mutex and it will think it is the first instance, and will run. You can then exit the one that called CreateProcess().

  5. #5
    Join Date
    Mar 2002
    Location
    Philadelphia
    Posts
    150

    Smile thanks

    Thank you all for your responses. The trick was to wait until after the mutex was released before starting the next instance of the app. Yes, kirants, this is a workaround. I don't have the source code for Crystal Reports.

    Code:
    class CMyApp : public CWinApp
    {
    	public:
    	CMyApp();
    	void Restart();
    	// . . .
    	protected:
    	HANDLE	m_hMutex;
    	bool m_bRestartAppOnExit;
    };
    
    
    CMyApp::CMyApp() :
    	m_hMutex(NULL),
    	m_bRestartAppOnExit(false)
    {
    	// ...
    }
    
    BOOL CMyApp::InitInstance()
    {
    	// Single-instance code
    	m_hMutex = NULL;
    	HANDLE hMutex;
    	if (hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, m_pszAppName))
    	{
    		CString sErrorMsg;
    		sErrorMsg.Format(_T("Only one %s is allowed to run."), m_pszAppName);
    		::MessageBox(NULL, sErrorMsg, m_pszAppName, MB_OK);
    		return FALSE;
    	}
    	else
    	{
    		m_hMutex=::CreateMutex(NULL, TRUE, m_pszAppName);
    	}
    	// ...
    	return TRUE;
    }
    
    void CMyApp::Restart()
    {
    	m_bRestartAppOnExit = true;
    	PostQuitMessage(ERROR_SUCCESS_RESTART_REQUIRED);
    }
    
    int CMyApp::ExitInstance() 
    {
    	if (m_hMutex)
    	{
    		::ReleaseMutex(m_hMutex);
    		CloseHandle(m_hMutex);
    		m_hMutex = NULL;
    	}
    	if (m_bRestartAppOnExit)
    	{
    		TCHAR szFileName[MAX_PATH];	
    		szFileName[0] = 0;
    		DWORD dwSize = MAX_PATH;	
    		GetModuleFileName(0, szFileName, dwSize);
    		HINSTANCE hInst = ShellExecute(0,                           
    			_T("open"), // Operation to perform
    			szFileName, // Application name
    			_T(""),     // Additional parameters
    			0,          // Default directory
    			SW_SHOW);
    	}
    	return CWinApp::ExitInstance();
    }
    Sincerely,
    - Ron

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured