Program not terminating on Windows 10 lazarus / 34-Windows ---------------------------------------------------------------------- scamb09 · 2016-06-04 19:34 Hi, I am currently in the process of writing a database application that will start at Windows start up and reside in the system tray with all forms hidden until the user selects from the system tray icons popup menu or double clicks the desktop icon, at which time a form (currently the main form is shown). The application will be used on a large network of computers with various operating systems ranging from Windows XP to Windows 10 and thus needs to be adaptable. When the application is run a mutex is created using the applications GUID. When the user double clicks on the desktop icon a second instance of the application is created which again tries to create a mutex using the same GUID, this being unsuccessful, the second instance of the application broadcasts a message to all top level windows and then terminates. On receiving the message the first instance of the application then shows it main form. The code located in the project file for creating the mutex and determining if another instance of the program running is as follows. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var   vmutex : THandle; begin  // Register GUID as windows message.  AppMessage := RegisterWindowMessage(AppGUID);  // Create application mutex with GUID  vmutex := Crea]"]>Blockedtex(nil, True, AppGUID);  // If mutex already exists then broardcast windows message.  if GetLastError = ERROR_ALREADY_EXISTS then  begin       Windows.SendMessage(HWND_BROADCAST, AppMessage, 0, 0);       Exit;  end; end; And the handler within the main form is a override of the 'WndProc' routine. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainForm.WndProc(var Msg: TMessage);begin        if Msg.msg = AppMessage then        begin               MainForm.Show;             MainForm.ShowInTaskBar:= stDefault;        end;        inherited WndProc(Msg);end; I have tested the application on all major versions of Windows and it works fine, up to and including Windows 8.1, however on Windows 10, running the second instance of the application triggers the first's to show it's form as expected but does not terminate, it instead continues to run as a background task. I have tried the alternatives, PostMessage and PostThreadMessage but these are ignored by the message handler, presumable because of ownership issues. Please could anyone help with this problem as I cannot see what could be wrong and why it would only affect running on one of the 5 operating systems tested on. Many thanks scamb09 ---------------------------------------------------------------------- RAW · 2016-06-04 23:16 Quote..as I cannot see what could be wrong and why it would only affect running on one of the 5 operating systems tested on. Because that one is Windows 10   ... What about Defender and other security-like programs or services ?? Obviously in Windows 10 they installed a lot of "useful" features... I've never used a mutex... normally I use two functions "EnumWindowsProc" and "FindAllWindows" (EnumWindows). For me that works well enough..  but I've never written a real world program... But maybe you can test some alternatives with W10: a semaphore or something like that.. or TCriticalSections... Good Luck... ---------------------------------------------------------------------- rvk · 2016-06-05 10:41 Quote from: scamb09 on June 04, 2016, 09:34:34 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if GetLastError = ERROR_ALREADY_EXISTS then  begin       Windows.SendMessage(HWND_BROADCAST, AppMessage, 0, 0);       Exit; // <--- Exit right before end....? What's the use ???  end; end;I don't understand your Mutex-procedure. You have a Exit right before end. This does nothing. So if your Sendmessage succeeds the control is just brought back to the main procedure. I don't believe this function is your main procedure... so where are you really exiting your program ?? If this is not your complete code.... please provide more. ---------------------------------------------------------------------- scamb09 · 2016-06-05 13:57 Quotervk - I don't understand your Mutex-procedure. You have a Exit right before end. This does nothing. So if your Sendmessage succeeds the control is just brought back to the main procedure. I don't believe this function is your main procedure... so where are you really exiting your program ?? If this is not your complete code.... please provide more. As mentioned in my initial message, this section of code is located in the program  information file(*.lpr). I have also tried using 'Application.Terminate' in place of 'Exit' but this has no affect on the function of the application. The full code for the lpr file is as follows. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program BenchCheck; //{$mode objfpc}{$H+}{$MODE DELPHI}{$H+} uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Interfaces, // this includes the LCL widgetset  Forms, StringVar, lazcontrols, runtimetypeinfocontrols, treelistviewpackage,  bcmain, bcoptions, RunElevatedSupport, sysutils, windows, messages, bcsplash,  AppRoutines, bcgplviewer, bcelevatedtasks, bcconstants,  bcfilecopythread; {$R *.res} var   vmutex : THandle; begin  // Register GUID as windows message.  AppMessage := RegisterWindowMessage(AppGUID);  // Create application mutex with GUID  vmutex := Crea]"]>Blockedtex(nil, True, AppGUID);  // If mutex already exists then broardcast windows message and exit.  if GetLastError = ERROR_ALREADY_EXISTS then  begin       Windows.SendMessage(HWND_BROADCAST, AppMessage, 0, 0);       Exit;  end;   try     RequireDerivedFormResource := True;     Application.Initialize;     Application.ShowMainForm:= false;     Application.CreateForm(TMainForm, MainForm);     Application.Run;  finally         CloseHandle(vmutex);  end;end. I have now tested the application on Windows 10 Home and Professional versions with the same results. Seems as if that under Windows 10, 'SendMessage' is not receiving a reply and therefore the 'Exit' command is never executed and hence the second instance of the application is not terminating. Any help please? scamb09 ---------------------------------------------------------------------- rvk · 2016-06-05 14:25 Can you put dialogs in the uses and put a Showmessage('Broadcast done and returned'); directly after the SendMessage. If it shows the Showmessage on second run there must be something else wrong. (Exit should end the program in this case) If the message does not show your SendMessage does not return and we can look at that more specifically. I tested this with a small sample here on Windows 10 Pro 64b and it works fine. Did you try disabling you virusscanner etc.? If you start the program multiple times, do you also get multiple instances (i.e. >2 times)? ---------------------------------------------------------------------- ezlage · 2016-06-05 15:14 Main form needs to be closed if you want to get out from Application.Run loop and enter on "finally" statement. Where and how users can tell the app to close? Where and how app closes itself? Sorry by my poor english. ---------------------------------------------------------------------- rvk · 2016-06-05 15:20 Quote from: ezlage on June 05, 2016, 05:14:51 pmMain form needs to be closed if you want to get out from Application.Run loop and enter on "finally" statement. When the second instance is run it should even reach Application.Initialize;. So there is no mainform to close. There isn't even an Application to close (it doesn't come that far). So Exit after Sendmessage should just do the trick. Quote from: ezlage on June 05, 2016, 05:14:51 pmWhere and how users can tell the app to close? Where and how app closes itself? If a second instance on the same computer is run it should "activate" the first instance and exit directly. There is no "how many users". Also... there is no instruction to close the first application. The second run instance should detect the first instance (with the mutex) and activate the first after which the second should quit immediately. And that's also what happens for me. So my guess is still a troubled virusscanner or that SendMessage doesn't return for some reason. ---------------------------------------------------------------------- scamb09 · 2016-06-05 15:27 Quotervk - Can you put dialogs in the uses and put a Showmessage('Broadcast done and returned'); directly after the SendMessage. If it shows the Showmessage on second run there must be something else wrong. (Exit should end the program in this case) If the message does not show your SendMessage does not return and we can look at that more specifically. Ok, as you suggested, I put a showmessage instruction directly after the SendMessage command, this has no effect, so my initial assumption that the second instance of the application is not receiving a return value from the first. Quotervk - Did you try disabling you virusscanner etc.? Windows Defender and AVG have been disabled. Quotervk - If you start the program multiple times, do you also get multiple instances (i.e. >2 times)? A new instance of the application can be found as a background process after every attempt to run. This is puzzling . scamb09 ---------------------------------------------------------------------- ezlage · 2016-06-05 15:31 Many times the McAfee causes unexpected things on my apps. But see, this code never shows me the message: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   try    RequireDerivedFormResource:=True;    Application.Initialize;    Application.ShowMainForm:=False;    Application.CreateForm(TForm1, Form1);    Application.Run;  finally    ShowMessage('ok');  end; Something in other piece of code needs to terminate the app or close the main form. This doesn't fit to your case? ---------------------------------------------------------------------- rvk · 2016-06-05 15:33 Ok, so the SendMessage does not return and that's the one that hangs. (So actually it hangs in your first instance because that should just return a result). Could you try the following: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainform.WndProc(var Msg: TMessage);begin  if Msg.msg = AppMessage then  begin    Mainform.Show;    Mainform.ShowInTaskBar := stDefault;  end  else // <-------- ADD THE ELSE    inherited WndProc(Msg);end; You don't need to call inherited if your Msg.msg is AppMessage. Does it work now? If not you could add a showmessage right after Mainform.Show to see if it doesn't hang in Show. ---------------------------------------------------------------------- ezlage · 2016-06-05 15:52 You also can try the LPK UniqueInstance, from Luipack. ---------------------------------------------------------------------- scamb09 · 2016-06-05 15:57 Quote from: rvk on June 05, 2016, 05:33:48 pmOk, so the SendMessage does not return and that's the one that hangs. (So actually it hangs in your first instance because that should just return a result). Could you try the following: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainform.WndProc(var Msg: TMessage);begin  if Msg.msg = AppMessage then  begin    Mainform.Show;    Mainform.ShowInTaskBar := stDefault;  end  else // <-------- ADD THE ELSE    inherited WndProc(Msg);end; You don't need to call inherited if your Msg.msg is AppMessage. Does it work now? If not you could add a showmessage right after Mainform.Show to see if it doesn't hang in Show. Ok, the else state was originally  in the 'WndProc' procedure, I removed it prior to starting this thread in a hope that calling inherited would cause a response, I have now replaced it. As suggested, I have added a sendmessage statement immediately after the 'Mainform.Show' command,  this fires and shows he message when the second application instance is run, as expected. scamb09 ---------------------------------------------------------------------- scamb09 · 2016-06-05 16:00 Quote from: ezlage on June 05, 2016, 05:52:40 pmYou also can try the LPK UniqueInstance, from Luipack. Thanks for the hint, downloading now, but the routine I am tring to use, I have used many times before on Delphi, will give your suggestion a try. scamb09 ---------------------------------------------------------------------- ezlage · 2016-06-05 16:13 I understand. I'm creating a LPK similar to UniqueInstance, with more options, like instances counting and limit them to a license, stop the first and continue the job from next instances, and some more useful things for me. If your problem persists, maybe I can finish my package including a solution for your case. Please, sorry by my poor english. ---------------------------------------------------------------------- rvk · 2016-06-05 16:19 Ok, I think I have a (partial possible) reason. QuoteFor backward compatibility with Windows 3.0, SendMessage will not return until all of the top level windows in the system have responded to your broadcast.http://stackoverflow.com/a/1956702/1037511 So there might be a top-level window without GetMessage or PeekMessage. I can't imagine what kind of window that would be. The only window I could think of is that Lazarus itself creates a thread/window which doesn't implement that GetMessage yet until Application.Run is run. But I'm also puzzled why it runs fine for me then. You could try using SendMessageTimeout(). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  Dummy: DWORD;//...  if GetLastError = ERROR_ALREADY_EXISTS then  begin    //Windows.SendMessageTimeout(HWND_BROADCAST, AppMessage, 0, 0);    Windows.SendMessageTimeout(HWND_BROADCAST, AppMessage, 0, 0, SMTO_NORMAL or SMTO_ABORTIFHUNG, 1000, Dummy);    Exit;  end;But that would always mean a delay of 1000ms. Although... that might not be a problem because it's in the background... You could try to find out what kind of window is not responding to that broadcast. (Does Lazarus create a hidden window/thread before Application.Initialize is run??) ---------------------------------------------------------------------- scamb09 · 2016-06-05 16:32 Quote from: ezlage on June 05, 2016, 06:13:45 pmI understand. I'm creating a LPK similar to UniqueInstance, with more options, like instances counting and limit them to a license, stop the first and continue the job from next instances, and some more useful things for me. If your problem persists, maybe I can finish my package including a solution for your case. Please, sorry by my poor english. How easy was that, problem solved! Many thanks for this simple to use component, and if you do finish your version I will be interested. Again, many thanks to you all. scamb09. ---------------------------------------------------------------------- scamb09 · 2016-06-05 16:41 Quote from: rvk on June 05, 2016, 06:19:15 pmYou could try using SendMessageTimeout(). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  Dummy: DWORD;//...  if GetLastError = ERROR_ALREADY_EXISTS then  begin    //Windows.SendMessageTimeout(HWND_BROADCAST, AppMessage, 0, 0);    Windows.SendMessageTimeout(HWND_BROADCAST, AppMessage, 0, 0, SMTO_NORMAL or SMTO_ABORTIFHUNG, 1000, Dummy);    Exit;  end; Fantastic, this also works, you guys are great, now I have two solutions. Many thanks all. scamb09.