2 shortcuts, 1 instance

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?


Who is Participating?

Improve company productivity with a Business Account.Sign Up

Slick812Connect With a Mentor Commented:
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
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,
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
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Mutley2003Author Commented:
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?

Oh this DOES not set a Mutex if there is Not one, so you will still need to set the mutex in your MegaApp
Mutley2003Author Commented:
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

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;

Mutley2003Author Commented:
thanks Slick812 .. I have plenty to work with now
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.