One component instance

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

One component instance

Postby HsiaLin » Sat Mar 07, 2015 3:42 pm

How can i make my component only allow one instance?

i can try this:

Code: Select all
//---------------------------------------------------------------------------
__fastcall TSpectrum::TSpectrum(TComponent *Owner): TPaintBox(Owner)
{

   HANDLE Mutex = CreateMutex(NULL, true, L"TSPECTRUM");
   if(Mutex == 0 || (GetLastError() == ERROR_ALREADY_EXISTS))
    ; //what to do here?

   ...
}


How do i end loading once i know theres a previous instance?
HsiaLin
BCBJ Master
BCBJ Master
 
Posts: 299
Joined: Sun Jul 08, 2007 6:29 pm

Re: One component instance

Postby 2ffat » Mon Mar 09, 2015 4:52 am

The following is based upon some code that I did in BCB6. I tried to change my names to yours but . . .
be aware that this code might not work exactly correct in XE and I may have misnamed some of the variables. Hopefully it will give you a starting place.

Code: Select all
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    HANDLE TSPECTRUMmtx;
    try
    {
        // Only one instance of this program can be run
        TSPECTRUMmtx = OpenMutex (MUTEX_ALL_ACCESS, false, "TSPECTRUM");
        if (TSPECTRUMmtx == NULL)
            TSPECTRUMmtx = CreateMutex (NULL, true, "TSPECTRUM");
        else
        {
            ShowMessage("TSPECTRUM is already running!");
            return 0;
        }

// The following should be set up by C++ for you
        Application->Initialize();
        Application->Title = "TSPECTRUM";
        // Data Module MUST be created first
        Application->CreateForm(__classid(TSPECTRUMDataModule), &TSPECTRUMDataModule);
       Application->CreateForm(__classid(TSPECTRUMMainForm), &TSPECTRUMMainForm);
       Application->Run();
    }
    catch (Exception &exception)
    {
         Application->ShowException(&exception);
    }
    catch (...)
    {
         try
         {
             throw Exception("");
         }
         catch (Exception &exception)
         {
             Application->ShowException(&exception);
         }
    }

    ReleaseMutex(TSPECTRUMmtx);
    return 0;
}
//---------------------------------------------------------------------------
James P. Cottingham

Look at me still talking
when there is science to do.
User avatar
2ffat
Forum Mod
Forum Mod
 
Posts: 433
Joined: Wed Jun 23, 2004 7:07 am
Location: South Hill, VA

Re: One component instance

Postby HsiaLin » Mon Mar 09, 2015 11:20 am

Thanks 22fat,
i did try that based on the same logic you have there, but i dont know how to
stop a component from being dropped on the form. I guess i`ll just catch the duplicate and
issue a msgbox saying only one component will be valid.
HsiaLin
BCBJ Master
BCBJ Master
 
Posts: 299
Joined: Sun Jul 08, 2007 6:29 pm

Re: One component instance

Postby rlebeau » Mon Mar 09, 2015 3:08 pm

HsiaLin wrote:How can i make my component only allow one instance?


The easily way is to simply keep track of the first instance, and throw an exception if any subsequent instances are created:

Code: Select all
static TSpectrum *TheOnlyOne = NULL;

//---------------------------------------------------------------------------
__fastcall TSpectrum::TSpectrum(TComponent *Owner)
    : TPaintBox(Owner)
{
    if (TheOnlyOne != NULL)
        throw Exception("There can be only one");
    TheOnlyOne = this;
    ...
}

//---------------------------------------------------------------------------
__fastcall TSpectrum::~TSpectrum()
{
    ...
    if (TheOnlyOne == this)
        TheOnlyOne = NULL;
}
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1528
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: One component instance

Postby rlebeau » Mon Mar 09, 2015 3:24 pm

2ffat wrote:The following is based upon some code that I did in BCB6.


That code is geared towards preventing multiple instances of the application itself. That kind of logic is not well-suited for preventing multiple instances of a given component within a single instance of the application.

On a side note, for your kind of code, you should be calling CreateMutex() first and then calling OpenMutex() only if CreateMutex() fails with an ERROR_ACCESS_DENIED error. Otherwise, you have a race condition.

Code: Select all
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    HANDLE TSPECTRUMmtx = NULL;

    try
    {
        // Only one instance of this program can be run
        TSPECTRUMmtx = CreateMutex (NULL, FALSE, "TSPECTRUM");
        if (!TSPECTRUMmtx)
        {
            if (GetLastError() != ERROR_ACCESS_DENIED)
               RaiseLastOSError();

            ShowMessage("TSPECTRUM is already running!");
        }
        else if (GetLastError() == ERROR_ALREADY_EXISTS)
        {
            ShowMessage("TSPECTRUM is already running!");
        }
        else
        {
            // normal app stuff here ...
        }
    }
    catch (Exception &exception)
    {
         Application->ShowException(&exception);
    }
    catch (...)
    {
         try
         {
             throw Exception("");
         }
         catch (Exception &exception)
         {
             Application->ShowException(&exception);
         }
    }

    if (TSPECTRUMmtx)
        CloseHandle(TSPECTRUMmtx);

    return 0;
}
//---------------------------------------------------------------------------
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1528
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: One component instance

Postby rlebeau » Mon Mar 09, 2015 3:26 pm

HsiaLin wrote:i did try that based on the same logic you have there


A named mutex is overkill for what you are attempting, unless you need to prevent multiple instances across process boundaries.

HsiaLin wrote:i dont know how to stop a component from being dropped on the form.


The only way is to have the component's constructor throw an exception.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1528
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: One component instance

Postby HsiaLin » Mon Mar 09, 2015 5:58 pm

Hi5....... thanks for that info.
HsiaLin
BCBJ Master
BCBJ Master
 
Posts: 299
Joined: Sun Jul 08, 2007 6:29 pm

Re: One component instance

Postby 2ffat » Tue Mar 10, 2015 4:27 am

Thanks, rlebeau. That code comes from the (very) old C++Builder:How-To book.
James P. Cottingham

Look at me still talking
when there is science to do.
User avatar
2ffat
Forum Mod
Forum Mod
 
Posts: 433
Joined: Wed Jun 23, 2004 7:07 am
Location: South Hill, VA


Return to Technical

Who is online

Users browsing this forum: Google [Bot] and 12 guests