Board index » cppbuilder » Prevent User from starting Myprog more than once
JV
![]() CBuilder Developer |
JV
![]() CBuilder Developer |
Prevent User from starting Myprog more than once2005-10-03 09:07:41 PM cppbuilder82 Hi, How can I prevent my users to start my program more than one time? Thanks very much Jan |
Andrew Fedoseev
![]() CBuilder Developer |
2005-10-03 09:39:33 PM
Re:Prevent User from starting Myprog more than once
I think you should take a look at this
www.codeproject.com/Purgatory/single_instance.asp "JV" < XXXX@XXXXX.COM >сообщи?сообщила ?новостях следующе? QuoteHi, |
poojo hackma
![]() CBuilder Developer |
2005-10-03 11:04:21 PM
Re:Prevent User from starting Myprog more than onceQuoteHow can I prevent my users to start my program more than one time? WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { // determine if another instance is running: HWND hWnd1, hWnd2; hWnd1 = FindWindow("TMyForm", NULL); if (hWnd1) { MessageBox(NULL, "A version is already running.", "App Msg", MB_OK); hWnd2 = GetLastActivePopup(hWnd1); BringWindowToTop(hWnd1); if (hWnd1 != hWnd2) { BringWindowToTop(hWnd2); return false; } } else { try { Application->Initialize(); } catch (Exception &exception) { Application->ShowException(&exception); } catch (...) { try { throw Exception(""); } catch (Exception &exception) { Application->ShowException(&exception); } } } return 0; } {smallsort} |
Remy Lebeau (TeamB)
![]() CBuilder Developer |
2005-10-04 01:20:36 AM
Re:Prevent User from starting Myprog more than once
"JV" < XXXX@XXXXX.COM >wrote in message
QuoteHow can I prevent my users to start my program more than one time? Gambit |
JD
![]() CBuilder Developer |
2005-10-04 01:26:03 AM
Re:Prevent User from starting Myprog more than once
"JV" < XXXX@XXXXX.COM >wrote:
Quote
to set the first instance of you application as the current window, there is only one 100% reliable way to do that and that's because of how windows works. If the first instance is minimized, you need to restore it first before you bring it to front. However, unless you apply WS_APPWINDOW to the window's ExStyle (which causes 2 icons on the taskbar) all attempts to determine a minimized window's state will fail. If you blindly restore a restored window, you'll really mess up how Window's reads the window's state. The only reliable way to correctly restore the first instance is to manually keep track of the state and then send it a custom message and let it decide to restore or not. The following class keeps does exactly that and is ready to be made into a component. The only thing that it needs from you is a unique main form class name. Something like: TCompanyNameProgramName //------------------------------------------------------------- #ifndef Unit2H #define Unit2H //------------------------------------------------------------- #include <Classes.hpp> //------------------------------------------------------------- class TSingleInstance : public TComponent { private: bool FMinimized, FMainWindowHooked; HANDLE hMutex; HWND FHandle; HHOOK FMainThreadHook; UINT SI_RESTORE, SI_INITIALIZE; TForm* FParentForm; protected: bool __fastcall MainWindowHook( TMessage &Message ); virtual void __fastcall WndProc( TMessage &Message ); static int __stdcall MainThreadWndProcRetHook( int Code, WPARAM WParam, LPARAM LParam ); public: __fastcall TSingleInstance(TComponent* Owner); __fastcall ~TSingleInstance(); __published: }; //------------------------------------------------------------- #endif //------------------------------------------------------------- #include <vcl.h> #include <basepch.h> //------------------------------------------------------------- #pragma hdrstop //------------------------------------------------------------- #include "Unit2.h" #pragma package(smart_init) //------------------------------------------------------------- TSingleInstance* ThisSingleInstance = NULL; HWND hFirstInstance, hSecondInstance; //------------------------------------------------------------- BOOL CALLBACK EnumWindowsCallBack( HWND hWnd, LPARAM lParam ) { char WindowClassName[256] = {0}; if( ::GetClassName(hWnd, WindowClassName, 255) ) { if( stricmp(WindowClassName, (char*)lParam) == 0) { if( hFirstInstance ) { hSecondInstance = hWnd; return FALSE; } else hFirstInstance = hWnd; } } return TRUE; } //------------------------------------------------------------- __fastcall TSingleInstance::TSingleInstance(TComponent* Owner) : TComponent(Owner) { FParentForm = dynamic_cast<TForm*>(Owner); if( !Owner ) { throw Exception("TSingleInstance : You must assign an Owner."); } if( !FParentForm ) { throw Exception("TSingleInstance : The Owner must be a TForm."); } if( ThisSingleInstance ) { throw Exception("TSingleInstance : Only one instance of TSingleInstance is allowed per application."); } hMutex = NULL; FHandle = NULL; FMainThreadHook = NULL; FMainWindowHooked = false; ThisSingleInstance = this; if( !ComponentState.Contains(csDesigning) ) { char ThisClassName[ 256 ] = { 0 }; SI_RESTORE = ::RegisterWindowMessage( "TSingleInstanceRestoreMessage" ); SI_INITIALIZE = ::RegisterWindowMessage( "TSingleInstanceInitializeMessage" ); if( ! SI_RESTORE || ! SI_INITIALIZE ) { throw Exception("TSingleInstance : RegisterWindowMessage failed."); } ::GetClassName( FParentForm->Handle, ThisClassName, 255 ); hMutex = ::CreateMutex( NULL, TRUE, ThisClassName ); if( GetLastError() == ERROR_ALREADY_EXISTS ) { ::ShowWindow( Application->Handle, SW_HIDE ); Application->ShowMainForm = false; hFirstInstance = hSecondInstance = NULL; ::EnumWindows((WNDENUMPROC)EnumWindowsCallBack, (LPARAM)ThisClassName ); if( hFirstInstance == FParentForm->Handle ) { hFirstInstance = hSecondInstance; } ::SendMessage( hFirstInstance, SI_RESTORE, 0, 0 ); ::SetForegroundWindow( hFirstInstance ); Application->Terminate(); } else { // Need to monitor main form window state Application->HookMainWindow( MainWindowHook ); FMainWindowHooked = true; // To catch messages sent to the HWND found by the above win32 API EnumWindows FMainThreadHook = ::SetWindowsHookEx( WH_CALLWNDPROCRET, (int (__stdcall*)())MainThreadWndProcRetHook, HInstance, ::GetCurrentThreadId() ); if( !FMainThreadHook ) { throw Exception("TSingleInstance : Hooking Main Thread failed."); } // Still need some final initialization but it needs to be delayed until Application::MainForm is valid. FHandle = AllocateHWnd( WndProc ); if( !FHandle ) { throw Exception("TSingleInstance : AllocateHWnd failed."); } ::PostMessage( FHandle, SI_INITIALIZE, 0, 0 ); } } } //------------------------------------------------------------- __fastcall TSingleInstance::~TSingleInstance() { if( FHandle ) DeallocateHWnd( FHandle ); if( FMainWindowHooked ) Application->UnhookMainWindow( MainWindowHook ); if( FMainThreadHook ) ::UnhookWindowsHookEx( FMainThreadHook ); if( hMutex ) ::CloseHandle( hMutex ); ThisSingleInstance = NULL; } //------------------------------------------------------------- void __fastcall TSingleInstance::WndProc( TMessage &Message ) { if( Message.Msg == SI_INITIALIZE ) { if( FParentForm != Application->MainForm ) { MessageDlg("TSingleInstance : Object can only be placed on the Main Form.", mtError, TMsgDlgButtons() << mbOK, 0); Application->Terminate(); } else { if( Application->MainForm->WindowState == wsMinimized ) FMinimized = true; else FMinimized = false; } } Message.Result = DefWindowProc( FHandle, Message.Msg, Message.WParam, Message.LParam ); } //------------------------------------------------------------- bool __fastcall TSingleInstance::MainWindowHook( TMessage &Message ) { if( Message.Msg == WM_SYSCOMMAND ) { switch( Message.WParam ) { case SC_RESTORE: case SC_MAXIMIZE: FMinimized = false; break; case SC_MINIMIZE: FMinimized = true; } } return false; } //------------------------------------------------------------- int __stdcall TSingleInstance::MainThreadWndProcRetHook( int Code, WPARAM WParam, LPARAM LParam ) { if( Code == HC_ACTION ) { CWPRETSTRUCT* cwp = (CWPRETSTRUCT *) LParam; if( cwp->message == ThisSingleInstance->SI_RESTORE ) { if( ThisSingleInstance->FMinimized ) { ::SendMessage( Application->Handle, WM_SYSCOMMAND, SC_RESTORE, 0 ); } } } return ::CallNextHookEx( ThisSingleInstance->FMainThreadHook, Code, WParam, LParam ); } //------------------------------------------------------------- To use it as is, click File | New | Unit and cut and paste. Then include the header in the main unit and simple dynamically allocate an instance of it in the main form's contructor. ~ JD |
JD
![]() CBuilder Developer |
2005-10-04 01:28:01 AM
Re:Prevent User from starting Myprog more than once
"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >wrote:
Quote
~ JD |
JD
![]() CBuilder Developer |
2005-10-04 01:28:18 AM
Re:Prevent User from starting Myprog more than once
"poojo hackma" <poojo.com/mail>wrote:
Quote
|
poojo hackma
![]() CBuilder Developer |
2005-10-04 02:51:30 AM
Re:Prevent User from starting Myprog more than onceQuoteThe following class keeps does exactly that and is ready to be |
JV
![]() CBuilder Developer |
2005-10-04 02:38:24 PM
Re:Prevent User from starting Myprog more than onceQuote
Jan |