Click here to Skip to main content
15,895,142 members
Articles / Programming Languages / C#

.NET Object Spy and InvokeRemote

Rate me:
Please Sign up or sign in to vote.
4.79/5 (62 votes)
5 Mar 2007CPOL8 min read 262.4K   13.4K   164  
A tool for browsing public and private members in any running .NET application (and a generic InvokeRemote method that wraps the code injection).
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Collections;
using System.Reflection;

namespace Bds.ObjectSpy
{
    class ObjectSpyEvaluator
    {
        private static Regex _indexRegex = new Regex(@"\[\d+\]$"); // Matches e.g. "[123]" in the end of a string
        private static Regex _argRexex = new Regex(@"\(\)$"); // Matches "()" in the end of a string

        // This method is the entry point for the remote invocation
        public static string Evaluate(IntPtr hWnd, string expression)
        {
            object obj = Control.FromHandle(hWnd);

            if (expression != String.Empty)
            {
                string[] members = expression.Split('.');
                foreach (string member in members)
                {
                    try
                    {
                        obj = EvaluateMember(obj, member);
                    }
                    catch (Exception ex)
                    {
                        return "ERROR: Evaluating '" + member + "' failed: " + ex.Message;
                    }
                }
            }

            return (obj != null ? obj.ToString() : "(null)");
        }

        private static object EvaluateMember(object obj, string memberName)
        {
            // Extract index, if any
            Match indexMatch = _indexRegex.Match(memberName);
            if (indexMatch.Success)
            {
                memberName = memberName.Substring(0, indexMatch.Index);
            }

            // Extract arguments, if any (note: we only handle "()" currently)
            Match argMatch = _argRexex.Match(memberName);
            if (argMatch.Success)
            {
                memberName = memberName.Substring(0, argMatch.Index);
            }

            // Invoke the member, i.e. field, property or method (without parameters and parenthesis)
            obj = obj.GetType().InvokeMember(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.GetField | BindingFlags.InvokeMethod, null, obj, null);

            // If we had an index, apply it now
            if (indexMatch.Success)
            {
                string indexStr = indexMatch.Value.Substring(1, indexMatch.Length - 2);
                int index = Int32.Parse(indexStr);
                obj = GetObjectAtIndex(obj, index);
            }

            return obj;
        }

        private static object GetObjectAtIndex(object obj, int index)
        {
            if (obj is IList)
            {
                // Use the index directly
                return ((IList)obj)[index];
            }
            else
            {
                // Assume obj implements IEnumerable, so we have a "pseudo" index
                int i = 0;
                foreach (object tmpObj in (IEnumerable)obj)
                {
                    if (i == index)
                    {
                        return tmpObj;
                    }
                    i++;
                }
                throw new IndexOutOfRangeException("Index was " + index + " but object contained " + i + " items only");
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer
Denmark Denmark
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions