<?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, 25 Jan 2010 23:29:35 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=ff01bb8b-7b08-4454-b98d-57da20279df2</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,ff01bb8b-7b08-4454-b98d-57da20279df2.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,ff01bb8b-7b08-4454-b98d-57da20279df2.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=ff01bb8b-7b08-4454-b98d-57da20279df2</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">Developing applications that target multiple version of Office
on a single computer can be difficult, daunting, disturbing, and down-right dirty.</font>
        </p>
        <p>
          <font face="Tahoma">The Microsoft Office team has performed some herculean tasks to
ease our burdens, but there are still some hurdles to overcome.  Having multiple
versions of Office installed on a single development machine is not possible and it
appears that you cannot install the Office PIAs on a machine that doesn't have that
version of Office installed (e.g., you cannot install the </font>
          <a href="http://www.microsoft.com/downloads/details.aspx?familyid=3c9a983a-ac14-4125-8ba0-d36d67e0f4ad&amp;displaylang=en">
            <font face="Tahoma">Office
2003 PIA</font>
          </a>
          <font face="Tahoma">s on a box with Office 2007 on it).  Additionally,
having multiple development environments each targeting a specific version of Office
is not always practical.</font>
        </p>
        <p>
          <font face="Tahoma">It is fortunate that add-ins created targeting the Office 2003
PIAs will work seamlessly in Office 2007 (they will not, however, be able to take
advantage of the new features of the 2007 system such as the Ribbon, etc).</font>
        </p>
        <p>
          <font face="Tahoma">If you have a VS project that was built on a box with Office 2003
+ </font>
          <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=8315654B-A5AE-4108-B7FC-186402563F2B&amp;displaylang=en">
            <font face="Tahoma">VSTO
2005 SE</font>
          </a>
          <font face="Tahoma"> + </font>
          <a href="http://www.microsoft.com/downloads/details.aspx?familyid=3c9a983a-ac14-4125-8ba0-d36d67e0f4ad&amp;displaylang=en">
            <font face="Tahoma">Office
2003 PIA</font>
          </a>
          <font face="Tahoma"> and you open it on a machine with Office
2007 + VSTO 2005 SE + Visual Studio Tools for the Office system 3.0 Runtime, you will
be prompted to upgrade your project to the new office platform.  Upgrading your
project will have the unfortunate side-effect of rendering the project useless on
your other dev environment that doesn't have Office 2007, etc on it.</font>
        </p>
        <p>
          <font face="Tahoma">Fortunately, there is a handy VS setting neatly tucked away in <strong><font face="Courier New"><font color="#a52a2a">Tools</font> -&gt; <font color="#a52a2a">Options</font> -&gt; <font color="#a52a2a">Office
Tools</font> -&gt; <font color="#a52a2a">Project Upgrade</font></font></strong> called <strong><font color="#a52a2a" face="Courier New">Always
upgrade to installed version of Office</font></strong>.  Unchecking this option
will allow you to open the project in Visual Studio without being compelled to upgrade.</font>
        </p>
        <p>
          <font face="Tahoma">I find it somewhat comical that using VS2008 on a machine with
Office 2007 + the two VSTO editions you can create a project targeting Office 2003
but when you reopen it you'll be prompted to upgrade (unless you have the setting
disabled) it.</font>
        </p>
        <p>
          <font face="Tahoma">If you don't have them there, don't forget to add the <font face="Courier New">Office2003PIA</font> and <font face="Courier New">VSTOSERuntime</font> bootstrappers
to <font color="#a52a2a" face="Courier New">%ProgramFiles%\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages</font> in
order to compile your projects.</font>
        </p>
        <p>
          <font face="Tahoma">
          </font> 
</p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=ff01bb8b-7b08-4454-b98d-57da20279df2" />
      </body>
      <title>Preventing an upgrade of an Office 2003 Add-in</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,ff01bb8b-7b08-4454-b98d-57da20279df2.aspx</guid>
      <link>http://blog.devstone.com/aaron/2010/01/25/PreventingAnUpgradeOfAnOffice2003Addin.aspx</link>
      <pubDate>Mon, 25 Jan 2010 23:29:35 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;Developing applications that target multiple version of Office on
a single computer can be difficult, daunting, disturbing, and down-right dirty.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;The Microsoft Office team has performed some herculean tasks to
ease our burdens, but there are still some hurdles to overcome.&amp;nbsp; Having multiple
versions of Office installed on a single development machine is not possible and it
appears that you cannot install the Office PIAs on a machine that doesn't have that
version of Office installed (e.g., you cannot install the &lt;/font&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=3c9a983a-ac14-4125-8ba0-d36d67e0f4ad&amp;amp;displaylang=en"&gt;&lt;font face=Tahoma&gt;Office
2003 PIA&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;s on a box with Office 2007 on it).&amp;nbsp; Additionally,
having multiple development environments each targeting a specific version of Office
is not always practical.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;It is fortunate that add-ins created targeting the Office 2003 PIAs
will work seamlessly in Office 2007 (they will not, however, be able to take advantage
of the new features of the 2007 system such as the Ribbon, etc).&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;If you have a VS project that was built on a box with Office 2003
+ &lt;/font&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=8315654B-A5AE-4108-B7FC-186402563F2B&amp;amp;displaylang=en"&gt;&lt;font face=Tahoma&gt;VSTO
2005 SE&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt; + &lt;/font&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=3c9a983a-ac14-4125-8ba0-d36d67e0f4ad&amp;amp;displaylang=en"&gt;&lt;font face=Tahoma&gt;Office
2003 PIA&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;&amp;nbsp;and you open it on a machine with Office
2007 + VSTO 2005 SE + Visual Studio Tools for the Office system 3.0 Runtime, you will
be prompted to upgrade your project to the new office platform.&amp;nbsp; Upgrading your
project will have the unfortunate side-effect of rendering the project useless on
your other dev environment that doesn't have Office 2007, etc on it.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Fortunately, there is a handy VS setting neatly tucked away in &lt;strong&gt;&lt;font face="Courier New"&gt;&lt;font color=#a52a2a&gt;Tools&lt;/font&gt; -&amp;gt; &lt;font color=#a52a2a&gt;Options&lt;/font&gt; -&amp;gt; &lt;font color=#a52a2a&gt;Office
Tools&lt;/font&gt; -&amp;gt; &lt;font color=#a52a2a&gt;Project Upgrade&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt; called &lt;strong&gt;&lt;font color=#a52a2a face="Courier New"&gt;Always
upgrade to installed version of Office&lt;/font&gt;&lt;/strong&gt;.&amp;nbsp; Unchecking this option
will allow you to open the project in Visual Studio without being compelled to upgrade.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I find it somewhat comical that using VS2008 on a machine with Office
2007 + the two VSTO editions you can create a project targeting Office 2003 but when
you reopen it you'll be prompted to upgrade (unless you have the setting disabled)
it.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;If you don't have them there, don't forget to add the &lt;font face="Courier New"&gt;Office2003PIA&lt;/font&gt; and &lt;font face="Courier New"&gt;VSTOSERuntime&lt;/font&gt; bootstrappers
to &lt;font color=#a52a2a face="Courier New"&gt;%ProgramFiles%\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages&lt;/font&gt; in
order to compile your projects.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;&lt;/font&gt;&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=ff01bb8b-7b08-4454-b98d-57da20279df2" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,ff01bb8b-7b08-4454-b98d-57da20279df2.aspx</comments>
      <category>Office</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=1a18e011-ea44-459e-84be-55a9046bce7d</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,1a18e011-ea44-459e-84be-55a9046bce7d.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,1a18e011-ea44-459e-84be-55a9046bce7d.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=1a18e011-ea44-459e-84be-55a9046bce7d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">I had the need today to create an application must run with administrative
privileges.  Fortunately, this is a pretty straightforward endeavor.</font>
        </p>
        <p>
          <font face="Tahoma">On Windows Vista, Windows 7, or Windows Server 2008 (and beyond)
