<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Brian McMaster's Blog on QA, .NET, and VS</title><subtitle type="html" /><id>http://blogs.msdn.com/brianmcm/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/brianmcm/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2005-12-12T21:01:00Z</updated><entry><title>Registry Fix for VS 2008 Intellisense Bug</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2009/08/25/registry-fix-for-vs-2008-intellisense-bug.aspx" /><id>http://blogs.msdn.com/brianmcm/archive/2009/08/25/registry-fix-for-vs-2008-intellisense-bug.aspx</id><published>2009-08-25T23:03:00Z</published><updated>2009-08-25T23:03:00Z</updated><content type="html">&lt;P&gt;I love my intellisense.&amp;nbsp; As such, I am very critical when there's a bug affecting its functionality.&amp;nbsp; The bug I ran into late in the VS 2008 product cycle while doing application-building was, unfortunately, not considered high enough priority to fix so late in the game.&amp;nbsp; As a result of the investigation, we did find a fix, and I've been&amp;nbsp;using&amp;nbsp;it ever since with no problems.&amp;nbsp; Here are the details of the problem and how to work around it.&lt;/P&gt;
&lt;P&gt;The basic bug is that if you type fast enough, and your CPU is slow or overloaded, you can accidentally bypass the intellisense engine.&amp;nbsp; This will leave you with unwanted text in the editor.&amp;nbsp; As an example, when I first saw this bug on my slow Lenova Thinkpad, I was trying to make a Window.Resources tag.&amp;nbsp; As such, I typed:&lt;/P&gt;
&lt;P&gt;&amp;lt;Window.Reso{TAB}&lt;/P&gt;
&lt;P&gt;where "{TAB}" was me hitting the tab character to complete the intellisense match.&amp;nbsp; Much to my dismay, instead of my editor containing "&amp;lt;Window.Resources", it actually contained&amp;nbsp;"&amp;lt;Window.Reso&amp;nbsp;&amp;nbsp;&amp;nbsp; ", where the tab character had been replaced by spaces in the editor.&amp;nbsp; To me, this is totally broken!&amp;nbsp; Do I have to stare at my editor and wait for the intellisense dropdown to appear before I can hit the Tab key?&amp;nbsp;&amp;nbsp;I type pretty fast... 95 words per minute&amp;nbsp;according to &lt;A href="http://www.typingtest.com/"&gt;www.TypingTest.com&lt;/A&gt;... but I know there are many, many people out there who type (and code)&amp;nbsp;much faster.&amp;nbsp; And depending on how many apps I was running, or whether Outlook was downloading mail in the background, or whatever, I could reproduce this intellisense failure about 5-10% of the time&amp;nbsp;on my old laptop.&lt;/P&gt;
&lt;P&gt;I was in dire need of a workaround.&amp;nbsp;During the investigation, one of our developers found that a simple bit flip in the registry fixes this issue.&amp;nbsp; Basically, by default, the Orcas XAML intellisense is set to asynchronous behavior.&amp;nbsp; That means, you can keep typing away, and intellisense will run in&amp;nbsp;a background thread and try to keep up... but if you type too fast or it doesn't get enough CPU time, it doesn't want to&amp;nbsp;block the keystrokes from getting&amp;nbsp;placed in&amp;nbsp;the editor, so it just ignores them.&amp;nbsp;&amp;nbsp;That's&amp;nbsp;the bug.&amp;nbsp; The fix is to set the following registry value:&lt;/P&gt;
&lt;P&gt;[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Languages\Language Services\XAML]&lt;BR&gt;"EnableAsyncCompletion"=dword:00000000&lt;/P&gt;
&lt;P&gt;Setting this registry value to 0, and restarting VS will make it so your keystrokes&amp;nbsp;never bypass the XAML intellisense engine again.&amp;nbsp; If you've ever hit this issue, or think you might,&amp;nbsp;you should&amp;nbsp;make this registry change and never look back.&lt;/P&gt;
&lt;P&gt;-Bri&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9884126" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author><category term="XAML" scheme="http://blogs.msdn.com/brianmcm/archive/tags/XAML/default.aspx" /><category term="Bug Fix" scheme="http://blogs.msdn.com/brianmcm/archive/tags/Bug+Fix/default.aspx" /><category term="Cider" scheme="http://blogs.msdn.com/brianmcm/archive/tags/Cider/default.aspx" /><category term="Intellisense" scheme="http://blogs.msdn.com/brianmcm/archive/tags/Intellisense/default.aspx" /><category term="Visual Studio" scheme="http://blogs.msdn.com/brianmcm/archive/tags/Visual+Studio/default.aspx" /></entry><entry><title>Enabling Assistive Devices programmatically for UI Automation on the Mac</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2007/05/02/enabling-assistive-devices-programmatically-for-ui-automation-on-the-mac.aspx" /><id>http://blogs.msdn.com/brianmcm/archive/2007/05/02/enabling-assistive-devices-programmatically-for-ui-automation-on-the-mac.aspx</id><published>2007-05-03T00:14:00Z</published><updated>2007-05-03T00:14:00Z</updated><content type="html">&lt;P&gt;As part of our effort to test Windows Presentation Foundation Everywhere (WPF/E) on the Mac, I'm working on a&amp;nbsp;UI Automation tool to drive WPF/E apps from out of process.&amp;nbsp; In the anticipation that WPF/E will eventually support Accessibility (and I assure you it will!), we need to programmatically turn on the checkbox in Mac OS X to enable the AXAPI (Mac's technology similar&amp;nbsp;to MSAA).&lt;/P&gt;
&lt;P&gt;It turns out this option in the UI is controlled by the magical file: "/private/var/db/.AccessibilityAPIEnabled".&amp;nbsp; If this file exists, the checkbox is checked, and we can drive applications through AXAPI.&amp;nbsp; If you delete the file, then accessibility is obviously disabled.&amp;nbsp; This operation is reversible on the fly and does not appear to require a reboot to swap, which is really handy.&lt;/P&gt;
&lt;P&gt;The final requirement is to create this file programmatically, in my case, through a shell script... although I'm sure there's a cleaner, more involved way to do it.&amp;nbsp; This is the quick and (very) dirty way.&amp;nbsp; Put the following script into a file, and execute it from&amp;nbsp;a Mac Terminal window with "sh myFile".&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face="Courier New" color=navy size=2&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;#!/bin/sh&lt;/SPAN&gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT face="Courier New" color=navy size=2&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;cd /private/var/db&lt;/SPAN&gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT face="Courier New" color=navy size=2&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=navy size=2&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Courier New'"&gt;Echo “$ADMINPWD” | sudo touch .AccessibilityAPIEnabled&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Of course, emitting the admin password in a text file is what really constitutes "dirty", but it suits my immediate purposes.&amp;nbsp; Someone on the Mac Office team suggested compiling this into an app and setting the "sticky" bit by installing with "1755 permissions" so I don't have to embed the admin pword in my script, which sounds like a good next step.&amp;nbsp; There are many, many more issues to go =).&amp;nbsp; I'm still very new to automation issues on the Mac.&amp;nbsp; We have experts in the company, but having me bother them isn't always optimal, so I'd definitely be interested in any good online resources that you community folks have in mind.&amp;nbsp; Any help is greatly appreciated!&lt;/P&gt;
&lt;P&gt;Thanks, &lt;/P&gt;
&lt;P&gt;Bri&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2381237" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author></entry><entry><title>Yahoo! Messenger built in Windows Presentation Foundation</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2007/02/27/yahoo-messenger-built-in-windows-presentation-foundation.aspx" /><id>http://blogs.msdn.com/brianmcm/archive/2007/02/27/yahoo-messenger-built-in-windows-presentation-foundation.aspx</id><published>2007-02-28T01:46:00Z</published><updated>2007-02-28T01:46:00Z</updated><content type="html">&lt;P&gt;You've probably seen this already, but if not, you should really check out the video preview of Yahoo!'s messenger app built with WPF.&amp;nbsp; &lt;A href="http://messenger.yahoo.com/windowsvista.php"&gt;http://messenger.yahoo.com/windowsvista.php&lt;/A&gt;&amp;nbsp;is the link.&amp;nbsp; I can't wait to see this thing running live.&amp;nbsp; It really seems like they've captured the power of what you can do with WPF.&lt;/P&gt;
&lt;P&gt;My team within Microsoft is working on releasing our first beta of Cider, which is a visual designer targetting&amp;nbsp;developers wanting to write cool WPF apps in a WYSIWYG editing environment within Visual Studio 9.0.&amp;nbsp; Our designer will fit in with the rest of the &lt;A class="" title="Microsoft Expression" href="http://www.microsoft.com/products/expression/en/default.mspx" target=_blank mce_href="http://www.microsoft.com/products/expression/en/default.mspx"&gt;Microsoft Expression&lt;/A&gt; technologies, so you'll be able to open your Cider apps in Blend to spice them up with beautiful gradients and animations, but still get your awesome development, layout,&amp;nbsp;and debugging experience within Visual Studio and seamlessly go back and forth between your Expression apps to get your forms looking the way you like.&lt;/P&gt;
&lt;P&gt;Of course, after watching this Yahoo! Messenger demo, the question we're all asking is... why not MSN Messenger?&amp;nbsp; Good question.&amp;nbsp; I have no idea.&amp;nbsp; I hope MSN does something sweet, too, otherwise I may have a reason to get an @yahoo email address ;-0.&lt;/P&gt;
&lt;P&gt;Bri&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1771121" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author></entry><entry><title>Huge VS Debugger Fix in Orcas (IMHO) =)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2007/01/20/huge-vs-debugger-fix-in-orcas-imho.aspx" /><id>http://blogs.msdn.com/brianmcm/archive/2007/01/20/huge-vs-debugger-fix-in-orcas-imho.aspx</id><published>2007-01-20T04:11:00Z</published><updated>2007-01-20T04:11:00Z</updated><content type="html">&lt;P&gt;The bug in the VS debugger that has been a thorn in my side for well over a year is now fixed in the next version of VS!&amp;nbsp; If you're a religious VS developer, I'm almost positive you've hit this bug before, although you may not have noticed.&amp;nbsp; The bug in Whidbey is basically that "Set Next Statement" in the right-click menu is broken when your cursor is at the end of a line.&amp;nbsp; In reality, it thinks the insertion point is on the &lt;STRONG&gt;next &lt;/STRONG&gt;line, so it tries to set the next statement there, instead.&lt;/P&gt;
&lt;P&gt;This bug can manifest itself in one of two ways.&amp;nbsp; If the line &lt;STRONG&gt;after &lt;/STRONG&gt;the line your cursor is on is a valid breakpoint line, then the next statement will be set to that line.&amp;nbsp; If this happens to you once, you will probably just think that you mis-clicked, and you will simply attempt to set the next statement to the previous line again.&amp;nbsp; However, if the next line is &lt;STRONG&gt;not&lt;/STRONG&gt; a valid line for a breakpoint, then you will see an error message saying, "unable to set the next statement to this location."&lt;/P&gt;
&lt;P&gt;Here's an official MS knowledge base article on the issue, as well. &lt;A href="http://support.microsoft.com/kb/919808"&gt;http://support.microsoft.com/kb/919808&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;This bug really bothered me, because it made me change the way I do work.&amp;nbsp; Anytime the tool makes me conciously do something differently than what I'm used to doing, it's a bad bug.&amp;nbsp; I was unable to convince the triage team for Whidbey, however =(.&amp;nbsp; The good news is, after fighting for this bug off-and-on for over a year and a half, it will now be fixed in the next version!&lt;/P&gt;
&lt;P&gt;Bri&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1495569" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author></entry><entry><title>Using StringBuilder to improve performance of your apps</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2006/09/27/using-stringbuilder-to-improve-performance-of-your-apps.aspx" /><id>http://blogs.msdn.com/brianmcm/archive/2006/09/27/using-stringbuilder-to-improve-performance-of-your-apps.aspx</id><published>2006-09-27T03:30:00Z</published><updated>2006-09-27T03:30:00Z</updated><content type="html">&lt;P&gt;TestSuites.cs file generated by my model, and parse it out into multiple .cs files each representing one testcase.&amp;nbsp; This sounded great to me, because my TestSuites.cs file was 113Mb, and splitting it out into around 300 testcase files sounded good to me.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;However, when I ran the tool for about 3 hours without it completing, I began to wonder what was going on.&amp;nbsp; From debugging it with a friend of mine, David Owens, we discovered that the main reason it took so long was because the original tool author was using normal string concatenation during the parsing.&amp;nbsp; Here is some sample code which illustrates the problem.&lt;BR&gt;&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Main(&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] args) {
    &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; contents = &lt;SPAN class=str&gt;""&lt;/SPAN&gt;;
    DateTime dtStart = DateTime.Now;

    StreamReader sr = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; StreamReader(&lt;SPAN class=str&gt;@"C:\TestSuites.cs"&lt;/SPAN&gt;);
    &lt;SPAN class=kwrd&gt;while&lt;/SPAN&gt; (!sr.EndOfStream) {
        contents += sr.ReadLine();  &lt;SPAN class=rem&gt;// Don’t do this =)&lt;/SPAN&gt;
    }
    DateTime dtEnd = DateTime.Now;
    TimeSpan ts = dtEnd.Subtract(dtStart);
    Console.WriteLine(contents + &lt;SPAN class=str&gt;"\r\n"&lt;/SPAN&gt; + ts.Seconds.ToString());
} 
&lt;/PRE&gt;
&lt;P&gt;&lt;BR&gt;If you’ve written code like this before, and you’re familiar with some of the static analysis tools like FxCop, you’ve probably been informed that this is bad.&amp;nbsp; The offending line is “contents += sr.ReadLine();”.&amp;nbsp; The root of the bug is that strings in .NET are “immutable.”&amp;nbsp; Basically, what that means is, whenever you assign a new string to a variable, the old string gets marked for garbage collection, and new memory is allocated to house the new string.&amp;nbsp; In this case, the code file is about 1.64 million lines, and memory allocation is bigger than the last.&amp;nbsp; Based on an average line length, it would take approximately 87.3 terra-bytes of memory to store all the strings allocated in this example.&amp;nbsp; Now you see why my laptop was thrashing for over 3 hours trying to parse this file.&amp;nbsp; Time for Microsoft to upgrade my laptop, IMO =).&lt;BR&gt;&amp;nbsp;&lt;BR&gt;Enter, the System.Text.StringBuilder class.&amp;nbsp; The idea behind this class is to allocate a fixed chunk of memory to build the string, and only allocate a new buffer if the string you're building becomes too long for the original allocation.&amp;nbsp; Once you're ready to use it, it allocates an immutable string object of the correct size.&amp;nbsp; In this example, the fix is to use the Append() method to build up my uber string, like so:&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Main(&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;[] args) {
    StringBuilder contents = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; StringBuilder(&lt;SPAN class=str&gt;""&lt;/SPAN&gt;);
    DateTime dtStart = DateTime.Now;
            
    StreamReader sr = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; StreamReader(&lt;SPAN class=str&gt;@"C:\TestSuites.cs"&lt;/SPAN&gt;);
    &lt;SPAN class=kwrd&gt;while&lt;/SPAN&gt; (!sr.EndOfStream) {
        contents.Append(sr.ReadLine());
    }
 
    DateTime dtEnd = DateTime.Now;
    TimeSpan ts = dtEnd.Subtract(dtStart);
    Console.WriteLine(contents + &lt;SPAN class=str&gt;"\r\n"&lt;/SPAN&gt; + ts.Seconds.ToString());
}
&lt;/PRE&gt;
&lt;P&gt;Now, each time I read a new line from the file, rather than allocating a new immutable string to store the current contents, the StringBuilder class just stores a pointer to that substring in memory until the last line of my Main() function where it outputs the string to the console window.&amp;nbsp; It takes quite a bit longer to output the 113Mb of my file to the console than it does to execute the while loop.&amp;nbsp; But the perf improvement is amazing.&amp;nbsp; My while loop now executes in 24 seconds instead of several hours!!&lt;BR&gt;&amp;nbsp;&lt;BR&gt;Fun stuff,&lt;BR&gt;Bri&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=773021" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author></entry><entry><title>ISU Tech Talk on WPF and UIAutomation</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2006/02/24/538942.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="8187" href="http://blogs.msdn.com/brianmcm/attachment/538942.ashx" /><id>http://blogs.msdn.com/brianmcm/archive/2006/02/24/538942.aspx</id><published>2006-02-25T02:31:00Z</published><updated>2006-02-25T02:31:00Z</updated><content type="html">&lt;P&gt;I had the pleasure of speaking to the ISU students on Tuesday this week.&amp;nbsp; I gave a high-level overview of WPF (Avalon)&amp;nbsp;and Windows UIAutomation (vNext of MSAA).&amp;nbsp; I wanted to go ahead and get my basic slide deck posted in case anyone wanted it.&amp;nbsp; Sorry I don't have videos of the demos.&lt;/P&gt;
&lt;P&gt;It was fun to show people some of the cool new features of Sparkle and Cider.&amp;nbsp; I got some great questions from the students, and it was cool to see them really "get" Microsoft's WPF story.&amp;nbsp; One of the students (Chris Sammis)&amp;nbsp;has even been downloading WinFX betas and doing real development with it and supplying us with feedback and bug reports.&amp;nbsp; Kudos to Chris!&lt;/P&gt;
&lt;P&gt;I also got to play Micro-Santa and held a raffle to give away cool prizes including, but not limited to:&amp;nbsp; MS Office 2003 Pro, Halo2, Fable, Age of Empires 3, Rise of Nations, MS Money, tons of T-Shirts, and an XBox 360!!&amp;nbsp; Congratulations to Brandon Kennedy on winning the XBox.&amp;nbsp; I hope he has fun w/that between mid-terms =).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Thanks a lot to the NSBE (National Society of Black Engineers) for sponsoring the event and providing the Pizza and pop.&amp;nbsp; I appreciate the students who took the time to help organize and advertise this event.&amp;nbsp; There were 85 people at the talk, which my MS recruiters tell me was a record attendance, so thanks to everyone who made it successful.&amp;nbsp; I would definitely do this again!&lt;/P&gt;
&lt;P&gt;Bri&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=538942" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author></entry><entry><title>PInvoke Declarations for My Sample Code</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2006/01/23/516418.aspx" /><id>http://blogs.msdn.com/brianmcm/archive/2006/01/23/516418.aspx</id><published>2006-01-24T00:40:00Z</published><updated>2006-01-24T00:40:00Z</updated><content type="html">&lt;P&gt;Thanks to Ed from Comcast for pointing out that my 1/17/06 post regarding Windows Forms ID's was missing the NativeMethods.cs file.&amp;nbsp; Sorry for the inconvenience, Ed.&amp;nbsp; Here's the NativeMethods.cs file that will help you get the code up and running.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Runtime.InteropServices;

