Board index » cppbuilder » Prevent User from starting Myprog more than once

Prevent User from starting Myprog more than once


2005-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
 
 

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 >сообщи?сообщила ?новостях следующе?
Quote
Hi,

How can I prevent my users to start my program more than one time?

Thanks very much

Jan


 

Re:Prevent User from starting Myprog more than once

Quote
How can I prevent my users to start my program more than one time?
Here is another approach:
//---------------------------------------------------------------------------
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}

Re:Prevent User from starting Myprog more than once

"JV" < XXXX@XXXXX.COM >wrote in message
Quote
How can I prevent my users to start my program more than one time?
Prevent multiple instances of the program from running
web.archive.org/web/20030626080800/www.bcbdev.com/faqs/faq74.htm
Gambit
 

Re:Prevent User from starting Myprog more than once

"JV" < XXXX@XXXXX.COM >wrote:
Quote


How can I prevent my users to start my program more than one time?
There are many ways that one can use to determine if a the
application has already been launched. However, if you want
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
 

Re:Prevent User from starting Myprog more than once

"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >wrote:
Quote


Prevent multiple instances of the program from running
web.archive.org/web/20030626080800/www.bcbdev.com/faqs/faq74.htm
While that code will prevent multiple instances, it does not
correctly restore the first instance 100% of the time.
~ JD
 

Re:Prevent User from starting Myprog more than once

"poojo hackma" <poojo.com/mail>wrote:
Quote

[...]
BringWindowToTop(hWnd1);
Won't work if the application is minimized.
~ JD
 

Re:Prevent User from starting Myprog more than once

Quote
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:
nice!
 

Re:Prevent User from starting Myprog more than once

Quote

There are many ways that one can use to determine if a the
application has already been launched. However, if you want
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.
~ JD

Thank you JD.
(also to the others)
Jan