Jump to content

How do I handle WM_CLOSE the correct way?


Recommended Posts

How can my LabVIEW EXE application handle the windows WM_Close message correctly?

 

I have tried the Windows Messaging Queue library without any resolution to this problem.

 

The behavior I'm seeing is that my application window closes but the app remains running as can be seen by looking at the process list in Windows Task Manager. The images below don't show it but I've added the Quit LabVIEW function to exit the app. So far I've tried:

  • Creating a loop that monitors the windows message queue:
post-2-0-17138600-1359585876_thumb.png
  • Application Instance Closed? Event:

post-2-0-07723600-1359585932.png

  • Panel Close? Event:

post-2-0-73383900-1359585981.png

 

I've read this thread but it didn't seem to address the issue head-on. Or I didn't see what the resolution was.

Any help is appreciated. Thanks.

Link to comment

The simple answer is that the 'correct' way to handle this message is indeed with the Application Instance Close? event.  I can pump this message directly to a LV executable and it fires the event every time (so far).

 

There is a bit of a goof in your top image, the code for WM_CLOSE is 0x10 or 16, either change the radix of your Case Structure (yes) or change the value.  Unless for some reason you have registered and are looking for WM_ENABLE.

 

Is this an intermittent problem?  By that I especially mean does it happen to some executables all of the time, all executables some of the time, or some executables some of the time?  And how exactly are you triggering the shutdown that fails to kill the process?  Perhaps it is not sending the message you expect.

 

Of course while testing I notice several Chrome processes running on my machine with the browser closed so perhaps it is not so uncommon.

  • Like 1
Link to comment

The simple answer is that the 'correct' way to handle this message is indeed with the Application Instance Close? event.  I can pump this message directly to a LV executable and it fires the event every time (so far).

 

The Application Instance Close? event doesn't work. If you can attach an example that works, that would be nice, but my tests show it not working.

 

You're correct in catching my bug. Nice to have a second set of eyes :) . That was the problem. After I fixed that it worked as expected.

 

So the updated diagram for anyone else needing this:

 

post-2-0-17260400-1359676373_thumb.png

Link to comment

Awesome thanks. I think I figured out why Application Instance Close? wasn't working for me.

 

So the WM_CLOSE message requires a handle to a window name. My executable had a custom window name. I was using this as the window name. So the window was closing fine but the event was not firing and the app remained in memory.

 

In your example, if you set the VI title name to CloseMe, instead of the default CloseMe.vi, then it won't work. So the message gets sent to the window instead of the app, which is also called CloseMe.exe.

 

Now I just have to make sure that my window title doesn't match my exe name.

Link to comment
The Application Instance Close? event doesn't work. If you can attach an example that works, that would be nice, but my tests show it not working.

Michael,

 

could you explain 'Does not work'. What do you expect from this event?

It should get triggered when Windows wants to close an application (I get this event when I shut down my computer).

Since you Discard the event your application is ignoring this event, and you should close your app yourself.

 

Ton

Link to comment

Ton definitely has pointed out one potential pitfal in your code. The Panel:Close? event always works for me. if you tell LabVIEW to discard it you have to make sure that your state machine then goes into a clean-up state, that eventually closes the front panel explicitly and then also terminates the state machine loop. If your front panel is the top level VI too, the code after the VI:Close method won't be executed in an executable as the LabVIEW runtime engine will be shutdown immediately after the last window is gone, but it helps when the application is run in the development environment.

 

I have personally only used the Application:Close? event in deamon like applications that do not show a front panel by default. The proper operation when a user requests to shutdown the machine is that Windows sends a WM_CLOSE message to every application window, which will result into a Panel:Close? event in the LabVIEW VI, and then a WM_QUIT to the main instance which will trigger the Application:Close? event. But if you handle all the Panel:Close? events properly there should be no panel (hidden or not) left over at the time the Application:Close? event will trigger. On the other hand adding both Panel:Close? and Application:Close? to the state machine handling and going into a proper VI terminate state when you chose to discard that event, wouldn't hurt either.

Link to comment

If I have an application that has lengthy processes (>10 seconds), or when it's unlikely that I regurarly (agian at least every 10 seconds) hit the main event loop, then I have a dedicated 'Terminate'  event loop, that's monitoring both the Application:Close? and Panel:Close? events and will signal an abort to these lengthy processes to stop prematurely. 

 

Ton

Link to comment
So the WM_CLOSE message requires a handle to a window name. My executable had a custom window name. I was using this as the window name. So the window was closing fine but the event was not firing and the app remained in memory.

 

In your example, if you set the VI title name to CloseMe, instead of the default CloseMe.vi, then it won't work. So the message gets sent to the window instead of the app, which is also called CloseMe.exe.

 

Now I just have to make sure that my window title doesn't match my exe name.

 

Should have been an obvious assumption on my part that you were changing the name.

 

If you remember the funny business with the 'HideRootWindow' ini key and multiple entries in the taskbar, this issue is almost certainly related to that.  At any rate, an executable appears multiple times in the windows list.  The name of the first entry (numerical order) is the window title.  The other two entries have the name of the executable without the extension.  The proper handle happens to be the second one in the list.

 

When you change the window title to match the name of the executable without the extension 'CloseMe' in this case, then FindWindow will now return the handle to the first window instead of the second.  Now you are pumping messages to the wrong one and havoc ensues.  Change the title to 'Change Me' and still use 'ChangeMe' to find the Handle and you are all set.

 

My personal naming convention combined with the very small number of times I have pumped messages to executables has kept me safe from this behavior.  When naming files I leave out spaces, but in the window titles I use them.  I'd rather be lucky than good.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.