&lt;SPAN class=kwrd&gt;namespace&lt;/SPAN&gt; GetWinFormsId
{
    &lt;SPAN class=rem&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=rem&gt;/// Summary description for NativeMethods.&lt;/SPAN&gt;
    &lt;SPAN class=rem&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; NativeMethods
    {
        
        [DllImport(&lt;SPAN class=str&gt;"kernel32.dll"&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; IntPtr OpenProcess(&lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; dwDesiredAccess, &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; bInheritHandle,
            &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; dwProcessId);
        [DllImport(&lt;SPAN class=str&gt;"kernel32.dll"&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
            UIntPtr dwSize, &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; flAllocationType, PageProtection flProtect);
        [DllImport(&lt;SPAN class=str&gt;"user32.dll"&lt;/SPAN&gt;, SetLastError=&lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; GetWindowThreadProcessId(IntPtr hWnd, &lt;SPAN class=kwrd&gt;out&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; lpdwProcessId);
        [DllImport(&lt;SPAN class=str&gt;"kernel32.dll"&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
            UIntPtr dwSize, &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; dwFreeType);
        [DllImport(&lt;SPAN class=str&gt;"kernel32.dll"&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; CloseHandle(IntPtr hObject);
        [DllImport(&lt;SPAN class=str&gt;"kernel32.dll"&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; IntPtr MapViewOfFile(IntPtr hFileMappingObject, &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt;
            dwDesiredAccess, &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; dwFileOffsetHigh, &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; dwFileOffsetLow,
            UIntPtr dwNumberOfBytesToMap);
        [DllImport(&lt;SPAN class=str&gt;"kernel32.dll"&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; UnmapViewOfFile(IntPtr lpBaseAddress);
        [DllImport(&lt;SPAN class=str&gt;"kernel32.dll"&lt;/SPAN&gt;, SetLastError=&lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; IntPtr CreateFileMapping(IntPtr hFile,
            IntPtr lpFileMappingAttributes, PageProtection flProtect, &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; dwMaximumSizeHigh,
            &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; dwMaximumSizeLow, &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; lpName);
        [DllImport(&lt;SPAN class=str&gt;"user32.dll"&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; IntPtr SendMessage(IntPtr hwnd, &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; wMsg, IntPtr wParam, IntPtr lParam);
        [DllImport(&lt;SPAN class=str&gt;"kernel32.dll"&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
            [Out] &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt; [] lpBuffer, UIntPtr nSize, IntPtr lpNumberOfBytesRead);
        [DllImport(&lt;SPAN class=str&gt;"Kernel32.dll"&lt;/SPAN&gt;, EntryPoint=&lt;SPAN class=str&gt;"RtlMoveMemory"&lt;/SPAN&gt;, SetLastError=&lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; MoveMemoryFromByte(IntPtr dest, &lt;SPAN class=kwrd&gt;ref&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt; src, &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; size);
        [DllImport(&lt;SPAN class=str&gt;"Kernel32.dll"&lt;/SPAN&gt;, EntryPoint=&lt;SPAN class=str&gt;"RtlMoveMemory"&lt;/SPAN&gt;, SetLastError=&lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; MoveMemoryToByte(&lt;SPAN class=kwrd&gt;ref&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt; dest, IntPtr src, &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; size);
        [DllImport(&lt;SPAN class=str&gt;"user32.dll"&lt;/SPAN&gt;, SetLastError=&lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;, CharSet=CharSet.Auto)]
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;extern&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; RegisterWindowMessage(&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; lpString);



        &lt;SPAN class=rem&gt;//=========== Win95/98/ME Shared memory staff===============&lt;/SPAN&gt;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; STANDARD_RIGHTS_REQUIRED = 0xF0000;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; SECTION_QUERY = 0x1;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; SECTION_MAP_WRITE = 0x2;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; SECTION_MAP_READ = 0x4;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; SECTION_MAP_EXECUTE = 0x8;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; SECTION_EXTEND_SIZE = 0x10;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS;

        &lt;SPAN class=rem&gt;//============NT Shared memory constant======================&lt;/SPAN&gt;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; PROCESS_VM_OPERATION = 0x8;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; PROCESS_VM_READ = 0x10;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; PROCESS_VM_WRITE = 0x20;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;long&lt;/SPAN&gt; PROCESS_ALL_ACCESS = 0x1F0FFF;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; MEM_COMMIT = 0x1000;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; MEM_RESERVE = 0x2000;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;short&lt;/SPAN&gt; MEM_DECOMMIT = 0x4000;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; MEM_RELEASE = 0x8000;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; MEM_FREE = 0x10000;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; MEM_PRIVATE = 0x20000;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; MEM_MAPPED = 0x40000;
        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; MEM_TOP_DOWN = 0x100000;


        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; INVALID_HANDLE_VALUE = -1;
        


    }

    [Flags]
    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;enum&lt;/SPAN&gt; PageProtection : &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; 
    {
        NoAccess =     0x01,
        Readonly =     0x02,
        ReadWrite =    0x04,
        WriteCopy =    0x08,
        Execute =      0x10,
        ExecuteRead =      0x20,
        ExecuteReadWrite = 0x40,
        ExecuteWriteCopy = 0x80,
        Guard =        0x100,
        NoCache =      0x200,
        WriteCombine =     0x400,
    }
}
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=516418" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author></entry><entry><title>Getting the WinForms ID of a Control</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2006/01/17/getting-the-winforms-id-of-a-control.aspx" /><id>http://blogs.msdn.com/brianmcm/archive/2006/01/17/getting-the-winforms-id-of-a-control.aspx</id><published>2006-01-17T03:35:00Z</published><updated>2006-01-17T03:35:00Z</updated><content type="html">&lt;P&gt;Happy New Year and stuff! =)&lt;/P&gt;
&lt;P&gt;If you've read my article on issues related to automating Windows Forms with traditional Win32-like UI Automation tools, then you know about what we refer to as the Windows Forms ID.&amp;nbsp; If you're not familiar with the issue, here's a quick intro.&amp;nbsp; Basically, when automating Win32 UI in the past, the typical way that you located a control through code was by using the Control ID.&amp;nbsp; You probably had some method in your automation framework called "FindControlById()" or something similar that took a window handle and an integer as parameters, and then searched the descendants of that window handle for a window who's Control ID matched the one you passed in.&amp;nbsp; Well that's all great, except this method is useless in automating Windows Forms.&amp;nbsp; That's because the Control ID for Windows Forms UI is a mirror of the HWND&amp;nbsp;of the control.&amp;nbsp; Thus, it will not be the same on subsequent launches of the app.&lt;/P&gt;
&lt;P&gt;The replacement for Control ID's in Windows Forms is "Windows Forms ID."&amp;nbsp; When you develop a Windows Forms application in Visual Studio using the designer, it will automatically set the ".Name" property for your controls to default values (usually "button1," "button2," "listBox1," etc.).&amp;nbsp; So what you really want to use in your automation is&amp;nbsp;to be able to ask a particular control what it's Name property is set to.&amp;nbsp;&amp;nbsp;Windows Forms supports just that.&amp;nbsp; If you send a&amp;nbsp;WM_GETCONTROLNAME message using a standard SendMessage&amp;nbsp;Windows API to any Windows&amp;nbsp;Forms control, it will respond in the LPARAM with it's Name property.&amp;nbsp; The code in my article is written in Rational Visual Test, which is&amp;nbsp;kind of pseudo-Basic I would say.&amp;nbsp; However, I often get asked for C# code to get the WinformsId, so I'm going to paste it in below.&lt;/P&gt;
&lt;P&gt;As you can see, it has a public static method called GetWinFormsId() that takes an HWND as a parameter and returns a string representing the Name.&amp;nbsp; So all you have to do is add this code to&amp;nbsp;a C# project, and then write some code to walk the Windows Hierarchy using the GetWindow() Function&amp;nbsp;or similar API's to find the HWNDs of the controls on your form.&amp;nbsp; Then you can call WinFormsUtilities.GetWinFormsId() on those HWNDS to see if you've found the HWND of the control you're looking for.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Text;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.ComponentModel;

&lt;SPAN class=kwrd&gt;namespace&lt;/SPAN&gt; GetWinFormsId
{
    &lt;SPAN class=rem&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=rem&gt;/// Summary description for WinFormsUtilities.&lt;/SPAN&gt;
    &lt;SPAN class=rem&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; WinFormsUtilities
    {
        &lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; GetControlNameMessage = 0;

        &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; WinFormsUtilities()
        {
            GetControlNameMessage = NativeMethods.RegisterWindowMessage(&lt;SPAN class=str&gt;"WM_GETCONTROLNAME"&lt;/SPAN&gt;);
        }

        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; GetWinFormsId(IntPtr hWnd)
        {
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; XProcGetControlName(hWnd, GetControlNameMessage);
        }

        &lt;SPAN class=kwrd&gt;protected&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; XProcGetControlName(IntPtr hwnd, &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; msg)
        {
            &lt;SPAN class=rem&gt;//define the buffer that will eventually contain the desired window's WinFormsId&lt;/SPAN&gt;

            &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[] bytearray = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[65536];

            &lt;SPAN class=rem&gt;//allocate space in the target process for the buffer as shared memory&lt;/SPAN&gt;
            IntPtr bufferMem = IntPtr.Zero; &lt;SPAN class=rem&gt;//base address of the allocated region for the buffer&lt;/SPAN&gt;
            IntPtr written= IntPtr.Zero;  &lt;SPAN class=rem&gt;//number of bytes written to memory&lt;/SPAN&gt;
            IntPtr retHandle= IntPtr.Zero;
            &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; retVal;

            
            &lt;SPAN class=rem&gt;//creating and reading from a shared memory region is done differently in Win9x then in newer OSs&lt;/SPAN&gt;
            IntPtr processHandle= IntPtr.Zero;
            IntPtr fileHandle= IntPtr.Zero;

            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(!(Environment.OSVersion.Platform == PlatformID.Win32Windows))
            {   
                &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
                {
                    &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; size; &lt;SPAN class=rem&gt;//the amount of memory to be allocated&lt;/SPAN&gt;
                    size = 65536;

                    processHandle = NativeMethods.OpenProcess(NativeMethods.PROCESS_VM_OPERATION | NativeMethods.PROCESS_VM_READ | NativeMethods.PROCESS_VM_WRITE, &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;, GetProcessIdFromHWnd(hwnd));

                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(processHandle.ToInt64() == 0)
                    {
                        &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Win32Exception();
                    }

                    bufferMem = NativeMethods.VirtualAllocEx(processHandle, IntPtr.Zero, &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; UIntPtr(size), NativeMethods.MEM_RESERVE | NativeMethods.MEM_COMMIT, PageProtection.ReadWrite);

                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(bufferMem.ToInt64() == 0)
                    {
                        &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Win32Exception();
                    }

                    &lt;SPAN class=rem&gt;//send message to the control's hWnd for getting the specified control name&lt;/SPAN&gt;
                    retHandle = NativeMethods.SendMessage(hwnd, msg, &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; IntPtr(size), bufferMem);

                    &lt;SPAN class=rem&gt;//now read the TVITEM's info from the shared memory location&lt;/SPAN&gt;
                    retVal = NativeMethods.ReadProcessMemory(processHandle, bufferMem, bytearray, &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; UIntPtr(size), written);
                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(!retVal)
                    {
                        &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Win32Exception();
                    }
                }
                &lt;SPAN class=kwrd&gt;finally&lt;/SPAN&gt;
                {
                    &lt;SPAN class=rem&gt;//free the memory that was allocated&lt;/SPAN&gt;
                    retVal = NativeMethods.VirtualFreeEx(processHandle, bufferMem, &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; UIntPtr(0), NativeMethods.MEM_RELEASE);
                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(!retVal)
                    {
                        &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Win32Exception();
                    }
                    NativeMethods.CloseHandle(processHandle);
                }
            }
            &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;
            {
                &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
                {
                    &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; size2; &lt;SPAN class=rem&gt;//the amount of memory to be allocated&lt;/SPAN&gt;
                    size2 = 65536;

                    fileHandle = NativeMethods.CreateFileMapping(&lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; IntPtr(NativeMethods.INVALID_HANDLE_VALUE), IntPtr.Zero, PageProtection.ReadWrite, 0, size2, &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;);
                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(fileHandle.ToInt64() == 0)
                    {
                        &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Win32Exception();
                    }
                    bufferMem = NativeMethods.MapViewOfFile(fileHandle, NativeMethods.FILE_MAP_ALL_ACCESS, 0, 0, &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; UIntPtr(0));
                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(bufferMem.ToInt64() == 0)
                    {
                        &lt;SPAN class=kwrd&gt;throw&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Win32Exception();
                    }
                    NativeMethods.MoveMemoryFromByte(bufferMem, &lt;SPAN class=kwrd&gt;ref&lt;/SPAN&gt; bytearray[0], size2);

                    retHandle = NativeMethods.SendMessage(hwnd, msg, &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; IntPtr(size2), bufferMem);

                    &lt;SPAN class=rem&gt;//read the control's name from the specific shared memory for the buffer&lt;/SPAN&gt;
                    NativeMethods.MoveMemoryToByte(&lt;SPAN class=kwrd&gt;ref&lt;/SPAN&gt; bytearray[0], bufferMem, 1024);

                }
                &lt;SPAN class=kwrd&gt;finally&lt;/SPAN&gt;
                {
                    &lt;SPAN class=rem&gt;//unmap and close the file&lt;/SPAN&gt;
                    NativeMethods.UnmapViewOfFile(bufferMem);
                    NativeMethods.CloseHandle(fileHandle);
                }
            }

            &lt;SPAN class=rem&gt;//get the string value for the Control name&lt;/SPAN&gt;
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; ByteArrayToString(bytearray);

        }

        &lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; GetProcessIdFromHWnd(IntPtr hwnd)
        {
            &lt;SPAN class=kwrd&gt;uint&lt;/SPAN&gt; pid;
            
            NativeMethods.GetWindowThreadProcessId(hwnd, &lt;SPAN class=kwrd&gt;out&lt;/SPAN&gt; pid);

            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; pid;
        }

        &lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; ByteArrayToString(&lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[] bytes)
        {
            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(Environment.OSVersion.Platform == PlatformID.Win32Windows)
            {
                &lt;SPAN class=rem&gt;// Use the Ansii encoder&lt;/SPAN&gt;
                &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; Encoding.Default.GetString(bytes).TrimEnd(&lt;SPAN class=str&gt;'\0'&lt;/SPAN&gt;);
            }
            &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;
            {
                &lt;SPAN class=rem&gt;// use Unicode&lt;/SPAN&gt;
                &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; Encoding.Unicode.GetString(bytes).TrimEnd(&lt;SPAN class=str&gt;'\0'&lt;/SPAN&gt;);
            }
        }
    }
}&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=513581" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author></entry><entry><title>Who am I and why should anyone care?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/brianmcm/archive/2005/12/12/who-am-i-and-why-should-anyone-care.aspx" /><id>http://blogs.msdn.com/brianmcm/archive/2005/12/12/who-am-i-and-why-should-anyone-care.aspx</id><published>2005-12-13T00:01:00Z</published><updated>2005-12-13T00:01:00Z</updated><content type="html">&lt;P&gt;The "why should you care?" part is much harder to answer, so I'll just start with who I am =).&amp;nbsp; I'm Brian McMaster, and I'm a Test Architect at Microsoft.&amp;nbsp; I'm currently working on "Cider."&amp;nbsp; Cider is the codename for the line of business application designer for Windows Presentation Foundation (aka Avalon) apps.&amp;nbsp; I will continue to call WPF, "Avalon," because it's a much more elegant name and easier to type =).&amp;nbsp; Avalon is an extremely cool framework, and Cider is shaping up to be an awesome designer for these types of applications.&amp;nbsp; Some of the other products I have worked on in the past are Access, Visual Basic, Visual InterDev, and Windows Forms.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I've been working at Microsoft full-time for almost exactly 9 years (excluding a few internships that I worked while in college).&amp;nbsp; In fact, that reminds me that I need to buy a bunch of M &amp;amp; M's.&amp;nbsp; There's a silly tradition at Microsoft where you put x number of pounds of M&amp;amp;M's outside your office where x is equal to the number of years you've been working there.&amp;nbsp; At 10 years, there's another silly tradition where the company gives you 10 shares of Microsoft stock.&amp;nbsp; Of course, since the stock experts have told me that Microsoft is more of a value stock now instead of a growth stock, this means that my 10 shares will not appreciate in the way that shares have in the past.&lt;/P&gt;
&lt;P&gt;When I first started working here, there were daily conversations about stock prices amongst the employees.&amp;nbsp; Sample applications for app-writing contests often involved writing the coolest ticker controls, or stock option vesting applications.&amp;nbsp; Back then the 10 shares might have become exceptionally valuable in short order due to splits.&amp;nbsp; 10-20-40-80-160, possibly several thousand dollars worth =).&amp;nbsp; Ah, but we must not give up.&amp;nbsp; With XBox already out, and Vista coming out, and a new Office, and of course Visual Studio + Cider, we have a lot of potential.&lt;/P&gt;
&lt;P&gt;So getting back to why you might care.&amp;nbsp; My main expertise at Microsoft has revolved around automated testing.&amp;nbsp; I've worked on various automated testing tools for technologies like HTML, Win32, Office, Windows Forms, and now Avalon.&amp;nbsp; Windows Forms has some subtle (and some not-so-subtle) differences from Win32 which makes it tricky to automate your applications.&amp;nbsp; So far, we've done a less than optimal job of helping our customers automate the testing of their Windows Forms applications.&amp;nbsp; This is something we're trying to remedy as quickly as possible with our next version of Visual Studio Team System.&amp;nbsp; In order to help explain the diferences and offer some guidance for our customers on how they might adapt their existing automated tools to Windows forms, I wrote this MSDN article.&amp;nbsp; &lt;SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: 'Calibri','sans-serif'; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms996405.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms996405.aspx&lt;/A&gt;&lt;/SPAN&gt;.&amp;nbsp; It's certainly not a great article, but it is pretty good at describing the Windows Forms technology from an automation perspective.&lt;/P&gt;
&lt;P&gt;I have a few more blog entries in mind right now, so hopefully, I'll be able to provide some useful tips and articles in the future.&lt;/P&gt;
&lt;P&gt;-Bri&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=502899" width="1" height="1"&gt;</content><author><name>brianmcm</name><uri>http://blogs.msdn.com/members/brianmcm.aspx</uri></author></entry></feed>