string name = String.IsNullOrEmpty(cproxy.GetComponentName()) ?
"<noname>" : cproxy.GetComponentName();
TreeNode node = procnode.Nodes.Add(cproxy.Handle.ToString(),
name + " [" + cproxy.GetClassName() + "]");
node.Tag = cproxy;
...
if (treeWindow.Nodes.Count == 0)
{
treeWindow.Nodes.Add("No managed processes running.");
treeWindow.Nodes.Add("Select View->Refresh.");
}
this.treeWindow.EndUpdate();
Figure 5 Listing Windows by Process
using System;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using Microsoft.ManagedSpy;class Program
{
static void Main(string[] args)
{
Dictionary<int, int> topWindowCounts =
new Dictionary<int, int>();foreach (ControlProxy proxy in ControlProxy.TopLevelWindows)
{
if (!topWindowCounts.ContainsKey(proxy.OwningProcess.Id))
{
topWindowCounts.Add(proxy.OwningProcess.Id, 0);
}
topWindowCounts[proxy.OwningProcess.Id]++;
}foreach (int pid in topWindowCounts.Keys)
{
Process p = Process.GetProcessById(pid);
Console.WriteLine("Process: " + p.ProcessName +
" has " + topWindowCount[pid].ToString() +
" top level windows");
}
}
}
Figure 6 ControlProxy Properties
|
Property |
Description |
| IntPtr Handle | Returns the underlying HWND of the Control. This would be equivalent to accessing the Handle property on the Control. |
| array<ControlProxy^>^ Children | Returns an array of ControlProxy classes that represent the child windows of the Control. |
| Process^ OwningProcess | Returns a Process object that the Control is running in. |
| bool IsManaged | If the window that the ControlProxy is examining represents a managed System.Windows.Forms.Control, then the value returned is true. Otherwise it is false. Most ControlProxy methods only work if the window is a System.Windows.Forms.Control. |
| Type^ ComponentType | Returns the Type of the Control. Note that this Type is originally from an Assembly loaded in the process being spied. The Assembly and Type are reloaded in the spying process when the ControlProxy is first created. |
| ControlProxy^ Parent | Returns the parent window as a ControlProxy. Use Parent and Children to navigate the window chain of the process. |
Figure 7 Modifying Other Instances of an Application
private void button1_Click(object sender, EventArgs e)
{
foreach (Process p in
Process.GetProcessesByName("WindowsApplication1"))
{
if (p.Id != Process.GetCurrentProcess().Id)
{
ControlProxy proxy =
ControlProxy.FromHandle(p.MainWindowHandle);
string val = (string)proxy.GetValue("MyStringValue");
MessageBox.Show("Changing " + val + " to " + MyStringValue);
proxy.SetValue("MyStringValue", (object)MyStringValue);
}
}
}public string MyStringValue
{
get { return this.textBox1.Text; }
set { this.textBox1.Text = value; }
}
private void button1_Click(object sender, EventArgs e)
{
Process[] procs = Process.GetProcessesByName("Multiply");
if (procs.Length != 1) return;
ControlProxy proxy =
ControlProxy.FromHandle(procs[0].MainWindowHandle);
if (proxy == null) return;//find the controls we are interested in...
if (cbutton1 == null)
{
foreach (ControlProxy child in proxy.Children)
{
if (child.GetComponentName() == "textBox1") {
textBox1 = child;
}
else if (child.GetComponentName() == "textBox2") {
textBox2 = child;
}
else if (child.GetComponentName() == "textBox3") {
textBox3 = child;
}
else if (child.GetComponentName() == "button1") {
cbutton1 = child;
}
}//sync testchanged on textbox3 so we can tell if it has changed.
textBox1.SetValue("Text", "5");
textBox2.SetValue("Text", "7");
textBox3.SetValue("Text", "");
textBox3.EventFired +=
new ControlProxyEventHandler(textBox3_EventFired);
textBox3.SubscribeEvent("TextChanged");
}
else textBox3.SetValue("Text", "");//now click on the button to start the test...
if (cbutton1 != null)
{
cbutton1.SendMessage(WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
cbutton1.SendMessage(WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
Application.DoEvents();
}if (result == 35) MessageBox.Show("Passed!");
else MessageBox.Show("Fail!");
}void textBox3_EventFired(object sender, ProxyEventArgs ed)
{
int val;
if (int.TryParse((string)textBox3.GetValue("Text"), out val) )
{
result = val;
}
}