Error Lookup

The Error Lookup program is one of those simple utilities that are simple in design and an obvious addition to the developer's toolbox once you think about it. This tool is important to the managed application developer because you don't have as many resources for locating error information—at least not without specifically adding them to your application. Generally, you'll receive error information as a number from the Win32 API. You must either locate the error number in the help file (an impossible task) or add code to locate the text version of the error message to your code. Fortunately, Error Lookup presents a third solution.

All you need to do to use Error Lookup is start the utility from within the IDE. Type the number into the Value field and click Look Up to see the associated text. Figure 3.12 shows an example of an error message output.

Error Lookup will locate all general Win32 API error messages as configured when you start it. However, you won't always work with generic modules. Sometimes, as in the MMC example later in the book, you'll need to work with specialized DLLs. In this case, you'll want to add that module to the list of modules that Error Lookup uses as a resource. All you need to do is click Modules, add the name of the DLL with the DLL extension to the Module Name field (include path information when necessary), click Add, and then click OK. Error Lookup will also look in the added modules when it can't find an error number in the general message list.

Spy++ is a complex utility that can give you more information about your application than you might have thought possible. This section is going to give you a very brief overview of this utility. What I'll do is point out some of the more interesting features that will make working with the applications in this book easier. Make sure you take time to work with this utility further once you've learned the basics. We'll also spend more time with it as the book progresses.

The first thing you'll see when you start Spy++ is a list of windows. A window can be any number of object types, but the most familiar is the application window. Figure 3.13 shows an example of what you might see when you start Spy++ with the ShowMessage sample application running.

SjWe-'me* iyy |Wtn+ww t|

{Zftsffi

15 V> Ww W*» Mar

. # M

1 c ^ o rj n M

cm

- I««

A

/ ill -.1 IV v

3 A*iJuMaacroi|4 -atf-WfAwrfmtttUT'CN«»! - • »xr-KMAw* w.va*»iorgcr mu.«»**« I c ncoai

_\

IrvN^pwn

•LM

Figure 3.13: Spy++ allows you to take your application apart and see it from the Windows perspective.

Notice that Spy++ shows two windows that belong to the main application window—all of which are components on the dialog box. In this case, the Test and Quit buttons are both considered windows. The buttons are all objects derived from the WindowsForms10 class, which means that Spy++ is right on track displaying the information as it has. Note that the class will vary by language, version of the .NET Framework, and even by the type of application. For example, unmanaged Visual C++ applications derive their windows from the CWindow class.

Tip Spy++ often displays more windows than you think are open on the client machine. Some of these windows are hidden from view; others appear in areas such as the Taskbar Tray (Notification Area for Windows XP developers). You can always ask Spy++ to show you where a window resides by right-clicking the window entry and choosing Highlight from the context menu. This menu also contains a Refresh option to update the Spy++ display (it's static) and a

Messages option that opens a new window to track messages for the selected window. Working with Window Properties

Windows are a central part of working with Spy++. They represent the method you'll normally use to begin deciphering how an application works and how well it runs. It makes sense, then, that you can access every aspect of an application, its child windows, processes, and threads through the Window Properties dialog box shown in Figure 3.14.

Window Properties

G«<Mj | Syn |

WnJoMt | Cl*n | P»oc»i! |

Menage Bat Dcmontftetcri

000C018C

Wntohtt

OOlTSOSfUneohl

|1I0 144)4410 Mil XOJOO

Headed Reel

1110. 14SH410 «451 XO.XC

dertRect

1« »H296 2». 292x2«

Inaunc* Haxle

00400000

Mini H«4t

ooooajoo

UMDM

ocoooooo

WnfenBj*«

Figure 3.14: The Window Properties dialog box enables you to learn more about the structure of your application.

Accessing this dialog box is easy: All you need to do is right-click the window you want to view, then choose Properties from the context menu. You can also access this dialog box using the View 0 Properties command.

The General tab of the Window Properties dialog box tells you about the window as a whole. It includes the window's display name, the window handle, the virtual address of the window procedure, the size of the rectangle used to display the window (both present and restored sizes), and various other pieces of general application information.

The Styles tab contains a list of the window style constants used to create the window. For example, you'll commonly find WS_VISIBLE as one of the items in the list unless you're dealing with an invisible window. This same tab contains extended styles for the window like WS_EX_APPWINDOW. These constants should be familiar to someone with C/C++ programming experience since you need them to display windows in most cases.

The Windows tab contains five entries. You can move between windows at the same level by clicking the links in the Next Window and Previous Window fields. The Parent Window field will contain a link if this is a child window or (None) if this is a main window. If the window contains child windows (like the components for the ShowMessage program), you'll see an entry in the First Child field. Clicking this link will take you down one level in the hierarchy so that you can examine any child windows that belong to the current window. Finally, the Owner Window field will contain a link if another window owns the current window—except for the Desktop, in which case the field displays a value of (None).

The Class tab tells you about the class used to create the window. For example, the main window for the ShowMessage program uses the WindowsForms10.Window.8.app1 class, while the components are all listed as being part of component-specific classes like the BUTTON class (actually the

WindowsForms10.BUTT0N.app1 class) used for the Quit button. You'll also find class-specific information such as class style codes, number of data bytes used by this class instance, a window instance handle, number of bytes used by the window, and window details like the name of any associated menus.

The Process tab provides a list of process IDs and thread IDs associated with the current window. Clicking the links associated with each field will display the properties dialog associated with the process or thread ID. We'll look at this properties dialog in more detail in the Viewing Processes section that follows.

Viewing Messages

Windows runs on messages. Every activity that the user engages in generates a message of some sort. It's important to monitor those messages and see how your application reacts. For example, if you expect a certain message to get generated when the user clicks a button, you can monitor the message stream to see if it really does get sent.

There are a number of ways to display the Messages window for a window that you're debugging. You could right-click on the window and choose Messages from the context menu. However, in this particular case, the best way to start the message monitoring process is to use the Spy 0 Log Messages command. (You won't see the Message Options dialog box when you use the context menu method of displaying the Messages window.) Using this command will display the Message Options dialog box shown in Figure 3.15.

