2 shortcuts, 1 instance

Posted on 2004-09-17
Last Modified: 2010-04-05
I asked a variant of this question at

"A single hotkey doing wakeup and global duty"

and accepted the answer - that it was basically a matter of using a mutex to enforce a single instance and passing through an indication of which shortcut key was used via SendMessage.

However, I started thinking <g> and it seems to me that enforcing a single instance via a mutex is inefficient.  My concern is that a second copy of the exe (MyMegaApp) is actually loaded into memory BEFORE it gets killed (after detecting the mutex).

How about this. The shortcut keys actually call a small "loader" app. It is that app which then "spawns" MyMegaApp but ONLY if needed (ie no mutex). Some sort of WinExecAndWait or is CreateProcess what I need?. We still use a SendMessage to send the arguments.. hmm, would it be better to use a more general interprocess communications approach (so I can send more stuff).

Anyone care to look at the previous answer and improve on it, given these ideas?


Question by:Mutley2003
  • 5
  • 3
LVL 33

Expert Comment

ID: 12090373
hello  Mutley2003, , I am not sure that I am getting what you want or need to have done? you say something about -
"is actually loaded into memory BEFORE it gets killed"
and why do you have a problem with this? are you getting complaints form users about system error of running out of memory when your program loads? or some memory problems?
anyway, here is a EE question that shows a better (in my opinion) mutex for single instance  PLUS it sends the first parameter to the running program! -

if you think you need a "Small Program" to run and  do the mutext thing and then launch your program, I could do an API program of 20 Kb or so to test the mutext, and then run your other program, but I can not at this point see any need for a  WinExecAndWait or a CreateProcess and a wait. . . you should just use a shellexecute if there is no mutext, but it seems, like this could cause other problems, if you need one program inorder to launch another (the main) program,
LVL 33

Expert Comment

ID: 12090387
oh yea, , It is my impression that if you never call the

  Application.CreateForm(TForm1, Form1);

the Application and "Form" are not loaded into a Memory block, so none of the Form's class is ever given any memory for functioning

Author Comment

ID: 12090783
hi Slick812

does a nice job of passing string data via WM_COPYDATA, thanks.

I guess I don't understand enough about how windows loads an exe .. you say

"It is my impression that if you never call the

  Application.CreateForm(TForm1, Form1);

the Application and "Form" are not loaded into a Memory block, so none of the Form's class is ever given any memory for functioning"

well, there would not be any dynamic memory allocations obviously, but I would have thought that all the code and data gets loaded ... that is, an "image" of the exe.

How to test this?

Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

LVL 33

Accepted Solution

Slick812 earned 500 total points
ID: 12091956
Yea, I spoke to soon, sleepy I guess :-) , the exe is loaded into the programs Instance on start of program , , , Sorry

so you want some way to NOT load your program, if a Mutex is up??
I think I would have a "Small" GUI program (only code for the basic Form) and then move all of my "Large Code" or whatever makes your program into a MegaApp into several DLL's and then if your program Runs, you then load the DLLs (this would make "Updating" your App easier also). .  However, It would probally take alot of work to do this. . . .

If you just want a "Small" do nothing app that ONLY tests for the Mutex, you might try something like this, Here is some code for a .DPR  file in delphi, there is NO GUI, no windows are created, the user sees NOTHING (well and error message is it craps out), all it does is Open a mutex and if there is no mutex then it starts a program. . . . . . .

program preMutex;

  ShellApi, Windows;

hMutex: Cardinal;
i: Integer;
StartApp, ParamS1: String;

hMutex := OpenMutex(MUTEX_ALL_ACCESS,False,'h8J3Cn90?%x7');
if hMutex = 0 then
  for i := 1 to ParamCount do
    ParamS1 := ParamS1+'"'+ParamStr(i)+'" ';
  StartApp := ExtractFilePath(ParamStr(0))+'WesThumbs.exe';
  if ShellExecute(0,'open',PChar(StartApp),PChar(ParamS1),nil,SW_SHOWDEFAULT) < 33 then
    MessageBox(0, PChar('ERROR - Could NOT start program'#10+StartApp),
               'ERROR Program was NOT Started', MB_ICONERROR or MB_TOPMOST);;
  end else

this DOES NOT send the parameters to an already running program,
if you need that, you can get the code for that at the other EE question
LVL 33

Expert Comment

ID: 12091959
Oh this DOES not set a Mutex if there is Not one, so you will still need to set the mutex in your MegaApp

Author Comment

ID: 12094187
maybe I am sleepy too (or just thick<g>).. but you have shown me how to start an app if there is no mutex, cool.

If there is a mutex, then OK we send stuff to the already running instance (via WM_COPYDATA) .  There is still the issue of how to "wake up" that instance. Maybe it is just something in the WM_COPYDATA event handler to make a form visible/active

LVL 33

Expert Comment

ID: 12094229
OK, I have NO IDEA what your program may or may not be doing. . .I don't know if it is minimized or hidden or whatever. So when you get the WM_COPYDATA message you can use the parameters in the TWmCopyData to indicate "Different" types of WM_COPYDATA data, if you need to do that,, , , ,
 but as for your "Wake Up" the main app, , well yes, you can do code to do whatever you need if minimized or hidden or small or whatever

procedure TForm1.GetCopyData(var Msg: TWmCopyData);
i: Integer;
PrePc, ScanPc: PChar;
Str1: String;
// add a test and then a change when you get a WM_COPYDATA message

if  not Visible then Show;
if mininized then Maximize;
if IsSmall then MakeBig;

Msg.Result := 0;
if StrLen(PChar(msg.CopyDataStruct^.lpData)) > 0 then
              Msg.Result := 17;
              if msg.CopyDataStruct^.dwData = 1 then
                Str1 := PChar(msg.CopyDataStruct^.lpData);
                Form1.Label3.Caption := Str1;


Author Comment

ID: 12094341
thanks Slick812 .. I have plenty to work with now

Featured Post

Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question