Click here to Skip to main content
11,578,954 members (66,415 online)
Click here to Skip to main content

A simple Windows forms properties spy

, 19 Aug 2003 CPOL 240.3K 8.3K 155
Rate this:
Please Sign up or sign in to vote.
A utility that can be used to spy the properties of any Windows forms control in the system.

Introduction

wfspy is a tool that helps you to view properties of any window form control in the system. I originally needed a small utility that will give me the managed control type name and the assembly name from a window handle, but gradually the tool became sophisticated enough to show all properties of a managed control (and optionally modify them). The only feature currently missing is the spying of events, which I plan to add later on.

wfspy uses Windows hooks to do its job. There are 3 assemblies in the project:-

  1. wfspy - a C# executable. This is the main application which has the UI code.
  2. wfspylib - a C# class library that contains utility functions and controls. This library gets injected into the process where the window belongs.
  3. wfspyhook - a managed C++ class library (.dll) which has code to inject a managed assembly into a process.

Using wfspy

The tool itself is pretty simple. The main window shows all the managed windows and their hierarchy, with the desktop window as the root. Any unmanaged window which is not parent of a managed window directly or indirectly, is not shown in the tree. The managed windows are shown using a slightly different icon. You can view the properties of the managed window by clicking on the details button in the main form. This brings up the dialog box with the property grid as shown in the second screen shot. The properties can even be modified in the grid. The next few sections discuss some important aspects of the implementation.

Enumerating managed windows

To enumerate managed windows, the standard Win32 API function EnumChildWindows is used. Unmanaged windows are filtered out from the tree if they don't parent any manage windows. In order to find out whether a window is managed or not, its class name is inspected. Any managed window that derives from System.Windows.Forms.Control has class name of the form WindowsForms10.<character sequence>.app<hash code of appdomain>. The character sequence in the middle is the class name of the window that is being superclassed like Button, SysListView32 etc. The following code determines whether a class name is managed or not.

private static Regex classNameRegex = new 
           Regex(@"WindowsForms10\..*\.app[\da-eA-E]*$", 
           RegexOptions.Singleline);
            
public static bool IsDotNetWindow(string className)
{
    Match match = classNameRegex.Match(className);
    return (match.Success);
}

Injecting a .NET assembly into a process

The technique to inject a .NET assembly in another process is slightly tricky as unlike functions in a regular Win32 DLL. .NET functions are compiled into native code during run time so the addresses are not static. This problem can be overcome by using managed C++, which allows managed global functions to be exported from an assembly. The exported function is actually a thunk that at runtime, points to the code generated by the JIT compiler. Thus the exported function can be used as a hook procedure. That function can be used to load another assembly. I will cover this technique in detail in another article.

Viewing properties of a control

Given an HWND the managed Control object can be found from the Control.FromHandle method. The properties of the control object can then be viewed in a property grid. There is a problem here the property grid should be created in the process where control object belongs. Luckily Windows allows a process to create child windows to a parent window belonging to another process. This technique is used to create the property grid from the target process, as a child of a form in the wfspy process. In order to do this the property grid control is placed in a user control. The CreateParams property of the user control is overridden.

protected override CreateParams CreateParams
{
    get
    {
        System.Windows.Forms.CreateParams cp = base.CreateParams;
        cp.Parent = parentWindow;
        RECT rc = new RECT();
        UnmanagedMethods.GetClientRect(parentWindow, ref rc);
        
        cp.X = rc.left;
        cp.Y = rc.top;
        cp.Width = rc.right - rc.left;
        cp.Height = rc.bottom - rc.top;

        return cp;
    }
}

The parentWindow is actually the handle of a form belonging to the wfspy process. This enables editable property view of a control in the wfspy application.

Known bugs/ remarks

