Friday, May 05, 2006

I just had the opportunity to attend a webcast presented by Scott Hanselman entitled “MSDN Architecture Webcast: Introduction to Programming Hardware with the .NET Framework 2.0“.  What a cool presentation., Scott was up to his usual great form when it comes to presentations, despite a few sharing glitches which were easily ignored.

Scott touched on many things new to .NET 2.0 most notably interfacing with serial ports.  Additionally, he addressed using USB devices.  His demos (which are fully available online) included receiving information from a USB GPS device (the one included with Streets and Maps), pushing data to an LED (in this case, showing what Media Player is playing), using a USB Wireless Security FOB, using WIA (Windows Image Aquisition) to receive images from a WIA-enabled webcam, and more.

If you missed it, it should be available in a recorded form on Microsoft's site within 24 hrs.

Thanks, Scott!

Friday, May 05, 2006 5:20:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Mark Russinovich, the brilliant co-mind behind of SysInternals and author of a vast array of extremely helpful utilities, just published a new utility that has already found a comfortable home among those utilities that I use on a daily basis.  This new one is called AccessChk.  This awesome tool will help you secure your system by allowing you to verify the kinds of access permissions that a user has (be they read or modify permissions) for files, directories, Registry keys, and Windows services.

I've been wanting a tool like this for some time, but never took the time to write anything.  Thanks, Mark, for yet another ultra-uber-helpful utility.

Speaking of helpful utilities, does anyone know of one that does the following?  I have long wanted an easy way to see a utility that I'll call PolicyChk which I could use to see which Group Policies a user/group has rights assigned (either directly or via group membership).  There have been times uncountable wherein I wanted to grant a user the same polciy rights as another user (such as ASPNET), but didn't know which rights to assign without laborious manual examination of the various policy settings looking for the account and it's various group memberships.

Friday, May 05, 2006 4:40:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, May 04, 2006

