Zach Burlingame
Programming, Computers, and Other Notes on Technology

April, 2011Archive for

Signal a Windows Application to Terminate from Another Process

Tuesday, April 12th, 2011

In usual fashion, I’ve written a complete sample application. The source code is available here.

Sometimes you want detect if a specific application is running and signal it to terminate in a clean manner. It may be your upgrade installer making sure that the current version of the application is not running before performing it’s upgrade. It could be a long running helper process that needs to be signaled when it is no longer needed. Whatever it is, one method to accomplish this is to use a uniquely named shared event.

NOTE: The method I’m about describe only works for processes who’s source code is under your control. If you want a way to generically signal any running process (e.g. search for a list of running OS and 3rd-party processes that might interfere with your installer and signal them to terminate) then this is not what you want.

A Bit of Background

A similar problem to the one we are discussing here is signaling all running threads to terminate. The idea is that there could be multiple places in the code where an application might need to initiate a process termination, but you need to synchronize that across all threads and allow them to perform their own cleanup. One way to do this is have long running threads periodically check to see if they should shutdown by checking to see if an event is signaled.

Windows Events

On the Windows platform when an event object is created it is done so in an object namespace. In addition to the ability to create your own private namespaces, there are also two special kernel object namespaces – Global and Local. There is a Local namespace associated with each client session on the machine. By default the Local namespace is used for any object created by a process that was started under a client session. As the name implies, there is a single Global namespace system-wide. The Global namespace is used primarily by system services but can also be used by client session processes by prefixing the event name with “Global\”.

The CreateEvent function is used to (surprise!) create an event. It can create either a named or unnamed event. If you use a named event and the named event already exists before the call to CreateEvent then the function returns a handle to the existing object and GetLastError returns ERROR_ALREADY_EXISTS. By creating a named event, the OS enforces that only a single instance of the object exists in that namespace at any one time and that all processes referring to that event will receive a handle to the same instance, creating a form of interprocess communication. Thus if the Local namespace is used, then the event object is shared across all processes that refer to it in that client session. Likewise if it is created in the Global namespace, it is shared across all processes that refer to it on the entire system.

There are two reset mechanisms used by event objects: AutoReset and ManualReset. An AutoReset event will automatically be reset to a non-signaled state as soon as single waiting thread is released. A ManualReset event requires a call to ResetEvent in order to be returned to a non-signaled state.

Lastly, an event can be set to either the signaled or non-signaled state when it is initially created.

Signal Terminate via Named Event Object

By combining the concept of checking for a signaled event to determine when to shutdown and using a named event object, it is possible to signal one process to shutdown via another process. By using an event object created in the Local namespace you can signal processes across a single client session. Conversely by using an event object created in the Global namespace you can signal processes across the entire system.

When creating the terminate event object you want to use a ManualReset event created in the non-signaled state initially. If it were instead an AutoReset event, then as soon as one of the waiting threads from any of the processes was released, the event would return to the non-signaled state. This would result in only a single thread receiving the terminate message, which is not what we want. As for the state, if it were instead initially signaled then the threads would begin terminating as soon as they started running and began checking the event.

Below is an example of creating a named ManualReset event in the Local object namespace that is intially non-signaled. I’m using a GUID for the object name to avoid the potential for unintentional naming collisions with other applications. While a GUID is probably overkill, using a name like “shutdown_event” probably isn’t a good idea.

static const LPCSTR fp_terminate_event_name =
   "Local\\0BAF85D0-0786-4cbf-AF3B-E36322382DBF";

// Create a manual-reset event in the non-signaled state
fh_terminate_event =
  CreateEvent( NULL,                              // default security attributes
               TRUE,                              // manual-reset event.
               FALSE,                             // initial state is non-signaled
               TEXT( fp_terminate_event_name ) ); // object name

Silently Terminate on Abort/Unhandled Exception in Windows

Monday, April 4th, 2011

When an application has an unhandled exception or a system routine calls abort (e.g. strcpy_s with a buffer size too small) the system is left to deal with the mess. Usually part of the process is displaying a crash dialog to the user notifying them that the application has unexpectedly terminated, creating a crash dump file, and possibly checking with Microsoft for a solution if it’s a known problem. Sometimes however, you’d prefer that your application not crash in such an “in your face” manner, such as when you spawn child or helper processes as part of a larger system which can manage the process termination on its own. The first thing you should do is focus on making your application NOT crash in the first place!

However, there are times when things may be beyond your control (e.g. making calls to a third-party library that sometimes wigs out on you) or you just want it as a fail safe in case. You can use you own unhandled-exception handler for instance, to perform custom logging. There are several manners in which the system and the C-runtime can notify the user of an abnormal application termination. In order to suppress all of them, most of the time, I use the following routines:

You’ll note that I said most of the time because this method doesn’t guarantee that all of them will be suppressed. Other libraries you call could overwrite your handlers for one. Secondly, the /GS (Buffer Security Check) compiler flags causes the CRT to directly invoke Dr. Watson in the case of a buffer-overrun for security purposes. To prevent and detect other libraries from overwriting your exception filter, you can use API hooking.  When it comes to the CRT directly calling Dr. Watson, this is by design and Microsoft has no plans of changing it.