The included wfspy works only for .NET windows 1.0.3705. If you want the tool to work with .NET 1.1, please build the code using VS.NET 2003. If you use wfspy to view a window in an application that uses a different .NET version, strange results may occur. Suggestions are welcome on how to fix this bug. I intend to update the article soon with the ability to spy control events.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rama Krishna Vavilala
Architect
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionMy Updates Now On GitHub Pin
cplotts15-May-12 8:06
membercplotts15-May-12 8:06 
AnswerRe: My Updates Now On GitHub Pin
cartspan15-Aug-12 11:17
membercartspan15-Aug-12 11:17 
GeneralRe: My Updates Now On GitHub Pin
cplotts15-Aug-12 12:27
membercplotts15-Aug-12 12:27 
GeneralRe: My Updates Now On GitHub Pin
SFWheeler15-Aug-12 13:30
memberSFWheeler15-Aug-12 13:30 
GeneralRe: My Updates Now On GitHub Pin
cplotts16-Aug-12 0:41
membercplotts16-Aug-12 0:41 
QuestionHow to get Window calc properties using reflection method. (Like button size, color, label color, font, font size). Pin
Member 426710927-Jan-11 17:47
memberMember 426710927-Jan-11 17:47 
QuestionHelp needed! Pin
mohandasgandhiG22-Jul-09 19:46
membermohandasgandhiG22-Jul-09 19:46 
GeneralCreating problem in Dual Core and Multithreaded application Pin
mohandasgandhiG21-Jul-09 1:24
membermohandasgandhiG21-Jul-09 1:24 
GeneralCool! Pin
Miguel Barros6-Mar-09 5:57
memberMiguel Barros6-Mar-09 5:57 
Generaldll are still in use after closing the application Pin
lsdisciples8-Jun-08 18:36
memberlsdisciples8-Jun-08 18:36 
QuestionCan use on WindowsMobile devices? Pin
Peter Rilling7-Feb-08 13:49
memberPeter Rilling7-Feb-08 13:49 
GeneralArticle on injecting assembly Pin
S. Senthil Kumar11-Oct-06 6:58
memberS. Senthil Kumar11-Oct-06 6:58 
GeneralRe: Article on injecting assembly Pin
Rama Krishna Vavilala11-Oct-06 8:18
memberRama Krishna Vavilala11-Oct-06 8:18 
GeneralRe: Article on injecting assembly Pin
tech.U29-May-07 16:10
membertech.U29-May-07 16:10 
QuestionAccessing the properties programatically? Pin
VanSkalen15-Sep-06 7:19
memberVanSkalen15-Sep-06 7:19 
AnswerRe: Accessing the properties programatically? Pin
Gopi Charan K12-Mar-07 0:29
memberGopi Charan K12-Mar-07 0:29 
GeneralVery nice!!!! Pin
Mike DiRenzo18-Aug-06 5:13
memberMike DiRenzo18-Aug-06 5:13 
QuestionUpdates Pin
cplotts20-Jun-06 7:46
membercplotts20-Jun-06 7:46 
AnswerRe: Updates Pin
Rama Krishna Vavilala20-Jun-06 7:59
memberRama Krishna Vavilala20-Jun-06 7:59 
GeneralRe: Updates Pin
cplotts20-Jun-06 8:22
membercplotts20-Jun-06 8:22 
GeneralRe: Updates Pin
lsdisciples28-Oct-07 10:38
memberlsdisciples28-Oct-07 10:38 
GeneralRe: Updates Pin
cplotts19-Apr-10 4:22
membercplotts19-Apr-10 4:22 
GeneralRe: Updates Pin
cplotts28-Oct-09 11:22
membercplotts28-Oct-09 11:22 
GeneralRe: Updates Pin
mohandasgandhiG2-Aug-06 19:20
membermohandasgandhiG2-Aug-06 19:20 
GeneralVS 2005 Pin
BuddyWork19-May-06 7:49
memberBuddyWork19-May-06 7:49 
GeneralRe: VS 2005 Pin
Rama Krishna Vavilala19-May-06 7:50
memberRama Krishna Vavilala19-May-06 7:50 
GeneralRe: VS 2005 Pin
BuddyWork19-May-06 22:31
memberBuddyWork19-May-06 22:31 
GeneralRe: VS 2005 Pin
mohandasgandhiG23-May-06 18:54
membermohandasgandhiG23-May-06 18:54 
GeneralAMAZING Pin
2006 Flauzer7-Apr-06 13:23
member2006 Flauzer7-Apr-06 13:23 
QuestionProblem with a different .NET version ? Pin
K.Yamaguchi11-Dec-05 0:03
memberK.Yamaguchi11-Dec-05 0:03 
GeneralWSPY -problem in release mode. Pin
mohandasgandhiG30-Jan-05 18:08
membermohandasgandhiG30-Jan-05 18:08 
GeneralRe: WSPY -problem in release mode. Pin
randob12-Mar-05 7:01
sussrandob12-Mar-05 7:01 
Questionhow to find a dialog window Pin
mahdi62b5-Oct-04 11:56
membermahdi62b5-Oct-04 11:56 
GeneralGreat tool! Spy++ suggestion Pin
Don Kackman7-May-04 3:12
memberDon Kackman7-May-04 3:12 
GeneralRe: Great tool! Spy++ suggestion Pin
mohandasgandhiG30-Jan-05 18:43
membermohandasgandhiG30-Jan-05 18:43 
GeneralRe: Great tool! Spy++ suggestion Pin
Don Kackman31-Jan-05 7:51
memberDon Kackman31-Jan-05 7:51 
Generalusing for all windows Pin
ploufs20-Feb-04 15:47
memberploufs20-Feb-04 15:47 
GeneralRe: using for all windows Pin
Behind The Scene29-Aug-06 16:58
memberBehind The Scene29-Aug-06 16:58 
GeneralControl Pin
olinat22-Sep-03 16:21
memberolinat22-Sep-03 16:21 
GeneralRe: Control Pin
neeleshd20-Feb-04 1:29
memberneeleshd20-Feb-04 1:29 
QuestionIntegrate with ControlInspector? Pin
swythan21-Aug-03 0:00
memberswythan21-Aug-03 0:00 
AnswerRe: Integrate with ControlInspector? Pin
Jabes21-Aug-03 0:32
memberJabes21-Aug-03 0:32 
AnswerRe: Integrate with ControlInspector? Pin
Rama Krishna22-Aug-03 3:30
memberRama Krishna22-Aug-03 3:30 
GeneralCool Pin
Stoyan Damov20-Aug-03 21:48
memberStoyan Damov20-Aug-03 21:48 
GeneralI like it! Pin
Holger Persch20-Aug-03 19:46
memberHolger Persch20-Aug-03 19:46 
GeneralClassic Pin
Kant20-Aug-03 13:10
memberKant20-Aug-03 13:10 
GeneralRe: Classic Pin
Rama Krishna21-Aug-03 4:13
memberRama Krishna21-Aug-03 4:13 
GeneralRe: Classic Pin
Kant21-Aug-03 15:59
memberKant21-Aug-03 15:59 
GeneralExcellent! Pin
jdunlap20-Aug-03 9:48
memberjdunlap20-Aug-03 9:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150603.1 | Last Updated 20 Aug 2003
Article Copyright 2003 by Rama Krishna Vavilala
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid