A lightweight trace facility is less likely to distort performance in the final stress of debugging.
Sometimes you may find yourself wanting to trace an application in its Release configuration. In a Release-mode application you may not be able to use a debugger, and tracing to a log file might slow down the program too much. The utility presented here lets Windows users trace an application in its Release configuration, without expensive writes to a log file.
The following code provides a Windows user with trace information based on WM_COPYDATA message processing. The trace utility is provided in two parts. The first part is a debug window, which runs as a stand-alone application (QMonitor.exe). It will receive trace output, via the Windows messaging system, from the application being traced. The second part is an API that the application uses to send out trace data as a Windows message.
The application under test can produce trace information in the following manner:
#include "QMonitorAPI.h" void MyFunc() { Tracer t("MyFunc"); ... Display("i=%d s=%s", i, d); ... }The output appears as in Figure 1.
The Tracer object shown in the snippet above calls the Display function internally, during construction and destruction. Listings 1 and 2 show the source code for QMonitorAPI.h and QMonitorAPI.cpp.
As you can see, if QMonitor.exe is not running, then FindWindow will fail in the Display function, thus generating no output [1].
Listings 3 and 4 show a partial implementation of QMonitor.exe using MFC. For brevity only the Dialog derived class is presented, and just the implementation of the OnCopyData member function. The rest can be easily recreated. The source code is self-explanatory. A plain ListBox control uses the following style flags: sort disabled, selection = none, and both scrolls enabled.
In my experience the performance overhead of the extra code involved is insignificant. This approach can be used in many projects to display trace data in Release mode applications.
Note
[1] In a very rare case on Windows NT, FindWindow might fail for an existing window when the application runs under a different account than the one bound to the current desktop. For example, the application may be an NT service or spawned by a service like a telnet server. To make it work, you need to set the process's window station to "WinSta0" and set the thread's desktop to "Default" at the beginning of the program by using SetProcessWindowStation and SetThreadDesktopWin32. For details, see the article, "Interacting with User in a Service," on the MSDN CD-ROM.
Boris Bromberg has an M.Sc. from the Moscow Institute of Petrochemical and Gas Technology. He has been working as a software developer for over ten years in the oil-gas, automation, and banking industries. He currently works as a Senior Software Developer for Q.Data Inc, Markham, Ontario, Canada, where he develops applications using Visual C++ on Windows NT. He can be reached at brom@interlog.com.