Here’s the important parts of the source. The entire project is available here.

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

// Function Declarations
void suppress_crash_handlers( void );
long WINAPI unhandled_exception_handler( EXCEPTION_POINTERS* p_exceptions );

int main( int argc, char* argv[] )
{
  // Suppress C4100 Warnings for unused parameters
  (void*)argc;
  (void*)argv;

  suppress_crash_handlers( );

  abort( );

  return -1;
}

void suppress_crash_handlers( )
{
  // Register our own unhandled exception handler
  // http://msdn.microsoft.com/en-us/library/ms680634(v=vs.85).aspx
  SetUnhandledExceptionFilter( unhandled_exception_handler );

  // Minimize what notifications are made when an error occurs
  // http://msdn.microsoft.com/en-us/library/ms680621(v=vs.85).aspx
  SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX ); 

  // When the app crashes, don't print the abort message and don't call Dr. Watson to make a crash dump.
  // http://msdn.microsoft.com/en-us/library/e631wekh(v=VS.100).aspx
  _set_abort_behavior( 0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT );
}

long WINAPI unhandled_exception_handler( EXCEPTION_POINTERS* p_exceptions )
{
  // Suppress C4100 Warnings unused parameters required to match the 
  // function signature of the API call.
  (void*)p_exceptions;

  // Throw any and all exceptions to the ground.
  return EXCEPTION_EXECUTE_HANDLER;
}

Capturing Windows Power Events in a Console Application

Friday, April 1st, 2011

So you’re writing a console application and you think “Hey, it would be great if I could catch power events so I could:”

  • get all my data in a sane state before a shutdown
  • defer heavy processing until we are back on AC power
  • reinitialize network resources if we just returned from an unexpected sleep state

You fire off a Google search for “Windows Power Events” and you quickly come across this MSDN article that tells you that you need to call the RegisterPowerSettingNotification API function. Super! Then you quickly notice a few problems:

  1. The RegisterPowerSettingNotification function takes either a Window Handle or a SERVICE_STATUS_HANDLE.
    1. You’re a console application so you don’t have a Window handle.
    2. You aren’t running as a service so you can’t call RegisterServiceCtrlHandlerEx to get a SERVICE_STATUS_HANDLE
  2. The minimum supported client is Windows Vista and you would like to at least support Windows XP forward.

Ahh, crap. As far as my (prolonged) search results show, there is no way to receive power events without either having a window handle, running as a service or being a device driver. Period.

Enter the Hidden Window

The best solution to this problem that I’ve come across is to create a hidden window. It seems like such a hack, but it does work! There are a few things you need to be aware of when using this method. As per MSDN recommendations one should generally use a single thread to create all of their windows. The system directs messages to individual windows, so you need to process the message queue on the same thread that created the window*. In a Windows application this is generally all done in WinMain. However for a console application, we likely have other things going on in the main thread, especially if we want the power event notifications to be available early on in the application startup process. Therefore I create a separate thread which will create the hidden window, register for power events, and then continuously process the message loop.

* In fact, the message queue is really the thing that we need in all this so that we can receive the WM_POWERBROADCAST messages. AFAIK, the only ways to get a message queue are via creating a window or running as a service.

Power Events

After you have a thread and create a window you will automatically receive the WM_POWERBROADCAST messages in your message queue for the following power events:

Windows 2000 and Later
PBT_APMPOWERSTATUSCHANGE
PBT_APMRESUMEAUTOMATIC
PBT_APMRESUMESUSPEND
PBT_APMSUSPEND
PBT_POWERSETTINGCHANGE

Windows 2000, Windows XP, and Windows Server 2003 only
PBT_APMBATTERYLOW
PBT_APMOEMEVENT
PBT_APMQUERYSUSPEND
PBT_APMQUERYSUSPENDFAILED
PBT_APMRESUMECRITICAL

As you can see you may not even need to call RegisterPowerSettingNotification at all to get the events you need! In the case of Windows XP, these are all that you are going to get. On Vista and later however, you may still want to register for additional power events. There are several more event types that you can register for, which are described here. The ones that I cared about were:

GUID_ACDC_POWER_SOURCE
GUID_BATTERY_PERCENTAGE_REMAINING
GUID_MONITOR_POWER_ON

Show Me Teh Codez!

I wrote a sample console application in C that creates a hidden window on a separate thread, tries to register for additional power events if they are available, and then processes the message queue until the user enters input twice. It prints the message type of any window message it receives, but it provides additional information for power events. The application has both 32- and 64-bit builds and has been tested on Windows XP Home RTM 32-bit and Windows 7 Home Premium 64-bit.  It is written with Visual Studio 2010 but the code should work on previous versions of VS as well, you’ll just have to migrate the project and solution settings.

NOTE: In order to build for Windows XP RTM/SP1 I targeted the v90 (Visual Studio 2008) toolset. You must have Visual Studio 2008 installed to do this. See my post here on how and why I have to do this.

https://bitbucket.org/zachburlingame/windowspowerevents

Additional Resources