<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Zupancic Perspective (v2.0)</title>
    <link>http://blog.devstone.com/aaron/</link>
    <description>An insight into the world of R. Aaron Zupancic, software development (.NET, et al), muses, and much more...</description>
    <language>en-us</language>
    <copyright>R. Aaron Zupancic</copyright>
    <lastBuildDate>Mon, 08 Sep 2008 01:08:42 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.0.7226.0</generator>
    <managingEditor>aaron@devstone.com</managingEditor>
    <webMaster>aaron@devstone.com</webMaster>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=58a12801-ebbf-477d-910e-aff37ae901bd</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,58a12801-ebbf-477d-910e-aff37ae901bd.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,58a12801-ebbf-477d-910e-aff37ae901bd.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=58a12801-ebbf-477d-910e-aff37ae901bd</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">When granting database permissions to built-in security accounts
you need to be aware of potentially localized account names.</font>
        </p>
        <p>
          <font face="Tahoma">Just this past week I ran into an issue when attempting to execute
a SQL Server database script on a German server OS.  The database script in question
had hard-coded the usage of 'NT AUTHORITY\NETWORK SERVICE' as the account name for
granting database permissions.  As it turns out, however, this account doesn't
exist in the German version of Windows.  Instead, the account is '<span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true">NT-AUTORITÄT\NETZWERKDIENST'. 
I found it interesting that the account name is not localized on other non-English
versions of Windows.</span></font>
        </p>
        <p>
          <span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true">
            <font face="Tahoma">Unless
I misunderstanding something, the </font>
            <a href="http://msdn.microsoft.com/en-us/library/ms684272(VS.85).aspx">
              <font face="Tahoma">documentation</font>
            </a>
            <font face="Tahoma"> indicates
that "the name of the account in all locales is NT AUTHORITY\NETWORK SERVICE" so I
was initially confused by this.</font>
          </span>
        </p>
        <p>
          <font face="Tahoma">
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true">In
this particular case my script file is</span>
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true">,
conveniently, not executed 100% verbatim.  Via a little script engine that I
wrote, I have the ability to update variables with runtime values.  In this case,
rather than use the exact string 'NT AUTHORITY\NETWORK SERVICE', I replaced it with
a variable and determined the value to use at runtime.</span>
          </font>
        </p>
        <p>
          <span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true">
            <font face="Tahoma">Resolving
to the properly localized account name is pretty easy:</font>
          </span>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true">
              <font face="Courier New">
                <font color="#008000">private
static string</font> getNetworkServiceAcctName() {<br />
   SecurityIdentifier id = <font color="#008000">new</font> SecurityIdentifier(WellKnownSidType.NetworkServiceSid, <font color="#008000">null</font>);<br />
   NTAccount acct = ( NTAccount )id.Translate(<font color="#008000">typeof</font>(
NTAccount ));<br />
   <font color="#008000">return</font> acct.Value;<br />
}</font>
            </span>
          </p>
        </blockquote>
        <p>
          <span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true">
            <font face="Tahoma">What's
quite interesting is after researching the issue and updating the application to properly
resolve the account name, we stumbled upon a </font>
            <a href="http://blogs.msdn.com/jbower/archive/2005/04/01/404829.aspx">
              <font face="Tahoma">blog
post</font>
            </a>
            <font face="Tahoma"> made a couple of years ago that resolved the exact
same issue.</font>
          </span>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=58a12801-ebbf-477d-910e-aff37ae901bd" />
      </body>
      <title>Resolving Localized System Account Names</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,58a12801-ebbf-477d-910e-aff37ae901bd.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/09/08/ResolvingLocalizedSystemAccountNames.aspx</link>
      <pubDate>Mon, 08 Sep 2008 01:08:42 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;When granting database permissions to built-in security accounts
you need to be aware of potentially localized account names.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Just this past week I ran into an issue when attempting to execute
a SQL Server database script on a German server OS.&amp;nbsp; The database script in question
had hard-coded the usage of 'NT AUTHORITY\NETWORK SERVICE' as the account name for
granting database permissions.&amp;nbsp; As it turns out, however, this account doesn't
exist in the German version of Windows.&amp;nbsp; Instead, the account is '&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true"&gt;NT-AUTORITÄT\NETZWERKDIENST'.&amp;nbsp;
I found it interesting that the account name is not localized on other non-English
versions of Windows.&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true"&gt;&lt;font face=Tahoma&gt;Unless
I misunderstanding something, the &lt;/font&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms684272(VS.85).aspx"&gt;&lt;font face=Tahoma&gt;documentation&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt; indicates
that "the name of the account in all locales is NT AUTHORITY\NETWORK SERVICE" so I
was initially confused by this.&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true"&gt;In
this particular case my script file is&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true"&gt;,
conveniently, not executed 100% verbatim.&amp;nbsp; Via a little script engine that I
wrote, I have the ability to update variables with runtime values.&amp;nbsp; In this case,
rather than use the exact string 'NT AUTHORITY\NETWORK SERVICE', I replaced it with
a variable and determined the value to use at runtime.&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true"&gt;&lt;font face=Tahoma&gt;Resolving
to the properly localized account name is pretty easy:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true"&gt;&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;private
static string&lt;/font&gt; getNetworkServiceAcctName() {&lt;br&gt;
&amp;nbsp;&amp;nbsp; SecurityIdentifier id = &lt;font color=#008000&gt;new&lt;/font&gt; SecurityIdentifier(WellKnownSidType.NetworkServiceSid, &lt;font color=#008000&gt;null&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp; NTAccount acct = ( NTAccount )id.Translate(&lt;font color=#008000&gt;typeof&lt;/font&gt;(
NTAccount ));&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;return&lt;/font&gt; acct.Value;&lt;br&gt;
}&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana" minmax_bound="true"&gt;&lt;font face=Tahoma&gt;What's
quite interesting is after researching the issue and updating the application to properly
resolve the account name, we stumbled upon a &lt;/font&gt;&lt;a href="http://blogs.msdn.com/jbower/archive/2005/04/01/404829.aspx"&gt;&lt;font face=Tahoma&gt;blog
post&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt; made a couple of years ago that resolved the exact
same issue.&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=58a12801-ebbf-477d-910e-aff37ae901bd" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,58a12801-ebbf-477d-910e-aff37ae901bd.aspx</comments>
      <category>C#</category>
      <category>SQL Server</category>
      <category>Security</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=044c3b22-1b9e-48ce-bcde-d728e524795c</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,044c3b22-1b9e-48ce-bcde-d728e524795c.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,044c3b22-1b9e-48ce-bcde-d728e524795c.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=044c3b22-1b9e-48ce-bcde-d728e524795c</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">I ran across some interesting (read "unexpected") behavior the
other day when writing a .NET WinForms control.  This particular control has
some logic that executes if and only if the host OS has visual themes enabled.</font>
        </p>
        <p>
          <font face="Tahoma">In order to check for the existence of enabled themes, I call a
method called 'IsVisualStylesEnabled()' which is defined as below:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">public static bool </font>IsVisualStylesEnabled()
{<br />
   <font color="#008000">bool</font> isEnabled = <font color="#008000">false</font>;<br />
   <font color="#008000">try</font> {<br />
      OperatingSystem os = Environment.OSVersion;<br />
      <em><font color="#a9a9a9">// decide whether the OS
even supports visual styles</font></em><br />
      <font color="#008000">bool</font> isSupported = ( os.Platform
== PlatformID.Win32NT )<br />
                        
&amp;&amp; ( ( ( os.Version.Major == 5 ) &amp;&amp; ( os.Version.Minor &gt;= 1 ) )<br />
                             
|| ( os.Version.Major &gt; 5 ) );<br />
      <font color="#008000">if</font> ( isSupported ) {<br />
         int majorDllVersion = getComCtlMajorVersion();<br />
         isEnabled = ( majorDllVersion &gt;
5 ) &amp;&amp; IsThemeActive() &amp;&amp; IsAppThemed();<br />
      }<br />
   }<br />
   <font color="#008000">catch</font> ( Exception ) {<br />
      <em><font color="#a9a9a9">// do nothing explicitly</font></em><br />
   }<br />
   <font color="#008000">return</font> isEnabled;<br />
}</font>
          </p>
          <p>
            <br />
            <font face="Courier New">
              <font color="#008000">private static int</font> getComCtlMajorVersion()
{<br />
   DLLVERSIONINFO dllVersion = <font color="#008000">new</font> DLLVERSIONINFO
{ cbSize = Marshal.SizeOf(typeof( DLLVERSIONINFO )) };<br />
   DllGetVersion(<font color="#008000">ref</font> dllVersion);<br />
   <font color="#008000">return</font> dllVersion.dwMajorVersion;<br />
}</font>
          </p>
          <p>
            <font face="Courier New">
            </font> 
</p>
          <p>
            <font face="Courier New">[StructLayout(LayoutKind.Sequential)]<br /><font color="#008000">private struct</font> DLLVERSIONINFO {<br />
   <font color="#008000">public int</font> cbSize;<br />
   <font color="#008000">public int</font> dwMajorVersion;<br />
   <font color="#008000">public int</font> dwMinorVersion;<br />
   <font color="#008000">public int</font> dwBuildNumber;<br />
   <font color="#008000">public int</font> dwPlatformID;<br />
}</font>
          </p>
          <p>
            <font face="Courier New">
            </font> 
</p>
          <p>
            <font face="Courier New">[DllImport(<font color="#a52a2a">"comctl32.dll"</font>, CharSet
= CharSet.Auto)]<br /><font color="#008000">private static extern int</font> DllGetVersion(<font color="#008000">ref</font> DLLVERSIONINFO
version);</font>
          </p>
          <p>
            <br />
            <font face="Courier New">[DllImport(<font color="#a52a2a">"uxtheme.dll"</font>, CharSet
= CharSet.Auto)]<br /><font color="#008000">private static extern bool</font> IsThemeActive();</font>
          </p>
          <p>
            <br />
            <font face="Courier New">[DllImport(<font color="#a52a2a">"uxtheme.dll"</font>, CharSet
= CharSet.Auto)]<br /><font color="#008000">private static extern bool</font> IsAppThemed();</font>
          </p>
        </blockquote>
        <p dir="ltr">
          <font face="Tahoma">This code is pretty standard.</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">At design-time (i.e., within Visual Studio) my control would render
