<?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"><title type="html">gaisen</title><subtitle type="html" /><id>http://blogs.msdn.com/b/gisenberg/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/b/gisenberg/atom.aspx" /><generator uri="http://telligent.com" version="5.6.50428.7875">Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><updated>2006-11-28T06:45:00Z</updated><entry><title>Custom WCF Authorization using ServiceAuthorizationManager</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2008/12/09/custom-wcf-authorization-using-serviceauthorizationmanager.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2008/12/09/custom-wcf-authorization-using-serviceauthorizationmanager.aspx</id><published>2008-12-09T19:37:00Z</published><updated>2008-12-09T19:37:00Z</updated><content type="html">&lt;P&gt;I was recently tasked with implementing authentication and authorization in an existing WCF-based service using Windows Live ID. The service already had an extensive set of BVT tests that I didn't necessarily want to break. Integrating Live ID authentication in our service tests would require some additional code modifications and require another pass through those tests.&lt;/P&gt;
&lt;P&gt;So, implement authentication and authorization and&amp;nbsp;don't make modifications to existing test code. Seems relatively straight-forward! I grabbed my favorite group of triage to bounce design decisions around and our authorization scheme more or less ended up with two code paths: 1) If the Windows user account is present and in a Test security group OR 2) If the LiveID user is authenticated and authorized, return true.&lt;/P&gt;
&lt;P&gt;That's alright; we're adding in some code to make things testable. And, of course, that code would require testing. And creating/maintaining a security group.&amp;nbsp;&amp;nbsp;But it could be better. In comes the ServiceAuthorizationManager class.&lt;/P&gt;
&lt;P&gt;WCF allows you to create classes that derive off of ServiceAuthorizationManager. When you do this and override the CheckAccessCore method, you can implement an authorization scheme across all of your web service method calls. In my case, I created a LiveIdServiceAuthorizationManager class that attempts to cast the HttpContext.Current.User.Identity to a PassportIdentity. Some internal authorization checks are made based on that information. &lt;/P&gt;
&lt;P&gt;Creating a custom ServiceAuthorizationManager is straightforward and looks like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class LiveIdServiceAuthorizationManager : ServiceAuthorizationManager&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected override bool CheckAccessCore(OperationContext operationContext)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PassportIdentity currentUser = HttpContext.Current.User.Identity as PassportIdentity;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool isAuthorized = false;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (currentUser != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return isAuthorized;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Enabling our custom authorization manager is a configuration change that looks something like this:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;serviceBehaviors&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;behavior name="SomeBehavior"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;serviceAuthorization serviceAuthorizationManagerType="SomeNamespace.LiveIdServiceAuthorizationManager, SomeAssembly" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/behavior&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/serviceBehaviors&amp;gt;&lt;/P&gt;
&lt;P&gt;The &amp;lt;serviceAuthorization&amp;gt; node can be removed in BVT scenarios, allowing the service to successfully run through our BVT process without any code changes. However, when the node is present, callers must be authenticated through Live ID. This fulfills both of our requirements in a seemingly elegant way.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9187559" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author><category term="authentication" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/authentication/" /><category term="WCF" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/WCF/" /><category term="authorization" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/authorization/" /></entry><entry><title>UI Automation in Silverlight - Part II (The Easy Way)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2008/07/17/ui-automation-in-silverlight-part-ii-the-easy-way.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2008/07/17/ui-automation-in-silverlight-part-ii-the-easy-way.aspx</id><published>2008-07-17T19:19:00Z</published><updated>2008-07-17T19:19:00Z</updated><content type="html">&lt;DIV id=wmfy&gt;So, I wrote a blog post a bit earlier on exposing custom controls for accessibility and automation in Silverlight. If you're only interested in the automation perspective and the Silverlight unit testing framework doesn't quite suit your needs, then there's an easier way than going out and&amp;nbsp;implementing AutomationPeer types.&lt;/DIV&gt;
&lt;DIV id=eyj5&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=eyj50&gt;As of Silverlight Beta 2, you can utilize the AutomationProperties.AutomationId attribute in your XAML to make types you use unique and identifiable through automation:&lt;/DIV&gt;
&lt;DIV id=h4dk&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=h4dk0&gt;
&lt;DIV style="BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=h4dk1&gt;
&lt;P style="MARGIN: 0px" id=h4dk2&gt;&amp;nbsp; &amp;nbsp;&lt;SPAN style="COLOR: blue" id=h4dk5&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515" id=h4dk6&gt;TextBox&lt;/SPAN&gt;&lt;SPAN style="COLOR: red" id=h4dk7&gt; AutomationProperties.AutomationId&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=h4dk8&gt;="SearchTextBox"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red" id=h4dk18&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=h4dk19&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red" id=h4dk20&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=h4dk21&gt;="SearchText"&lt;/SPAN&gt;&lt;SPAN style="COLOR: red" id=h4dk22&gt; KeyDown&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=h4dk23&gt;="CheckKey" /&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=h9hh&gt;AutomationProperties.AutomationId doesn't come up in Intellisense in&amp;nbsp;Beta&amp;nbsp;2, and you'll get a false positive on the "The&amp;nbsp;attachable property 'AutomationId' was not found in type 'AutomationProperties'." error message. Ignore it for now and spin&amp;nbsp;up your Silverlight app&amp;nbsp;:)&amp;nbsp;Once this has been done, your element should look something like this when identified in UISpy (&lt;A id=gxp_ title=more href="http://blogs.msdn.com/windowssdk/archive/2008/02/18/where-is-uispy-exe.aspx" mce_href="http://blogs.msdn.com/windowssdk/archive/2008/02/18/where-is-uispy-exe.aspx"&gt;more&lt;/A&gt;):&lt;/DIV&gt;
&lt;DIV id=h4dk28&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=imri&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=imri0&gt;
&lt;P style="MARGIN: 0px" id=imri1&gt;&lt;FONT id=imri2 color=#45818e size=2&gt;&amp;nbsp;&amp;nbsp; Identification&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri3&gt;&lt;FONT id=x_n6 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ClassName:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri4&gt;""&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri5&gt;&lt;FONT id=x_n60 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ControlType:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri6&gt;"ControlType.Custom"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri7&gt;&lt;FONT id=x_n61 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Culture:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri8&gt;"(null)"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri9&gt;&lt;FONT id=x_n62 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutomationId:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri10&gt;"SearchTextBox"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri11&gt;&lt;FONT id=x_n63 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LocalizedControlType:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri12&gt;"custom"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri13&gt;&lt;FONT id=x_n64 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri14&gt;""&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri15&gt;&lt;FONT id=x_n65 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProcessId:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri16&gt;"2808 (iexplore)"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri17&gt;&lt;FONT id=x_n66 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RuntimeId:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri18&gt;"42 197822 3"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri19&gt;&lt;FONT id=x_n67 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsPassword:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri20&gt;"False"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri21&gt;&lt;FONT id=x_n68 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsControlElement:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri22&gt;"True"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri23&gt;&lt;FONT id=x_n69 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsContentElement:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri24&gt;"True"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri25&gt;&lt;FONT id=x_n610 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri26&gt;&lt;FONT id=x_n611 size=2&gt;&amp;nbsp; &lt;SPAN style="COLOR: #2b91af" id=imri27&gt;Visibility&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri28&gt;&lt;FONT id=x_n612 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BoundingRectangle:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri29&gt;"(240, 327, 300, 23)"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri30&gt;&lt;FONT id=x_n613 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ClickablePoint:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri31&gt;"390,338"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=imri32&gt;&lt;FONT id=x_n614 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsOffscreen:&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #a31515" id=imri33&gt;"False"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;!--EndFragment--&gt;&lt;/DIV&gt;
&lt;DIV id=h4dk29&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=h4dk30&gt;So, if we want to simulate a user at this point, we have three objectives:&lt;/DIV&gt;
&lt;DIV id=zvu4&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=zvu40&gt;&amp;nbsp;&amp;nbsp; 1. Move the mouse cursor over to the ClickablePoint.&lt;/DIV&gt;
&lt;DIV id=zvu41&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;2. Click the mouse button.&lt;/DIV&gt;
&lt;DIV id=zvu42&gt;&amp;nbsp;&amp;nbsp; 3. Start typing.&lt;/DIV&gt;
&lt;DIV id=h4dk32&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=lm3y&gt;To move the cursor to the clickable point, we need to set the Cursor.Position property. To do this, we must do a conversion between System.Windows.Point and System.Drawing.Point. I chose to handle this conversion through an extension method that looks something like:&lt;/DIV&gt;
&lt;DIV id=cd22&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=cd220&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=i5zq&gt;
&lt;P style="MARGIN: 0px" id=i5zq0&gt;&lt;FONT id=x_n615 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=i5zq1&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=i5zq2&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=i5zq3&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af" id=i5zq4&gt;ExtensionMethods&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq5&gt;&lt;FONT id=x_n616 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq6&gt;&lt;FONT id=x_n617 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=i5zq7&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=i5zq8&gt;static&lt;/SPAN&gt; System.Drawing.&lt;SPAN style="COLOR: #2b91af" id=i5zq9&gt;Point&lt;/SPAN&gt; ToDrawingPoint(&lt;SPAN style="COLOR: blue" id=i5zq10&gt;this&lt;/SPAN&gt; System.Windows.&lt;SPAN style="COLOR: #2b91af" id=i5zq11&gt;Point&lt;/SPAN&gt; windowsPoint)&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq12&gt;&lt;FONT id=x_n618 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq13&gt;&lt;FONT id=x_n619 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=i5zq14&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=i5zq15&gt;new&lt;/SPAN&gt; System.Drawing.&lt;SPAN style="COLOR: #2b91af" id=i5zq16&gt;Point&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq17&gt;&lt;FONT id=x_n620 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq18&gt;&lt;FONT id=x_n621 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; X = &lt;SPAN style="COLOR: #2b91af" id=i5zq19&gt;Convert&lt;/SPAN&gt;.ToInt32(windowsPoint.X),&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq20&gt;&lt;FONT id=x_n622 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Y = &lt;SPAN style="COLOR: #2b91af" id=i5zq21&gt;Convert&lt;/SPAN&gt;.ToInt32(windowsPoint.Y) &lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq22&gt;&lt;FONT id=x_n623 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq23&gt;&lt;FONT id=x_n624 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=i5zq24&gt;&lt;FONT id=x_n625 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;!--EndFragment--&gt;&lt;/DIV&gt;
&lt;DIV id=cd221&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=lscq&gt;Once we've moved the mouse, we also need to simulate a click. We're a DllImport away from making that happen. We can create a nice wrapper class to simplify our calling code:&lt;/DIV&gt;
&lt;DIV id=lscq0&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=bf0u&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=bf0u0&gt;
&lt;P style="MARGIN: 0px" id=bf0u1&gt;&lt;FONT id=x_n626 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=bf0u2&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u3&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u4&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af" id=bf0u5&gt;Mouse&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u6&gt;&lt;FONT id=x_n627 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u7&gt;&lt;FONT id=x_n628 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=bf0u8&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u9&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af" id=bf0u10&gt;UInt32&lt;/SPAN&gt; MouseEventLeftDown = 0x0002;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u11&gt;&lt;FONT id=x_n629 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=bf0u12&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u13&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af" id=bf0u14&gt;UInt32&lt;/SPAN&gt; MouseEventLeftUp = 0x0004;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u15&gt;&lt;FONT id=x_n630 size=2&gt;&lt;/FONT&gt;
&lt;P style="MARGIN: 0px" id=bf0u16&gt;&lt;SPAN style="COLOR: blue" id=bf0u17&gt;&lt;FONT id=x_n631 size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P id=kdpa&gt;&lt;FONT id=x_n633 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;SPAN style="COLOR: #2b91af" id=bf0u19&gt;DllImport&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515" id=bf0u20&gt;"user32.dll"&lt;/SPAN&gt;)]&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u21&gt;&lt;FONT id=x_n634 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=bf0u22&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u23&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u24&gt;extern&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u25&gt;void&lt;/SPAN&gt; mouse_event(&lt;SPAN style="COLOR: #2b91af" id=bf0u26&gt;UInt32&lt;/SPAN&gt; dwFlags, &lt;SPAN style="COLOR: #2b91af" id=bf0u27&gt;UInt32&lt;/SPAN&gt; dx, &lt;SPAN style="COLOR: #2b91af" id=bf0u28&gt;UInt32&lt;/SPAN&gt; dy, &lt;SPAN style="COLOR: #2b91af" id=bf0u29&gt;UInt32&lt;/SPAN&gt; dwData, &lt;SPAN style="COLOR: #2b91af" id=bf0u30&gt;IntPtr&lt;/SPAN&gt; dwExtraInfo);&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u31&gt;&lt;FONT id=x_n635 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u32&gt;&lt;FONT id=x_n636 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=bf0u33&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u34&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=bf0u35&gt;void&lt;/SPAN&gt; Click()&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u36&gt;&lt;FONT id=x_n637 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u37&gt;&lt;FONT id=x_n638 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; mouse_event(MouseEventLeftDown, 0, 0, 0, &lt;SPAN style="COLOR: #2b91af" id=bf0u38&gt;IntPtr&lt;/SPAN&gt;.Zero);&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u39&gt;&lt;FONT id=x_n639 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; mouse_event(MouseEventLeftUp, 0, 0, 0, &lt;SPAN style="COLOR: #2b91af" id=bf0u40&gt;IntPtr&lt;/SPAN&gt;.Zero);&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u41&gt;&lt;FONT id=x_n640 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=bf0u42&gt;&lt;FONT id=x_n641 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;!--EndFragment--&gt;&lt;/DIV&gt;
&lt;DIV id=bf0u43&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=lscq1&gt;So, we set automation IDs on our&amp;nbsp;elements in XAML, we&amp;nbsp;can identify elements with unique automation IDs, we can move the mouse with an element's ClickablePoint property, and we can simulate a mouse click. How does this all come together?&lt;/DIV&gt;
&lt;DIV id=cd222&gt;&amp;nbsp; 
&lt;DIV style="BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=z0y82&gt;
&lt;P style="MARGIN: 0px" id=z0y83&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;SPAN style="COLOR: #2b91af" id=z0y84&gt;TestMethod&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=z0y85&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue" id=z0y86&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue" id=z0y87&gt;void&lt;/SPAN&gt; TestMethod1()&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=z0y88&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=ycnd&gt;
&lt;P style="MARGIN: 0px" id=ycnd0&gt;&lt;SPAN style="COLOR: green" id=ycnd1&gt;&lt;FONT id=x_n642 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Assumes an existing Internet Explorer process is running and pointed at your Silverlight app&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;!--EndFragment--&gt;
&lt;P style="MARGIN: 0px" id=z0y89&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #2b91af" id=z0y810&gt;Process&lt;/SPAN&gt; process = System.Diagnostics.&lt;SPAN style="COLOR: #2b91af" id=z0y811&gt;Process&lt;/SPAN&gt;.GetProcessesByName(&lt;SPAN style="COLOR: #a31515" id=z0y812&gt;"iexplore"&lt;/SPAN&gt;).First();&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=z0y813&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #2b91af" id=z0y815&gt;AutomationElement&lt;/SPAN&gt; browserInstance = System.Windows.Automation.&lt;SPAN style="COLOR: #2b91af" id=z0y816&gt;AutomationElement&lt;/SPAN&gt;.FromHandle(process.MainWindowHandle);&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=wu95&gt;&lt;SPAN style="COLOR: #2b91af" id=wu950&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Thread&lt;/SPAN&gt;.Sleep(1000);&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=wu951 mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=z0y817&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #2b91af" id=z0y818&gt;TreeWalker&lt;/SPAN&gt; tw = &lt;SPAN style="COLOR: blue" id=z0y819&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af" id=z0y820&gt;TreeWalker&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue" id=z0y821&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af" id=z0y822&gt;PropertyCondition&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af" id=z0y823&gt;AutomationElement&lt;/SPAN&gt;.AutomationIdProperty, &lt;SPAN style="COLOR: #a31515" id=z0y824&gt;"SearchTextBox"&lt;/SPAN&gt;));&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=z0y825&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #2b91af" id=z0y826&gt;AutomationElement&lt;/SPAN&gt; searchBox = tw.GetFirstChild(browserInstance);&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=z0y827&gt;&lt;SPAN style="COLOR: #2b91af" id=wu952&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Thread&lt;/SPAN&gt;.Sleep(1000);&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=wu953 mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=h25h&gt;
&lt;P style="MARGIN: 0px" id=h25h0&gt;&lt;FONT id=x_n643 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Windows.&lt;SPAN style="COLOR: #2b91af" id=h25h1&gt;Point&lt;/SPAN&gt; uiaPoint;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=wu954 mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=h25h2&gt;&lt;FONT id=x_n645 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue" id=h25h3&gt;if&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue" id=h25h4&gt;&lt;FONT id=cd-e color=#000000&gt;searchBox&lt;/FONT&gt;&lt;/SPAN&gt;.TryGetClickablePoint(&lt;SPAN style="COLOR: blue" id=h25h5&gt;out&lt;/SPAN&gt; uiaPoint))&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=h25h6&gt;&lt;FONT id=x_n646 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/FONT&gt;&lt;/P&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=cd-e0&gt;
&lt;P style="MARGIN: 0px" id=cd-e1&gt;&lt;FONT id=x_n647 size=2&gt;&lt;SPAN style="COLOR: #2b91af" id=cd-e2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Cursor&lt;/SPAN&gt;.Position = &lt;SPAN style="COLOR: blue" id=cd-e3&gt;&lt;FONT id=o64e0 color=#000000&gt;uiaPoint&lt;/FONT&gt;&lt;/SPAN&gt;.ToDrawingPoint();&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=gmcq&gt;&lt;FONT id=x_n648 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT id=gmcq0 color=#2b91af&gt;Mouse&lt;/FONT&gt;&lt;FONT id=gmcq1 color=#000000&gt;.Click();&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=gmcq2&gt;&lt;FONT id=x_n649 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #2b91af" id=z0y842&gt;SendKeys&lt;/SPAN&gt;.SendWait(&lt;SPAN style="COLOR: #a31515" id=z0y843&gt;"Hello, world!"&lt;/SPAN&gt;);&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;!--EndFragment--&gt;
&lt;P style="MARGIN: 0px" id=h25h9&gt;&lt;FONT id=x_n650 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=kdpa0&gt;&lt;FONT id=x_n651 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=kdpa1&gt;&lt;FONT id=x_n652 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/FONT&gt;&lt;/P&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=kdpa2&gt;
&lt;P style="MARGIN: 0px" id=kdpa3&gt;&lt;FONT id=x_n653 size=2&gt;&lt;SPAN style="COLOR: #2b91af" id=kdpa4&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert&lt;/SPAN&gt;.Fail();&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P style="MARGIN: 0px" id=kdpa5&gt;&lt;FONT id=x_n654 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P style="MARGIN: 0px" id=z0y846&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/DIV&gt;
&lt;P id=t0pm41 mce_keep="true"&gt;But what if you're dynamically building out your controls in code? You can still set the AutomationId property of generated controls using the static methods in AutomationProperties, which would look something like this:&lt;/P&gt;&lt;/DIV&gt;
&lt;DIV id=s.5z0&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=s.5z1&gt;
&lt;P style="MARGIN: 0px" id=s.5z2&gt;&lt;FONT id=dz2d size=2&gt;&lt;SPAN style="COLOR: #2b91af" id=s.5z3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ListBoxItem&lt;/SPAN&gt; myDynamicListBoxItem = &lt;SPAN style="COLOR: blue" id=s.5z4&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af" id=s.5z5&gt;ListBoxItem&lt;/SPAN&gt; { Content = &lt;SPAN style="COLOR: #a31515" id=s.5z6&gt;"Hello, world!"&lt;/SPAN&gt; };&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=s.5z7&gt;&lt;FONT id=dz2d0 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #2b91af" id=s.5z8&gt;AutomationProperties&lt;/SPAN&gt;.SetAutomationId(myDynamicListBoxItem, &lt;SPAN style="COLOR: #a31515" id=s.5z9&gt;"myDynamicListBoxAutomationId"&lt;/SPAN&gt;);&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;!--EndFragment--&gt;&lt;/DIV&gt;
&lt;DIV id=cd224&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=hu1i&gt;SendKeys has some new behaviors that were introduced in the .NET Framework 3.0. If that sort of thing interests you, you can read more about it &lt;A id=p2_l title=here href="http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.sendwait.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.sendwait.aspx"&gt;here&lt;/A&gt;. If you find that those results give you some inconsistent behaviors, you can make the following addition to your app.config in your Test project: &lt;/DIV&gt;
&lt;DIV id=hu1i0&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=hu1i1&gt;
&lt;DIV style="FONT-SIZE: 8pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: Consolas" id=p:c-&gt;
&lt;P style="MARGIN: 0px" id=p:c-0&gt;&lt;FONT id=dz2d1 size=2&gt;&lt;SPAN style="COLOR: blue" id=p:c-1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515" id=p:c-2&gt;appSettings&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=p:c-3&gt;&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=p:c-4&gt;&lt;FONT id=dz2d2 size=2&gt;&lt;SPAN style="COLOR: blue" id=p:c-5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515" id=p:c-6&gt;add&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=p:c-7&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red" id=p:c-8&gt;key&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=p:c-9&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue" id=p:c-10&gt;SendKeys&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue" id=p:c-11&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red" id=p:c-12&gt;value&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=p:c-13&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue" id=p:c-14&gt;SendInput&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue" id=p:c-15&gt;/&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px" id=p:c-16&gt;&lt;FONT id=dz2d3 size=2&gt;&lt;SPAN style="COLOR: blue" id=p:c-17&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515" id=p:c-18&gt;appSettings&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue" id=p:c-19&gt;&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;!--EndFragment--&gt;&lt;/DIV&gt;
&lt;DIV id=hu1i2&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=hu1i3&gt;Hope this helps :)&lt;/DIV&gt;
&lt;DIV id=hu1i4&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV id=cd225&gt;&amp;nbsp;&lt;/DIV&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8744351" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author><category term="UIA" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/UIA/" /><category term="Automation" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/Automation/" /><category term="UI Automation" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/UI+Automation/" /><category term="Silverlight" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/Silverlight/" /></entry><entry><title>UI Automation in Silverlight - Simulating User Interactions</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2008/07/12/ui-automation-in-silverlight-simulating-user-interactions.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2008/07/12/ui-automation-in-silverlight-simulating-user-interactions.aspx</id><published>2008-07-12T06:07:27Z</published><updated>2008-07-12T06:07:27Z</updated><content type="html">&lt;p id="kd45"&gt;I was recently tasked with automating Silverlight Rich Internet Applications (RIAs) in our immediate group. Some tools out there provide limited assistance in this regard; for example, you can write unit tests against your Silverlight controls for in-proc testing. You can read more about that approach here: &lt;a id="yduj" href="http://www.jeff.wilcox.name/2008/03/31/silverlight2-unit-testing/"&gt;http://www.jeff.wilcox.name/2008/03/31/silverlight2-unit-testing/&lt;/a&gt;&lt;/p&gt;  &lt;p id="yduj0"&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Unfortunately, my requirement is to enable &lt;i id="kd452"&gt;scenario &lt;/i&gt;automation. We must simulate a user that goes through several user flows both within and outside of our RIA; move the mouse somewhere, click on a thing, go to a 3rd party authentication provider, start typing some keys, and so on. The Silverlight unit testing framework doesn't quite address this requirement.&lt;/p&gt;  &lt;p id="yduj1"&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;UI automation in Silverlight has been a hotly followed topic around here. With the release of Silverlight Beta 2, we started seeing some accessibility stubs come into play. More correctly, we started seeing the WPF way of doing UI automation start to trickle in. If you want to follow along, you're going to want to grab UISpy (&lt;a id="u.ui" href="http://blogs.msdn.com/windowssdk/archive/2008/02/18/where-is-uispy-exe.aspx"&gt;http://blogs.msdn.com/windowssdk/archive/2008/02/18/where-is-uispy-exe.aspx&lt;/a&gt;).&lt;/p&gt;  &lt;p id="vzj8"&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The Microsoft UI Automation (UIA) assemblies were released with the .NET Framework 3.0. Traditionally, we've had various COM wrappers to work with Microsoft Active Accessibility (MSAA), which isn't going to get you very far with your Silverlight application. If you've done any sort of UI automation in WPF, then you're going to feel right at home. So, without dwelling on that further, let's start working with UIA!&lt;/p&gt;  &lt;p id="s7th"&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;First, let's start a new Test project in Visual Studio 2008. The UIA namespaces that you'll need to start automating applications in Silverlight are System.Windows.Automation and System.Windows.Automation.Providers. You'll need to add references to these assemblies that ship with .NET 3.0+ to get the relevant parts:&lt;/p&gt;  &lt;p id="f16m"&gt;&amp;#160;&amp;#160;&amp;#160; - UIAutomationProvider.dll &lt;/p&gt;  &lt;p id="dsbp"&gt;&amp;#160;&amp;#160; - UIAutomationClient.dll&lt;/p&gt;  &lt;p id="yzjx"&gt;&amp;#160;&amp;#160; - UIAutomationClientsideProviders.dll&lt;/p&gt;  &lt;p id="yzjx0"&gt;&amp;#160;&amp;#160; - UIAutomationTypes.dll&lt;/p&gt;  &lt;p id="n9sh"&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Let's say that we need to automate a Silverlight control that we own. We'll need to override the OnCreateAutomationPeer method (from the Control class) to return our own Peer type that handles the accessibility functions of the control. This is important, because the accessibility functions will be key in letting us automate our application.&lt;/p&gt;  &lt;p id="q9v3"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="q9v30"&gt;Assume a hypothetical Search control that consists of a text box and a search button: &lt;/p&gt;  &lt;div id="zd330" style="background: silver; color: black; font-family: consolas"&gt;   &lt;div id="a26o" style="background: silver; color: black; font-family: consolas"&gt;     &lt;p id="a26o0" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span id="a26o1" style="color: blue"&gt;public&lt;/span&gt; &lt;span id="a26o2" style="color: blue"&gt;partial&lt;/span&gt; &lt;span id="a26o3" style="color: blue"&gt;class&lt;/span&gt; &lt;span id="a26o4" style="color: #2b91af"&gt;SearchBar&lt;/span&gt; : &lt;span id="a26o5" style="color: #2b91af"&gt;Control&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;      &lt;p id="a26o6" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;   &lt;/div&gt;    &lt;p id="zd331" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ...&lt;/font&gt;&lt;/p&gt;    &lt;p id="f2w-" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;div id="kl:4" style="font-size: 8pt; background: silver; color: black; font-family: consolas"&gt;     &lt;p id="kl:40" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="kl:41" style="color: blue"&gt;public&lt;/span&gt; SearchBar()&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:42" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:43" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="kl:44" style="color: blue"&gt;this&lt;/span&gt;.GotFocus += (sender, args)&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:45" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; =&amp;gt;&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:46" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:47" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="kl:48" style="color: blue"&gt;this&lt;/span&gt;.SearchText.Focus();&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:49" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:410" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:411" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; InitializeComponent();&lt;/font&gt;&lt;/p&gt;      &lt;p id="kl:412" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;   &lt;/div&gt; &lt;!--EndFragment--&gt;    &lt;p id="a26o7" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="zd332" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="zd333" style="color: blue"&gt;protected&lt;/span&gt; &lt;span id="zd334" style="color: blue"&gt;override&lt;/span&gt; &lt;span id="zd335" style="color: #2b91af"&gt;AutomationPeer&lt;/span&gt; OnCreateAutomationPeer()&lt;/font&gt;&lt;/p&gt;    &lt;p id="zd336" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;    &lt;p id="zd337" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="zd338" style="color: blue"&gt;return&lt;/span&gt; &lt;span id="zd339" style="color: blue"&gt;new&lt;/span&gt; &lt;span id="zd3310" style="color: #2b91af"&gt;SearchBarAutomationPeer&lt;/span&gt;(&lt;span id="zd3311" style="color: blue"&gt;this&lt;/span&gt;);&lt;/font&gt;&lt;/p&gt;    &lt;p id="zd3312" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;    &lt;p id="a26o8" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p id="zd3313"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="zd3314"&gt;We've overridden the OnCreateAutomationPeer, which will get called by anything that's inspecting your control tree for accessibility functions (and consequently, your automation functions). The Peer object will be responsible for returning your combination of controls in a manner that is coherent to anything that needs accessibility. &lt;/p&gt;  &lt;p id="donw"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="donw0"&gt;In the process of doing so, we've also wired up the GotFocus handler to set up our controls' default .Focus() behavior. &lt;/p&gt;  &lt;p id="donw1"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="n-qm1"&gt;Let's take a look at what we need to implement the SearchBarAutomationPeer class: &lt;/p&gt;  &lt;div id="cdka" style="background: silver; color: black; font-family: consolas"&gt;   &lt;p id="cdka0" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span id="cdka1" style="color: blue"&gt;public&lt;/span&gt; &lt;span id="cdka2" style="color: blue"&gt;class&lt;/span&gt; &lt;span id="cdka3" style="color: #2b91af"&gt;SearchBarAutomationPeer&lt;/span&gt; : &lt;span id="cdka4" style="color: #2b91af"&gt;FrameworkElementAutomationPeer&lt;/span&gt;, &lt;span id="cdka5" style="color: #2b91af"&gt;IValueProvider&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="cdka7" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;    &lt;div id="sge:" style="background: silver; color: black; font-family: consolas"&gt;     &lt;p id="sge:0" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="sge:1" style="color: blue"&gt;public&lt;/span&gt; SearchBarAutomationPeer(&lt;span id="sge:2" style="color: #2b91af"&gt;SearchBar&lt;/span&gt; searchBar) : &lt;span id="sge:3" style="color: blue"&gt;base&lt;/span&gt;(searchBar)&lt;/font&gt;&lt;/p&gt;      &lt;p id="sge:4" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="sge:5" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;   &lt;/div&gt; &lt;/div&gt;  &lt;p id="n-qm3"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="cdka8"&gt;Our Peer class needs to derive from FrameworkElementautomationPeer to provide all the methods that we're going to need to work with. IValueProvider maps out to interacting with the TextBox component of our custom control. You can learn more about the Provider interface mapping to individual components here: &lt;a id="bh9g" href="http://msdn.microsoft.com/en-us/library/system.windows.automation.provider.aspx"&gt;http://msdn.microsoft.com/en-us/library/system.windows.automation.provider.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p id="c4xz"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="bzwl"&gt;We need to give our control a class name and an accessibility identifier to find it in the control tree. To do this, we must override GetAutomationIdCore() and GetClassNameCore() from FrameworkElementAutomationPeer.&lt;/p&gt;  &lt;p id="d1v4"&gt;&amp;#160;&lt;/p&gt;  &lt;div id="d1v40" style="background: silver; color: black; font-family: consolas"&gt;   &lt;p id="d1v41" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="d1v42" style="color: blue"&gt;protected&lt;/span&gt; &lt;span id="d1v43" style="color: blue"&gt;override&lt;/span&gt; &lt;span id="d1v44" style="color: blue"&gt;string&lt;/span&gt; GetAutomationIdCore()&lt;/font&gt;&lt;/p&gt;    &lt;p id="d1v45" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;    &lt;p id="d1v46" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="d1v47" style="color: blue"&gt;return&lt;/span&gt; &lt;span id="d1v418" style="color: #a31515"&gt;&amp;quot;SearchBar&amp;quot;&lt;/span&gt;; // You're going to want to make this unique. ;)&lt;/font&gt;&lt;/p&gt;    &lt;p id="d1v49" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;    &lt;p id="d1v410" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="d1v411" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="d1v412" style="color: blue"&gt;protected&lt;/span&gt; &lt;span id="d1v413" style="color: blue"&gt;override&lt;/span&gt; &lt;span id="d1v414" style="color: blue"&gt;string&lt;/span&gt; GetClassNameCore()&lt;/font&gt;&lt;/p&gt;    &lt;p id="d1v415" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;    &lt;p id="d1v416" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="d1v417" style="color: blue"&gt;return&lt;/span&gt; &lt;span id="r1w4" style="color: #a31515"&gt;&amp;quot;SearchBar&amp;quot;&lt;/span&gt;;&lt;/font&gt;&lt;/p&gt;    &lt;p id="d1v419" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;    &lt;p id="i:v3" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;div id="i:v30" style="background: silver; color: black; font-family: consolas"&gt;     &lt;p id="i:v31" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="i:v32" style="color: blue"&gt;protected&lt;/span&gt; &lt;span id="i:v33" style="color: blue"&gt;override&lt;/span&gt; &lt;span id="i:v34" style="color: blue"&gt;bool&lt;/span&gt; IsKeyboardFocusableCore()&lt;/font&gt;&lt;/p&gt;      &lt;p id="i:v35" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="i:v36" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="i:v37" style="color: blue"&gt;return&lt;/span&gt; &lt;span id="i:v38" style="color: blue"&gt;true&lt;/span&gt;;&lt;/font&gt;&lt;/p&gt;      &lt;p id="i:v39" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;   &lt;/div&gt; &lt;/div&gt;  &lt;p id="y-gp2"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="yzjx1"&gt;IsKeyboardFocusableCore is an important override to add in, as well; without it, our calls to SetFocus() on the control will fail. We should also think about implementing our Provider interface. The SearchBar that we passed into our constructor maps out to the base.Owner property. Casting base.Owner to SearchBar is going to get tedius, so we'll add a property to make working with that easier as well.&lt;/p&gt;  &lt;p id="dglh"&gt;&amp;#160;&lt;/p&gt;  &lt;div id="m58." style="background: silver; color: black; font-family: consolas"&gt;   &lt;p id="m58.0" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="m58.1" style="color: blue"&gt;public&lt;/span&gt; &lt;span id="m58.2" style="color: #2b91af"&gt;SearchBar&lt;/span&gt; SearchBar&lt;/font&gt;&lt;/p&gt;    &lt;p id="m58.3" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;    &lt;p id="m58.4" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="m58.5" style="color: blue"&gt;get&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="m58.6" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;    &lt;p id="m58.7" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="m58.8" style="color: blue"&gt;return&lt;/span&gt; (&lt;span id="m58.9" style="color: #2b91af"&gt;SearchBar&lt;/span&gt;)&lt;span id="m58.10" style="color: blue"&gt;base&lt;/span&gt;.Owner;&lt;/font&gt;&lt;/p&gt;    &lt;p id="m58.11" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;    &lt;p id="m58.12" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;    &lt;p id="m58.13" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="m58.14" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;span id="pxks" style="color: blue"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #region&lt;/span&gt; IValueProvider Members&lt;/font&gt;&lt;/p&gt;    &lt;div id="pxks0" style="background: silver; color: black; font-family: consolas"&gt;     &lt;p id="pxks1" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks2" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="pxks3" style="color: blue"&gt;public&lt;/span&gt; &lt;span id="pxks4" style="color: blue"&gt;bool&lt;/span&gt; IsReadOnly&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks5" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks6" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="pxks7" style="color: blue"&gt;get&lt;/span&gt; &lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks8" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks9" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="pxks10" style="color: blue"&gt;return&lt;/span&gt; &lt;span id="pxks11" style="color: blue"&gt;this&lt;/span&gt;.SearchBar.SearchText.IsReadOnly;&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks12" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks13" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks14" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks15" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="pxks16" style="color: blue"&gt;public&lt;/span&gt; &lt;span id="pxks17" style="color: blue"&gt;void&lt;/span&gt; SetValue(&lt;span id="pxks18" style="color: blue"&gt;string&lt;/span&gt; value)&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks19" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks20" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="pxks21" style="color: blue"&gt;this&lt;/span&gt;.SearchBar.SearchText.Text = value;&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks22" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks23" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks24" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="pxks25" style="color: blue"&gt;public&lt;/span&gt; &lt;span id="pxks26" style="color: blue"&gt;string&lt;/span&gt; Value&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks27" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks28" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="pxks29" style="color: blue"&gt;get&lt;/span&gt; &lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks30" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks31" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="pxks32" style="color: blue"&gt;return&lt;/span&gt; &lt;span id="pxks33" style="color: blue"&gt;this&lt;/span&gt;.SearchBar.SearchText.Text;&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks34" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks35" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks36" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;      &lt;p id="pxks37" style="margin: 0px"&gt;&lt;span id="pxks38" style="color: blue"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #endregion&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/div&gt; &lt;/div&gt;  &lt;p id="dglh0"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="dglh1"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="dglh2"&gt;If we take a look at our control in UISpy, it should now look something like this:&lt;/p&gt;  &lt;p id="g8tp"&gt;&amp;#160;&lt;/p&gt;  &lt;div id="t0pm" style="background: silver; color: black; font-family: consolas"&gt;   &lt;p id="t0pm0" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160; Identification&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm1" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; ClassName:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm2" style="color: #a31515"&gt;&amp;quot;SearchBar&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm3" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; ControlType:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm4" style="color: #a31515"&gt;&amp;quot;ControlType.Custom&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm5" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; Culture:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm6" style="color: #a31515"&gt;&amp;quot;(null)&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm7" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; AutomationId:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm8" style="color: #a31515"&gt;&amp;quot;SearchBar&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm9" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; LocalizedControlType:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm10" style="color: #a31515"&gt;&amp;quot;custom&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm11" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; Name:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm12" style="color: #a31515"&gt;&amp;quot;SearchBar&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm13" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; ProcessId:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm14" style="color: #a31515"&gt;&amp;quot;2276 (iexplore)&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm15" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; RuntimeId:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm16" style="color: #a31515"&gt;&amp;quot;42 197110 6&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm17" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; IsPassword:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm18" style="color: #a31515"&gt;&amp;quot;False&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm19" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; IsControlElement:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm20" style="color: #a31515"&gt;&amp;quot;True&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm21" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; IsContentElement:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm22" style="color: #a31515"&gt;&amp;quot;True&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm23" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm24" style="margin: 0px"&gt;&lt;font id="t0pm25" color="#000000"&gt;&lt;font size="2"&gt;&amp;#160; &lt;span id="t0pm26" style="color: #2b91af"&gt;&lt;font id="dglh3" color="#000000"&gt;Visibility&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm27" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; BoundingRectangle:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm28" style="color: #a31515"&gt;&amp;quot;(356, 286, 949, 36)&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm29" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; ClickablePoint:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm30" style="color: #a31515"&gt;&amp;quot;830,304&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm31" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; IsOffscreen:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm32" style="color: #a31515"&gt;&amp;quot;False&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm33" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm34" style="margin: 0px"&gt;&lt;font size="2"&gt;ControlPatterns&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm35" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160; Value&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm36" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; Value:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm37" style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p id="t0pm38" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160; IsReadOnly:&amp;#160;&amp;#160;&amp;#160; &lt;span id="t0pm39" style="color: #a31515"&gt;&amp;quot;False&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p id="g8tp0"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="t0pm40"&gt;The &amp;quot;Value&amp;quot; property under ControlPatterns automagically comes from the IValueProvider interface, mapping out to the value of our underlying TextBox. Slick, huh?&lt;/p&gt;  &lt;p id="z0y8"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="z0y80"&gt;So we've done some plumbing to enable our Silverlight control. Let's take a look at our test method looks like:&lt;/p&gt;  &lt;p id="z0y81"&gt;&amp;#160;&lt;/p&gt;  &lt;div id="z0y82" style="background: silver; color: black; font-family: consolas"&gt;   &lt;p id="z0y83" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [&lt;span id="z0y84" style="color: #2b91af"&gt;TestMethod&lt;/span&gt;]&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y85" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="z0y86" style="color: blue"&gt;public&lt;/span&gt; &lt;span id="z0y87" style="color: blue"&gt;void&lt;/span&gt; TestMethod1()&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y88" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y89" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="z0y810" style="color: #2b91af"&gt;Process&lt;/span&gt; process = System.Diagnostics.&lt;span id="z0y811" style="color: #2b91af"&gt;Process&lt;/span&gt;.GetProcessesByName(&lt;span id="z0y812" style="color: #a31515"&gt;&amp;quot;iexplore&amp;quot;&lt;/span&gt;).First();&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y813" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y814" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="z0y815" style="color: #2b91af"&gt;AutomationElement&lt;/span&gt; browserInstance = System.Windows.Automation.&lt;span id="z0y816" style="color: #2b91af"&gt;AutomationElement&lt;/span&gt;.FromHandle(process.MainWindowHandle);&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y817" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="z0y818" style="color: #2b91af"&gt;TreeWalker&lt;/span&gt; tw = &lt;span id="z0y819" style="color: blue"&gt;new&lt;/span&gt; &lt;span id="z0y820" style="color: #2b91af"&gt;TreeWalker&lt;/span&gt;(&lt;span id="z0y821" style="color: blue"&gt;new&lt;/span&gt; &lt;span id="z0y822" style="color: #2b91af"&gt;PropertyCondition&lt;/span&gt;(&lt;span id="z0y823" style="color: #2b91af"&gt;AutomationElement&lt;/span&gt;.ClassNameProperty, &lt;span id="z0y824" style="color: #a31515"&gt;&amp;quot;SearchBar&amp;quot;&lt;/span&gt;));&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y825" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="z0y826" style="color: #2b91af"&gt;AutomationElement&lt;/span&gt; searchBar = tw.GetFirstChild(browserInstance);&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y827" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y828" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; myElement.SetFocus(); &lt;/font&gt;&lt;/p&gt;    &lt;p id="m260"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="z0y834" style="color: #2b91af"&gt;Thread&lt;/span&gt;.Sleep(1000);&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y835" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; searchBar.SetFocus();&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y836" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="z0y839" style="color: #2b91af"&gt;Thread&lt;/span&gt;.Sleep(1000);&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y840" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y841" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="z0y842" style="color: #2b91af"&gt;SendKeys&lt;/span&gt;.SendWait(&lt;span id="z0y843" style="color: #a31515"&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;);&lt;/font&gt;&lt;/p&gt;    &lt;p id="z0y846" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p id="t0pm41"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="g8tp1"&gt;You might be asking yourself a couple of questions at this point: &amp;quot;Why did I implement IValueProvider?&amp;quot; for example. Well, the snippet above simulates user input. If that isn't your thing, in comes the ValuePattern. As an aside, I found interacting with the ValuePattern/TryGetCurrentPattern/etc and found the whole experience to be a bit clunky. You can see what I mean below:&lt;/p&gt;  &lt;p id="n79t"&gt;&amp;#160;&lt;/p&gt;  &lt;div id="n79t0" style="background: silver; color: black; font-family: consolas"&gt;   &lt;p id="n79t1" style="margin: 0px"&gt;&amp;#160;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [&lt;span id="n79t2" style="color: #2b91af"&gt;TestMethod&lt;/span&gt;]&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t3" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="n79t4" style="color: blue"&gt;public&lt;/span&gt; &lt;span id="n79t5" style="color: blue"&gt;void&lt;/span&gt; TestMethod1()&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t6" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t7" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="n79t8" style="color: #2b91af"&gt;Process&lt;/span&gt; process = System.Diagnostics.&lt;span id="n79t9" style="color: #2b91af"&gt;Process&lt;/span&gt;.GetProcessesByName(&lt;span id="n79t10" style="color: #a31515"&gt;&amp;quot;iexplore&amp;quot;&lt;/span&gt;).First();&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t11" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t12" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="n79t13" style="color: #2b91af"&gt;AutomationElement&lt;/span&gt; myElement = System.Windows.Automation.&lt;span id="n79t14" style="color: #2b91af"&gt;AutomationElement&lt;/span&gt;.FromHandle(process.MainWindowHandle);&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t15" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="n79t16" style="color: #2b91af"&gt;TreeWalker&lt;/span&gt; tw = &lt;span id="n79t17" style="color: blue"&gt;new&lt;/span&gt; &lt;span id="n79t18" style="color: #2b91af"&gt;TreeWalker&lt;/span&gt;(&lt;span id="n79t19" style="color: blue"&gt;new&lt;/span&gt; &lt;span id="n79t20" style="color: #2b91af"&gt;PropertyCondition&lt;/span&gt;(&lt;span id="n79t21" style="color: #2b91af"&gt;AutomationElement&lt;/span&gt;.ClassNameProperty, &lt;span id="n79t22" style="color: #a31515"&gt;&amp;quot;SearchBar&amp;quot;&lt;/span&gt;));&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t23" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="n79t24" style="color: #2b91af"&gt;AutomationElement&lt;/span&gt; searchBar = tw.GetFirstChild(myElement);&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t25" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t26" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span id="n79t27" style="color: blue"&gt;object&lt;/span&gt; valuePattern;&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t28" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; searchBar.TryGetCurrentPattern(&lt;span id="n79t29" style="color: #2b91af"&gt;ValuePattern&lt;/span&gt;.Pattern, &lt;span id="n79t30" style="color: blue"&gt;out&lt;/span&gt; valuePattern);&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t31" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((&lt;span id="n79t32" style="color: #2b91af"&gt;ValuePattern&lt;/span&gt;)valuePattern).SetValue(&lt;span id="n79t33" style="color: #a31515"&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;);&lt;/font&gt;&lt;/p&gt;    &lt;p id="n79t34" style="margin: 0px"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p id="p_vp"&gt;&amp;#160;&lt;/p&gt;  &lt;p id="sm7x"&gt;This is by no means a comprehensive guideline, but it should be enough to get those of you out there interested in UI automation going. &lt;/p&gt;  &lt;p id="ltrf"&gt;One caveat: applications with Windowless enabled show up as one huge control if you're looking in UISpy. Hopefully, support for accessibility (and subsequently, automation) will be in RTW builds of Silverlight. If you want to perform UI automation on your Silverlight application today, you'll have to do it without Windowless.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8722413" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author><category term="UIA" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/UIA/" /><category term="Automation" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/Automation/" /><category term="UI Automation" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/UI+Automation/" /><category term="Silverlight" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/Silverlight/" /></entry><entry><title>LINQ to SQL: Optimizing DataContext construction with the factory pattern</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2008/05/20/linq-to-sql-optimizing-datacontext-construction-with-the-factory-pattern.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2008/05/20/linq-to-sql-optimizing-datacontext-construction-with-the-factory-pattern.aspx</id><published>2008-05-20T02:10:00Z</published><updated>2008-05-20T02:10:00Z</updated><content type="html">&lt;p&gt;In the context of building out a web application, the corresponding DataContext is meant to be built out several times. The application's DataContext is constructed, some sort of data retrieval or manipulation is done, and then the DataContext goes out of scope. This operation will most likely be done several, several times throughout common user flows. &lt;/p&gt;  &lt;p&gt;However, constructing a DataContext object is a relatively expensive operation. 99.9% of this performance hit is spent building out the MappingSource object that gets used by your DataContext. Consider that, in a stock scenario, your application goes out and builds out the MappingSource object every single time that the DataContext object is created. Typically, this is something that will happen very frequently.&lt;/p&gt;  &lt;p&gt;These calls can be significantly optimized by caching the expensive part of the operation, which is the construction of the MappingSource object. If we wrap our DataContext construction around a factory method, we have a nice, centralized point for making this happen.&lt;/p&gt;  &lt;p&gt;Consider the following code example:&lt;/p&gt;  &lt;table class="" cellspacing="0" cellpadding="2" width="439" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td class="" valign="top" width="437"&gt;         &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public static class MyDataContextFactory&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; private static MappingSource _myMappingSource;&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public static MyDataContext Get()&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MyDataContext ctx;&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (_myMappingSource == null)&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ctx = new MyDataContext();&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _myMappingSource = ctx.Mapping.MappingSource;&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ctx = new MyDataContext(_myMappingSource);&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return ctx;&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;          &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;This example caches the MappingSource object by storing it in a static variable. We have another source file containing a partial class of MyDataContext. This partial class adds a new constructor that takes in a MappingSource object. &lt;/p&gt;  &lt;p&gt;This partial class is used to ensure that calling code doesn't have to worry about where the connection string comes from when passing a MappingSource into the constructor of a DataContext object. Our partial class now looks something like this:&lt;/p&gt;  &lt;table class="" cellspacing="0" cellpadding="2" width="441" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td class="" valign="top" width="439"&gt;         &lt;p&gt;public partial class MyDataContext            &lt;br /&gt;{             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public MyDataContext(MappingSource mappingSource)             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; : this(Settings.Default.MyConnectionString, mappingSource)             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }             &lt;br /&gt;}&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Now, our DataContext construction is exceptionally cheap after the first call. All subsequent calls will gain the performance advantage of the cached MappingSource object. In some informal performance testing, we found this approach to be a significant reduction in the amount of time it takes to construct a DataContext.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8519939" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>LINQ to SQL: Performance and Security</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2008/02/20/linq-to-sql-performance-and-security.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2008/02/20/linq-to-sql-performance-and-security.aspx</id><published>2008-02-20T19:41:00Z</published><updated>2008-02-20T19:41:00Z</updated><content type="html">&lt;P&gt;Like many people around the office, I've spent the last several weeks being completely enamored with LINQ. It started out innocently enough with a link to Joseph Albahari's &lt;A class="" title=LINQPad href="http://www.linqpad.net/" target=_blank mce_href="http://www.linqpad.net"&gt;LINQPad&lt;/A&gt; and it just took off from there. I'm pleased to say that it has pretty much replaced SQL Management Studio for my purposes.&amp;nbsp;And as an added bonus, it serves as an awesome C# scratchpad. :)&lt;/P&gt;
&lt;P&gt;I recall the "good ol' days" when people weren't entirely sure what LINQ had to offer; after all, we already had a decent query language that accomplished the same task! People were already quite proficient with SQL. Why would you need to learn a second query language? What was the point? There is absolutely no excuse to stay in this mindset; if you're not sure what LINQ has to offer, I &lt;EM&gt;strongly &lt;/EM&gt;recommend downloading LINQPad. See it for yourself; there is a &lt;EM&gt;lot&lt;/EM&gt; that LINQ has to offer. &lt;/P&gt;
&lt;P&gt;It isn't so much the syntax of the language as much as it is the implementation of all the tools.&amp;nbsp;The instant you connect to a database with LINQPad or generate your LINQ to SQL classes, you'll have&amp;nbsp;a collection of intuitive and easy-to-interact with objects that have well-defined associations to other objects.&amp;nbsp;For instance, an object with a 1:N relation to another table immediately has a collection of strongly-typed items from that other table. A 1:1 relation becomes a typed object; for example, an "AddedByUserId" column becomes an "AddedByUser" object, mapping out based on relationship on the User table. That related object has all of its associations set; suddenly, traversing from one corner of the database to the other becomes much easier.&lt;/P&gt;
&lt;P&gt;By intuitively working with the generated LINQ to SQL classes, a lot of work gets done &lt;EM&gt;for&lt;/EM&gt; you. Before I knew it, I had complex queries that were &lt;EM&gt;infinitely&lt;/EM&gt; more maintainable than their SQL equivalents. And&amp;nbsp;they took a &lt;EM&gt;fraction&lt;/EM&gt; of the time to write. In fact, I was able to rewire some of our more complex middle tiers within hours to start taking advantage of LINQ-based queries.&lt;/P&gt;
&lt;P&gt;However, despite the colossal benefits I've seen in such a short time, I've encountered a lot of resistance to LINQ. This resistance usually stems from these two reasons:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Myth 1: "LINQ is slow. Dynamically generating SQL queries is a costly maneuver; far moreso than just executing a stored procedure equivalent." This is one of the pitfalls of premature optimization; I've spoken with several people &lt;EM&gt;internally &lt;/EM&gt;who immediately discounted LINQ, saying that it wasn't ready for production code. Not surprisingly, these were people who had no interest in doing their research and had a relationship with SQL that could be best described as unhealthy ;)&amp;nbsp;&lt;A class="" title="Rico Mariani" href="http://blogs.msdn.com/ricom/" target=_blank mce_href="http://blogs.msdn.com/ricom/"&gt;Rico Mariani&lt;/A&gt; has a great 5 part blog post about performance in LINQ (summary &lt;A class="" title=here href="http://blogs.msdn.com/ricom/archive/2007/06/22/dlinq-linq-to-sql-performance-part-5.aspx" target=_blank mce_href="http://blogs.msdn.com/ricom/archive/2007/06/22/dlinq-linq-to-sql-performance-part-5.aspx"&gt;here&lt;/A&gt;);&amp;nbsp;in a&amp;nbsp;worst case scenario, you're looking at roughly a 7% reduction in performance. Within our group, this is an acceptable tradeoff between performance and productivity. &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Myth 2: "LINQ is insecure. Dynamically generating SQL queries means that my attack vector for SQL injection is much greater." This is another one of those healthy knee-jerk reactions; if I'm dynamically generating SQL, then&amp;nbsp;it would make sense that my SQL injection vector is higher.&amp;nbsp;If LINQ is dynamically generating SQL, then this should hold true. But it doesn't. Under the covers, LINQ is breaking down queries into parameterized SQL. Security was a huge concern that was revisited several times in LINQ's development; even through unusual vectors that couldn't be parameterized, LINQ remained a secure way to build out your SQL queries.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;I highly recommend taking some time out of the day to learn LINQ; the return on investment is tremendous. Even for something as small as the adhoc queries you make day-to-day, you'll find yourself saving a great chunk of time.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7820830" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author><category term="Performance" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/Performance/" /><category term=".NET 3.5" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/-NET+3-5/" /><category term="Security" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/Security/" /><category term="LINQ" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/LINQ/" /><category term="LINQPad" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/LINQPad/" /></entry><entry><title>WIX v3 and XmlConfig / XmlFile troubleshooting</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2007/10/09/wix-v3-and-xmlconfig-xmlfile-troubleshooting.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2007/10/09/wix-v3-and-xmlconfig-xmlfile-troubleshooting.aspx</id><published>2007-10-09T23:18:00Z</published><updated>2007-10-09T23:18:00Z</updated><content type="html">&lt;P&gt;I've recently been tasked with implementing deployment automation for each component of a relatively large project. Armed with a colleague who had done similar work before, I dove into WiX with a great resource at hand :)&lt;/P&gt;
&lt;P&gt;Let me preface this whole thing by saying that, despite the snags I've ran into, WiX is absolutely worth the effort. For as easy as WiX is to implement, it's criminal to *not* implement it in your project. Currently, the entire deployment process we have takes around 10-15% of the team's time. Dev and Test come up with a release plan, review with the program manager and release manager, refine, revise, rinse and repeat. Then, when the time to deploy actually comes, a hole in the document everyone signed off on becomes apparent. WiX helps solve that dilemma.&lt;/P&gt;
&lt;P&gt;My goal was to add an entry to the machine.config file's appSettings node. I needed to output: &amp;lt;add key="MSCOM/Environment" value="[MyVariable]" /&amp;gt;&lt;/P&gt;
&lt;P&gt;I wasn't able to find a lot of great documentation on this, so I'm hoping to save someone else some time :) That said,&amp;nbsp;let's move ahead to the XmlConfig/XmlFile issues I ran into:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;XmlConfig, despite my best efforts, didn't seem to actually *do* anything. Taking known-good examples yielded absolutely no edits to my target file. The root cause? At the time of this post, the latest build of WiX available on the Sourceforge download page 3.0.2925; however, the actual latest build is 3.0.3405 (&lt;A href="http://wix.sourceforge.net/releases/"&gt;http://wix.sourceforge.net/releases/&lt;/A&gt;). In build 2925, XmlConfig seems totally broken, but in build 3405, it functions as expected.&lt;/LI&gt;
&lt;LI&gt;Before realizing that a newer build was available, I resigned and tried to utilize an XmlFile to perform the same task. This proved difficult for a variety of reasons; XmlConfig lets you pass an ID to a new element, where XmlFile makes you do an XPath query each time. This results in a hacky solution where you create a temporary value, do queries based on that temporary value, and then null the value of the newly created node when done. Once this has been done, uninstalling doesn't remove the nodes. For manipulating Xml documents, XmlConfig is the way to go.&lt;/LI&gt;
&lt;LI&gt;Once I updated builds and XmlConfig was "working", the XmlConfig node wasn't actually creating a new element. The second XmlConfig node that added an attribute couldn't find the XmlElement created previously. I had to scope down from all attributes to a specific set&amp;nbsp;of attributes to get something to create.&lt;/LI&gt;
&lt;LI&gt;Once I had my &amp;lt;add&amp;gt; node&amp;nbsp;being written to the file,&amp;nbsp;my attributes wouldn't get written.&amp;nbsp;To successfully write attributes to a&amp;nbsp;newly created node, I had to scope down my XmlConfig node to&amp;nbsp;a few select attributes. Specifically, I believe&amp;nbsp;having "Action" and "Node"&amp;nbsp;values trips up the Util assembly.&lt;/LI&gt;
&lt;LI&gt;Once I had my attributes writing to the correct node, my uninstall process wouldn't remove the node it added. I added an XmlConfig node with On="uninstall" that *seemed* right. However, the parameters you expect to pass to XmlConfig vary by operation; it takes using the same attributes differently to actually do something on an uninstall. Specifically, ElementPath points to the *parent* node of the node you want to delete, and the VerifyPath is an XPath query to the node you want to delete, relative to the ElementPath. &lt;/LI&gt;
&lt;LI&gt;Documentation on XmlConfig is not good enough; the way you utilize parameters vary based on operation. The documentation doesn't make this apparent, leaving you to trial and error and a dozen searches that don't yield a solution. &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;The actual XML snippet I ended up using to get a successful uninstall/reinstall process was:&lt;/P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;util:XmlConfig&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id="MachineConfigAdd"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; File="[DOTNETCONFIGPATH]\machine.config"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Action="create"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ElementPath="//configuration/appSettings"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name="add"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Node="element"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sequence="1"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; On="install" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;util:XmlConfig&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id="MachineConfigKey"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; File="[DOTNETCONFIGPATH]\machine.config"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ElementPath="MachineConfigAdd"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name="key"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="MSCOM/ConfigEnvironment"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sequence="2" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;util:XmlConfig&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id="MachineConfigValue"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; File="[DOTNETCONFIGPATH]\machine.config"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ElementPath="MachineConfigAdd"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name="value"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="[ENVIRONMENT]"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sequence="3" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;util:XmlConfig&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id="MachineConfigRemoveNode"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; File="[DOTNETCONFIGPATH]\machine.config"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Action="delete"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Node="element"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VerifyPath="add[\[]@key='MSCOM/ConfigEnvironment'[\]]"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ElementPath="//configuration/appSettings"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; On="uninstall"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sequence="1" /&amp;gt; 
&lt;P&gt;I can only hope that this saves someone, somewhere a headache&amp;nbsp;:)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5385816" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author><category term="XmlFile" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/XmlFile/" /><category term="WiX 3" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/WiX+3/" /><category term="XmlConfig" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/XmlConfig/" /><category term="WiX" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/WiX/" /></entry><entry><title>Hooray!</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2007/01/18/hooray.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2007/01/18/hooray.aspx</id><published>2007-01-18T03:07:00Z</published><updated>2007-01-18T03:07:00Z</updated><content type="html">&lt;P&gt;Power was out for 9 days, from December 14th to December 23rd. Being stuck in freezing weather really helped take the edge off of Christmas :D Also, I'm pretty much useless without some sort of electronic gadget.&lt;/P&gt;
&lt;P&gt;The MSHTML COM object I was having problems with before isn't so much a *problem*. What I was running into was something that was done by design, and with good reasons. However, in this scenario, it didn't make much sense.&lt;/P&gt;
&lt;P&gt;I was writing a program to scrape relevant values off of a series of HTML pages. When you're using Passport (Windows Live ID) as an authentication mechanism, the login page always resides on login.live.com. The actual login page you visit is a page that hosts an iframeset. The contents you see outside of the login page are framed in from other sources/other domains. &lt;/P&gt;
&lt;P&gt;This scenario has an iframeset originating from login.live.com with content in iframes originating from &lt;A href="http://www.microsoft.com/"&gt;www.microsoft.com&lt;/A&gt;. I was interested in programmatically fetching the data from the content in those iframes. No problem! I wrote an application that used the .NET 2.0 WebBrowser object to navigate to the login page. I then went through the Window.Frames collection to get the underlying HTML documents. This is when I hit a System.UnauthorizedAccessException. What? Why should that happen?&lt;/P&gt;
&lt;P&gt;My understanding is that JavaScript works by manipulating the MSHTML COM object, and that limiting access to the content in the iframes is a by-design XSS countermeasure to prevent one domain from accessing sensitive information in another domain. Which makes total sense in terms of client-side script. But in this scenario, there simply wasn't a "clean" way to pull all of the information that didn't originate from login.live.com. &lt;/P&gt;
&lt;P&gt;My workaround?&amp;nbsp;A somewhat convoluted system in which after the initial request, three other hidden web browser objects (one for each iframe) are utilized to directly make requests to the URL value of each iframe. On the DocumentCompleted event, I'm able to&amp;nbsp;use the existing object model and scrape all of the&amp;nbsp;relevant information.&amp;nbsp;It's not ideal, but it works and I'm not recreating a ton of existing functionality.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1485864" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author><category term=".NET" scheme="http://blogs.msdn.com/b/gisenberg/archive/tags/-NET/" /></entry><entry><title>Still no power...</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2006/12/20/still-no-power.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2006/12/20/still-no-power.aspx</id><published>2006-12-20T23:31:00Z</published><updated>2006-12-20T23:31:00Z</updated><content type="html">&lt;P&gt;My area of Washington is still without power after last Thursday's windstorm. Power went out on Thursday night, and as of this posting, there's still no power. I'm feeling pretty useless without electronics :D&lt;/P&gt;
&lt;P&gt;To do: Write a whiny post about the WebBrowser COM interface.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1333542" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Good news, everyone! (Wii impressions)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2006/12/07/good-news-everyone-wii-impressions.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2006/12/07/good-news-everyone-wii-impressions.aspx</id><published>2006-12-07T07:20:00Z</published><updated>2006-12-07T07:20:00Z</updated><content type="html">&lt;P&gt;The 360 made it back, safe and sound, after three weeks of being out for repair. More correctly, a replacement unit made it back... And the unit that showed up is defective. It crashes frequently, the DVD drive is inoperable while the unit stands upright, and the DVD drive also makes terrible thunking sounds preceding hardware crashes. After a particularly scathing email to the support team, which I have no doubts will be met with an automated response, I feel a bit better. Alas, it looks like I'm still out of "The Game".&lt;/P&gt;
&lt;P&gt;I took advantage of the &lt;A class="" title="crippling snowstorm" href="http://www.komotv.com/news/local/4797576.html" target=_blank mce_href="http://www.komotv.com/news/local/4797576.html"&gt;crippling snowstorm&lt;/A&gt; a while back and called some nearby stores hoping to find a Wii in stock... Sure enough, they were in stock, but nobody could actually get to them on account of the snow. So off I went, facing the treacherous two to four inches of snow, all for a Wii! My grizzled Alaskan mountain man self was able to successfully navigate the snow... so by the time I arrived at the store, there were still plenty of Wii units on the shelf. The Factoria Target received roughly 50 units on the day I arrived, and the Redmond Target received somewhere in the range of 120. Accessories are almost more difficult to find at this point, but the good news is I made off with a Wii console while demand was still high :)&lt;/P&gt;
&lt;P&gt;If you read my earlier post on the Wii AILive SDK demo, you can see that I had reservations going in on the Wii. My primary concerns were that the control set would be completely gimmicky, feeling tacked on in games that they had no right to, and being used in a way that doesn't add anything to the gameplay (mapping gestures to buttons). The good news is that Wii Sports puts these fears to rest! Motions with the controller map very well to what is happening in the game. Bowling has become one of my favorite past times; being able to hold the wiimote in one hand and a beer in the other makes it an excellent party system :) I feel confident that gamers and non-gamers alike will play Wii Sports and leave, pleased with the experience they just had. &lt;/P&gt;
&lt;P&gt;The bad news is that, of the 20-something launch titles, most of them are multiplatform titles. Let me emphasize: Games that are not designed from the ground up for the Wii will not have control sets that make sense on the Wii. Wii Sports is an excellent use of the controller; golf swings, bat swings, throwing a bowling ball, and even boxing feel completely intuitive and can be picked up and played by anyone. However, Wii Sports is one of a sea of launch titles. Because it is a first party game, it is designed with the Wiimote control scheme and it completely makes sense. It feels intuitive to the non-gamer, and has the finesse to add lasting appeal. Other games? Not so much. &lt;/P&gt;
&lt;P&gt;Even Zelda: Twilight Princess has the tacked on control set feeling, and I'd be much happier with the game if I could play from the couch using a wireless gamepad. Flailing the nunchuk madly, trying to execute the "Special Move" that could just as easily be done by pressing the X button on the Gamecube "port" is not an ideal experience. Nunchuk flailing was added for the sake of utilizing an accelerometer, not because it made sense in the context of gameplay.&lt;/P&gt;
&lt;P&gt;This creates an interesting dilemma. The Wii has a reasonable launch library, far better than the 360 at launch. However, if given the choice between a game available on multiple platforms, I would never make the purchase for the Wii if the same option were available for&amp;nbsp;the 360. Unless the game is designed from the ground up for use on the Wii, it will be guaranteed to not "feel right" when played on the Wii. Additionally, opportunities for network play become extremely limited, visuals get kicked down&amp;nbsp;several notches, etc.&lt;/P&gt;
&lt;P&gt;The Wii and the 360 don't come close to occupying the same space. I believe the Wii will be the party game system with a handful of excellent first party titles. The library today is large, but first-party games that are designed to use the Wiimote will become the only "worthy" purchases. The number of worthy purchases will be a miniscule fraction of the total number of games available. The 360 still offers a different and unique experience, with big budget flashy titles and the best online implementation of The Three. &lt;/P&gt;
&lt;P&gt;&amp;nbsp;If you have a say in the matter, go Wii60 :)&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1231086" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Setting up a Windows Vista + XP Dual Boot</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/gisenberg/archive/2006/11/28/setting-up-a-windows-vista-xp-dual-boot.aspx" /><id>http://blogs.msdn.com/b/gisenberg/archive/2006/11/28/setting-up-a-windows-vista-xp-dual-boot.aspx</id><published>2006-11-28T09:45:00Z</published><updated>2006-11-28T09:45:00Z</updated><content type="html">&lt;P&gt;With my 360 out for repairs for the Thanksgiving weekend, I was looking for other ways to entertain myself during the long weekend. I've been running Vista as my primary OS since RC1 and swore I'd stick with it, but inevitably, I don't think Vista is something that can completely replace XP for gamers today.&lt;/P&gt;
&lt;P&gt;This weekend, I decided I'd try to play Knights of the Old Republic 2 on the PC.&amp;nbsp;I went to the options screen to turn the pretty effects up, but clicking on the "Advanced Options" button yielded a crash to desktop. Okay, no problem! I just won't go to the options. That's fine. I'll just play, and all will be well. But hey, what's with these framerates? In an engine that looks roughly equivalent to Quake 2, I was lucky to get ~20FPS on an AMD64 4800+ X2 on a 7900GTX 512MB machine with 2 gigs of RAM as soon as transparent particles came into the picture. And what's this? Another crash to desktop, just going from level to level? The crashes eventually made the game unplayable, so moving right along...&lt;/P&gt;
&lt;P&gt;Well, maybe I'll try playing Dark Messiah of Might and Magic. Which worked to some extent (after disabling a CPU core to bypass some driver issues!), but with intermittent and random crashes to the desktop. Keep in mind, these have been filed as bugs, but didn't make it into the business RTM. The second level was basically a death knell; if it didn't crash to the desktop upon loading, it would crash before the end of the level or run at 2FPS until I terminated the process. &lt;/P&gt;
&lt;P&gt;At this point, who's to blame? I'd wager 99.9% of the problems I'm running into at this point are all driver related. The actual operating system itself is sturdy, and it's a pleasure to work on. However, I don't believe it's ready for widespread adoption among gamers until the release in January. Support for games today is somewhat reasonable; there were more titles that worked for me than titles that didn't. And to be fair, the games above have had extremely problematic releases and support. However, I noticed that: 1) The new&amp;nbsp;Vista video drivers&amp;nbsp;are in their infancy. Running games in Vista will incur a large performance hit. 2) Not all games will run right out of the box. I bought Dark Messiah over a month ago and wasn't able to play it until setting up a Vista/XP dual boot. What if this had been Portal that didn't work? I, as well as nerds everywhere, would be crushed&amp;nbsp;:)&amp;nbsp;&lt;/P&gt;
&lt;P&gt;At the time I came to this realization, I still had a long weekend ahead of me... I thought, hey! Let's just install XP.&amp;nbsp;We'll set up a dual boot and be done with this nonsense! I did some cursory Live searches to see what others had discovered, and it sounded like a snap. So in goes the Windows XP CD.. I boot up, install on the same drive under the WINXP folder, setup restarts... and the machine won't start. The bootloader got totally hosed by the Windows XP install process, rendering the machine inoperable until running a Vista startup repair. At this point, the Windows XP install was incomplete, so I couldn't really do anything but do a clean format or stick with Vista.&lt;/P&gt;
&lt;P&gt;So I decide that my previous approach of trying to set up XP from Vista might be a bit backwards. I tackle the problem with newfound resolve and format my C drive, installing XP as a base to install Windows Vista in a dual boot fashion. Some time goes by, I install Windows XP, boot up the Vista DVD, and start the install process.. But wait! I can't install Vista side by side with Windows XP? The "Custom" installation is allowing me to pick a partition, and it even nicely offers to move my old OS to Windows.old, but I don't see an option to have the two living side-by-side in perfect harmony.&lt;/P&gt;
&lt;P&gt;At that point, I had to reformat my drive again and create two different partitions from the Vista installer. I then installed Windows XP on the C partition, and after a successful install, I started up the installer for Windows Vista. I picked the new partition, and lo! Everything worked just as I had wanted it to. The final tally was around 6 hours, 3 installs of Windows XP and two unplanned reformats.&lt;/P&gt;
&lt;P&gt;Unfortunately, as I use my home machine for gaming more than anything else, I'm finding that the increased performance and broader support in Windows XP is hard to leave. Even with a dual boot setup, I've spent more time in Windows XP than in Vista. At this stage, I couldn't see a gamer running Vista exclusively. I'm sure that will change as we get closer to the "For Everybody" release, but that doesn't do much good for the early adopters. :)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;In other news, the Xbox box showed up on Wednesday. It was picked up by UPS today, right before everything got &lt;A class="" title="snowed in" href="http://www.komotv.com/news/4758226.html" mce_href="http://www.komotv.com/news/4758226.html"&gt;snowed in&lt;/A&gt;. That puts me at 8 business days before receiving a new console. Hooray! I'm about a thousand points behind first place in the building 6 leaderboards. King K-0wn'g..ed? I guess? :D&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1164389" width="1" height="1"&gt;</content><author><name>gisenberg</name><uri>http://blogs.msdn.com/gisenberg/ProfileUrlRedirect.ashx</uri></author></entry></feed>