I wanted to take advange of the Admin Approval Mode (AAM) or Over The Shoulder (OST)
UAC elevation prompt automatically (and as a side-effect have the little shield
icon accompanying my app's icon).  This wouldn't be possible on a previous OS
(such as Windows Server 2003 or XP), so I needed to add an explicit permission check.</font>
        </p>
        <p>
          <font face="Tahoma">To get the UAC prompt all you need to do is embed an application
manifest.  Vista+, when displaying the application icon, will probe the app and,
upon finding the manifest requiring admin rights, will display the icon properly.</font>
        </p>
        <p>
          <font face="Tahoma">Create a manifest file (e.g., app.exe.manifest) in your project. 
This is what mine looked like:</font>
        </p>
        <blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
          <p>
            <font face="Courier New">&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;<br />
&lt;assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"&gt;<br />
  &lt;assemblyIdentity version="1.0.0.0" name="<strong>APPLICATION_NAME</strong>"/&gt;<br />
  &lt;trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"&gt;<br />
    &lt;security&gt;<br />
      &lt;requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"&gt;<br />
        &lt;requestedExecutionLevel level="<strong>requireAdministrator</strong>"
uiAccess="false"/&gt;<br />
      &lt;/requestedPrivileges&gt;<br />
    &lt;/security&gt;<br />
  &lt;/trustInfo&gt;<br />
&lt;/assembly&gt;</font>
          </p>
        </blockquote>
        <p dir="ltr">
          <font face="Tahoma">By default (if you don't create a manifest), a .NET application
will have the &lt;requestedExecutionLevel /&gt; set to 'asInvoker' and run the application
as the user invoking it.  You can set this to one of three values: asInvoker,
highestAvailable, and requireAdministrator.  Also, don't forget to set the name
to match your application's name.</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">Then, to embed the application you can do a few things.</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">One technique is to use the <strong>mt.exe</strong> (ManifestTool)
from the Visual Studio Command Prompt:</font>
        </p>
        <blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
          <p dir="ltr">
            <font face="Courier New">mt.exe -manifest app.exe.manifest -updateresource:app.exe,#1</font>
          </p>
        </blockquote>
        <p dir="ltr">
          <font face="Tahoma">But I don't believe this would work if your application is signed
with a strong name unless you were to delay-sign it.</font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">The easier (and better) approach is to use the Project Properties
--&gt; Application tab.  Simply select your app.exe.manifest file in the Manifest
dropdown.  It will automatically be embedded.</font>
        </p>
        <p dir="ltr">
          <font color="#0000ff" face="Tahoma">
            <em>NOTE: In order to debug your application that
requires admin rights you'll need to run Visual Studio from an elevated token. 
Otherwise you won't have privileges enough to attach to the process.</em>
          </font>
        </p>
        <p dir="ltr">
          <font face="Tahoma">Next, I wanted to ensure that the user runs the application with
administrative rights.  This check was placed particularly for the pre-Vista
operating systems which didn't have UAC.  To do this I added the following code:</font>
        </p>
        <blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
          <p dir="ltr">
            <font face="Courier New">[STAThread()]<br /><font color="#008000">private static void</font> Main() {<br />
   Application.EnableVisualStyles();<br />
   Application.SetCompatibleTextRenderingDefault(<font color="#008000">false</font>);<br /><br />
   <font color="#a9a9a9"><em>// check to make sure that the user is running
with administrative rights.<br />
   // in Vista/Win7/Svr2008 this is automatically taken care of via the<br />
   // embedded manifest (which ensures administrative rights) via UAC.</em></font><br />
   <font color="#008000">try</font> {<br />
      <font color="#008000">if</font> ( !userHasAdminRights()
) {<br />
         MessageBox.Show(<font color="#a52a2a">"This
application requires administrative privileges."</font>,<br />
                         <font color="#a52a2a">"Unauthorized
Access"</font>,<br />
                        
MessageBoxButtons.OK, MessageBoxIcon.Information);<br />
         <font color="#008000">return</font>;<br />
      }<br />
   }<br />
   <font color="#008000">catch</font> ( Exception er ) {<br />
      MessageBox.Show(er.ToString());  <font color="#a9a9a9"><em>//
Of course you'd handle this differently</em></font><br />
   }<br /><br />
   Application.Run(<font color="#008000">new</font> MainForm());<br />
}<br /><br /><br /><font color="#008000">private static bool</font> userHasAdminRights() {<br />
   WindowsIdentity identity = WindowsIdentity.GetCurrent();<br />
   <font color="#008000">return</font> ( <font color="#008000">null</font> !=
identity &amp;&amp; <font color="#008000">new</font> WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator)
);<br />
}</font>
          </p>
        </blockquote>
        <p dir="ltr">
          <font face="Tahoma">Pretty simple, really.</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=1a18e011-ea44-459e-84be-55a9046bce7d" />
      </body>
      <title>Enforcing Administrative Privileges</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,1a18e011-ea44-459e-84be-55a9046bce7d.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/10/23/EnforcingAdministrativePrivileges.aspx</link>
      <pubDate>Fri, 23 Oct 2009 02:28:57 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;I had the need today to create an application must run with administrative
privileges.&amp;nbsp; Fortunately, this is a pretty straightforward endeavor.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;On Windows Vista, Windows 7, or Windows Server 2008 (and beyond)
I wanted to take advange of the Admin Approval Mode (AAM) or Over The Shoulder (OST)
UAC&amp;nbsp;elevation prompt automatically (and as a side-effect have the little shield
icon accompanying my app's icon).&amp;nbsp; This wouldn't be possible on a previous OS
(such as Windows Server 2003 or XP), so I needed to add an explicit permission check.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;To get the UAC prompt all you need to do is embed an application
manifest.&amp;nbsp; Vista+, when displaying the application icon, will probe the app and,
upon finding the manifest requiring admin rights, will display the icon properly.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Create a manifest file (e.g., app.exe.manifest) in your project.&amp;nbsp;
This is what mine looked like:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote style="MARGIN-RIGHT: 0px" dir=ltr&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&amp;gt;&lt;br&gt;
&amp;lt;assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;assemblyIdentity version="1.0.0.0" name="&lt;strong&gt;APPLICATION_NAME&lt;/strong&gt;"/&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;security&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;requestedExecutionLevel level="&lt;strong&gt;requireAdministrator&lt;/strong&gt;"
uiAccess="false"/&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/requestedPrivileges&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/security&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;/trustInfo&amp;gt;&lt;br&gt;
&amp;lt;/assembly&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;By default (if you don't create a manifest), a .NET application
will have the &amp;lt;requestedExecutionLevel /&amp;gt; set to 'asInvoker' and run the application
as the user invoking it.&amp;nbsp; You can set this to one of three values: asInvoker,
highestAvailable, and requireAdministrator.&amp;nbsp; Also, don't forget to set the name
to match your application's name.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;Then, to embed the application you can do a few things.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;One technique is to use the &lt;strong&gt;mt.exe&lt;/strong&gt; (ManifestTool)
from the Visual Studio Command Prompt:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote style="MARGIN-RIGHT: 0px" dir=ltr&gt; 
&lt;p dir=ltr&gt;
&lt;font face="Courier New"&gt;mt.exe -manifest app.exe.manifest -updateresource:app.exe,#1&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;But I don't believe this would work if your application is signed
with a strong name unless you were to delay-sign it.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;The easier (and better) approach is to use the Project Properties
--&amp;gt; Application tab.&amp;nbsp; Simply select your app.exe.manifest file in the Manifest
dropdown.&amp;nbsp; It will automatically be embedded.&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font color=#0000ff face=Tahoma&gt;&lt;em&gt;NOTE: In order to debug your application that
requires admin rights you'll need to run Visual Studio from an elevated token.&amp;nbsp;
Otherwise you won't have privileges enough to attach to the process.&lt;/em&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;Next, I wanted to ensure that the user runs the application with
administrative rights.&amp;nbsp; This check was placed particularly for the pre-Vista
operating systems which didn't have UAC.&amp;nbsp; To do this I added the following code:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote style="MARGIN-RIGHT: 0px" dir=ltr&gt; 
&lt;p dir=ltr&gt;
&lt;font face="Courier New"&gt;[STAThread()]&lt;br&gt;
&lt;font color=#008000&gt;private static void&lt;/font&gt; Main() {&lt;br&gt;
&amp;nbsp;&amp;nbsp; Application.EnableVisualStyles();&lt;br&gt;
&amp;nbsp;&amp;nbsp; Application.SetCompatibleTextRenderingDefault(&lt;font color=#008000&gt;false&lt;/font&gt;);&lt;br&gt;
&lt;br&gt;
&amp;nbsp; &amp;nbsp;&lt;font color=#a9a9a9&gt;&lt;em&gt;// check to make sure that the user is running
with administrative rights.&lt;br&gt;
&amp;nbsp;&amp;nbsp; // in Vista/Win7/Svr2008 this is automatically taken care of via the&lt;br&gt;
&amp;nbsp;&amp;nbsp; // embedded manifest (which ensures administrative rights) via UAC.&lt;/em&gt;&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; &lt;font color=#008000&gt;if&lt;/font&gt; ( !userHasAdminRights()
) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageBox.Show(&lt;font color=#a52a2a&gt;"This
application requires administrative privileges."&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;font color=#a52a2a&gt;"Unauthorized
Access"&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;
MessageBoxButtons.OK, MessageBoxIcon.Information);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;return&lt;/font&gt;;&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 er ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageBox.Show(er.ToString());&amp;nbsp; &lt;font color=#a9a9a9&gt;&lt;em&gt;//
Of course you'd handle this differently&lt;/em&gt;&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; Application.Run(&lt;font color=#008000&gt;new&lt;/font&gt; MainForm());&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;font color=#008000&gt;private static bool&lt;/font&gt; userHasAdminRights() {&lt;br&gt;
&amp;nbsp;&amp;nbsp; WindowsIdentity identity = WindowsIdentity.GetCurrent();&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;return&lt;/font&gt; ( &lt;font color=#008000&gt;null&lt;/font&gt; !=
identity &amp;amp;&amp;amp; &lt;font color=#008000&gt;new&lt;/font&gt; WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator)
);&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;Pretty simple, really.&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=1a18e011-ea44-459e-84be-55a9046bce7d" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,1a18e011-ea44-459e-84be-55a9046bce7d.aspx</comments>
      <category>C#</category>
      <category>Security</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=bc8582e7-73de-49d7-bb91-c801bf9f71ba</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,bc8582e7-73de-49d7-bb91-c801bf9f71ba.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,bc8582e7-73de-49d7-bb91-c801bf9f71ba.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=bc8582e7-73de-49d7-bb91-c801bf9f71ba</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">Here's something I threw together the other day to help me organize
my ripped audio books.  I have several audio books (Harry Potter, LOTR, Dresden
Files, etc) that I've been ripping to file so that I could gather an entire 10-20
CD set onto a single disc for easy listening while driving without needing to switch
discs.  I like to use WMA files for easy ripping (via Media Player) and the small
footprint.</font>
        </p>
        <p>
          <font face="Tahoma">I've found, much to my chagrin, that the information retrieved
online for these books (via CDDB, FreeDB, or All Music Guide (which WMP uses))
is unreliable, frequently contains typos and misspellings, and is extremely inconsistent
with respect to formatting and convention.</font>
        </p>
        <p>
          <font face="Tahoma">I found that when I inserted a CD I would spend a good amount
of time entering the book name, the genre, the year it was recorded, the author, and
the performer, and I'd take the time to rename the tracks.  After a handful of
CDs this was almost unbearable and extremely tedious.</font>
        </p>
        <p>
          <font face="Tahoma">I therefore set out to write a script that would do this, updating
all of the ID3 tags after the fact.  The only thing I would need to concern myself
with was that the book name (I like the form <em>Book Name - Disc XX</em>) was correct. 
This script belows makes a few assumptions about the folder and file names:</font>
        </p>
        <ul>
          <li>
            <font face="Tahoma">each folder contains a single disk and that they are named according
to the pattern <em>"Book Name - Disc XX"</em></font>
          </li>
          <li>
            <font face="Tahoma">all books will be collected into a single folder with the name
pattern <em>"Book Set - Book Name"</em></font>
          </li>
        </ul>
        <p>
          <font face="Tahoma">For example, I ripped a book by </font>
          <a href="http://www.jim-butcher.com/">
            <font face="Tahoma">Jim
Butcher</font>
          </a>
          <font face="Tahoma"> named Small Favor.  Each disc went into
a folder named "Small Favor - Disc 01", "Small Favor - Disc 02", etc.  I would
then collect all the ripped files into a single directory named "Dresden Files - Book
10 - Small Favor".  This way, when all was said and done, I'd have all the books
in order and grouped.</font>
        </p>
        <p>
          <font face="Tahoma">I decided to use <a href="http://technet.microsoft.com/en-us/scriptcenter/dd742419.aspx">PowerShell</a> as
the language of preference for automating this procedure.  Not only does it provide
a very powerful scripting environment, but I can also leverage the .NET Framework
(which I love dearly).  As such, I was able to take advantage of </font>
          <a href="http://developer.novell.com/wiki/index.php/TagLib_Sharp">
            <font face="Tahoma">TagLib#</font>
          </a>
          <font face="Tahoma">'s
ability to edit the tags within the files.  This script assumes that the taglib-sharp.dll
is in the same directory as the .ps1 script file.</font>
        </p>
        <p>
          <font face="Tahoma">The following PowerShell scripts performs all the collecting,
enumerating, and tagging of my files.  Feel free to adapt it and tweak it according
to your own preferences.  If you have suggestions, I'd welcome them.  Like
I said, I threw it together in a very short time so it's probably weak in many regards
but seems to get the job done.</font>
        </p>
        <p>
          <font face="Tahoma">Taking my example above, my command line would be:</font>
        </p>
        <blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
          <p>
            <em>
              <font face="Tahoma">.\collectaudiobook "Small Favor" "Dresden Files - Book 10"
"Jim Butcher" "James Marsters" 2008</font>
            </em>
          </p>
        </blockquote>
        <p dir="ltr">
          <font face="Tahoma">Now I don't need to worry about what information was loaded from
the CDDB-esque service, the script updates it all after-the-fact. :)</font>
        </p>
        <p>
          <strong>
            <font size="3" face="Courier New">CollectAudioBook.ps1</font>
          </strong>
        </p>
        <blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
          <p>
            <font face="Courier New">$a = $args.length</font>
          </p>
          <p>
            <font face="Courier New">if ( $a -lt 2 ) {<br />
  write @"</font>
          </p>
          <p>
            <font face="Courier New">USAGE:</font>
          </p>
          <p>
            <font face="Courier New">`t.\CollectAudioBook.ps1 titlePrefix targetFolderPrefix [author]
[artist] [year]</font>
          </p>
          <p>
            <font face="Courier New">REQUIRED PARAMETERS:</font>
          </p>
          <p>
            <font face="Courier New">titlePrefix<br />
`tSpecifies the subfolders to process as a single book.<br />
`t(e.g., 'Small Favor' would locate 'Small Favor - Disc 01', 'Small Favor - Disc 02',
etc)<br />
`tThe folders are processed in order by name, assuming that to be the proper sequencing
of the resulting files.</font>
          </p>
          <p>
            <font face="Courier New">targetFolderPrefix<br />
`tSpecifies the target folder to which all tracks are collected.  If this<br />
`tfolder doesn't exist, it is created.<br />
`tNOTE: The folder's full name will be comprised of the targetFolderPrefix, a hyphen,
and the titlePrefix.<br />
`t(e.g., a titlePrefix of 'Small Favor' and a targetFolderPrefix of 'Dresden Files
- Book 10' becomes<br />
`tDresden Files - Book 10 - Small Favor)</font>
          </p>
          <p>
            <font face="Courier New">author<br />
`tIdentifies the author of the book.</font>
          </p>
          <p>
            <font face="Courier New">artist<br />
`tIdentifies the name of the performer.</font>
          </p>
          <p>
            <font face="Courier New">year<br />
`tIdentifies the year of the recording.</font>
          </p>
          <p>
            <font face="Courier New">"@<br />
  exit<br />
}</font>
          </p>
          <p>
            <font face="Courier New">$bookName = $args[0]<br />
$bookSet = $args[1] + ' - ' + $bookName<br />
$author = $args[2]<br />
$artist = $args[3]<br />
$year = $args[4]</font>
          </p>
          <p>
            <font face="Courier New">$target = '.\' + $bookSet<br />
$partNum = 0</font>
          </p>
          <p>
            <font face="Courier New"># load taglib-sharp.dll which allows for the manipulation
on the media tags in the files<br />
$asm = [Reflection.Assembly]::LoadFrom((Resolve-Path ".\taglib-sharp.dll"))</font>
          </p>
          <p>
            <font face="Courier New"># create the target directory<br />
$dir = New-Item -path "$target" -type directory -force</font>
          </p>
          <p>
            <font face="Courier New"># enumerate all files in each folder that start with the
prefix, copying and renaming each file<br />
foreach ( $folder in ( Get-ChildItem .\$bookName* | Where-Object { $_.Mode.StartsWith('d')
} | Sort Name ) ) {<br />
  foreach ( $file in ( Get-ChildItem $folder | Sort Name ) ) {<br />
    ++$partNum</font>
          </p>
          <p>
            <font face="Courier New">    $targetPrefix = 'Part ' + $partNum.ToString("00")<br />
    $targetFileName = $targetPrefix + '.wma'<br />
    write "Copying $file`t--&gt;`t$targetFileName"<br />
    Copy-Item $folder\$file $target\$targetFileName</font>
          </p>
          <p>
            <font face="Courier New">    # update the media information in the file<br />
    $media = [TagLib.File]::Create((Resolve-Path "$target\$targetFileName"))<br />
    $media.Tag.Title = $bookName + ' - ' + $targetPrefix<br />
    if ( $author -ne $null ) { $media.Tag.AlbumArtists = $author }<br />
    if ( $artist -ne $null ) { $media.Tag.Performers = $artist }<br />
    $media.Tag.Genres = { Audio Book }<br />
    if ( $year -ne $null ) { $media.Tag.Year = $year }<br />
    $media.Save()<br />
  }<br />
}</font>
          </p>
        </blockquote>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=bc8582e7-73de-49d7-bb91-c801bf9f71ba" />
      </body>
      <title>Simplifying the Ripping of AudioBooks and Tagging with PowerShell</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,bc8582e7-73de-49d7-bb91-c801bf9f71ba.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/08/25/SimplifyingTheRippingOfAudioBooksAndTaggingWithPowerShell.aspx</link>
      <pubDate>Tue, 25 Aug 2009 05:20:53 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;Here's something I threw together the other day to help me organize
my ripped audio books.&amp;nbsp; I have several audio books (Harry Potter, LOTR, Dresden
Files, etc) that I've been ripping to file so that I could gather an entire 10-20
CD set onto a single disc for easy listening while driving without needing to switch
discs.&amp;nbsp; I like to use WMA files for easy ripping (via Media Player) and the small
footprint.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I've found, much to my chagrin, that the information retrieved online
for these books&amp;nbsp;(via CDDB, FreeDB, or All Music Guide (which WMP uses)) is unreliable,
frequently contains typos and misspellings, and is extremely inconsistent with respect
to formatting and convention.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I found that when I inserted a CD I would spend a good amount of
time entering the book name, the genre, the year it was recorded, the author, and
the performer, and I'd take the time to rename the tracks.&amp;nbsp; After a handful of
CDs this was almost unbearable and extremely tedious.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I therefore set out to write a script that would do this, updating
all of the ID3 tags after the fact.&amp;nbsp; The only thing I would need to concern myself
with was that the book name (I like the form &lt;em&gt;Book Name - Disc XX&lt;/em&gt;) was correct.&amp;nbsp;
This script belows makes a few assumptions about the folder and file names:&lt;/font&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;font face=Tahoma&gt;each folder contains a single disk and that they are named according
to the pattern &lt;em&gt;"Book Name - Disc XX"&lt;/em&gt;&lt;/font&gt; 
&lt;li&gt;
&lt;font face=Tahoma&gt;all books will be collected into a single folder with the name pattern &lt;em&gt;"Book
Set - Book Name"&lt;/em&gt;&lt;/font&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;For example, I ripped a book by &lt;/font&gt;&lt;a href="http://www.jim-butcher.com/"&gt;&lt;font face=Tahoma&gt;Jim
Butcher&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt; named Small Favor.&amp;nbsp; Each disc went into
a folder named "Small Favor - Disc 01", "Small Favor - Disc 02", etc.&amp;nbsp; I would
then collect all the ripped files into a single directory named "Dresden Files - Book
10 - Small Favor".&amp;nbsp; This way, when all was said and done, I'd have all the books
in order and grouped.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I decided to use &lt;a href="http://technet.microsoft.com/en-us/scriptcenter/dd742419.aspx"&gt;PowerShell&lt;/a&gt; as
the language of preference for automating this procedure.&amp;nbsp; Not only does it provide
a very powerful scripting environment, but I can also leverage the .NET Framework
(which I love dearly).&amp;nbsp; As such, I was able to take advantage of &lt;/font&gt;&lt;a href="http://developer.novell.com/wiki/index.php/TagLib_Sharp"&gt;&lt;font face=Tahoma&gt;TagLib#&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;'s
ability to edit the tags within the files.&amp;nbsp; This script assumes that the taglib-sharp.dll
is in the same directory as the .ps1 script file.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;The following PowerShell scripts performs all the collecting, enumerating,
and tagging of my files.&amp;nbsp; Feel free to adapt it and tweak it according to your
own preferences.&amp;nbsp; If you have suggestions, I'd welcome them.&amp;nbsp; Like I said,
I threw it together in a very short time so it's probably weak in many regards but
seems to get the job done.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Taking my example above, my command line would be:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote style="MARGIN-RIGHT: 0px" dir=ltr&gt; 
&lt;p&gt;
&lt;em&gt;&lt;font face=Tahoma&gt;.\collectaudiobook "Small Favor" "Dresden Files - Book 10" "Jim
Butcher" "James Marsters" 2008&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;Now I don't need to worry about what information was loaded from
the CDDB-esque service,&amp;nbsp;the script&amp;nbsp;updates it all after-the-fact. :)&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;font size=3 face="Courier New"&gt;CollectAudioBook.ps1&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;blockquote style="MARGIN-RIGHT: 0px" dir=ltr&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;$a = $args.length&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;if ( $a -lt 2 ) {&lt;br&gt;
&amp;nbsp; write @"&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;USAGE:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;`t.\CollectAudioBook.ps1 titlePrefix targetFolderPrefix [author]
[artist] [year]&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;REQUIRED PARAMETERS:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;titlePrefix&lt;br&gt;
`tSpecifies the subfolders to process as a single book.&lt;br&gt;
`t(e.g., 'Small Favor' would locate 'Small Favor - Disc 01', 'Small Favor - Disc 02',
etc)&lt;br&gt;
`tThe folders are processed in order by name, assuming that to be the proper sequencing
of the resulting files.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;targetFolderPrefix&lt;br&gt;
`tSpecifies the target folder to which all tracks are collected.&amp;nbsp; If this&lt;br&gt;
`tfolder doesn't exist, it is created.&lt;br&gt;
`tNOTE: The folder's full name will be comprised of the targetFolderPrefix, a hyphen,
and the titlePrefix.&lt;br&gt;
`t(e.g., a titlePrefix of 'Small Favor' and a targetFolderPrefix of 'Dresden Files
- Book 10' becomes&lt;br&gt;
`tDresden Files - Book 10 - Small Favor)&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;author&lt;br&gt;
`tIdentifies the author of the book.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;artist&lt;br&gt;
`tIdentifies the name of the performer.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;year&lt;br&gt;
`tIdentifies the year of the recording.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;"@&lt;br&gt;
&amp;nbsp; exit&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;$bookName = $args[0]&lt;br&gt;
$bookSet = $args[1] + ' - ' + $bookName&lt;br&gt;
$author = $args[2]&lt;br&gt;
$artist = $args[3]&lt;br&gt;
$year = $args[4]&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;$target = '.\' + $bookSet&lt;br&gt;
$partNum = 0&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;# load taglib-sharp.dll which allows for the manipulation
on the media tags in the files&lt;br&gt;
$asm = [Reflection.Assembly]::LoadFrom((Resolve-Path ".\taglib-sharp.dll"))&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;# create the target directory&lt;br&gt;
$dir = New-Item -path "$target" -type directory -force&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;# enumerate all files in each folder that start with the
prefix, copying and renaming each file&lt;br&gt;
foreach ( $folder in ( Get-ChildItem .\$bookName* | Where-Object { $_.Mode.StartsWith('d')
} | Sort Name ) ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;foreach ( $file in ( Get-ChildItem $folder | Sort Name ) ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;++$partNum&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;nbsp; &amp;nbsp; $targetPrefix = 'Part ' + $partNum.ToString("00")&lt;br&gt;
&amp;nbsp; &amp;nbsp; $targetFileName = $targetPrefix + '.wma'&lt;br&gt;
&amp;nbsp; &amp;nbsp; write "Copying $file`t--&amp;gt;`t$targetFileName"&lt;br&gt;
&amp;nbsp; &amp;nbsp; Copy-Item $folder\$file $target\$targetFileName&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;nbsp; &amp;nbsp; # update the media information in the file&lt;br&gt;
&amp;nbsp; &amp;nbsp; $media = [TagLib.File]::Create((Resolve-Path "$target\$targetFileName"))&lt;br&gt;
&amp;nbsp; &amp;nbsp; $media.Tag.Title = $bookName + ' - ' + $targetPrefix&lt;br&gt;
&amp;nbsp; &amp;nbsp; if ( $author -ne $null ) { $media.Tag.AlbumArtists = $author }&lt;br&gt;
&amp;nbsp; &amp;nbsp; if ( $artist -ne $null ) { $media.Tag.Performers = $artist }&lt;br&gt;
&amp;nbsp; &amp;nbsp; $media.Tag.Genres = { Audio Book }&lt;br&gt;
&amp;nbsp; &amp;nbsp; if ( $year -ne $null ) { $media.Tag.Year = $year }&lt;br&gt;
&amp;nbsp; &amp;nbsp; $media.Save()&lt;br&gt;
&amp;nbsp; }&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=bc8582e7-73de-49d7-bb91-c801bf9f71ba" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,bc8582e7-73de-49d7-bb91-c801bf9f71ba.aspx</comments>
      <category>.NET</category>
      <category>PowerShell</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=9cf329d9-8865-4722-ba21-25e308a28325</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,9cf329d9-8865-4722-ba21-25e308a28325.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,9cf329d9-8865-4722-ba21-25e308a28325.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=9cf329d9-8865-4722-ba21-25e308a28325</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font size="2" face="Tahoma">
            <a href="http://windowsteamblog.com/blogs/windows7/archive/2009/07/21/when-will-you-get-windows-7-rtm.aspx" target="_blank">http://windowsteamblog.com/blogs/windows7/archive/2009/07/21/when-will-you-get-windows-7-rtm.aspx</a>
          </font>
        </p>
        <p>
          <font size="2" face="Tahoma">Can't wait! I've been using Windows 7 in the Beta and
RC (Release Candidate) builds for some time now and I LOVE it! It's been rock solid
(particularly for it's pre-release form) and very fast. It's been my primary OS now
on 3 separate computers so I'm really excited about being able to get my hands on
the RTM version in the next few weeks.</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=9cf329d9-8865-4722-ba21-25e308a28325" />
      </body>
      <title>Get your hands on the Windows 7 RTM...soon!</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,9cf329d9-8865-4722-ba21-25e308a28325.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/07/22/GetYourHandsOnTheWindows7RTMsoon.aspx</link>
      <pubDate>Wed, 22 Jul 2009 19:11:47 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font size="2" face="Tahoma"&gt;&lt;a href="http://windowsteamblog.com/blogs/windows7/archive/2009/07/21/when-will-you-get-windows-7-rtm.aspx" target="_blank"&gt;http://windowsteamblog.com/blogs/windows7/archive/2009/07/21/when-will-you-get-windows-7-rtm.aspx&lt;/a&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size="2" face="Tahoma"&gt;Can't wait! I've been using Windows 7 in the Beta and
RC (Release Candidate) builds for some time now and I LOVE it! It's been rock solid
(particularly for it's pre-release form) and very fast. It's been my primary OS now
on 3 separate computers so I'm really excited about being able to get my hands on
the RTM version in the next few weeks.&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=9cf329d9-8865-4722-ba21-25e308a28325" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,9cf329d9-8865-4722-ba21-25e308a28325.aspx</comments>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=41af86d0-e4cf-47b5-abd8-8f048a3cff61</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,41af86d0-e4cf-47b5-abd8-8f048a3cff61.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,41af86d0-e4cf-47b5-abd8-8f048a3cff61.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=41af86d0-e4cf-47b5-abd8-8f048a3cff61</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <font size="2" face="Tahoma">Well, I've
always <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;261186">loved
classical music</a>...too bad I'm not on Windows 95 anymore.<br /></font>
        <p>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=41af86d0-e4cf-47b5-abd8-8f048a3cff61" />
      </body>
      <title>Windows Classical Music</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,41af86d0-e4cf-47b5-abd8-8f048a3cff61.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/06/17/WindowsClassicalMusic.aspx</link>
      <pubDate>Wed, 17 Jun 2009 19:20:03 GMT</pubDate>
      <description>&lt;font size="2" face="Tahoma"&gt;Well, I've always &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;261186"&gt;loved
classical music&lt;/a&gt;...too bad I'm not on Windows 95 anymore.&lt;br&gt;
&lt;/font&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=41af86d0-e4cf-47b5-abd8-8f048a3cff61" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,41af86d0-e4cf-47b5-abd8-8f048a3cff61.aspx</comments>
      <category>Humor</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=21a5f7e2-3cb4-4092-a438-11015b78f657</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,21a5f7e2-3cb4-4092-a438-11015b78f657.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,21a5f7e2-3cb4-4092-a438-11015b78f657.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=21a5f7e2-3cb4-4092-a438-11015b78f657</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <font face="Tahoma">
          <font size="2">This
is definitely not news, but I wanted to blog it anyway.<br /><br />
Having recently just reset a development server to use Windows Server 2008, I needed
to open the firewall to allow ICMP packets through.  Essentially, I wanted to
have the server respond to PING requests.  On a fresh Windows Vista or Windows
Server 2008 install (and I imagine Windows 7, though I've not checked), the ICMP protocol
is blocked by default; the server won't respond to PINGs.  When you ping an IP
address and don't get a reply that doesn't mean that there isn't a computer on the
other end, but it sure is a handy way to check.<br /><br />
In Windows Vista/2008 enabling ICMP through the firewall isn't difficult, but if you
want to use a GUI, you have to do it through an inbound rule in the <b>Windows Firewall
with Advanced Security</b> option.<br /><br />
Personally, I prefer to do it via the command-line through this simple operation: <b>netsh
firewall set icmpsetting 8</b></font>
          <br />
        </font>
        <p>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=21a5f7e2-3cb4-4092-a438-11015b78f657" />
      </body>
      <title>Enabling PING in Windows Server 2008 and Vista</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,21a5f7e2-3cb4-4092-a438-11015b78f657.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/06/12/EnablingPINGInWindowsServer2008AndVista.aspx</link>
      <pubDate>Fri, 12 Jun 2009 22:41:21 GMT</pubDate>
      <description>&lt;font face="Tahoma"&gt;&lt;font size="2"&gt;This is definitely not news, but I wanted to blog
it anyway.&lt;br&gt;
&lt;br&gt;
Having recently just reset a development server to use Windows Server 2008, I needed
to open the firewall to allow ICMP packets through.&amp;nbsp; Essentially, I wanted to
have the server respond to PING requests.&amp;nbsp; On a fresh Windows Vista or Windows
Server 2008 install (and I imagine Windows 7, though I've not checked), the ICMP protocol
is blocked by default; the server won't respond to PINGs.&amp;nbsp; When you ping an IP
address and don't get a reply that doesn't mean that there isn't a computer on the
other end, but it sure is a handy way to check.&lt;br&gt;
&lt;br&gt;
In Windows Vista/2008 enabling ICMP through the firewall isn't difficult, but if you
want to use a GUI, you have to do it through an inbound rule in the &lt;b&gt;Windows Firewall
with Advanced Security&lt;/b&gt; option.&lt;br&gt;
&lt;br&gt;
Personally, I prefer to do it via the command-line through this simple operation: &lt;b&gt;netsh
firewall set icmpsetting 8&lt;/b&gt;&lt;/font&gt;
&lt;br&gt;
&lt;/font&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=21a5f7e2-3cb4-4092-a438-11015b78f657" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,21a5f7e2-3cb4-4092-a438-11015b78f657.aspx</comments>
      <category>Windows Vista</category>
      <category>Windows Server 2008</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=b1532b74-f32c-4bfb-9943-294340251147</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,b1532b74-f32c-4bfb-9943-294340251147.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,b1532b74-f32c-4bfb-9943-294340251147.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=b1532b74-f32c-4bfb-9943-294340251147</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">As you may or may not be aware IE 7+ (and other browsers) support
using CSS 2.1 </font>
          <a href="http://www.w3.org/TR/CSS21/selector.html">
            <font face="Tahoma">attribute
selectors</font>
          </a>
          <font face="Tahoma">.  Attribute selectors allow you to specify
a style on an element whose element matches a particular pattern.  For instance:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">td[x] { font-weight:bold; }</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">This selector will bold the text of any TD element on the page
that has an attribute "x" (regardless of value).  Other attribute selector styles
include:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Tahoma">
              <font face="Courier New">...[x="value"]</font> matches where x
is exactly 'value'<br /><font face="Courier New">...[x~="value"]</font> matches where x contains a space-separated list
of values, one of which is exactly 'value'<br /><font face="Courier New">...[x^="value"]</font> matches where the attribute x begins
with 'value'<br /><font face="Courier New">...[x$="value"]</font> matches where the attribute x ends
with 'value'<br /><font face="Courier New">...[x*="value"]</font> matches where the attribute x contains
'value'<br /><font face="Courier New">...[x|="value"]</font> matches where the attribute x begins
with either 'value' or 'value-'</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">In and of themselves, these are pretty darn cool.  You can
do some neat things with CSS and HTML.</font>
        </p>
        <p>
          <font face="Tahoma">I ran into an interested scenario this past week that I'd like
to share.  I have some JavaScript that alters the value of attributes at runtime. 
I found that the page doesn't automatically update according to the stylesheet specification. 
Curiously, it would update when I moused-over the element in question.</font>
        </p>
        <p>
          <font face="Tahoma">I found, however, that I could force the issue by assigning the
CSS classname to the element that it already has.  This is enough to trigger
the change and have the element update according to its attribute values.</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br />
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;<br />
&lt;head&gt;<br />
   &lt;style type="text/css"&gt;<br />
      td[req] { font-weight:bold; }<br />
      td[err="1"] { color:red !important; }<br />
   &lt;/style&gt;<br />
   &lt;script type="text/javascript"&gt;<br />
      function fn() {<br />
         var td = document.getElementById("t");<br />
         td.err = "0";<br />
         td.className = td.className; 
// trigger the change by reassigning the CSS class<br />
      }<br />
   &lt;/script&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
   &lt;table&gt;<br />
      &lt;tr&gt;&lt;td class="test" err="1" req="1" id="t"&gt;Cell&lt;/td&gt;&lt;/tr&gt;<br />
   &lt;/table&gt;<br />
   &lt;button onclick="javascript:fn();"&gt;Remove Error&lt;/button&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">Interestingly, for this to work properly in a non-IE browser (such
as Firefox), I found I could not use the object.property=value syntax.  Instead,
I had to use the SetAttribute() function.  Also, with Firefox, reassigning the
className was unnecessary.</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">td.setAttribute("err", "0");</font>
          </p>
        </blockquote>
        <p dir="ltr">
          <font face="Tahoma">That's probably the best way to handle it then, for cross-browser
compliance.</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=b1532b74-f32c-4bfb-9943-294340251147" />
      </body>
      <title>CSS Attribute Selector Magic</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,b1532b74-f32c-4bfb-9943-294340251147.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/05/04/CSSAttributeSelectorMagic.aspx</link>
      <pubDate>Mon, 04 May 2009 04:28:44 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;As you may or may not be aware IE 7+ (and other browsers) support
using CSS 2.1 &lt;/font&gt;&lt;a href="http://www.w3.org/TR/CSS21/selector.html"&gt;&lt;font face=Tahoma&gt;attribute
selectors&lt;/font&gt;&lt;/a&gt;&lt;font face=Tahoma&gt;.&amp;nbsp; Attribute selectors allow you to specify
a style on an element whose element matches a particular pattern.&amp;nbsp; For instance:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;td[x] { font-weight:bold; }&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;This selector will bold the text of any TD element on the page that
has an attribute "x" (regardless of value).&amp;nbsp; Other attribute selector styles
include:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;&lt;font face="Courier New"&gt;...[x="value"]&lt;/font&gt; matches where x is
exactly 'value'&lt;br&gt;
&lt;font face="Courier New"&gt;...[x~="value"]&lt;/font&gt; matches where x contains a space-separated&amp;nbsp;list
of values, one of which is exactly 'value'&lt;br&gt;
&lt;font face="Courier New"&gt;...[x^="value"]&lt;/font&gt; matches where the attribute x begins
with 'value'&lt;br&gt;
&lt;font face="Courier New"&gt;...[x$="value"]&lt;/font&gt; matches where the attribute x ends
with 'value'&lt;br&gt;
&lt;font face="Courier New"&gt;...[x*="value"]&lt;/font&gt; matches where the attribute x contains
'value'&lt;br&gt;
&lt;font face="Courier New"&gt;...[x|="value"]&lt;/font&gt; matches where the attribute x begins
with either 'value' or 'value-'&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;In and of themselves, these are pretty darn cool.&amp;nbsp; You can
do some neat things with CSS and HTML.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I ran into an interested scenario this past week that I'd like to
share.&amp;nbsp; I have some JavaScript that alters the value of attributes at runtime.&amp;nbsp;
I found that the page doesn't automatically update according to the stylesheet specification.&amp;nbsp;
Curiously, it would update when I moused-over the element in question.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I found, however, that I could force the issue by assigning the
CSS classname to the element that it already has.&amp;nbsp; This is enough to trigger
the change and have the element update according to its attribute values.&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;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&amp;gt;&lt;br&gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;&lt;br&gt;
&amp;lt;head&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;style type="text/css"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; td[req] { font-weight:bold; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; td[err="1"] { color:red !important; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;/style&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;script type="text/javascript"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; function fn() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; var td = document.getElementById("t");&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; td.err = "0";&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;td.className = td.className;&amp;nbsp;
// trigger the change by reassigning the CSS class&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;/script&amp;gt;&lt;br&gt;
&amp;lt;/head&amp;gt;&lt;br&gt;
&amp;lt;body&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;table&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;tr&amp;gt;&amp;lt;td class="test" err="1" req="1" id="t"&amp;gt;Cell&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;/table&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;button onclick="javascript:fn();"&amp;gt;Remove Error&amp;lt;/button&amp;gt;&lt;br&gt;
&amp;lt;/body&amp;gt;&lt;br&gt;
&amp;lt;/html&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;Interestingly, for this to work properly in a non-IE browser (such
as Firefox), I found I could not use the object.property=value syntax.&amp;nbsp; Instead,
I had to use the SetAttribute() function.&amp;nbsp; Also, with Firefox, reassigning the
className was unnecessary.&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;td.setAttribute("err", "0");&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
&lt;font face=Tahoma&gt;That's probably the best way to handle it then, for cross-browser
compliance.&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=b1532b74-f32c-4bfb-9943-294340251147" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,b1532b74-f32c-4bfb-9943-294340251147.aspx</comments>
      <category>CSS</category>
      <category>Web</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=eb7b0741-d973-4dda-9325-1a4cf5f3fdfc</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,eb7b0741-d973-4dda-9325-1a4cf5f3fdfc.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,eb7b0741-d973-4dda-9325-1a4cf5f3fdfc.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=eb7b0741-d973-4dda-9325-1a4cf5f3fdfc</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">My buddy Rob Bagby has announced this exciting event called <strong>XamlFest</strong> which
will be in Salt Lake City on May 1st.  If you have the chance, I'd encourage
you to sign up and attend.</font>
        </p>
        <p>
          <font face="Tahoma">Here's the info: </font>
          <a href="http://blogs.msdn.com/bags/archive/2009/03/31/xamlfest-in-salt-lake-city-on-may-1.aspx">
            <font face="Tahoma">http://blogs.msdn.com/bags/archive/2009/03/31/xamlfest-in-salt-lake-city-on-may-1.aspx</font>
          </a>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=eb7b0741-d973-4dda-9325-1a4cf5f3fdfc" />
      </body>
      <title>XamlFest in SLC on May 1st</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,eb7b0741-d973-4dda-9325-1a4cf5f3fdfc.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/04/23/XamlFestInSLCOnMay1st.aspx</link>
      <pubDate>Thu, 23 Apr 2009 19:35:44 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;My buddy Rob Bagby has announced this exciting event called &lt;strong&gt;XamlFest&lt;/strong&gt; which
will be in Salt Lake City on May 1st.&amp;nbsp; If you have the chance, I'd encourage
you to sign up and attend.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Here's the info: &lt;/font&gt;&lt;a href="http://blogs.msdn.com/bags/archive/2009/03/31/xamlfest-in-salt-lake-city-on-may-1.aspx"&gt;&lt;font face=Tahoma&gt;http://blogs.msdn.com/bags/archive/2009/03/31/xamlfest-in-salt-lake-city-on-may-1.aspx&lt;/font&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=eb7b0741-d973-4dda-9325-1a4cf5f3fdfc" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,eb7b0741-d973-4dda-9325-1a4cf5f3fdfc.aspx</comments>
      <category>Events</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=994798c1-3e00-4b01-8807-6ed42fb0d446</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,994798c1-3e00-4b01-8807-6ed42fb0d446.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,994798c1-3e00-4b01-8807-6ed42fb0d446.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=994798c1-3e00-4b01-8807-6ed42fb0d446</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">I was putting together a WinForms utility application today that
consists of a TabStrip control on the main dialog box.  On a themed system the
TabStrip displays a nice gradual gradient on the page.  As part of this
application I wanted to output statistical and detailed information about the user's
selections in a readonly fashion, but I wanted to have the text appear as though it
were written directly on the TabStrip page rather than within a control.</font>
        </p>
        <p>
          <font face="Tahoma">Of course my first thought was to use a Label control, but I almost
immediately wrote that off as the amount of information to be displayed was prohibitive
and variable.  The data being displayed might exceed the space on the TabStrip,
so scrolling the information is a must.</font>
        </p>
        <p>
          <font face="Tahoma">Next I thought of using a TextBox control, but without some pretty
intense subclassing and overriding, I wouldn't be able to achieve the 'written-on'
look I was after.  The TextBox will always render an opaque background color. 
Sure, there are ways of faking transparency, like overriding TextBox and adding a
PictureBox and telling the parent control to WM_PRINT into it, but that seems to be
a kludgy way of getting the results I wanted.</font>
        </p>
        <p>
          <font face="Tahoma">Additionally, there are mechanisms to use a RichTextBox (v5.0)
to achieve transparency that are well documented online, but try as I might with these
implementations, I found them to be quite buggy.  In particular, the appearance
of the scrollbars was erratic and sometimes didn't render properly with the control
was resized.  After battling with it for a few hours I gave up.  It wasn't
for lack of desire, it just wasn't worth it given the scope of the project I was working
on.</font>
        </p>
        <p>
          <font face="Tahoma">So this morning I went back to the drawing board and came up with
a solution in about 45 minutes that seems to do exactly what I wanted.  I've
called this control the ScrollableLabel.  Essentially, it offers the readonlyness
of a Label control and the scrollability of a TextBox.  This implementation here
is very fundamental.  I plan on enhancing it some more to incorporate user-defined
colors, headers, and much more.</font>
        </p>
        <p>
          <font face="Tahoma">I made some executive decisions about how this control should
render.  For instance, it will always use your system's colors for text and I
set the BackColor property of the UserControl to Transparent via the designer. 
For both of these I plan on making them user-selectable choices, but for not,
they're the look I was after.</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">public partial class</font> ScrollableLabel
: UserControl {<br />
   <font color="#008000">public</font> ScrollableLabel() {<br />
      InitializeComponent();<br />
      SetStyle(ControlStyles.Selectable, <font color="#008000">false</font>);<br />
      <em><font color="#a9a9a9">// the preferred mechanism
for enabling double-buffering is to set the DoubleBuffered property<br />
      // of the control rather than the equivalent SetStyle(DoubleBuffer
| UserPaint | AllPaintingInWmPaint, true).<br /></font></em>      DoubleBuffered = <font color="#008000">true</font>;<br />
      AutoScroll = <font color="#008000">true</font>;<br />
      AutoScrollMinSize = Size.Empty;<br />
   }<br /><br />
   <font color="#008000">private</font> SizeF _actualTextSize;<br /><br />
   <font color="#008000">public override string</font> Text {<br />
      <font color="#008000">get</font> { <font color="#008000">return
base</font>.Text; }<br />
      <font color="#008000">set</font> {<br />
         <font color="#008000">base</font>.Text
= <font color="#008000">value</font>;<br />
         calcLabelDimensions();<br />
         Invalidate();<br />
      }<br />
   }<br /><br />
   <font color="#008000">protected override void</font> OnScroll(ScrollEventArgs
se) {<br />
      <font color="#008000">base</font>.OnScroll(se);<br />
      Invalidate();<br />
   }<br /><br />
   <font color="#008000">public void</font> Clear() {<br />
      Text = <font color="#008000">string</font>.Empty;<br />
   }<br /><br />
   <font color="#008000">#region Hidden design-time properties</font><br />
   [Browsable(<font color="#008000">false</font>)]<br />
   <font color="#008000">public override bool</font> AutoScroll {<br />
      <font color="#008000">get</font> { <font color="#008000">return
true</font>; }<br />
      <font color="#008000">set</font> { <font color="#a9a9a9"><em>/*
do nothing for now; control is always AutoScroll */</em></font> }<br />
   }</font>
          </p>
          <p>
            <br />
            <font face="Courier New">   [Browsable(<font color="#008000">false</font>)]<br />
   <font color="#008000">public override</font> Color ForeColor {<br />
      <font color="#008000">get</font> { <font color="#008000">return</font> SystemColors.ControlText;
}<br />
      <font color="#008000">set</font> { <em><font color="#a9a9a9">/*
do nothing for now; only ControlText is currently supported */</font></em> }<br />
   }<br />
   <font color="#008000">#endregion</font><br /><br />
   <font color="#008000">private void</font> calcLabelDimensions() {<br />
      <font color="#008000">using</font> ( Graphics g = CreateGraphics()
) {<br />
         <em><font color="#a9a9a9">// assume
that no text should wrap</font></em><br />
         _actualTextSize = g.MeasureString(Text,
Font);<br />
         AutoScrollMinSize = Size.Round(_actualTextSize);<br />
      }<br />
   }<br /><br />
   <font color="#008000">protected override void</font> OnPaint(PaintEventArgs
e) {<br />
      RectangleF rct = <font color="#008000">new</font> RectangleF(AutoScrollPosition,
_actualTextSize);<br />
      </font>
            <font face="Courier New">Brush br = Enabled<br />
                   
? SystemBrushes.ControlText<br />
                   
: SystemBrushes.GrayText;<br />
      e.Graphics.DrawString(Text, Font, br, rct);<br />
   }<br />
}</font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">When this control is added to a Form it will automatically add
scrollbars if the contents exceed the dimensions of the control.  At design-time,
however I wanted to make sure that I could see where the ScrollableLabel was positioned
so I created a simple Designer.</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#008000">public sealed class</font> BorderlessBorderDesigner
: ControlDesigner {<br />
   <font color="#008000">protected override void</font> OnPaintAdornments(PaintEventArgs
pe) {<br />
      <font color="#008000">base</font>.OnPaintAdornments(pe);<br />
      <font color="#008000">if</font> ( BorderStyle.None
== getBorderStyle() ) {<br />
         Rectangle rct = Control.ClientRectangle;<br />
         rct.Width -= 1;<br />
         rct.Height -= 1;<br />
         <font color="#008000">using</font> (
Pen p = <font color="#008000">new</font> Pen(SystemColors.ControlDark) ) {<br />
            p.DashStyle = DashStyle.Dash;<br />
            pe.Graphics.DrawRectangle(p,
rct);<br />
         }<br />
      }<br />
   }<br /></font>
            <font face="Tahoma">
              <br />
              <font face="Courier New">   <font color="#008000">private</font> BorderStyle
getBorderStyle() {<br /></font>
              <font face="Courier New">      UserControl ctl = Control <font color="#008000">as</font> UserControl;<br />
      <font color="#008000">if</font> ( <font color="#008000">null</font> !=
ctl ) <font color="#008000">return</font> ctl.BorderStyle;<br /></font>
              <font face="Courier New">      <font color="#008000">return</font> BorderStyle.None;<br />
   }<br />
}</font>
            </font>
          </p>
        </blockquote>
        <p>
Then, I added<strong> [Designer(typeof(BorderlessBorderDesigner)]</strong> to my ScrollableLabel
class declaration.
</p>
        <p>
It's a simple control that achieves a simple goal.  I'll post my updates to it
as I get a chance to modify it and make it all the more flexible and powerful.
</p>
        <p>
Enjoy!
</p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=994798c1-3e00-4b01-8807-6ed42fb0d446" />
      </body>
      <title>ScrollableLabel control</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,994798c1-3e00-4b01-8807-6ed42fb0d446.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/04/07/ScrollableLabelControl.aspx</link>
      <pubDate>Tue, 07 Apr 2009 04:19:13 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;I was putting together a WinForms utility application today that
consists of a TabStrip control on the main dialog box.&amp;nbsp; On a themed system the
TabStrip displays a nice gradual gradient on the page.&amp;nbsp;&amp;nbsp;As part of this
application I wanted to output statistical and detailed information about the user's
selections in a readonly fashion, but I wanted to have the text appear as though it
were written directly on the TabStrip page rather than within a control.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Of course my first thought was to use a Label control, but I almost
immediately wrote that off as the amount of information to be displayed was prohibitive
and variable.&amp;nbsp; The data being displayed might exceed the space on the TabStrip,
so scrolling the information is a must.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Next I thought of using a TextBox control, but without some pretty
intense subclassing and overriding, I wouldn't be able to achieve the 'written-on'
look I was after.&amp;nbsp; The TextBox will always render an opaque background color.&amp;nbsp;
Sure, there are ways of faking transparency, like overriding TextBox and adding a
PictureBox and telling the parent control to WM_PRINT into it, but that seems to be
a kludgy way of getting the results I wanted.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;Additionally, there are mechanisms to use a RichTextBox (v5.0) to
achieve transparency that are well documented online, but try as I might with these
implementations, I found them to be quite buggy.&amp;nbsp; In particular, the appearance
of the scrollbars was erratic and sometimes didn't render properly with the control
was resized.&amp;nbsp; After battling with it for a few hours I gave up.&amp;nbsp; It wasn't
for lack of desire, it just wasn't worth it given the scope of the project I was working
on.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;So this morning I went back to the drawing board and came up with
a solution in about 45 minutes that seems to do exactly what I wanted.&amp;nbsp; I've
called this control the ScrollableLabel.&amp;nbsp; Essentially, it offers the readonlyness
of a Label control and the scrollability of a TextBox.&amp;nbsp; This implementation here
is very fundamental.&amp;nbsp; I plan on enhancing it some more to incorporate user-defined
colors, headers, and much more.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;I made some executive decisions about how this control should render.&amp;nbsp;
For instance, it will always use your system's colors for text and I set the BackColor
property of the UserControl to Transparent via the designer.&amp;nbsp; For both of these
I plan on making&amp;nbsp;them user-selectable choices, but for not, they're the look
I was after.&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 partial class&lt;/font&gt; ScrollableLabel
: UserControl {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public&lt;/font&gt; ScrollableLabel() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InitializeComponent();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetStyle(ControlStyles.Selectable, &lt;font color=#008000&gt;false&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&lt;font color=#a9a9a9&gt;// the preferred mechanism
for enabling double-buffering is to set the DoubleBuffered property&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // of the control rather than the equivalent SetStyle(DoubleBuffer
| UserPaint | AllPaintingInWmPaint, true).&lt;br&gt;
&lt;/font&gt;&lt;/em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoubleBuffered = &lt;font color=#008000&gt;true&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoScroll = &lt;font color=#008000&gt;true&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoScrollMinSize = Size.Empty;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;private&lt;/font&gt; SizeF _actualTextSize;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public override string&lt;/font&gt; Text {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;get&lt;/font&gt; { &lt;font color=#008000&gt;return
base&lt;/font&gt;.Text; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;set&lt;/font&gt; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;base&lt;/font&gt;.Text
= &lt;font color=#008000&gt;value&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; calcLabelDimensions();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Invalidate();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;protected override void&lt;/font&gt; OnScroll(ScrollEventArgs
se) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;base&lt;/font&gt;.OnScroll(se);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Invalidate();&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public void&lt;/font&gt; Clear() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Text = &lt;font color=#008000&gt;string&lt;/font&gt;.Empty;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;#region Hidden design-time properties&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; [Browsable(&lt;font color=#008000&gt;false&lt;/font&gt;)]&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public override bool&lt;/font&gt; AutoScroll {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;get&lt;/font&gt; { &lt;font color=#008000&gt;return
true&lt;/font&gt;; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;set&lt;/font&gt; { &lt;font color=#a9a9a9&gt;&lt;em&gt;/*
do nothing for now; control is always AutoScroll */&lt;/em&gt;&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; [Browsable(&lt;font color=#008000&gt;false&lt;/font&gt;)]&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;public override&lt;/font&gt; Color ForeColor {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;get&lt;/font&gt; { &lt;font color=#008000&gt;return&lt;/font&gt; SystemColors.ControlText;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;set&lt;/font&gt; { &lt;em&gt;&lt;font color=#a9a9a9&gt;/*
do nothing for now; only ControlText is currently supported */&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;#endregion&lt;/font&gt;
&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;private void&lt;/font&gt; calcLabelDimensions() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;using&lt;/font&gt; ( Graphics g = CreateGraphics()
) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&lt;font color=#a9a9a9&gt;// assume
that no text should wrap&lt;/font&gt;&lt;/em&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _actualTextSize = g.MeasureString(Text,
Font);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoScrollMinSize = Size.Round(_actualTextSize);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;protected override void&lt;/font&gt; OnPaint(PaintEventArgs
e) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RectangleF rct = &lt;font color=#008000&gt;new&lt;/font&gt; RectangleF(AutoScrollPosition,
_actualTextSize);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Courier New"&gt;Brush br = Enabled&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;
? SystemBrushes.ControlText&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;
: SystemBrushes.GrayText;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; e.Graphics.DrawString(Text, Font, br, rct);&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;When this control is added to a Form it will automatically add scrollbars
if the contents exceed the dimensions of the control.&amp;nbsp; At design-time, however
I wanted to make sure that I could see where the ScrollableLabel was positioned so
I created a simple 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;public sealed class&lt;/font&gt; BorderlessBorderDesigner
: ControlDesigner {&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;protected override void&lt;/font&gt; OnPaintAdornments(PaintEventArgs
pe) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;base&lt;/font&gt;.OnPaintAdornments(pe);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;if&lt;/font&gt; ( BorderStyle.None ==
getBorderStyle() ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Rectangle rct = Control.ClientRectangle;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rct.Width -= 1;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rct.Height -= 1;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;using&lt;/font&gt; (
Pen p = &lt;font color=#008000&gt;new&lt;/font&gt; Pen(SystemColors.ControlDark) ) {&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; p.DashStyle = DashStyle.Dash;&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; pe.Graphics.DrawRectangle(p,
rct);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;/font&gt;&lt;font face=Tahoma&gt;
&lt;br&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;private&lt;/font&gt; BorderStyle
getBorderStyle() {&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UserControl ctl = Control &lt;font color=#008000&gt;as&lt;/font&gt; UserControl;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;if&lt;/font&gt; ( &lt;font color=#008000&gt;null&lt;/font&gt; !=
ctl ) &lt;font color=#008000&gt;return&lt;/font&gt; ctl.BorderStyle;&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;return&lt;/font&gt; BorderStyle.None;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Then, I added&lt;strong&gt; [Designer(typeof(BorderlessBorderDesigner)]&lt;/strong&gt; to my ScrollableLabel
class&amp;nbsp;declaration.
&lt;/p&gt;
&lt;p&gt;
It's a simple control that achieves a simple goal.&amp;nbsp; I'll post my updates to it
as I get a chance to modify it and make it all the more flexible and powerful.
&lt;/p&gt;
&lt;p&gt;
Enjoy!&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=994798c1-3e00-4b01-8807-6ed42fb0d446" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,994798c1-3e00-4b01-8807-6ed42fb0d446.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>WinForms</category>
      <category>Controls</category>
    </item>
    <item>
      <trackback:ping>http://blog.devstone.com/aaron/Trackback.aspx?guid=fb1bbf27-9f81-4a3d-b600-456291ac6711</trackback:ping>
      <pingback:server>http://blog.devstone.com/aaron/pingback.aspx</pingback:server>
      <pingback:target>http://blog.devstone.com/aaron/PermaLink,guid,fb1bbf27-9f81-4a3d-b600-456291ac6711.aspx</pingback:target>
      <dc:creator>R. Aaron Zupancic (Administrator)</dc:creator>
      <wfw:comment>http://blog.devstone.com/aaron/CommentView,guid,fb1bbf27-9f81-4a3d-b600-456291ac6711.aspx</wfw:comment>
      <wfw:commentRss>http://blog.devstone.com/aaron/SyndicationService.asmx/GetEntryCommentsRss?guid=fb1bbf27-9f81-4a3d-b600-456291ac6711</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Tahoma">I have an external HDD that I use to store various files and products
that I download.  Today, while downloading one such application my computer decided
to freeze.  I've been having a sporatic issue with my hardware lately, so this
freeze (while not entirely unexpected) happened at a most inopportune moment.</font>
        </p>
        <p>
          <font face="Tahoma">When my computer 'came-to' after rebooting, my HDD was put into
a read-only state.  Any change I tried to make to the drive was greeted with
a "The media is write protected" error message.  The only <em>fix</em> I could
come up with was the following:</font>
        </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Tahoma">1. Open the command prompt.<br />
2. Type <strong>DISKPART</strong><br />
3. <strong>LIST VOLUME</strong> (to identify the volume in question)<br />
4. <strong>SELECT VOLUME #</strong> (where # represents the volume identifier)<br />
5. <strong>ATTRIBUTES VOLUME CLEAR READONLY</strong></font>
          </p>
        </blockquote>
        <p>
          <font face="Tahoma">After this, I could select the folders on my drive and unmark
their read-only state.  Note that I had to clear the read-only flag even
though DISKPART reported the volume as not being read-only.</font>
        </p>
        <p>
          <font face="Tahoma">We'll see whether the drive falls back into its read-only state
in the future.</font>
        </p>
        <img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=fb1bbf27-9f81-4a3d-b600-456291ac6711" />
      </body>
      <title>Working through "The media is write protected"</title>
      <guid isPermaLink="false">http://blog.devstone.com/aaron/PermaLink,guid,fb1bbf27-9f81-4a3d-b600-456291ac6711.aspx</guid>
      <link>http://blog.devstone.com/aaron/2009/03/17/WorkingThroughTheMediaIsWriteProtected.aspx</link>
      <pubDate>Tue, 17 Mar 2009 23:31:52 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face=Tahoma&gt;I have an external HDD that I use to store various files and products
that I download.&amp;nbsp; Today, while downloading one such application my computer decided
to freeze.&amp;nbsp; I've been having a sporatic issue with my hardware lately, so this
freeze (while not entirely unexpected) happened at a most inopportune moment.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;When my computer 'came-to' after rebooting, my HDD was put into
a read-only state.&amp;nbsp; Any change I tried to make to the drive was greeted with
a "The media is write protected" error message.&amp;nbsp; The only &lt;em&gt;fix&lt;/em&gt; I could
come up with was the following:&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;1. Open the command prompt.&lt;br&gt;
2. Type &lt;strong&gt;DISKPART&lt;/strong&gt;
&lt;br&gt;
3. &lt;strong&gt;LIST VOLUME&lt;/strong&gt; (to identify the volume in question)&lt;br&gt;
4. &lt;strong&gt;SELECT VOLUME #&lt;/strong&gt; (where # represents the volume identifier)&lt;br&gt;
5. &lt;strong&gt;ATTRIBUTES VOLUME CLEAR READONLY&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;font face=Tahoma&gt;After this, I could select the folders on my drive and unmark their
read-only state.&amp;nbsp; Note that I had to clear the read-only&amp;nbsp;flag even though
DISKPART reported the volume as not being read-only.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Tahoma&gt;We'll see whether the drive falls back into its read-only state
in the future.&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.devstone.com/aaron/aggbug.ashx?id=fb1bbf27-9f81-4a3d-b600-456291ac6711" /&gt;</description>
      <comments>http://blog.devstone.com/aaron/CommentView,guid,fb1bbf27-9f81-4a3d-b600-456291ac6711.aspx</comments>
      <category>Utilities</category>
      <category>Windows Vista</category>
    </item>
  </channel>
</rss>