properly.  The problem, however, was evident when I executed the code - it
would think that visual styles were disabled and degrade gracefully to the non-themed
output.</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">After a little bit of debugging I discovered that the comctl32.dll
version being loaded at design-time was version 6 (the desired version) whereas at
runtime I was getting version 5.  The first thing I tried was embedding a manifest
into my executable to explicitly load version 6.  No dice - I was still getting
version 5.</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">Ultimately, however, I did discover the source of the issue: I
was calling the IsVisualStylesEnabled() too early in the load process of my application. 
This was made apparent by placing my control on a form other than the start-up form
- everything worked!</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">When initialized, my control began setting up UI components such
as brushes, pens, etc and some of this logic was based on whether the themes were
enabled.  Most, if not all, of the setup logic occurs in the InitializeComponent()
method which is called from the .ctor() of the control.</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">In order to guarantee that the proper version of comctl32.dll
is loaded, you cannot call the GetDllVersion() method until at least the OnHandleCreated()
method of your control.  If you call it earlier, you effectively <em>lock</em> your
application (and consequently the host application if your application is a visual
component) into using version 5 whether or not the manifest dictates otherwise.</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">For my purposes, I had to wait until the OnPaintBackground() method
to initialize the brushes and other auxiliary objects, but that at least happens after
the OnHandleCreated().</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=044c3b22-1b9e-48ce-bcde-d728e524795c" />
      </body>
      <title>Watch How and When You Check For Windows Themes</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,044c3b22-1b9e-48ce-bcde-d728e524795c.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/09/02/WatchHowAndWhenYouCheckForWindowsThemes.aspx</link>
      <pubDate>Tue, 02 Sep 2008 05:50:27 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;I ran across some interesting (read "unexpected") behavior the other
day when writing a .NET WinForms control.&amp;nbsp; This particular control has some logic
that executes if and only&amp;nbsp;if the host OS has visual themes enabled.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;In order to check for the existence of enabled themes, I call&amp;nbsp;a
method called 'IsVisualStylesEnabled()' which is defined as below:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;public static bool &lt;/font&gt;IsVisualStylesEnabled()
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;bool&lt;/font&gt; isEnabled = &lt;font color=#008000&gt;false&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;try&lt;/font&gt; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OperatingSystem os = Environment.OSVersion;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&lt;font color=#a9a9a9&gt;// decide whether the OS even
supports visual styles&lt;/font&gt;&lt;/em&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;bool&lt;/font&gt; isSupported = ( os.Platform
== PlatformID.Win32NT )&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;amp;&amp;amp; ( ( ( os.Version.Major == 5 ) &amp;amp;&amp;amp; ( os.Version.Minor &amp;gt;= 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
|| ( os.Version.Major &amp;gt; 5 ) );&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;if&lt;/font&gt; ( isSupported ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int majorDllVersion = getComCtlMajorVersion();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isEnabled = ( majorDllVersion &amp;gt;
5 ) &amp;amp;&amp;amp; IsThemeActive() &amp;amp;&amp;amp; IsAppThemed();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;catch&lt;/font&gt; ( Exception ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&lt;font color=#a9a9a9&gt;// do nothing explicitly&lt;/font&gt;&lt;/em&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;return&lt;/font&gt; isEnabled;&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;private static int&lt;/font&gt; getComCtlMajorVersion()
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; DLLVERSIONINFO dllVersion = &lt;font color=#008000&gt;new&lt;/font&gt; DLLVERSIONINFO
{ cbSize = Marshal.SizeOf(typeof( DLLVERSIONINFO )) };&lt;br&gt;
&amp;nbsp;&amp;nbsp; DllGetVersion(&lt;font color=#008000&gt;ref&lt;/font&gt; dllVersion);&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;return&lt;/font&gt; dllVersion.dwMajorVersion;&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;/font&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;[StructLayout(LayoutKind.Sequential)]&lt;br&gt;
&lt;font color=#008000&gt;private struct&lt;/font&gt; DLLVERSIONINFO {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public int&lt;/font&gt; cbSize;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public int&lt;/font&gt; dwMajorVersion;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public int&lt;/font&gt; dwMinorVersion;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public int&lt;/font&gt; dwBuildNumber;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public int&lt;/font&gt; dwPlatformID;&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;/font&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;[DllImport(&lt;font color=#a52a2a&gt;"comctl32.dll"&lt;/font&gt;, CharSet
= CharSet.Auto)]&lt;br&gt;
&lt;font color=#008000&gt;private static extern int&lt;/font&gt; DllGetVersion(&lt;font color=#008000&gt;ref&lt;/font&gt; DLLVERSIONINFO
version);&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;font face="Courier New"&gt;[DllImport(&lt;font color=#a52a2a&gt;"uxtheme.dll"&lt;/font&gt;, CharSet
= CharSet.Auto)]&lt;br&gt;
&lt;font color=#008000&gt;private static extern bool&lt;/font&gt; IsThemeActive();&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;font face="Courier New"&gt;[DllImport(&lt;font color=#a52a2a&gt;"uxtheme.dll"&lt;/font&gt;, CharSet
= CharSet.Auto)]&lt;br&gt;
&lt;font color=#008000&gt;private static extern bool&lt;/font&gt; IsAppThemed();&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;This code is pretty standard.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;At design-time (i.e., within Visual Studio) my control would render
properly.&amp;nbsp; The problem, however, was evident when I executed the code -&amp;nbsp;it
would think that visual styles were disabled and degrade gracefully to the non-themed
output.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;After a little bit of debugging I discovered that the comctl32.dll
version being loaded at design-time was version 6 (the desired version) whereas at
runtime I was getting version 5.&amp;nbsp; The first thing I tried was embedding a manifest
into my executable to explicitly load version 6.&amp;nbsp; No dice - I was still getting
version 5.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;Ultimately, however, I did discover the source of the issue: I was
calling the IsVisualStylesEnabled() too early in the load process of my application.&amp;nbsp;
This was made apparent by placing my control on a form other than the start-up form
- everything worked!&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;When initialized, my control began setting up UI components such
as brushes, pens, etc and some of this logic was based on whether the themes were
enabled.&amp;nbsp; Most, if not all, of the setup logic occurs in the InitializeComponent()
method which is called from the .ctor() of the control.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;In order to guarantee that the proper version of comctl32.dll is
loaded, you cannot call the GetDllVersion() method until at least the OnHandleCreated()
method of your control.&amp;nbsp; If you call it earlier, you effectively &lt;em&gt;lock&lt;/em&gt; your
application (and consequently the host application if your application is a visual
component) into using version 5 whether or not the manifest dictates otherwise.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;For my purposes, I had to wait until the OnPaintBackground() method
to initialize the brushes and other auxiliary objects, but that at least happens after
the OnHandleCreated().&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=044c3b22-1b9e-48ce-bcde-d728e524795c" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,044c3b22-1b9e-48ce-bcde-d728e524795c.aspx</comments>
      <category>C#</category>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=941944d3-44ad-423e-8ec5-08519fa7b2e8</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,941944d3-44ad-423e-8ec5-08519fa7b2e8.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,941944d3-44ad-423e-8ec5-08519fa7b2e8.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=941944d3-44ad-423e-8ec5-08519fa7b2e8</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">I've been putting together a nice little WinForms Wizard control
recently that had a few twist and turns to its development.  In particular, I
wanted to make the design-time experience a good one for the end user.  I wanted
to support design-time navigation of the wizard pages, drag/drop of control to each
child page, reordering of the pages, and much more.  In fact, as soon as
I tidy up the code a bit and flesh it out a bit, I'll be posting the component here
on my blog for general use.  But enough of that...</font>
        </p>
        <p>
          <font face="Tahoma">The wizard control has a rich design-time experience. 
I owe some of the thanks for the functionality to control's ControlDesigner and DesignerActionList. 
Among many other things, these classes provides a mechanism for a developer to
associate custom verbs and actions with the control at design-time.  These actions
are made available to the developer through the smart-tag menu when the control is
selected on its design surface.</font>
        </p>
        <p>
          <font face="Tahoma">It is through these custom actions that I've given the programmer
the ability to manage pages on the wizard.  Internally, these pages are represented
not only as controls on the wizard itself, but also in a collection of pages that
the wizard uses to properly navigate the sequence of pages.  It is this collection
that gets persisted (serialized) in the form's InitializeComponent() method when saving
changes made to the wizard at design-time.</font>
        </p>
        <p>
          <font face="Tahoma">I quickly discovered, however, that all wasn't green grass and
blue skies.  I wanted to support reordering the pages through the design-time
smart-tags.  While I was able to easily reorder the elements in the page collection
and even update the control's display at design-time to reflect the changes, the Visual
Studio environment didn't register the change.  Unless I then went ahead and
further edited a property through Visual Studio itself (effectively to <em>cause a
change</em> in the environment), the reordering of the pages never persisted. 
So I had to figure out how to notify Visual Studio that a change had been made.</font>
        </p>
        <p>
          <font face="Tahoma">Fortunately, this isn't difficult, but it's not very intuitive
at the same time.</font>
        </p>
        <p>
          <font face="Tahoma">The ControlDesigner's GetService() method provides access to the
services available to the control at design time.  Among these is the IComponentChangeService. 
It is through this service that you can notify the designer of a change.  To
do so, you need a property to update.  I, for one, don't really like the idea
of utilizing an existing property for this purpose (though it could be done).</font>
        </p>
        <p>
          <font face="Tahoma">What I did in my solution was create a design-time-only property
in the ControlDesigner.  Then, when a change is made that requires the change
notification I call a method which 'updates' the property.  The property doesn't
really get updated, but at least the code is clearer.</font>
        </p>
        <p>
          <font face="Tahoma">In the control designer:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">protected override void</font> PreFilterProperties(IDictionary
properties) {<br />
   <font color="#008000">base</font>.PreFilterProperties(properties);<br /><br />
   Attribute[] attribs = {<br />
                            <font color="#008000">new</font> BrowsableAttribute(<font color="#008000">false</font>),<br />
                            <font color="#008000">new</font> DesignOnlyAttribute(<font color="#008000">true</font>)<br />
                        
};<br />
   PropertyDescriptor prop = TypeDescriptor.CreateProperty(GetType(), <font color="#a52a2a">"DesignTimeChange"</font>, <font color="#008000">typeof</font>(<font color="#008000">string</font>),
attribs);<br />
   properties.Add(<font color="#a52a2a">"DesignTimeChange"</font>, prop);<br />
}<br /><br /><font color="#a9a9a9">/// &lt;summary&gt;<br />
/// Property created exclusively for the purpose of notifying the<br />
/// designer of changes to properties made through the designer<br />
/// (such as reordering the pages).<br />
/// &lt;/summary&gt;<br /></font><font color="#008000">public string</font> DesignTimeChange { <font color="#008000">get</font>; <font color="#008000">set</font>;
}</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">Then, also in the Designer, a method that causes a change to be
acknowledged:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">private void</font> notifyOfChange()
{<br />
   PropertyDescriptor prop = TypeDescriptor.GetProperties(<font color="#008000">this</font>)[<font color="#a52a2a">"DesignTimeChange"</font>];<br />
   getComponentChangeService().OnComponentChanged(<font color="#008000">this</font>,
prop, <font color="#008000">null</font>, <font color="#008000">null</font>);<br />
}</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">That's all there is to it.  When an action occurs in the
designer that would not otherwise register a change in the environment, I simply have
it call the notifyOfChange() method.</font>
        </p>
        <p>
          <font face="Tahoma">A little more work would be involved if the change were coming
from outside the designer.  For instance, if the change was made within the collection
or within the control, you'd first have to evaluate whether it's running in design
mode, and then retrieve a reference to the ControlDesigner, invoking the method (it'd
probably have to be made <strong>internal</strong> (and it's name appropriately Pascal-cased)
rather than <strong>private</strong>).</font>
        </p>
        <p>
          <font face="Tahoma">Maybe something like this (NOTE: untested, but seemingly approximately
accurate):</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">if</font> ( DesignMode ) {<br />
   IDesignerHost host = ( IDesignerHost )Site.Container;<br />
   ControlDesigner designer = ( ControlDesigner )host.GetDesigner(<font color="#008000">this</font>);<br />
   designer.NotifyOfChange();<br />
}</font>
          </p>
        </blockquote>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=941944d3-44ad-423e-8ec5-08519fa7b2e8" />
      </body>
      <title>Registering Design-Time Changes Programmatically in Custom .NET Controls</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,941944d3-44ad-423e-8ec5-08519fa7b2e8.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/08/29/RegisteringDesignTimeChangesProgrammaticallyInCustomNETControls.aspx</link>
      <pubDate>Fri, 29 Aug 2008 01:47:20 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;I've been putting together a nice little WinForms Wizard control
recently that had a few twist and turns to its development.&amp;nbsp; In particular, I
wanted to make the design-time experience a good one for the end user.&amp;nbsp; I wanted
to support design-time navigation of the wizard pages, drag/drop of control to each
child page, reordering of the pages,&amp;nbsp;and much more.&amp;nbsp; In fact, as soon as
I tidy up the code a bit and flesh it out a bit, I'll be posting the component here
on my blog for general use.&amp;nbsp; But enough of that...&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;The wizard&amp;nbsp;control has a rich design-time experience.&amp;nbsp;
I owe some of the thanks for the functionality to control's ControlDesigner and DesignerActionList.&amp;nbsp;
Among many other things, these classes&amp;nbsp;provides a mechanism for a developer to
associate custom verbs and actions with the control at design-time.&amp;nbsp; These actions
are made available to the developer through the smart-tag menu when the control is
selected on its design surface.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;It is through these custom actions that I've given the programmer
the ability to manage pages on the wizard.&amp;nbsp; Internally, these pages are represented
not only as controls on the wizard itself, but also in a collection of pages that
the wizard uses to properly navigate the sequence of pages.&amp;nbsp; It is this collection
that gets persisted (serialized) in the form's InitializeComponent() method when saving
changes made to the wizard at design-time.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I quickly discovered, however, that all wasn't green grass and blue
skies.&amp;nbsp; I wanted to support reordering the pages through the design-time smart-tags.&amp;nbsp;
While I was able to easily reorder the elements in the page collection and even update
the control's display at design-time to reflect the changes, the Visual Studio environment
didn't register the change.&amp;nbsp; Unless I then went ahead and further edited a property
through Visual Studio itself (effectively to &lt;em&gt;cause a change&lt;/em&gt; in the environment),
the reordering of the pages never persisted.&amp;nbsp; So I had to figure out how to notify
Visual Studio that a&amp;nbsp;change had been made.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Fortunately, this isn't difficult, but it's not very intuitive at
the same time.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;The ControlDesigner's GetService() method provides access to the
services available to the control at design time.&amp;nbsp; Among these is the IComponentChangeService.&amp;nbsp;
It is through this service that you can notify the designer of a change.&amp;nbsp; To
do so, you need a property to update.&amp;nbsp; I, for one, don't really like the idea
of utilizing an existing property for this purpose (though it could be done).&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;What I did in my solution was create a design-time-only property
in the ControlDesigner.&amp;nbsp; Then, when a change is made that requires the change
notification I call a method which 'updates' the property.&amp;nbsp; The property doesn't
really get updated, but at least the code is clearer.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;In the control designer:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;protected override void&lt;/font&gt; PreFilterProperties(IDictionary
properties) {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;base&lt;/font&gt;.PreFilterProperties(properties);&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; Attribute[] attribs = {&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;new&lt;/font&gt; BrowsableAttribute(&lt;font color=#008000&gt;false&lt;/font&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;new&lt;/font&gt; DesignOnlyAttribute(&lt;font color=#008000&gt;true&lt;/font&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
};&lt;br&gt;
&amp;nbsp;&amp;nbsp; PropertyDescriptor prop = TypeDescriptor.CreateProperty(GetType(), &lt;font color=#a52a2a&gt;"DesignTimeChange"&lt;/font&gt;, &lt;font color=#008000&gt;typeof&lt;/font&gt;(&lt;font color=#008000&gt;string&lt;/font&gt;),
attribs);&lt;br&gt;
&amp;nbsp;&amp;nbsp; properties.Add(&lt;font color=#a52a2a&gt;"DesignTimeChange"&lt;/font&gt;, prop);&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;font color=#a9a9a9&gt;/// &amp;lt;summary&amp;gt;&lt;br&gt;
/// Property created exclusively for the purpose of notifying the&lt;br&gt;
/// designer of changes to properties made through the designer&lt;br&gt;
/// (such as reordering the pages).&lt;br&gt;
/// &amp;lt;/summary&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font color=#008000&gt;public string&lt;/font&gt; DesignTimeChange { &lt;font color=#008000&gt;get&lt;/font&gt;; &lt;font color=#008000&gt;set&lt;/font&gt;;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;Then, also in the Designer, a method that causes a change to be
acknowledged:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;private void&lt;/font&gt; notifyOfChange()
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; PropertyDescriptor prop = TypeDescriptor.GetProperties(&lt;font color=#008000&gt;this&lt;/font&gt;)[&lt;font color=#a52a2a&gt;"DesignTimeChange"&lt;/font&gt;];&lt;br&gt;
&amp;nbsp;&amp;nbsp; getComponentChangeService().OnComponentChanged(&lt;font color=#008000&gt;this&lt;/font&gt;,
prop, &lt;font color=#008000&gt;null&lt;/font&gt;, &lt;font color=#008000&gt;null&lt;/font&gt;);&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;That's all there is to it.&amp;nbsp; When an action occurs in the designer
that would not otherwise register a change in the environment, I simply have it call
the notifyOfChange() method.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;A little more work would be involved if the change were coming from
outside the designer.&amp;nbsp; For instance, if the change was made within the collection
or within the control, you'd first have to evaluate whether it's running in design
mode, and then retrieve a reference to the ControlDesigner, invoking the method (it'd
probably have to be made &lt;strong&gt;internal&lt;/strong&gt; (and it's name appropriately Pascal-cased)
rather than &lt;strong&gt;private&lt;/strong&gt;).&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Maybe something like this (NOTE: untested, but seemingly approximately
accurate):&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;if&lt;/font&gt; ( DesignMode ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp; IDesignerHost host = ( IDesignerHost )Site.Container;&lt;br&gt;
&amp;nbsp;&amp;nbsp; ControlDesigner designer = ( ControlDesigner )host.GetDesigner(&lt;font color=#008000&gt;this&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp; designer.NotifyOfChange();&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt;&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=941944d3-44ad-423e-8ec5-08519fa7b2e8" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,941944d3-44ad-423e-8ec5-08519fa7b2e8.aspx</comments>
      <category>C#</category>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=f3c84b9c-6b85-45ab-8158-fa8e3f0d0819</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,f3c84b9c-6b85-45ab-8158-fa8e3f0d0819.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,f3c84b9c-6b85-45ab-8158-fa8e3f0d0819.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=f3c84b9c-6b85-45ab-8158-fa8e3f0d0819</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">Earlier this year I <a href="http://blog.devstone.com/aaron/2008/02/07/UsingSGENexeFromWithinVisualStudio.aspx">posted
an article</a> demonstrating how to use the SGEN.exe utility to generate a serialization
assembly.  The article identified how to create a custom MSBuild task by editing
the project file (e.g., csproj).  I've recently come to discover that the MSBuild
task will fail when automating a build of the project through TFS Build. 
The error presents itself as follows:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Tahoma" color="#ff0000">SGEN(0,0): error : File or assembly name 'C:....\bin\CustomLibrary.dll',
or one of its dependencies, was not found.</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">Ultimately, the root of the problem goes back to the SGEN
MSBuild task's usage of the $(OutputPath) variable.  Even in TFS Build this is
pointing to same location that Visual Studio would point to.  TFS, however, will
override the output locations of the compiled applications, but this variable doesn't
get updated.  As stated in the </font>
          <a href="http://msdn.microsoft.com/en-us/library/bb629394.aspx">
            <font face="Tahoma">MSDN
documentation</font>
          </a>
          <font face="Tahoma">, "OutputPath has been deprecated and
OutDir should be used instead whenever possible.".  I was happy to discover that
by simply replacing the $(OutputPath) with $(OutDir) in the MSBuild task was all I
needed to do; the task will execute properly both from my development machine as well
as the build server.</font>
        </p>
        <p>
          <font face="Tahoma">My updated task resembles the following:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">&lt;<font color="#a52a2a">Target</font><font color="#ff0000">Name</font>="<font color="#0000ff">GenSerializationAssembly</font>"<br />
        <font color="#ff0000">DependsOnTargets</font>="<font color="#0000ff">AssignTargetPaths;Compile;ResolveKeySource</font>"<br />
        <font color="#ff0000">Inputs</font>="<font color="#0000ff">$(MSBuildAllProjects);@(IntermediateAssembly)</font>"<br />
        <font color="#ff0000">Outputs</font>="<font color="#0000ff">$(OutDir)$(_<span class="searchword">SGen</span>DllName)</font>"&gt;<br />
  &lt;<font color="#a52a2a"><span class="searchword">SGen</span></font><font color="#ff0000">BuildAssemblyName</font>="<font color="#0000ff">$(TargetFileName)</font>"<br />
        <font color="#ff0000">BuildAssemblyPath</font>="<font color="#0000ff">$(OutDir)</font>"<br />
        <font color="#ff0000">References</font>="<font color="#0000ff">@(ReferencePath)</font>"<br />
        <font color="#ff0000">ShouldGenerateSerializer</font>="<font color="#0000ff">true</font>"<br />
        <font color="#ff0000">UseProxyTypes</font>="<font color="#0000ff">false</font>"<br />
        <font color="#ff0000">KeyContainer</font>="<font color="#0000ff">$(KeyContainerName)</font>"<br />
        <font color="#ff0000">KeyFile</font>="<font color="#0000ff">$(KeyOriginatorFile)</font>"<br />
        <font color="#ff0000">DelaySign</font>="<font color="#0000ff">$(DelaySign)</font>"<br />
        <font color="#ff0000">ToolPath</font>="<font color="#0000ff">$(<span class="searchword">SGen</span>ToolPath)</font>"&gt;<br />
    &lt;<font color="#a52a2a">Output</font><font color="#ff0000">TaskParameter</font>="<font color="#0000ff">SerializationAssembly</font>" <font color="#ff0000">ItemName</font>="<font color="#0000ff">SerializationAssembly</font>"
/&gt; 
<br />
  &lt;/<font color="#a52a2a"><span class="searchword">SGen</span></font>&gt;<br />
&lt;/<font color="#a52a2a">Target</font>&gt;<br />
&lt;<font color="#a52a2a">Target</font><font color="#ff0000">Name</font>="<font color="#0000ff">AfterBuild</font>" <font color="#ff0000">DependsOnTargets</font>="<font color="#0000ff">GenSerializationAssembly</font>"
/&gt;</font>
          </p>
        </blockquote>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=f3c84b9c-6b85-45ab-8158-fa8e3f0d0819" />
      </body>
      <title>Using an SGEN.exe MSBuild task in TFS Build</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,f3c84b9c-6b85-45ab-8158-fa8e3f0d0819.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/08/26/UsingAnSGENexeMSBuildTaskInTFSBuild.aspx</link>
      <pubDate>Tue, 26 Aug 2008 19:06:57 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;Earlier this year I &lt;a href="http://blog.devstone.com/aaron/2008/02/07/UsingSGENexeFromWithinVisualStudio.aspx"&gt;posted
an article&lt;/a&gt; demonstrating how to use the SGEN.exe utility to generate a serialization
assembly.&amp;nbsp; The article identified how to create a custom MSBuild task by editing
the project file (e.g., csproj).&amp;nbsp; I've recently come to discover that the MSBuild
task will fail when automating a build of the project&amp;nbsp;through TFS Build.&amp;nbsp;
The error presents itself as follows:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face=Tahoma color=#ff0000&gt;SGEN(0,0): error : File or assembly name 'C:....\bin\CustomLibrary.dll',
or one of its dependencies, was not found.&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;Ultimately, the root of the problem goes back to the&amp;nbsp;SGEN MSBuild
task's usage of the $(OutputPath) variable.&amp;nbsp; Even in TFS Build this is pointing
to same location that Visual Studio would point to.&amp;nbsp; TFS, however, will override
the output locations of the compiled applications, but this variable doesn't get updated.&amp;nbsp;
As stated in the &lt;/font&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb629394.aspx"&gt;&lt;font face=Tahoma&gt;MSDN
documentation&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;, "OutputPath has been deprecated and OutDir
should be used instead whenever possible.".&amp;nbsp; I was happy to discover that by
simply replacing the $(OutputPath) with $(OutDir) in the MSBuild task was all I needed
to do; the task will execute properly both from my development machine as well as
the build server.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;My updated task resembles the following:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;&lt;font color=#a52a2a&gt;Target&lt;/font&gt; &lt;font color=#ff0000&gt;Name&lt;/font&gt;="&lt;font color=#0000ff&gt;GenSerializationAssembly&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;DependsOnTargets&lt;/font&gt;="&lt;font color=#0000ff&gt;AssignTargetPaths;Compile;ResolveKeySource&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;Inputs&lt;/font&gt;="&lt;font color=#0000ff&gt;$(MSBuildAllProjects);@(IntermediateAssembly)&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;Outputs&lt;/font&gt;="&lt;font color=#0000ff&gt;$(OutDir)$(_&lt;span class=searchword&gt;SGen&lt;/span&gt;DllName)&lt;/font&gt;"&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;&lt;font color=#a52a2a&gt;&lt;span class=searchword&gt;SGen&lt;/span&gt;&lt;/font&gt; &lt;font color=#ff0000&gt;BuildAssemblyName&lt;/font&gt;="&lt;font color=#0000ff&gt;$(TargetFileName)&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;BuildAssemblyPath&lt;/font&gt;="&lt;font color=#0000ff&gt;$(OutDir)&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;References&lt;/font&gt;="&lt;font color=#0000ff&gt;@(ReferencePath)&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;ShouldGenerateSerializer&lt;/font&gt;="&lt;font color=#0000ff&gt;true&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;UseProxyTypes&lt;/font&gt;="&lt;font color=#0000ff&gt;false&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;KeyContainer&lt;/font&gt;="&lt;font color=#0000ff&gt;$(KeyContainerName)&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;KeyFile&lt;/font&gt;="&lt;font color=#0000ff&gt;$(KeyOriginatorFile)&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;DelaySign&lt;/font&gt;="&lt;font color=#0000ff&gt;$(DelaySign)&lt;/font&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;ToolPath&lt;/font&gt;="&lt;font color=#0000ff&gt;$(&lt;span class=searchword&gt;SGen&lt;/span&gt;ToolPath)&lt;/font&gt;"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color=#a52a2a&gt;Output&lt;/font&gt; &lt;font color=#ff0000&gt;TaskParameter&lt;/font&gt;="&lt;font color=#0000ff&gt;SerializationAssembly&lt;/font&gt;" &lt;font color=#ff0000&gt;ItemName&lt;/font&gt;="&lt;font color=#0000ff&gt;SerializationAssembly&lt;/font&gt;"
/&amp;gt; 
&lt;br&gt;
&amp;nbsp; &amp;lt;/&lt;font color=#a52a2a&gt;&lt;span class=searchword&gt;SGen&lt;/span&gt;&lt;/font&gt;&amp;gt;&lt;br&gt;
&amp;lt;/&lt;font color=#a52a2a&gt;Target&lt;/font&gt;&amp;gt;&lt;br&gt;
&amp;lt;&lt;font color=#a52a2a&gt;Target&lt;/font&gt; &lt;font color=#ff0000&gt;Name&lt;/font&gt;="&lt;font color=#0000ff&gt;AfterBuild&lt;/font&gt;" &lt;font color=#ff0000&gt;DependsOnTargets&lt;/font&gt;="&lt;font color=#0000ff&gt;GenSerializationAssembly&lt;/font&gt;"
/&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt;&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=f3c84b9c-6b85-45ab-8158-fa8e3f0d0819" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,f3c84b9c-6b85-45ab-8158-fa8e3f0d0819.aspx</comments>
      <category>Team Foundation Server</category>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=3de56574-c826-4e92-a777-dd0232633cf2</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,3de56574-c826-4e92-a777-dd0232633cf2.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,3de56574-c826-4e92-a777-dd0232633cf2.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=3de56574-c826-4e92-a777-dd0232633cf2</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">
            <img style="FLOAT: left" src="http://blog.devstone.com/aaron/content/binary/TeamExplorer01.gif" border="0" />I've
had an issue on two computers (my primary development machine and a virtual pc dev
box) which I was <em>finally</em> able to solve today after many hours of frustrated
searching and experimenting.  Interestingly, this issue only affected my two
machines, but not those of a co-worker.  What was more peculiar was that I have
higher privileges in TFS.  The issue revolved around getting the Team Foundation
Server Team Explorer 2008 to recognize our automated builds.</font>
        </p>
        <p>
          <font face="Tahoma">Within Visual Studio 2008's Team Explorer pane I am able to browse
all work items, documents, reports, etc, but not builds.  In fact, the node shows
up with a red 'X' icon and is mislabeled 'Build' rather than the correct 'Builds'.</font>
        </p>
        <p>
          <font face="Tahoma">I attempted to fix it by uninstalling / reinstalling the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=00803636-1d16-4df1-8a3d-ef1ad4f4bbab&amp;displaylang=en">TFS
2008 Power Tools (July Release)</a>, repairing my VS2008 installation, disabling my
firewall, disabling my antivirus.  I tried digging into various configuration
files and renaming / deleting my cache folder to no avail.</font>
        </p>
        <p>
          <font face="Tahoma">Ultimately, to fix the issue I had to resort to resetting my Visual
Studio settings to their factory settings.  To do this, I did the following:</font>
        </p>
        <ol>
          <li>
            <font face="Tahoma">Renamed/Deleted by TFS Cache folder.  On my Vista machine
it's found in (C:\Users\[USERNAME]\AppData\Local\Microsoft\Team Foundation\2.0).</font>
          </li>
          <li>
            <font face="Tahoma">Reset Visual Studio 2008 settings by typing <font face="Courier New"><strong>devenv
/resetuserdata</strong></font> from the command line.</font>
          </li>
        </ol>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=3de56574-c826-4e92-a777-dd0232633cf2" />
      </body>
      <title>Repairing TFS's Team Explorer Build Node in Visual Studio 2008</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,3de56574-c826-4e92-a777-dd0232633cf2.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/08/18/RepairingTFSsTeamExplorerBuildNodeInVisualStudio2008.aspx</link>
      <pubDate>Mon, 18 Aug 2008 05:34:53 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;&lt;img style="FLOAT: left" src="http://blog.devstone.com/aaron/content/binary/TeamExplorer01.gif" border=0&gt;I've
had an issue on two computers (my primary development machine and a virtual pc dev
box) which I was &lt;em&gt;finally&lt;/em&gt; able to solve today after many hours of frustrated
searching and experimenting.&amp;nbsp; Interestingly, this issue only affected my two
machines, but not those of a co-worker.&amp;nbsp; What was more peculiar was that I have
higher privileges in TFS.&amp;nbsp; The issue revolved around getting the Team Foundation
Server Team Explorer 2008 to recognize our automated builds.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Within Visual Studio 2008's Team Explorer pane I am able to browse
all work items, documents, reports, etc, but not builds.&amp;nbsp; In fact, the node shows
up with a red 'X' icon and is mislabeled 'Build' rather than the correct 'Builds'.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I attempted to fix it by uninstalling / reinstalling the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=00803636-1d16-4df1-8a3d-ef1ad4f4bbab&amp;amp;displaylang=en"&gt;TFS
2008 Power Tools (July Release)&lt;/a&gt;, repairing my VS2008 installation, disabling my
firewall, disabling my antivirus.&amp;nbsp; I tried digging into various configuration
files and renaming / deleting my cache folder to no avail.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Ultimately, to fix the issue I had to resort to resetting my Visual
Studio settings to their factory settings.&amp;nbsp; To&amp;nbsp;do this, I did the following:&lt;/font&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;font face=Tahoma&gt;Renamed/Deleted by TFS Cache folder.&amp;nbsp; On my Vista machine it's
found in (C:\Users\[USERNAME]\AppData\Local\Microsoft\Team Foundation\2.0).&lt;/font&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;font face=Tahoma&gt;Reset Visual Studio 2008 settings by typing &lt;font face="Courier New"&gt;&lt;strong&gt;devenv
/resetuserdata&lt;/strong&gt;&lt;/font&gt; from the command line.&lt;/font&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=3de56574-c826-4e92-a777-dd0232633cf2" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,3de56574-c826-4e92-a777-dd0232633cf2.aspx</comments>
      <category>Team Foundation Server</category>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=7fb0b94f-7b10-407d-8772-852e3edc2469</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,7fb0b94f-7b10-407d-8772-852e3edc2469.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,7fb0b94f-7b10-407d-8772-852e3edc2469.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=7fb0b94f-7b10-407d-8772-852e3edc2469</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">I upgraded my Visual Studio 2008 installation the other day to </font>
          <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=FBEE1648-7106-44A7-9649-6D9F6D58056E&amp;displaylang=en">
            <font face="Tahoma">SP1</font>
          </a>
          <font face="Tahoma"> and
everything went beautifully.  One of the issues that Microsoft fixed centered
around the naming of embedded binary resource files.</font>
        </p>
        <p>
          <font face="Tahoma">Traditionally, binary resource files have an extension of
.resources.  However, when VS2008 was introduced, </font>
          <a href="http://blog.devstone.com/aaron/2008/02/20/LosingResourcesInVS2008CompiledAssemblies.aspx">
            <font face="Tahoma">it came
with a bug that forced you to tack on a second extension</font>
          </a>
          <font face="Tahoma">: fileName.resources.resources.</font>
        </p>
        <p>
          <font face="Tahoma">Apparently, this is now fixed, but I did have to go back and rename
my files accordingly.</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=7fb0b94f-7b10-407d-8772-852e3edc2469" />
      </body>
      <title>VS 2008 SP1 Fixes Missing .resources Issue</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,7fb0b94f-7b10-407d-8772-852e3edc2469.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/08/14/VS2008SP1FixesMissingResourcesIssue.aspx</link>
      <pubDate>Thu, 14 Aug 2008 22:27:22 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;I upgraded my Visual Studio 2008 installation the other day to &lt;/font&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=FBEE1648-7106-44A7-9649-6D9F6D58056E&amp;amp;displaylang=en"&gt;&lt;font face=Tahoma&gt;SP1&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;&amp;nbsp;and
everything went beautifully.&amp;nbsp; One of the issues that Microsoft fixed centered
around the naming of embedded binary resource files.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Traditionally,&amp;nbsp;binary resource files have an extension of .resources.&amp;nbsp;
However, when VS2008 was introduced, &lt;/font&gt;&lt;a href="http://blog.devstone.com/aaron/2008/02/20/LosingResourcesInVS2008CompiledAssemblies.aspx"&gt;&lt;font face=Tahoma&gt;it&amp;nbsp;came
with a bug that&amp;nbsp;forced you to&amp;nbsp;tack on a second extension&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;:&amp;nbsp;fileName.resources.resources.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Apparently, this is now fixed, but I did have to go back and rename
my files accordingly.&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=7fb0b94f-7b10-407d-8772-852e3edc2469" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,7fb0b94f-7b10-407d-8772-852e3edc2469.aspx</comments>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=f2b849eb-26fd-434d-a4b3-a68c6a745187</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,f2b849eb-26fd-434d-a4b3-a68c6a745187.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,f2b849eb-26fd-434d-a4b3-a68c6a745187.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=f2b849eb-26fd-434d-a4b3-a68c6a745187</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">I finally gave in (for better or for worse) and signed up on </font>
          <a href="http://www.facebook.com/">
            <font face="Tahoma">facebook.com</font>
          </a>
          <font face="Tahoma"> this
past weekend.  I've always had an aversion to such social networking sites for
one reason or another.  In fact, </font>
          <a href="http://www.facebook.com/">
            <font face="Tahoma">facebook.com</font>
          </a>
          <font face="Tahoma"> and
myspace.com have long been blocked on my firewall at home until just recently. 
I may go back to block myspace.com, however; pretty much everything I've seen on it has
been annoying, sleasy, trashy, and not worth my time - basically stuff I didn't
want on my computer in the first place.</font>
        </p>
        <p>
          <font face="Tahoma">Now I don't know all the specifics about </font>
          <a href="http://www.facebook.com/">
            <font face="Tahoma">facebook.com</font>
          </a>
          <font face="Tahoma">,
but I've had a great time on it in the past few days reestablishing connections with
friends from my youth in New Mexico.  I've made contact with some people that
I've not been able to find until now, which is very exciting.</font>
        </p>
        <p>
          <font face="Tahoma">I realize that I'm a <em>late bloomer</em> of a sort with regards
to social networking, but such is the way of things I suppose.  Among other things,
I've simply not had time for it.  I still don't have time for it, but I may make
some for it, we'll see how it goes.</font>
        </p>
        <p>
          <font face="Tahoma">If you on </font>
          <a href="http://www.facebook.com/">
            <font face="Tahoma">facebook.com</font>
          </a>
          <font face="Tahoma"> and
you know me, drop me a line!</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=f2b849eb-26fd-434d-a4b3-a68c6a745187" />
      </body>
      <title>Succumbing to Peer Pressure</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,f2b849eb-26fd-434d-a4b3-a68c6a745187.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/08/05/SuccumbingToPeerPressure.aspx</link>
      <pubDate>Tue, 05 Aug 2008 07:18:27 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;I finally gave in (for better or for worse) and signed up on &lt;/font&gt;&lt;a href="http://www.facebook.com/"&gt;&lt;font face=Tahoma&gt;facebook.com&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt; this
past weekend.&amp;nbsp; I've always had an aversion to such social networking sites for
one reason or another.&amp;nbsp; In fact, &lt;/font&gt;&lt;a href="http://www.facebook.com/"&gt;&lt;font face=Tahoma&gt;facebook.com&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt; and
myspace.com have long been blocked on my firewall at home until just recently.&amp;nbsp;
I may go back to block myspace.com, however; pretty much everything I've seen on it&amp;nbsp;has
been annoying, sleasy, trashy, and not worth my time&amp;nbsp;- basically stuff I didn't
want on my computer in the first place.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Now I don't know all the specifics about &lt;/font&gt;&lt;a href="http://www.facebook.com/"&gt;&lt;font face=Tahoma&gt;facebook.com&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;,
but I've had a great time on it in the past few days reestablishing connections with
friends from my youth in New Mexico.&amp;nbsp; I've made contact with some people that
I've not been able to find until now, which is very exciting.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I realize that I'm a &lt;em&gt;late bloomer&lt;/em&gt; of a sort with regards
to social networking, but such is the way of things I suppose.&amp;nbsp; Among other things,
I've simply not had time for it.&amp;nbsp; I still don't have time for it, but I may make
some for it, we'll see how it goes.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;If you on &lt;/font&gt;&lt;a href="http://www.facebook.com/"&gt;&lt;font face=Tahoma&gt;facebook.com&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt; and
you know me, drop me a line!&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=f2b849eb-26fd-434d-a4b3-a68c6a745187" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,f2b849eb-26fd-434d-a4b3-a68c6a745187.aspx</comments>
      <category>facebook.com</category>
      <category>Journal</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=3b0d363e-42aa-41a9-95fb-782dbf5b1567</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,3b0d363e-42aa-41a9-95fb-782dbf5b1567.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,3b0d363e-42aa-41a9-95fb-782dbf5b1567.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=3b0d363e-42aa-41a9-95fb-782dbf5b1567</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p dir="ltr" style="MARGIN-RIGHT: 0px">
          <font face="Tahoma">I've recently been thinking about database authentication in an
ASP.NET application.  While this concept is most definitely unoriginal - a great
many web applications must perform data access of some sort - it is easy to get confused
by the many variations of data access.</font>
        </p>
        <p>
          <font face="Tahoma">To summarize in brief, there are two primary methods for authenticating
to a database: Windows Authentication (also called Integrated Security), and Sql
Authentication.  All SQL Servers support Windows Authentication and it's the
natural choice.  Enabling Sql Authentication, on the other hand, requires that
the server be configured to support it; this can be accomplished either during installation
or after the fact.  What's more, not all organizations will support Sql Authentication.</font>
        </p>
        <p>
          <font face="Tahoma">Despite the aforementioned, perhaps he simplest technique to authenticate
a user in the database is to use Sql Authentication.  It requires that 1) a login
be created in the SQL Server and mapped to the database and 2) the connection string
contain the appropriate User ID and Password parameters.  It is the simplest
also because the database can be located locally or remotely and the authentication
will succeed.</font>
        </p>
        <p>
          <font face="Tahoma">As soon as you use Windows Authentication in a web application
the level of difficulty raises, even if only slightly.  To properly implement
Windows Authentication in a web application, the identity of the process must be determined. 
For purposes of this article, as it is not directly pertinent and can be quite large
in scope, I will refrain from exploring the topic of ASP.NET process identity. 
Suffice it to say that on a Windows Server 2003/2008 the default identity for an IIS
application pool is NT AUTHORITY\NETWORK SERVICE.  On other platforms this identity
will vary.</font>
        </p>
        <p>
          <font face="Tahoma">
            <strong>ASP.NET Application - Anonymous or Integrated Windows
Authentication, No Impersonation</strong>
          </font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Tahoma">If the requesting user is not being impersonated, IIS will access
resources using the identity of the application pool (e.g., NT AUTHORITY\NETWORK SERVICE).</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">
            <strong>ASP.NET Application - Anonymous Authentication, Impersonation
Enabled</strong>
          </font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Tahoma">If your web application is using anonymous access and the user
is being impersonated a couple of things can happen.  First, if, in your web.config
file, you specify <font face="Courier New">&lt;identity impersonate="true" /&gt;</font>,
IIS will impersonate the anonymous user specified for your web site (e.g., IUSR_MACHINENAME,
IUSR, etc.).  A user may be specified in the web.config file as well via <font face="Courier New">&lt;identity
impersonate="true" userName="DOMAIN\User" password="xxx" /&gt;</font>.  In this
case, the web server will impersonate the user on the server.  NOTE: This user
needs, at a minimum, Write access to the \Temporary ASP.NET Files folder.</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">
            <strong>ASP.NET Application - Integrated Windows Authentication,
Impersonation Enabled</strong>
          </font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Tahoma">This is functionally similar to the previous item except if you
use the simple form of the identity element (i.e., &lt;identity impersonate="true"
/&gt;), the user account that is performing the request is impersonated.  This
is quite helpful especially if you need to control access to a server-side resource
by ACL.</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">When connecting to a SQL Server database that is local to the
web server, that is, it is physically on the same machine, you can grant access to
the identity under which the web application is running (ASPNET, NT AUTHORITY\NETWORK
SERVICE, IUSR_MACHINENAME, or the impersonated user for instance).</font>
        </p>
        <p>
          <font face="Tahoma">When the database is physically remote, however, care must be
taken to properly flow user credentials to remote server.  That is, in fact,
something of a misnomer.  Credentials aren't actually flowing to the remote server,
but rather an authentication token.  This token is generated on the computer
where the user identity is authenticated.</font>
        </p>
        <p>
          <font face="Tahoma">A user token generated on the web server will be able to flow
to the remote machine without any extra work.  This token is created in the following
scenarios:</font>
        </p>
        <ol>
          <li>
            <font face="Tahoma">Using Basic authentication - the user is actually logged-in on
the server.</font>
          </li>
          <li>
            <font face="Tahoma">Using no impersonation - the website is locally authenticated
as ASPNET or NT AUTHORITY\NETWORK SERVICE.</font>
          </li>
          <li>
            <font face="Tahoma">The impersonation identity is manually set in the web.config's
&lt;identity /&gt; element.</font>
          </li>
        </ol>
        <p>
          <font face="Tahoma">NTLM will permit the token a 'single hop' to the remote server. 
Provided the identity in question has access to the database, the connection will
be successfully established, and the requested information returned.</font>
        </p>
        <p>
          <font face="Tahoma">If, on the other hand, the web server is impersonating the requesting
user, the solution is not so cut-and-dry.  The user's token is created on the
client computer and makes a 'single hop' to the web server.  When making a request
to a remote server a 'double hop' must be performed.  NTLM will prohibit the
token from being passed to the server and you will encounter an error resembling "<strong>Login
failed for user 'NT AUTHORITY\ANONYMOUS LOGON'</strong>".</font>
        </p>
        <p>
          <font face="Tahoma">This error may be confusing and disheartening to a developer who
has not seen it before.  This is often the result of having tested the website
on a development machine (which is usually local) - "<em>It works on my machine.</em>" 
Well, it works because the token is created locally and only needs a 'single hop'
to get to the database server.</font>
        </p>
        <p>
          <font face="Tahoma">There are a few solutions that may help to address the oft-times
confusing and frustrating 'double hop' conundrum.</font>
        </p>
        <ol>
          <li>
            <font face="Tahoma">
              <strong>Setup Constrained Delegation<br /></strong>Less far-sweeping than full delegation, Kerberos constrained delegation allows
tokens to flow against a limited set of services.  This option is only available
on Windows Server 2003+.  To properly implement constrained delegation, you must
set up a Service Principal Name (SPN), identifying the service and the machine trusted
for delegating the tokens.  While simple in principle, I've found this solution
to be tempermental and very sensitive.  You may seemingly have everything set
up correctly and still not get it to work.</font>
          </li>
          <li>
            <font face="Tahoma">
              <strong>Fall back (a.k.a., revert) to the base IIS process's identity<br /></strong>Having fought the 'double hop' issue more times than I care to admit, and
for more hours than are healthy, this idea came to me last week while discussing the
'problem' with a friend and associate at Microsoft.  While this idea is not revolutionary
nor original, it is definitely useful.  This technique allows your website to
retain its ability to identify the calling user while deferring to the process's identity
(e.g., NT AUTHORITY\NETWORK SERVICE) to access remote databases.</font>
          </li>
        </ol>
        <p>
          <font face="Tahoma">To make this (#2) work we need the ability to 'undo' the impersonation
that ASP.NET performs and then reimpersonate when we're finished.  Unfortunately,
this functionality is not native to the .NET Framework as far as I'm aware - it is,
however, accessible via the RevertToSelf() Window API function.  In order to
encapsulate the logic of reverting to the base process's identity and restoring impersonation,
I've created a simple disposable class which is presented below:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#a9a9a9">
                <em>/// &lt;summary&gt;<br />
/// Represents a disposable class that, for the lifetime of the object, runs using
the<br />
/// underlying identity of the process.  This class is useful within an ASP.NET
application<br />
/// that is impersonating the caller, but needs to access network or directory resources<br />
/// that would otherwise be prohibited without setting up constrained delegation in
Active<br />
/// Directory.<br />
/// &lt;/summary&gt;</em>
              </font>
              <br />
              <font color="#008000">public sealed class</font> RevertImpersonator : IDisposable
{<br />
  <font color="#008000">public</font> RevertImpersonator() {<br />
     <font color="#a9a9a9"><em>// acquire the identity of the
current user (the user being impersonated)<br /></em></font>     _userIdentity = WindowsIdentity.GetCurrent();<br /><br /></font>
            <font face="Courier New">     <font color="#a9a9a9"><em>//
revert to the underlying process' identity<br />
     // for ASP.NET applications that impersonate, this will be
the identity of the IIS process<br />
     // (e.g., the identity of the application pool which, by
default, is NETWORK SERVICE).<br />
     // NOTE: the NETWORK SERVICE account will access network
resources as the MACHINE$ account, local resources as NT AUTHORITY\NETWORK SERVICE.</em></font><br />
     RevertedIdentity = ( 0 != RevertToSelf() );<br />
  }<br /><br /></font>
            <font face="Courier New">  <font color="#008000">private readonly</font> WindowsIdentity
_userIdentity;<br /><br />
  <br />
  [DllImport(<font color="#a52a2a">"advapi32.dll"</font>)]<br />
  <font color="#008000">private static extern int</font> RevertToSelf();<br /><br /></font>
            <font face="Courier New">  ~RevertImpersonator() {<br />
     restore();<br />
  }<br /><br /><br /></font>
            <font face="Courier New">  <font color="#a9a9a9"><em>/// &lt;summary&gt;<br />
  /// Returns whether the user's identity was successfully reverted on initialization.<br />
  /// &lt;/summary&gt;<br /></em></font>  <font color="#008000">public bool</font> RevertedIdentity { <font color="#008000">get</font>; <font color="#008000">private
set</font>; }<br /><br /><br /></font>
            <font face="Courier New">  <font color="#008000">public void</font> Dispose()
{<br />
     GC.SuppressFinalize(<font color="#008000">this</font>);<br />
     restore();<br />
  }<br /><br /><br /></font>
            <font face="Courier New">  <font color="#008000">private void</font> restore()
{<br />
     <font color="#a9a9a9"><em>// re-impersonate the user during
cleanup<br /></em></font>     <font color="#008000">if</font> ( RevertedIdentity
)<br />
        _userIdentity.Impersonate();<br />
  }<br />
}</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">Effectively, this class allows you to encapsulate database calls
thus:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">using</font> ( <font color="#008000">new</font> RevertImpersonator()
) {<br />
   <font color="#a9a9a9"><em>// perform data access here<br /></em></font>}</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">
            <font color="#ff0000">
              <strong>An important note is warranted.</strong>
            </font> 
As previously mentioned, using this class will revert the identity on the thread to
the process's identity.  You can set your IIS Application Pool to use a domain
account rather than the default NT AUTHORITY\NETWORK SERVICE.  Doing so will
require that the domain user have access to the database in question.  If, however,
you decide to use the default, you must be aware of a few items.  First, a local
database will be accessed with the NT AUTHORITY\NETWORK SERVICE account as expected. 
A remote database will be accessed with the MACHINE$ account - this is how the NT
AUTHORITY\NETWORK SERVICE account is authenticated remotely.</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=3b0d363e-42aa-41a9-95fb-782dbf5b1567" />
      </body>
      <title>Accessing a Remote Database in ASP.NET (Working Around the Double Hop Conundrum)</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,3b0d363e-42aa-41a9-95fb-782dbf5b1567.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/07/14/AccessingARemoteDatabaseInASPNETWorkingAroundTheDoubleHopConundrum.aspx</link>
      <pubDate>Mon, 14 Jul 2008 04:02:49 GMT</pubDate>
      <description>&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;font face=Tahoma&gt;I've recently been thinking about database authentication in an
ASP.NET application.&amp;nbsp; While this concept is most definitely unoriginal - a great
many web applications must perform data access of some sort - it is easy to get confused
by the many variations of data access.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;To summarize in brief, there are two primary methods for authenticating
to a database: Windows Authentication (also called Integrated Security), and&amp;nbsp;Sql
Authentication.&amp;nbsp; All SQL Servers support Windows Authentication and it's the
natural choice.&amp;nbsp; Enabling Sql Authentication, on the other hand, requires that
the server be configured to support it; this can be accomplished either during installation
or after the fact.&amp;nbsp; What's more, not all organizations will support Sql Authentication.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Despite the aforementioned, perhaps he simplest technique to authenticate
a user in the database is to use Sql Authentication.&amp;nbsp; It requires that 1) a login
be created in the SQL Server and mapped to the database and 2) the connection string
contain the appropriate User ID and Password parameters.&amp;nbsp; It is the simplest
also because the database can be located locally or remotely and the authentication
will succeed.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;As soon as you use Windows Authentication in a web application the
level of difficulty raises, even if only slightly.&amp;nbsp; To properly implement Windows
Authentication in a web application, the identity of the process must be determined.&amp;nbsp;
For purposes of this article, as it is not directly pertinent and can be quite large
in scope, I will refrain from exploring the topic of ASP.NET process identity.&amp;nbsp;
Suffice it to say that on a Windows Server 2003/2008 the default identity for an IIS
application pool is NT AUTHORITY\NETWORK SERVICE.&amp;nbsp; On other platforms this identity
will vary.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;&lt;strong&gt;ASP.NET Application - Anonymous or Integrated Windows Authentication,
No Impersonation&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;If the requesting user is not being impersonated, IIS will access
resources using the identity of the application pool (e.g., NT AUTHORITY\NETWORK SERVICE).&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;&lt;strong&gt;ASP.NET Application - Anonymous Authentication, Impersonation
Enabled&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;If your web application is using anonymous access and the user is
being impersonated a couple of things can happen.&amp;nbsp; First, if, in your web.config
file, you specify &lt;font face="Courier New"&gt;&amp;lt;identity impersonate="true" /&amp;gt;&lt;/font&gt;,
IIS will impersonate the anonymous user specified for your web site (e.g., IUSR_MACHINENAME,
IUSR, etc.).&amp;nbsp; A user may be specified in the web.config file as well via &lt;font face="Courier New"&gt;&amp;lt;identity
impersonate="true" userName="DOMAIN\User" password="xxx" /&amp;gt;&lt;/font&gt;.&amp;nbsp; In this
case, the web server will impersonate the user on the server.&amp;nbsp; NOTE: This user
needs, at a minimum, Write access to the \Temporary ASP.NET Files folder.&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;&lt;strong&gt;ASP.NET Application - Integrated Windows Authentication,
Impersonation Enabled&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;This is functionally similar to the previous item except if you
use the simple form of the identity element (i.e., &amp;lt;identity impersonate="true"
/&amp;gt;), the user account that is performing the request is impersonated.&amp;nbsp; This
is quite helpful especially if you need to control access to a server-side resource
by ACL.&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;When connecting to a SQL Server database that is local to the web
server, that is, it is physically on the same machine, you can grant access to the
identity under which the web application is running (ASPNET, NT AUTHORITY\NETWORK
SERVICE, IUSR_MACHINENAME, or the impersonated user for instance).&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;When the database is physically remote, however, care must be taken
to properly flow user credentials to remote server.&amp;nbsp; That is, in fact, something
of a misnomer.&amp;nbsp; Credentials aren't actually flowing to the remote server, but
rather an authentication token.&amp;nbsp; This token is generated on the computer where
the user identity is authenticated.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;A user token generated on the web server will be able to flow to
the remote machine without any extra work.&amp;nbsp; This token is created in the following
scenarios:&lt;/font&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;font face=Tahoma&gt;Using Basic authentication - the user is actually logged-in on the
server.&lt;/font&gt; 
&lt;li&gt;
&lt;font face=Tahoma&gt;Using no impersonation - the website is locally authenticated as
ASPNET or NT AUTHORITY\NETWORK SERVICE.&lt;/font&gt; 
&lt;li&gt;
&lt;font face=Tahoma&gt;The impersonation identity is manually set in the web.config's &amp;lt;identity
/&amp;gt; element.&lt;/font&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;NTLM will permit the token a 'single hop' to the remote server.&amp;nbsp;
Provided the identity in question has access to the database, the connection will
be successfully established, and the requested information returned.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;If, on the other hand, the web server is impersonating the requesting
user, the solution is not so cut-and-dry.&amp;nbsp; The user's token is created on the
client computer and makes a 'single hop' to the web server.&amp;nbsp; When making a request
to a remote server a 'double hop' must be performed.&amp;nbsp; NTLM will prohibit the
token from being passed to the server and you will encounter an error resembling "&lt;strong&gt;Login
failed for user 'NT AUTHORITY\ANONYMOUS LOGON'&lt;/strong&gt;".&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;This error may be confusing and disheartening to a developer who
has not seen it before.&amp;nbsp; This is often the result of having tested the website
on a development machine (which is usually local) - "&lt;em&gt;It works on my machine.&lt;/em&gt;"&amp;nbsp;
Well, it works because the token is created locally and only needs a 'single hop'
to get to the database server.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;There are a few solutions that may help to address the oft-times
confusing and frustrating 'double hop' conundrum.&lt;/font&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;font face=Tahoma&gt;&lt;strong&gt;Setup Constrained Delegation&lt;br&gt;
&lt;/strong&gt;Less far-sweeping than full delegation, Kerberos constrained delegation allows
tokens to flow against a limited set of services.&amp;nbsp; This option is only available
on Windows Server 2003+.&amp;nbsp; To properly implement constrained delegation, you must
set up a Service Principal Name (SPN), identifying the service and the machine trusted
for delegating the tokens.&amp;nbsp; While simple in principle, I've found this solution
to be tempermental and very sensitive.&amp;nbsp; You may seemingly have everything set
up correctly and still not get it to work.&lt;/font&gt; 
&lt;li&gt;
&lt;font face=Tahoma&gt;&lt;strong&gt;Fall back (a.k.a., revert) to the base IIS process's identity&lt;br&gt;
&lt;/strong&gt;Having fought the 'double hop' issue more times than I care to admit, and
for more hours than are healthy, this idea came to me last week while discussing the
'problem' with a friend and associate at Microsoft.&amp;nbsp; While this idea is not revolutionary
nor original, it is definitely useful.&amp;nbsp; This technique allows your website to
retain its ability to identify the calling user while deferring to the process's identity
(e.g., NT AUTHORITY\NETWORK SERVICE) to access remote databases.&lt;/font&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;To make this (#2) work we need the ability to 'undo' the impersonation
that ASP.NET performs and then reimpersonate when we're finished.&amp;nbsp; Unfortunately,
this functionality is not native to the .NET Framework as far as I'm aware - it is,
however, accessible via the RevertToSelf() Window API function.&amp;nbsp; In order to
encapsulate the logic of reverting to the base process's identity and restoring impersonation,
I've created a simple disposable class which is presented below:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#a9a9a9&gt;&lt;em&gt;/// &amp;lt;summary&amp;gt;&lt;br&gt;
/// Represents a disposable class that, for the lifetime of the object, runs using
the&lt;br&gt;
/// underlying identity of the process.&amp;nbsp; This class is useful within an ASP.NET
application&lt;br&gt;
/// that is impersonating the caller, but needs to access network or directory resources&lt;br&gt;
/// that would otherwise be prohibited without setting up constrained delegation in
Active&lt;br&gt;
/// Directory.&lt;br&gt;
/// &amp;lt;/summary&amp;gt;&lt;/em&gt;&lt;/font&gt;
&lt;br&gt;
&lt;font color=#008000&gt;public sealed class&lt;/font&gt; RevertImpersonator : IDisposable {&lt;br&gt;
&amp;nbsp; &lt;font color=#008000&gt;public&lt;/font&gt; RevertImpersonator() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#a9a9a9&gt;&lt;em&gt;// acquire the identity of the current
user (the user being impersonated)&lt;br&gt;
&lt;/em&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _userIdentity = WindowsIdentity.GetCurrent();&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#a9a9a9&gt;&lt;em&gt;//
revert to the underlying process' identity&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // for ASP.NET applications that impersonate, this will be
the identity of the IIS process&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // (e.g., the identity of the application pool which, by
default, is NETWORK SERVICE).&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // NOTE: the NETWORK SERVICE account will access network
resources as the MACHINE$ account, local resources as NT AUTHORITY\NETWORK SERVICE.&lt;/em&gt;&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RevertedIdentity = ( 0 != RevertToSelf() );&lt;br&gt;
&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp; &lt;font color=#008000&gt;private readonly&lt;/font&gt; WindowsIdentity
_userIdentity;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp; [DllImport(&lt;font color=#a52a2a&gt;"advapi32.dll"&lt;/font&gt;)]&lt;br&gt;
&amp;nbsp; &lt;font color=#008000&gt;private static extern int&lt;/font&gt; RevertToSelf();&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp; ~RevertImpersonator() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; restore();&lt;br&gt;
&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp; &lt;font color=#a9a9a9&gt;&lt;em&gt;/// &amp;lt;summary&amp;gt;&lt;br&gt;
&amp;nbsp; /// Returns whether the user's identity was successfully reverted on initialization.&lt;br&gt;
&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;br&gt;
&lt;/em&gt;&lt;/font&gt;&amp;nbsp; &lt;font color=#008000&gt;public bool&lt;/font&gt; RevertedIdentity { &lt;font color=#008000&gt;get&lt;/font&gt;; &lt;font color=#008000&gt;private
set&lt;/font&gt;; }&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp; &lt;font color=#008000&gt;public void&lt;/font&gt; Dispose()
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC.SuppressFinalize(&lt;font color=#008000&gt;this&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; restore();&lt;br&gt;
&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp; &lt;font color=#008000&gt;private void&lt;/font&gt; restore()
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#a9a9a9&gt;&lt;em&gt;// re-impersonate the user during
cleanup&lt;br&gt;
&lt;/em&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;if&lt;/font&gt; ( RevertedIdentity
)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _userIdentity.Impersonate();&lt;br&gt;
&amp;nbsp; }&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;Effectively, this class allows you to encapsulate database calls
thus:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;using&lt;/font&gt; ( &lt;font color=#008000&gt;new&lt;/font&gt; RevertImpersonator()
) {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#a9a9a9&gt;&lt;em&gt;// perform data access here&lt;br&gt;
&lt;/em&gt;&lt;/font&gt;}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;&lt;font color=#ff0000&gt;&lt;strong&gt;An important note is warranted.&lt;/strong&gt;&lt;/font&gt;&amp;nbsp;
As previously mentioned, using this class will revert the identity on the thread to
the process's identity.&amp;nbsp; You can set your IIS Application Pool to use a domain
account rather than the default NT AUTHORITY\NETWORK SERVICE.&amp;nbsp; Doing so will
require that the domain user have access to the database in question.&amp;nbsp; If, however,
you decide to use the default, you must be aware of a few items.&amp;nbsp; First, a local
database will be accessed with the NT AUTHORITY\NETWORK SERVICE account as expected.&amp;nbsp;
A remote database will be accessed with the MACHINE$ account - this is how the NT
AUTHORITY\NETWORK SERVICE account is authenticated remotely.&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=3b0d363e-42aa-41a9-95fb-782dbf5b1567" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,3b0d363e-42aa-41a9-95fb-782dbf5b1567.aspx</comments>
      <category>C#</category>
      <category>SQL Server</category>
      <category>ASP.NET</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=e7051698-fe1f-4c1b-a981-9547a519be29</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,e7051698-fe1f-4c1b-a981-9547a519be29.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,e7051698-fe1f-4c1b-a981-9547a519be29.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=e7051698-fe1f-4c1b-a981-9547a519be29</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">While we use TFS (Team Foundation Server) for all of our current
development projects, we do maintain a SourceGear Vault server for most if not all
of our legacy projects.  I've had nothing but a great experience with Vault over
the past 3 or 4 years that I've used it.</font>
        </p>
        <p>
          <font face="Tahoma">Recently, however, I moved the server and SQL databases over to
a new Windows Server 2008 x64 system with SQL Server 2005 SP2.  Everything seems
to transition smoothly.  This particular SCC system does not get a lot of activity
due to the nature of what data it maintains, but about a month after the upgrade one
user suddenly couldn't access the system with authentication errors.  Likewise,
I was unable to access several pages on the administrative Vault website.  The
error reported was 'Object reference not set to an instance of an object.'</font>
        </p>
        <p>
          <font face="Tahoma">The next thing I did was open the Sql Profiler and watch the activity
as it pertained to the Vault database (sgvault).  I noticed that it was attempting
to execute a stored procedure by the name of spgettreestructure with the repository
id and the transaction id.  Attempting to run the statement directly, I was presented
with a SQL Server error:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p class="MsoPlainText" style="MARGIN: 0in 0in 0pt">
            <font face="Courier New" color="#a52a2a">Msg 0, Level 11, State 0, Line 0</font>
          </p>
          <p class="MsoPlainText" style="MARGIN: 0in 0in 0pt">
            <font face="Courier New" color="#a52a2a">A severe error occurred on the current command.<span style="mso-spacerun: yes">  </span>The
results, if any, should be discarded.</font>
          </p>
          <p class="MsoPlainText" style="MARGIN: 0in 0in 0pt">
            <font face="Courier New" color="#a52a2a">Msg 0, Level 20, State 0, Line 0</font>
          </p>
          <p class="MsoPlainText" style="MARGIN: 0in 0in 0pt">
            <font face="Courier New" color="#a52a2a">A severe error occurred on the current command.<span style="mso-spacerun: yes">  </span>The
results, if any, should be discarded.</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">This had me a little worried, but I opened up a ticket with SourceGear
support.  After a few emails back and forth, a GoToMeeting, I was referred to
Pinalkumar's blog page.  It turns out this was a bug in SQL Server that was fixed
in the Cumulative update package 6 for SQL Server 2005 SP2.  Applying the patch
(</font>
          <a href="http://support.microsoft.com/default.aspx/kb/946608/LN/">
            <font face="Tahoma">http://support.microsoft.com/default.aspx/kb/946608/LN/</font>
          </a>
          <font face="Tahoma">)
fixed the issue :)</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=e7051698-fe1f-4c1b-a981-9547a519be29" />
      </body>
      <title>Patching 'A severe error occurred on the current command.'</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,e7051698-fe1f-4c1b-a981-9547a519be29.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/07/01/PatchingASevereErrorOccurredOnTheCurrentCommand.aspx</link>
      <pubDate>Tue, 01 Jul 2008 16:53:43 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;While we use TFS (Team Foundation Server) for all of our current
development projects, we do maintain a SourceGear Vault server for most if not all
of our legacy projects.&amp;nbsp; I've had nothing but a great experience with Vault over
the past 3 or 4 years that I've used it.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Recently, however, I moved the server and SQL databases over to
a new Windows Server 2008 x64 system with SQL Server 2005 SP2.&amp;nbsp; Everything seems
to transition smoothly.&amp;nbsp; This particular SCC system does not get a lot of activity
due to the nature of what data it maintains, but about a month after the upgrade one
user suddenly couldn't access the system with authentication errors.&amp;nbsp; Likewise,
I was unable to access several pages on the administrative Vault website.&amp;nbsp; The
error reported was 'Object reference not set to an instance of an object.'&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;The next thing I did was open the Sql Profiler and watch the activity
as it pertained to the Vault database (sgvault).&amp;nbsp; I noticed that it was attempting
to execute a stored procedure by the name of spgettreestructure with the repository
id and the transaction id.&amp;nbsp; Attempting to run the statement directly, I was presented
with a SQL Server error:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;
&lt;font face="Courier New" color=#a52a2a&gt;Msg 0, Level 11, State 0, Line 0&lt;/font&gt;
&lt;/p&gt;
&lt;p class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;
&lt;font face="Courier New" color=#a52a2a&gt;A severe error occurred on the current command.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The
results, if any, should be discarded.&lt;/font&gt;
&lt;/p&gt;
&lt;p class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;
&lt;font face="Courier New" color=#a52a2a&gt;Msg 0, Level 20, State 0, Line 0&lt;/font&gt;
&lt;/p&gt;
&lt;p class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;
&lt;font face="Courier New" color=#a52a2a&gt;A severe error occurred on the current command.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The
results, if any, should be discarded.&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;This had me a little worried, but I opened up a ticket with SourceGear
support.&amp;nbsp; After a few emails back and forth, a GoToMeeting, I was referred to
Pinalkumar's blog page.&amp;nbsp; It turns out this was a bug in SQL Server that was fixed
in the Cumulative update package 6 for SQL Server 2005 SP2.&amp;nbsp; Applying the patch
(&lt;/font&gt;&lt;a href="http://support.microsoft.com/default.aspx/kb/946608/LN/"&gt;&lt;font face=Tahoma&gt;http://support.microsoft.com/default.aspx/kb/946608/LN/&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;)
fixed the issue :)&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=e7051698-fe1f-4c1b-a981-9547a519be29" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,e7051698-fe1f-4c1b-a981-9547a519be29.aspx</comments>
      <category>SQL Server</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=91d9e1f6-1e4e-4b88-bae1-9375bc1082bc</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,91d9e1f6-1e4e-4b88-bae1-9375bc1082bc.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,91d9e1f6-1e4e-4b88-bae1-9375bc1082bc.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=91d9e1f6-1e4e-4b88-bae1-9375bc1082bc</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">I was putting together a small application today that presents
data in a TextBox.  Now while this isn't too uncommon :), the text gets added
to the TextBox a line at a time via the TextBox's .AppendText() method.  I needed
to do this repeatedly and in succession.  As it turns out, an unwelcome
side effect of AppendText is that it scrolls the TextBox as the text is appended. 
This resulted in the TextBox getting cleared and then 'wiping' down as the text was
added.  Not only was this visually unappealing, but I wanted the insertion point to
stay at the top of the contents.</font>
        </p>
        <p>
          <font face="Tahoma">To my knowledge, which is quite flawed and limited, there's not
a built-in mechanism in .NET that provides this functionality.  Sure, I could
override the TextBox control and manage the WndProc method and/or use SetStyle to
make the control user drawn.  But I didn't want to do that.  Well, accomplishing
this is quite easy.</font>
        </p>
        <p>
          <font face="Tahoma">There are a few ways we can do it:</font>
        </p>
        <ol>
          <li>
            <font face="Tahoma">Use the LockWindowUpdate() API function.</font>
          </li>
          <li>
            <font face="Tahoma">Use SendMessage() API function with the WM_SETREDRAW message.</font>
          </li>
        </ol>
        <p>
          <font face="Tahoma">LockWindowUpdate() is slick and arguably easier to use, but it's
intended purpose isn't to suppress the redrawing of controls in this manner.  Plus,
you can only have one window locked at a time.  So I threw that one out.</font>
        </p>
        <p>
          <font face="Tahoma">I wrapped the logic to lock and unlock the redrawing of the control
in an IDisposable object so I wouldn't have to worry about remembering to clean up
after myself.  My class is as follows:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">public class</font> LockVisualUpdate
: IDisposable {<br />
   <font color="#008000">public</font> LockVisualUpdate(IWin32Window control)
{<br />
      _hWnd = control.Handle;<br />
      SendMessage(control.Handle, <font color="#0000ff">WM_SETREDRAW</font>, <font color="#0000ff">0</font>, <font color="#0000ff">0</font>);<br />
   }</font>
          </p>
          <p>
            <br />
            <font face="Courier New">   <font color="#008000">private readonly</font> IntPtr
_hWnd;<br />
   <font color="#008000">private const int</font><font color="#0000ff">WM_SETREDRAW</font> = <font color="#0000ff">0x000B</font>;</font>
          </p>
          <p>
            <br />
            <font face="Courier New">   [DllImport(<font color="#a52a2a">"user32.dll"</font>)]<br />
   <font color="#008000">private static extern bool</font> SendMessage(IntPtr
hWnd, <font color="#008000">int</font> msg, <font color="#008000">int</font> wParam, <font color="#008000">int</font> lParam);</font>
          </p>
          <p>
            <br />
            <font face="Courier New">   [DllImport(<font color="#a52a2a">"user32.dll"</font>)]<br />
   <font color="#008000">private static extern bool</font> InvalidateRect(IntPtr
hWnd, IntPtr lpRect, <font color="#008000">bool</font> bErase);</font>
          </p>
          <p>
            <br />
            <font face="Courier New">   <font color="#008000">public void</font> Dispose()
{<br />
      SendMessage(_hWnd, <font color="#0000ff">WM_SETREDRAW</font>, <font color="#0000ff">1</font>, <font color="#0000ff">0</font>);<br />
      InvalidateRect(_hWnd, IntPtr.Zero, <font color="#008000">false</font>);<br />
   }<br />
}</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">Really simple to use.  To consume it, I simply have to do
the following:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">using</font> ( <font color="#008000">new</font> LockVisualUpdate(textBox1)
) {<br />
   textBox1.AppendText(...);<br />
   <font color="#a9a9a9"><em>// ...repeated as often as necessary to populate
the control<br /><br />
   // when finished, position the insertion point to the top of the control<br /></em></font>   textBox1.SelectionStart = <font color="#0000ff">0</font>;<br />
   textBox1.ScrollToCaret();<br />
}</font>
          </p>
        </blockquote>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=91d9e1f6-1e4e-4b88-bae1-9375bc1082bc" />
      </body>
      <title>Suppressing Control Redrawing While Updating</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,91d9e1f6-1e4e-4b88-bae1-9375bc1082bc.aspx</guid>
      <link>http://blog.devstone.com/aaron/2008/06/27/SuppressingControlRedrawingWhileUpdating.aspx</link>
      <pubDate>Fri, 27 Jun 2008 20:28:14 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;I was putting together a small application today that presents data
in a TextBox.&amp;nbsp; Now while this isn't too uncommon :), the text gets added to the
TextBox a line at a time via the TextBox's .AppendText() method.&amp;nbsp; I needed to
do this repeatedly and in succession.&amp;nbsp;&amp;nbsp;As it turns out, an unwelcome side
effect of AppendText is that it scrolls the&amp;nbsp;TextBox as the text is appended.&amp;nbsp;
This resulted in the TextBox getting cleared and then 'wiping' down as the text was
added.&amp;nbsp; Not only was this visually unappealing, but I wanted the insertion point&amp;nbsp;to
stay at the top of the contents.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;To my knowledge, which is quite flawed and limited, there's not
a built-in mechanism in .NET that provides this functionality.&amp;nbsp; Sure, I could
override the TextBox control and manage the WndProc method and/or use SetStyle to
make the control user drawn.&amp;nbsp; But I didn't want to do that.&amp;nbsp; Well, accomplishing
this is quite easy.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;There are a few ways we can do it:&lt;/font&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;font face=Tahoma&gt;Use the LockWindowUpdate() API function.&lt;/font&gt; 
&lt;li&gt;
&lt;font face=Tahoma&gt;Use SendMessage() API function with the WM_SETREDRAW message.&lt;/font&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;LockWindowUpdate() is slick and arguably easier to use, but it's
intended purpose isn't to suppress the redrawing of controls in this manner.&amp;nbsp;&amp;nbsp;Plus,
you can only have one window locked at a time.&amp;nbsp; So I threw that one out.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I wrapped the logic to lock and unlock the redrawing of the control
in an IDisposable object so I wouldn't have to worry about remembering to clean up
after myself.&amp;nbsp; My class is as follows:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;public class&lt;/font&gt; LockVisualUpdate
: IDisposable {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public&lt;/font&gt; LockVisualUpdate(IWin32Window control)
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _hWnd = control.Handle;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SendMessage(control.Handle, &lt;font color=#0000ff&gt;WM_SETREDRAW&lt;/font&gt;, &lt;font color=#0000ff&gt;0&lt;/font&gt;, &lt;font color=#0000ff&gt;0&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;private readonly&lt;/font&gt; IntPtr
_hWnd;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;private const int&lt;/font&gt; &lt;font color=#0000ff&gt;WM_SETREDRAW&lt;/font&gt; = &lt;font color=#0000ff&gt;0x000B&lt;/font&gt;;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; [DllImport(&lt;font color=#a52a2a&gt;"user32.dll"&lt;/font&gt;)]&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;private static extern bool&lt;/font&gt; SendMessage(IntPtr
hWnd, &lt;font color=#008000&gt;int&lt;/font&gt; msg, &lt;font color=#008000&gt;int&lt;/font&gt; wParam, &lt;font color=#008000&gt;int&lt;/font&gt; lParam);&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; [DllImport(&lt;font color=#a52a2a&gt;"user32.dll"&lt;/font&gt;)]&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;private static extern bool&lt;/font&gt; InvalidateRect(IntPtr
hWnd, IntPtr lpRect, &lt;font color=#008000&gt;bool&lt;/font&gt; bErase);&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public void&lt;/font&gt; Dispose()
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SendMessage(_hWnd, &lt;font color=#0000ff&gt;WM_SETREDRAW&lt;/font&gt;, &lt;font color=#0000ff&gt;1&lt;/font&gt;, &lt;font color=#0000ff&gt;0&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InvalidateRect(_hWnd, IntPtr.Zero, &lt;font color=#008000&gt;false&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;Really simple to use.&amp;nbsp; To consume it, I simply have to do the
following:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;using&lt;/font&gt; ( &lt;font color=#008000&gt;new&lt;/font&gt; LockVisualUpdate(textBox1)
) {&lt;br&gt;
&amp;nbsp;&amp;nbsp; textBox1.AppendText(...);&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#a9a9a9&gt;&lt;em&gt;// ...repeated as often as necessary to populate
the control&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; // when finished, position the insertion point to the top of the control&lt;br&gt;
&lt;/em&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp; textBox1.SelectionStart = &lt;font color=#0000ff&gt;0&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp; textBox1.ScrollToCaret();&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt;&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=91d9e1f6-1e4e-4b88-bae1-9375bc1082bc" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,91d9e1f6-1e4e-4b88-bae1-9375bc1082bc.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
    </item>
  </channel>
</rss>