igure 3.15: The Message Options dialog box enables you to configure Spy++ for message snooping.

Notice that Selected Object frame on the right side of the dialog box. This frame provides you with information about the object that you've selected. This additional information enables you to determine if this is the window that you want to monitor. The Finder Tool on the left side of the dialog box is interesting as well. Drag this tool to any displayed window, then release the mouse button, and the information on the right side will change to match the data for that window. (Spy++ highlights the windows as you drag the mouse cursor over them so that you can see which one is being selected.) The Windows tab also helps you to choose additional windows. For example, you may want to monitor the child windows as well as the parent window for a specific kind of message.

There are 1,009 different messages that Spy++ can track for the average window. The Messages tab shown in Figure 3.16 gives you some idea of just how extensive the message coverage is.

igure 3.16: The Messages tab helps you select the messages that you want to track for a window.

Needless to say, you could end up with a lot of useless tracking information if you don't trim the number of messages down to a more reasonable selection. That's why the Messages tab is so important. This tab helps you choose which messages Spy++ tracks in the Messages window. You can choose messages singularly or by group. A Select All button chooses all of the messages, while a Clear All button clears the current selections. Make sure you tune these settings before you display the Messages window or your chances of getting the input you need are very small indeed.

It's also important to determine how you want information displayed in the Messages window. In most cases, the default options on the Output tab will work just fine. Spy++ assumes that you want to display only decoded information and only on screen. However, there are options for displaying raw message information. You can also choose to send the output to a file as well as to the screen.

Once you have the options set for your Messages window, you can click OK and Spy++ will display it for you. Figure 3.17 shows an example of what a Messages window would look like if you choose to monitor a subset of button and mouse events. As you can see, just selecting these two message groups generates a lot of message traffic.

xnr, rai a i-'-.i-.m:«,'; iccoor . liv*-. id i itrw- «Iir.iii/-M<r

*!«;• wsj a rv*'«oucto.t*« «p. mo ¿v« n ■.30MS ni] srw> «UKUM ft««»: DCCD«f»:;«!.,^ts«l OW) »fl^tf * «MO

■ urn iii i »♦ <iiiviii^m<y ■lllrf'm *

»■w xir. nv Mi*>tni#>,*/nn wm •/., n p w <oa;<»,': koo i«:<; r «CUKtOt- f»#«r-. fv^ k^^. boi ft* «41Nr K W- Hill rfto.-fe r^v ♦CLKT'tv;Koav.. f-w MM WIIA»^.

tmd Ml 1» i M-w«aM m ii ft-ft*"PfclCM'WO'l^'

^«M^tasftiai^vw.uiTrcscowii n vm muiocr mutt>«« ha ¿crvtft i «••cuK

i'm» «ivhiam^uii^mm^mw fsK.^uiiuMWft.«»^.»^« M0US€«O<*

<iirv it i> Mft- iiiiMt^ii/Mki t v4«.»u«ii-»niri «M.U jt *OIOO>»N rfh* n nrtcwno'i^

Sal "Ir.C

Ni^MI

igure 3.17: The Messages window will display the messages that you choose to monitor for an application.

In this case, I clicked the Test button several times and moved the mouse around on screen. Notice that the log entries contain the handle of the window where the action occurred, the action performed (mouse button up or down, mouse move, or set cursor), and the position where the action occurred. Obviously, this is a simple test case, but it's also easy to see that monitoring messages can provide you with very important debugging clues for your application.

Viewing Processes and Threads

Every application you create will have at least one process and one thread. Consider a process as the overall application identifier, while a thread consists of a particular set of actions taking place within that process. In a multi-threaded application, each thread of execution is performing a single task that affects the application (the process) as a whole.

Spy++ provides methods for monitoring both processes and threads. All you need to do is use the Spy 0 Processes or Spy 0 Threads command to display the appropriate window. Figure 3.18 shows an example of the Processes window.

It's interesting to note that the Processes window also contains a list of any threads owned by the process in a hierarchical format. For this reason, you'll normally want to use the Processes window over the Threads window. You get more information in an easier-to-use format using the Processes window. We'll discuss the Processes and Threads windows in more detail as the book progresses.

4UJVH* VT' ' ['1nr»n 1J

ETfefic

%w 1MA vr«k-

. m n

n & o rr rA m

tfLii

6 'kM^jaxxm:« © 'kM^iaoxicc i '.McrAfeCt^t H 000X11« V^' *rdnJm»i n ■■»'«•»»OOMCIX «Wok

•IIHTTCfc«*« il«tU"M ««1

"" OOOKIM XXH. <«'>*•' U< I-4M «'«a«!!» — i jxncr KII.MU

*».i«xn>oi

6 -kM*iaagc7X un

!*•* r^ti WilM

Figure 3.18: Spy++ will allow you to monitor both threads and processes.

Figure 3.18: Spy++ will allow you to monitor both threads and processes.

Was this article helpful?

0 0

Post a comment