It's been a crazy week!  Hardly any time for blogging, unfortunately.  I've been setting up my new Dell Precision M90 laptop :-) as well as doing TONS around the house.  Not to mention that I took Monday and Tuesday off (something I haven't done for a long time, too long).

I took the time to enable HTTP Compression on my various websites, this blog among them.  Hopefully performance is better all around.  Let me know if there are any issues or if you experience any outages.  There are many great references out there for successfully enabling compression in IIS.  I found this one, and this one, oh, and this one to be pretty doggone helpful.

Thursday, May 04, 2006 7:01:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, April 27, 2006

I have been playing with SQL Server a lot lately, but not from the programmatic side but rather from the DBA side.  Don't get me wrong, I like the programming side a bunch more, but we had the need to to do some database maintenance and upgrades among other things.  We were running SQL Server 2000 SP4 + Reporting Services on a domain controller under much of the default installation settings.  For instance, the ReportServer service was running under the NETWORK SERVICE account.

Upon attempting to upgrade this server to SQL Server 2005 I was greeted with a message identifying that it could not be upgraded with the NETWORK SERVICE as the report service account on a domain controller.  Therefore, I had to set out to change the account associated with the Reporting Services service account.  Changing the account, however, is not as easy as simply changing the account.  If you simply change the user account, you will probably be greeted with a message akin to

The report server cannot decrypt the symmetric key used to access sensitive or encrypted data in a report server database. You must either restore a backup key or delete all encrypted content and then restart the service. Check the documentation for more information. (rsReportServerDisabled) Get Online Help
Bad Data.

In addition to the various rights and permissions needed for the new account, you need to make sure you backup your symmetric keys before changing the account.  If you changed the account already, you'll have to change it back to NT AUTHORITY\NETWORK SERVICE (see note below).  Once done, follow the steps below (as found in the support.microsoft.com website KB842421)

  1. Start the Report Server Windows service and Report Server Web service
  2. Backup your encryption keys via
    RSKeyMgmt -e -f filename -p strongPassword
  3. Remove the reference to the encryption key (locate the InstallationID in the “%ProgramFiles%\Microsoft SQL Server\MSSQL\Reporting Services\ReportServer\RSReportServer.config“ file
    RSKeyMgmt -r InstallationIDGuid
  4. Stop IIS
  5. Stop the Report Server Windows service
  6. Change the user account on the Report Server Windows service
  7. Start IIS
  8. Start the Report Server Windows service
  9. Apply the encryption key previously backed up
    RSKeyMgmt -a -f filename -p strongPassword

That fixed the issue for me - what a relief!

NOTE: Changing the account back to NT AUTHORITY\NETWORK SERVICE (something I had to do) isn't as obvious as I would have liked.  Rather than performing a lookup on the user and not finding it on the domain controller, you have to know of the account's existence.  Type it in directly on the 'Log On' tab.  You won't know (or probably won't know) the password.  Simply blank out the password and the confirmation field.  The system will automatically associate the appropriate credentials for you.  This wasn't apparent, but I'm glad to have figured it out.  There have been so many times where I wanted to lookup accounts from the BUILTIN or NT AUTHORITY security groups but they simply wouldn't show up in the 'Browse' dialog on a domain controller.  Now I know and feel much better about it. :)

Thursday, April 27, 2006 4:13:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Wednesday, April 26, 2006

This had me pulling my hair out today (and there's not too much left, believe me).  I was so frustrated, but finally hope smiled down on my endeavors.

I had a SQL Server database that I was trying to drop (either via Enterprise Manager or via the script DROP DATABASE 'xxx').  Each time I tried, it would fail with the error message:

Error 3724: Cannot drop the database 'xxx' because it is being used for replication

This was disconcerting because I no longer had replication enabled on the server.  I tried all of the recommendations that I could find online to remove any association of replication from the database, and they all failed for me though they had worked for others.  For instance, the most frequently recommended strategy that I found was this:

sp_replicationdboption 'xxx', 'publish', FALSE
GO
sp_replicationdboption 'xxx', 'merge publish', FALSE
GO

or

sp_removedbreplication 'xxx'
GO

Once again, I could not successfully delete the database following these actions.  I simply could not see a way to remove the database.  Then a coworker had a stroke of genius that I'd like to share.

He suggested the following and it worked like a charm:

  1. Create a dummy, temp database called 'Hope' (we called it that because we hoped it would work).
  2. Backup the database.
  3. Restore the backup over the database you can't delete (you'll have to rename the target file so as to not conflict with your original, dummy, temp database).
  4. Happily delete both databases

That got rid of it.  Boy what a hassle.

Can any of you DBA's out there think of something else that I haven't tried?  Does this approach make you cringe? I battled it for the better part of 2 hrs before resorting to this approach and simply couldn't get anything else to work.

Wednesday, April 26, 2006 12:02:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [12]  |  Trackback

I like to consider myself a knowledgeable user of Windows - there's aren't too many nooks and crannies that I haven't explored and/or tried.  Today, however, I was introduced to a feature that I can't believe I didn't know before.

When presented with a Message Box dialog, simply press CTRL+C to copy it's contents to the clipboard.  So easy...so elegant...so brainless...so non-intuitive.

Wednesday, April 26, 2006 5:27:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, April 21, 2006

This is probably float around out there a ton by now, but today Microsoft released SP1 for it's rockin' SQL Server 2005.  Get it.  Install it.  Enjoy it.

Link: http://www.microsoft.com/sql/sp1.mspx

Friday, April 21, 2006 4:21:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, April 19, 2006

I don't claim to be an XML/XPath expert, but I can definitely hold my own - at least so far.  I just wanted to share something I was doing today in the hopes that someone might also benefit.

By and large, developers (and by developers, I mean people, though they're not always synonymous) use XPath with positive assertions.  What I mean is that XPath is used to query Xml documents looking for information they know or expect to exist.

For instance, the following XPath query will return the child nodes beneath the family element that contains a lastname attribute value of 'Rogers'

/family[@lastname='Rogers']/*

Removing the trailing '/*' such that the query is /family[@lastname='Rogers'] will return the family nodes that have a lastname attribute of 'Rogers'

Suppose further that you wanted to retrieve all family elements that had a value other than Rogers, you'd simply change the equality operator

/family[@lastname!='Rogers']

Ok, no magic.  It's all rudimentary, simple XPath.

However, what if you wanted to perform a negative assertion?  That is, what if you wanted to get the family elements that didn't have a lastname?  I'm not talking about an empty lastname (i.e. <FAMILY lastname="" />), I'm talking about all of the family elements that are missing the lastname attribute entirely (i.e. <FAMILY />).

I don't know of a way to solve this by simply using straight element/attribute syntax (but then again, I don't pretend to know much of anything about it in the first place).  The solution is actually quite simple, but you have use a function.

/family[count(@lastname)=0]

[EDIT 04/20/2006: Corey Kaylor left a comment that I'd like to share]
I had tried many variations on this exact theme, but failed to try the not() function.  Thanks Corey!
A better solution is this:

/family[not(@lastname)]

That simple query allows you to find all nodes with the specified name that don't have the lastname attribute.  Pretty slick.  This is just tapping the surface, because there's a whole bunch more that you can do.  I simply wanted to record it so I wouldn't forget.  Simple.  Easy.  I like it.

Wednesday, April 19, 2006 2:29:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Monday, April 17, 2006

I've been doing some experimentation lately regarding application configuration files.  I know that there is a horse out there that is really dead due to repetitive beatings, but I'd like to add my two kicks, er, cents.

In all of your .NET application development, if you've ever done configuration files and deserialized their XML contents to objects you may have encountered the following links (originally created, as I understand it, by Craig Andera):

They're all variations on a theme.  The predominant overriding theme describes how to read in a custom XML chunk from a configuration file and deserialize it into the appropriate object type at runtime.  This effectively renders the XML element and attribute values as properties and collections and makes the configuration file settings readable at runtime.  Rather than having to constantly re-code and re-engineer the details of reading XML elements manually and repetitively, these posts demonstrate a technique that relies on objects found the System.Xml.Serialization namspace to automatically do the work for you.  Very handy indeed.  I've used these exact strategies for a few years in my own work to great success.  All in all, I really feel that the original solution has lots of merit and I really like it.

Essentially, the gist is that you create a ConfigSectionHandler class that implements the IConfigurationSectionHandler interface.  This interface is required by the .NET runtime as the means by which it calls into your library so that you can perform custom work on the XmlNode that it provides in the .Create() method.  The strategy here is to create a generic handler that can resolve the appropriate Type to create for deserialization so that all of the work is done for you by a single handler.  This is accomplished by including a 'type' attribute on the XML element to be deserialized.

A simple example might resemble the following:

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
      <sectionGroup name="devstone">
         <section name="settings" type="TestApplication.Configuration.ConfigHandler, TestApplication" />
      </sectionGroup>
   </configSections>
   <devstone>
      <settings type="TestApplication.Configuration.Settings, Testapplication">
         <setting1>Test Value 1</setting1>
         <setting2>Test Value 2</setting2>
      </settings>
   </devstone>
</configuration>

ConfigSectionHandler.cs

namespace TestApplication.Configuration {
   public sealed class ConfigSectionHandler : IConfigurationSectionHandler {
      object IConfigurationSectionHandler.Create(object parent, object configContext, XmlNode section) {
         XPathNavigator nav = section.CreateNavigator();
         string typeName = (string)nav.Evaluate("string(@type)");
         Type type = Type.GetType(typeName);
         if ( null == type )
            throw new ArgumentException(string.Format("Invalid type specification in configuration file: '{0}'", typeName));
         XmlSerializer ser = new XmlSerializer(type);
         return ser.Deserialize(new XmlNodeReader(section));
      }
   }
}

Settings.cs

namespace TestApplication.Configuration {
   [XmlRoot("settings")]
   public sealed class Settings {
     private string _setting1, _setting02;
    
     [XmlElement("setting1")]
     public string Setting1 {
        get { return _setting1; }
        set { _setting1 = value; }
     }
    
     [XmlElement("setting2")]
     public string Setting2 {
        get { return _setting2; }
        set { _setting2 = value; }
     }
   }
}

I got to thinking recently as a simple, side, pet project to see if I might improve upon these methodologies.  A few avenues led to dead-ends while others were more fruitful and enjoyable.  I'd like to present these here, leading up to what I think might be my favorite solution, though the jury's still out on it.  I've got to give it a few more spins around the parking lot first.

First of all, I like to treat each 'configuration section object' as a singleton.  That is, that only one instance of the object should ever exist that represents the settings.  There is absolutely no need to be writing code like this everywhere:

Settings settings = (Settings)ConfigurationSettings.GetConfig("devstone/settings");

To accomplish this I convert my settings class into a singleton following the prescribed pattern for lazy initialization:

Settings.cs

namespace TestApplication.Configuration {
   [XmlRoot("settings")]
   public sealed class Settings {
      public static Settings Instance = SettingsProvider.Instance;
      private sealed class SettingsProvider {
         private SettingsProvider() { }
         internal static Settings Instance { get { return ConfigurationSettings.GetConfig("devstone/settings") as Settings; } }
     }
   
     
// same field and property declarations as before...
   }
}

Note, it's not a true singleton...more on that in a bit.  Now, to reference the settings object I can simply use the simpler, more intuitive code and access the single instance globally across my application:

Settings settings = Settings.Instance;

In fact, this is more akin to the methodology I've used now for some time, but still some things grate on me.

  1. I have to build my configuration XML files explicitly knowing the types.  One type for the <configSections /> section.  Another type for the attribute on the XML element to be deserialized.  I'd rather only need to remember one type.  Also, the 'type' of the object to be deserialized isn't the business of the configuration file nor the eyes of the person viewing it.  How many times do you want to actually be able 'change' the type via the configuration file?  Nonetheless, I enjoy the clean elegance of the aforementioned solution.
  2. While not explicitly heinous, I don't really like having seemingly unnecessary accessors on my deserialized type except for the sole purpose of supporting deserialization (e.g. public 'set' accessors on properties, having to make the 'Settings' type public with a public parameterless constructor (though implicit it may be in this case)).
  3. If there are other members (e.g. properties that aggregate values) I have to explicitly identify them as [XmlIgnore()] so as to not permit them to (de)serialize.  This is trivial in reality, but thought I'd mention it.

I'd like to address these bit by bit.

First of all, let's address the notion of 'Type'.  As I mentioned, I don't really care to have to remember two types (though Scott Weinstein's blog post does address this issue some by generating the XML necessary for you.  I'd rather not have my XML polluted with unnecessary type information.  Therefore, let's move the generic handler into a base class from which the Settings class can derive, thereby providing it's own type information.  This will also necessitate a change to the configuration file to reflect the new type information and to the handler to be an abstract base class:

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
      <sectionGroup name="devstone">
         <section name="settings" type="TestApplication.Configuration.Settings, TestApplication" />
      </sectionGroup>
   </configSections>
   <devstone>
      <settings>
      ...
      </settings>
   </devstone>
</configuration>

ConfigSectionHandlerBase.cs

namespace TestApplication.Configuration {
   public abstract class ConfigSectionHandlerBase : IConfigurationSectionHandler {
      object IConfigurationSectionHandler.Create(object parent, object configContext, XmlNode section) {
         try {
            XmlSerializer ser = new XmlSerializer(this.GetType());
            using ( StringReader reader = new StringReader(section.OuterXml) )
               return ser.Deserialize(reader);
         }
         catch ( Exception ) {
            // here, just for example return a clean instance if the object failed to deserialize
            return Activator.CreateInstance(this.GetType());
         }
      }
   }
}

Settings.cs

namespace TestApplication.Configuration {
   [XmlRoot("settings")]
   public class Settings : ConfigurationSectionHandlerBase {
      // same singleton, field, and property declarations as before
   }
}

Now the XML is cleaned up a little bit as no further type information needs to be specified.  However, there is an issue with this code.  Granted it's not very serious, but I view it as a shortcoming and not as clean as it might otherwise be.  The error isn't very obvious.

If you add the following code to the Settings class you'll see what I mean:

public Settings() { Console.WriteLine("Instance created"); }

The C# compiler will automatically provide a default, public constructor for a class that does not have an explicit constructor defined.  By adding this it simply makes it explicit and obvious.  If you were to run an application that consumed this Settings class, you'd see the text "Instance created" appear twice on the console window.  This illustrates two points:

  1. Even though we wrote code to make the class a 'singleton' it's not truly a singleton because it has a default public constructor.  This public constructor is required by the serialization engine so we're kinda stuck with it.  (We'll address this shortly).
  2. The .NET runtime is creating an instance of our class to be able to call the Create() method so that we can in turn create another instance (our 'singleton' instance) and return it.  This is pretty ugly.  Besides, the settings object shouldn't really have to know how to deserialize itself - that responsibility rightfully belongs to someone else.

Therefore, let's get to the final proposed solution.  Please bear with me on this as it's all kinda conceptual here - I've got to experiment a bit more to see if I like it, but I think I do.

SOLUTION:

First of all, let's move the implementation of the settings object (the one that gets deserialized) into an inner class.  Note, it still has to be public, with public get/set accessors on serialized methods, with a public constructor, but we can live with that.  I'll name this class Impl for 'Implementation'.  Ultimately, this type is not generally accessed except by the Settings class; unfortunately, there's nothing really stopping anyone from getting to it.  Peeve: I wish deserialized types could be internal or private.

Second, let's keep our base handler type, but delegate control to another inner class called Handler.  By doing this we can extend the base class to provide further metadata about the type to be deserialized along with some other information.  Additionally, it can be a private class - the runtime won't care in this case.

Third, we redo the Settings class such that it's properties are static readonly properties that redirect to the inner Impl 'singleton' class.

Fourth, we update the configuration file to reference the private, inner Handler class.

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
      <sectionGroup name="devstone">
         <section name="settings" type="TestApplication.Configuration.Settings+Handler, TestApplication" />
      </sectionGroup>
   </configSections>
   <devstone>
      <settings>
         <setting1>Test Value 1</setting1>
         <setting2>Test Value 2</setting2>
      </settings>
</configuration>

ConfigSectionHandlerBase.cs

namespace TestApplication.Configuration {
   public abstract class ConfigSectionHandlerBase : IConfigurationSectionHandler {
      protected virtual bool CreateOnError { get { return true; } }
      protected abstract Type DeserializedType { get; }
     
      object IConfigurationSectionHandler.Create(object parent, object configContext, XmlNode section) {
         try {
            XmlSerializer ser = new XmlSerializer(this.DeserializedType);
            using ( StringReader reader = new StringReader(section.OuterXml) )
               return ser.Deserialize(reader);
         }
         catch ( Exception ) {
            // perform logging if you'd like
            if ( this.CreateOnError )
               return Activator.CreateInstance(this.DeserializedType);
            else
               throw;
         }
      }
   }
}

Settings.cs

namespace TestApplication.Configuration {
   public sealed class Settings {
      private Settings() { }
     
      public static string Setting1 { get { return Impl.Instance.Setting1; } }
      public static string Setting2 { get { return Impl.Instance.Setting2; } }
     
      private class Handler : ConfigSectionHandlerBase {
         protected override Type DeserializedType { get { return typeof(Impl) } }
      }
     
      [XmlRoot("settings")]
      public sealed class Impl : ConfigurationSectionHandlerBase {
         public static Impl Instance = ImplProvider.Instance;
         private sealed class ImplProvider {
            private ImplProvider() { }
            internal static Impl Instance { get { return ConfigurationSettings.GetConfig("devstone/settings") as Impl; } }
         }
        
         private string _setting1, _setting02;
        
         [XmlElement("setting1")]
         public string Setting1 {
            get { return _setting1; }
            set { _setting1 = value; }
         }
        
         [XmlElement("setting2")]
         public string Setting2 {
            get { return _setting2; }
            set { _setting2 = value; }
         }
      }
   }
}

Ultimately, I think I like this solution a lot.  It does require a bit more code in the outset, but pays dividends in being much more readable.  Now, all XML serialization responsibilities are delegated directly to the Impl class and any other custom properties and methods can be tied directly to the Settings class as necessary.  Additionally, the implementor doesn't even need to know they're dealing with a single instance, but reference the properties directly:

string s1 = Settings.Setting1;

vs

string s1 = Settings.Instance.Setting1;

I'll have to experiment more with this, but it seems like a pretty cool solution.  What do you think?  I'll be posting a .NET 2.0 version soon, this is all 1.1 - I just wanted to get my thoughts out there.

Monday, April 17, 2006 9:29:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Friday, April 14, 2006

I have the privilege of speaking at the Utah County .NET User Group next Thursday night.  My topic will be 'Threading'.  I've given a similar presentation a few times now, though with each iteration I try to spice it up and make it different and better.  We'll talk about lots of .NET 1.x and the new 2.0 stuff as well.  We'd love to see you there!

Website: http://www.ucnug.org/
Time: 7:00 PM
Date: Thursday, April 20th, 2006
Place: Utah Vally State College (UVSC) room CS512

If you want to go and want to carpool, let me know, I'd be happy to drive.

Friday, April 14, 2006 6:53:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, April 13, 2006

Tonight was a success at the Utah .NET User Group.  Unfortunately we were not being able to get a reminder out to the group due to the site being down (more accurately the DNS server was down, but same difference in that it was inaccessible).  We had a pretty small turnout and a quiet crowd today, but it was fun nonetheless.

I had the opportunity to present on developing ASP.NET controls.  We focused on how to create UserControls and WebControls.  We talked about properly deriving from WebControl, rendering content and controls, utilizing embedded resources (a new .NET 2.0 feature which is totally awesome - I'll blog more about it in a future post), creating ITemplate-based controls server-side.  I've posted the code online if you'd like to download it here.

I'm glad for the faithful who showed up and had a great time and for TEKSystems for sponsoring this month's meeting.

Thursday, April 13, 2006 3:51:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback

For all those trying to hit my blog and view an individual post my apologies that it wasn't working.  I had no idea.  The main page was up and working, but it appeared that when you would browse to a single post the site would bomb with a Null reference exception.  I never got the error because I rarely visit my posts.  Today, however, I had the need to go back and review something I had written and that's when I got the error.  No wonder I hadn't received any comments or ratings for several days.  I wonder how long it had been down...?

Thanks for your patience.

Thursday, April 13, 2006 4:31:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback