Monday, February 07, 2005

This always bites me, but I wanted to post it here so that I don't waste another 15 or 20 minutes trying to remember this in the future.

If you want to create a new IIS site/virtual directory and designate an application pool with it's own identity, you'll probably be greeted with the all too wonderful and descriptive

Service Unavailable

message when you try to browse to the site.  This can get pretty infuriating to fix unless you remember a few simple rules:

1.  The identity under which the pool will execute needs to be a member of the local IIS_WPG group.
2.  The IIS_WPG group needs Read & Execute, List Folder Contents, and Read permissions on the folder.
3.  You might also need to manually assign the Adjust memory quotas for a process and Replace a process level token rights in your Local Security Policy.

Simply stop and start your application pool once the changes are made and you should be up and running.

See the brief, but excellent Tech Net article on the topic.

Monday, February 07, 2005 5:57:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Sunday, February 06, 2005

A colleague of mine encountered an interesting dilemma today.  All of the sudden, and seemingly out of the blue, Visual Studio .NET 2003 was reporting the following error: “...Web server is not running ASP.NET 1.1” when we've been developing applications using ASP.NET daily.  Now before we go blaming Microsoft for writing crappy software, let's take a look at the situation and try to fix it.

We did a bit of research online and the most prevalent remedy was to run aspnet_regiis -i.  In my experience you'll never really need to run that unless you install IIS after having installed Visual Studio .NET.  So we backtracked to what had changed recently.

It turns out that he had installed Skype this morning.  Everything was working great this morning, but once he rebooted, VS.NET could no longer interact with IIS.  As is so happens, Skype will steal port 80 before IIS has a chance to grab the port for its own uses.  You can, however, open Skype's options dialog and disable it from doing that.

I wonder why Skype decided to use port 80?  Perhaps it should check whether something already uses port 80 (like IIS) before auto-selecting that option...?

Sunday, February 06, 2005 6:19:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Saturday, February 05, 2005

[Updates 02/23/2005, 11/20/2006 - fixed spelling errors]

I'd like to think that I'm reasonably level headed.  It is part of my nature to analyze a situation before making an precipitated response that I might regret.  Of late I have found myself having to bite my tongue and not respond in an almost defensive posture on issues that are not even personally directed nor personal in nature (come to think of it, they might be, slightly just to try to make me mad).

My tenure with Microsoft (now a few years past) was one of the most evocative and eye-opening experiences in my professional career.  One the biggest messages that I gained from joining ranks with Microsoft was passion.  The vast majority of those with which I worked had an intense passion; passion for success, passion for technology, a raw, intense passion.  It was in many ways exhilirating...I absolutely loved it.

Prior to joining the company I had been a developer / trainer that specialized in the tools and technologies that Microsoft published.  For several years I was thus employed.

A few years ago, while I was with Microsoft, I attended the wedding of my cousin and her husband.  As we were performing the customary task of going through the line to greet the bride's and groom's respective families and to congratulate the couple I came upon some other cousins (same family as the bride, of course).  I made to shake their hands and instead of the complimentary 'thank you for coming' or 'good to see you', the following exchange ensued:


Cousin:  "Hey, Aaron, you work for Microsoft, right? With Windows XP?"
Me:  "Uh, yeah"
Cousin:  "It sucks!  Worst software ever.  It broke all my programs."


Needless to say, I was a little taken aback.  I guess I should have known than rather that having greeted my cousin and her new family warmly, I should have been preparing a comeback or a defense for such an imminent and predictable attack - of course! I was at a wedding, what else would I be thinking about?  I don't accurately recall my response except that I committed to talk to them afterwards and see if I could help them out of their predicaments.  I should have seen that one coming, though, because that particular cousin has always treated me (especially) and my family with a certain disdain and disrespect.

As it turns out, the problem wasn't with Windows XP, per se, but rather with a particular Math application that was designed to work on Windows 98.  Something in how Windows XP was created broke compatibility (even attempting to run the application in a Windows 98 emulated environment didn't work).  Therefore, Windows XP was crap and the worst thing to come out of Redmond.  As an aside, I have personally run Windows XP since Beta 2 (when it was the required OS for MS employees) and have seen 2 crashes in total.  Yes TWO.  It has been the best desktop operating system that I've worked with bar none.  The server OS's (e.g. Server 2003) has been even better.  Heh, the guy at the computer store the other day suggested that my server's hard drive crashed because I wasn't running Linux.  It crashed because I was running Windows Server 2003.

Ok, that was a little bit of a segue, but it brings me to my point of defensiveness.  It is difficult not to take attacks on Microsoft semi-personally, though my affiliation has always been somewhat peripheral (as an evangelist, proponent, consultant, trainer, developer, etc).

I frequently deal with individuals that have absolutely nothing but negative to say about Microsoft's products.  I have yet to hear a single sentence of praise, appreciation, or respect for a single thing.  The negative comments are quite literally every 3rd or 4th sentence uttered.  Such comments are invariably directed at Microsoft's poor decisions and are very rarely accompanied with any semblance of a solution; it's just a gripe session.

I simply bite my tongue and don't respond unless it's to offer a solution (which 95% of the time there is one), I let these individuals have their fun griping, for apparently there's fun in it.

Evidently, Microsoft has made all the wrong assumptions on a clean install of the operating system; that, as users, we must go through the drudgery of customizing our systems to undo all of the bad things that Microsoft assumed we wanted because we are not the typical 'dumb, brainless, idiot' user that was profiled when Microsoft performed its user testing is madness!

  • How could Microsoft assume that I'd EVER want to have a CD autoplay when I insert it in my drive!!?  Bad Microsoft!  How dare they assume that!
  • How dare they assume that I want 'My Documents' to store my files!?  Come to think of it, why do I need the stupid directory anyway?  No! I don't want to save my files in 'My Documents'!
  • ...and many more

I guess the real intentions of Microsoft are laid bare:  They want to make life harder on everyone by assuming certain behaviors; assumptions that were made based off of their spending of billions of R&D dollars annually.

I am somewhat of an advanced user of Windows and, upon installing a fresh system, will go through my little routine of flipping all the switches.  For example, I like to show hidden files (how could they assume I wouldn't want to see them?), to disable Simple Sharing (if you don't know how security works you shouldn't use the computer!), and change my resolution settings - plus much more).  In all, I probably take about 20 minutes configuring my system to the way I like it.  If something comes up later that I forgot to change or hadn't yet done, I'll fix it rather than curse Microsoft for making my life so hard.  Sure, some of the software that Microsoft has published in the past has some gaping holes in terms of functionality and security.  It's these same individuals that gripe about all of these oversights and weaknesses yet still insist on using these older applications.  I am happy to see the progress the MS has made with the likes of Windows XP SP2 and the various server platforms.

In fact, I have a novel idea:  Why not try to work WITH the system rather than AGAINST it?  Rather than curse Microsoft everytime the Save Dialog appears on 'My Documents' as the default, and begrudgingly navigate away to C:\Files\blah to save the file, CHANGE the folder to which My Documents refers and use it the way 90% of the applications out there are designed to function?  If Microsoft is making your life hard, change it...or perhaps rethink the way you're using software.  Please don't constantly yell at your computer because the application you're using (not the OS) has decided to do something a particular way.

These individuals dread having to install a utility (such as TweakUI) in order to make system settings changes (Why can't you change these settings within Windows itself rather than having to install ANOTHER program).  How ironic that the question never even arises if one must install the same type of utility on a different, non-Microsoft system (such as Linux).

Personally, I have found that the VAST majority of the decisions made in the base applications are sound and spot on.  The software that comes out of Redmond is designed to enable just about ANYONE to accomplish their tasks without having to understand all of the nitty-gritty details of HOW it works.  Rather, IJW (It Just Works).  Sure, once you need to step beyond the routine, simple tasks your knowledge needs to be expanded.  You may need to learn something new to accomplish that out-of-the-ordinary task.  Perhaps you need to disable on option here or enable another option there - but the switches are available.  Generally, if the software isn't working the way I'd want it to work, I find that I'm trying to get it to do something for which it was not designed.  Maybe I don't fully understand why it was designed that way in the first place.  There are times I'm at odds with the decisions anyway, but that is the exception, not the rule.

I find it interesting, too, that the same individuals that routinely curse Microsoft for one bad decision will not reciprocate the same attitude against a piece of software not from Redmond in which the same 'bad decision' is made.  It's as though the blinders are on and it is just Microsoft that is pure evil.

All of this isn't to say that I LOVE Microsoft.  I really appreciate the software that is developed on campus; were it not for Microsoft, I'd probably be a farmer, or a professional trampolinist, or a gypsy, or a Jedi Knight (though that might still be cool) and not a software engineer.  Microsoft has some of the most intelligent people working on their software, and I'd like to believe that they know what they're doing.  This is not to say that I blindly accept the food they feed me...I'll test it out and come to my own conclusions.  I, for one, praise the likes of Raymond Chen, for example, for enlightening us on why things are the way they are.  99% of the time there is a reasonable explanation.  I think the software they create is DANG good, and I'm proud to work with it and not against it.

Saturday, February 05, 2005 8:40:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [24]  |  Trackback
 Wednesday, February 02, 2005

Well, despite having my Domain Controller's hard drive go south last night, I'm back up and running!

I scurried down to the local computer store this afternoon and picked me up a brand new 160 GB drive (oh, and I also grabbed a 250 GB, 16MB Cache drive along with it).  This time I also got a 2 year warranty with them - I'm sick and tired of dealing with downed drives.

Well, prior to today, I had not had the experience of restoring an Active Directory and an Exchange Server...so this was uncharted territory for me.  I had made a backup of my System State last night and the Exchange data, so I was all set there; it was just a matter of restoring it properly.

These are the steps that I underwent:

  1. Put new drive in computer
  2. Format/Partition it as NTFS
  3. Installed the base OS (Windows Server 2003)
  4. Configured the NIC and IP address
  5. Installed IIS, DNS, and DHCP (though I did not configure them)
  6. Rebooted into Directory Recovery mode
  7. Restored my System State data, thereby bringing back the domain
  8. Rebooted
  9. Installed AntiVirus software
  10. Installed Exchange 2003 and SP1
  11. Restored the Exchange backup
  12. Repaired the database (ESEUTIL /P ...)

It's all up and working now and I'm so excited.  What pleased me most was that from taking out the old drive and being completely back up and running it took less than 90 minutes actual time (a few hrs real time including dinner and other sundry items).  Now the whole domain is back and it feels good!

Wednesday, February 02, 2005 3:10:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback

I must be a magnet.  A magnet for hard drive failures.  Which makes sense when you think about it.

Last night, during a not-so-routine backup of data on my domain controller (which happens to dual as my DNS, DHCP, Exchange, some file storage, etc), it encountered several Cyclical Redundancy Check (CRC) errors.  Dismayed, but not to the point of depression, I trudged forward and backed up the System State and the Exchange data and verified them.  I then proceeded to run CHKDSK /R which necessitated a reboot.  Durinng the CHKDSK it displayed each of the segments that were unreadable (starting at about 36,000 it went well into the 100,000s with the occasional skipping of a just few segments).  My rudimentary math tells me that it must have been about 50% of the drive that was bad.

So this turns out to be my 4th drive in about 2 years to go out (though officially this one hasn't crashed per se (yet) like the others).  Not only is it my 4th drive to go out, it's always been the boot volume on the domain controller that has gone out.  On reboot it warns me of imminent failure of the disk...nice, <sarcasm>at least I'm not sweating here</sarcasm>.

Maybe I'm a magnet for bad equipment? for bad luck?  Anyway, I'm on a budget and can't afford anything 'state of the art', nor do I expect 5 9's here at my house where it's only me and a few other people, but I'm heading down to my local Comp USA, Best Buy, or Office Max to get a new drive (as I need it TODAY).  Recommendations before I make the march in a bit here?  Anyone have recommendations for the 'best' drive?  My domain controller isn't even a 'server-class' box, but it's a pretty capable workstation, no SCSI or anything like that.

Wednesday, February 02, 2005 3:45:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, January 31, 2005

Last night (on January 31, 2005) we held our very first official code review for the game the Devstone programming group is writing entitled Island Frenzy.  As the initiator and primary proponent behind the code review, I was the voluntary guinea pig - we decided to review my code behind my messaging sub-system.  Though not everyone came prepared, which was quite a disappointment on a variety of levels, we were able to review the crux of the material and I feel that everyone left edified.

The purpose of the code review was multi-faceted.

  • To familiarize everyone with the various aspects of the application libraries.  Often times as developers we're islands in that we each work on our own focused areas, while blindly ignoring of the rest of the system.
  • To discuss the strengths and weaknesses of the objects within the system.  It's nice to have more than one set of eyes on the code.
  • To identify ways in which the objects should be extended/reused.
  • To identify the validity of the objects.  Some objects may no longer be used or perhaps are not even necessary anymore.  It's time to clean up the code.
  • To determine (and correct where applicable) whether the objects follow all established standards and conventions.
  • To learn new techniques and strategies.  Let's face it, we can all improve in this arena.

Conducting the code review was a great experience, despite not having full participation.  I was forced to recall historical reasonings behind various motives in the code - stuff that has been identified as candidates for better documentation and commenting.  It was neat to relive the decisions that I made months (sometimes years) ago in the design of the framework and come to the same conclusions in almost every single case.

Thanks to all that participated!

Monday, January 31, 2005 7:57:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, January 30, 2005

All my life I've been something of a boardgame nut...probably always will be.  Recently, I discovered a new boardgame that I very much enjoy and like to show to people.  It's called Carcassonne.  This game is a tile-based game in which players take turns strategically placing tiles on the table, ultimately creating a large map of cities, roads, and farmlands.  The game is fantastically addictive.  The game, not including its various expansions contains 72 tiles.  I had some spare cycles today and wondered if I could place all 72 tiles together to form a square board, and have all tiles legally placed.

As it turns out, this was easier that I thought it might be, only taking about 10-15 minutes.  One primary goal was to set the board up such that it was completely contained; that is, set up such that no cities and roads led off of the board.  Well, the result wasn't quite what I was aiming for, but I'll probably give it another try in the coming days (hrs).  Please forgive the blurriness of some of the tiles - I took the photograph at an angle so as to minimize the flash's glare and then photoshopped it with a perspective distortion and a stretch.

Update January 31st, 2005:
Here's an updated one that took a little more time.  As you can see, all of the roads and cities are completely self-contained on the board with the exception of the lower left corner.  Oh, well, it was fun while it lasted.

Sunday, January 30, 2005 5:32:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, January 28, 2005

They say practice makes perfect, and this is no exception to the rule.  You just never know what you'll find the Microsoft .NET SDK Documentation.  This is a best practice of which I've definitely grown fondle:

 

Does anyone have any best practice recommendations for 'handling' exceptions?

Friday, January 28, 2005 12:37:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Well, I finally had a free moment and I just got back in town the other night so I thought a take a moment and do some blogging.  It's been a while since I posted regarding my custom blog rating control; I've been meaning to get this up for download for some time but could never manage to - until now, not to mention that I've gotten quite a few requests to get it :).

Bear in mind, this is NOT the definitive, final release.  It is, however, enough to get started and have as a functional rating system.  Below, I've provided a bit of documentation to help you get it up and running on your site.  Please feel free to contact me if you have any questions.

The first thing you'll need to do is to run a database script against your blog database.  This script, found in the file 'DbScript.sql' does not do anything to alter existing schema.  All it does is adds a table (blog_DevstoneRating), a few store procedures (blog_DevstoneRateItem, blog_DevstoneGetItemRating, and blog_DevstoneGetTopRatedItems), and a function (blog_fnDevstoneGetPostUrl).  Be sure to change the database name to the appropriate name before running the script.  Oh, and backup your database.

The main rating control is called RatingSummary.  There is also another control that I haven't yet packaged because it's not quite finished that is called TopRatedPosts.  It is functional, but not yet friendly to all skins - I'll get it up as soon as I can.  Additionally, there is an HttpHandler and an HttpHandlerFactory class.  These provide integration into the .Text blog website.

The RatingSummary supports being embedded on a variety of pages within your blog (so that users can rate a blog post, a comment, etc).  One of the chief design tenets was that I wanted to be able to place the control on the main page along side each post, thereby providing the user a quick way to enter comments and rate the post.  Note: If a user rates a post and doesn't enter any comments it simply updates the post's rating.  However, if the user provided comments, not only is the post's rating is updated, but the user's comment is added to the list of posts for the site so it appears as a regular comment on the site.

The following examples identify a few of the changes you can make to incorporate the rating control on your site.  You will need to add the following page directive to the top of each control in which you intend to use the control:

<%@ Register tagPrefix="devstone" namespace="Devstone.Web.Blog.Controls" assembly="Devstone.Web.Blog.Controls.Rating" %>

The simple RatingSummary declaration resembles the following:

<devstone:ratingsummary runat=server visible=true />

The RatingSummary control offers a variety of properties that you can set to ensure proper behavior whereever posted.

ShowSummary (bool property):  Defaults to true.  Determines the presence of a descriptive text beneath the graphical rating, explaining the rating.

RatingBarType (RatingBarType property):  Defaults to RatingBarType.Star.  Determines the appearance of the rating control.  Valid values include Star, Dot, and Bar.

ShowRatingLink (bool property):  Defaults to true.  Determines if the link allowing users to rate the post is to be shown.

PostId (int property):  Defaults to -2 (autodetermine).  If you explicitly place the post id on the control, the user will be guided to rate a particular post.  If left as autodetermine (-2), the RatingSummary control attempt to read the post id from the url.  If it cannot, it returns -1 (invalid).

PostLink (string property):  The url to the post being rated.

PostType (PostType property):  Defaults to PostType.BlogPost.  The value of this property determines the text displayed to the user describing what they are rating.

Alignment (HorizontalAlign property):  Defaults to HorizontalAlign.Left.  Determines the alignment of the control.

Rated (bool readonly property):  Returns whether the particular post has been rated by the user.

Now, in order to get the control to work properly, you must make a few changes to the web.config file.  Within the <HandlerConfiguration/HttpHandlers /> node, add the following patterns (NOTE: see the previous post for further details on how to set these up properly if you have a multiple-blog site vs a single-blog site.  These tags are for a multiple-blog site):

   <HttpHandler pattern="^(?:/(\w|\s|\.)+/img/\d\.\d{2}/(?:Star|Dot|Bar)\.dspx)$" type="Devstone.Web.Blog.Controls.RatingHandlerFactory, Devstone.Web.Blog.Controls.Rating" handlerType="Factory" />
   <HttpHandler pattern="^(?:/(\w|\s|\.)+/rate/(?:Star|Dot|Bar)/[12345]/\d+\.dspx)$" type="Devstone.Web.Blog.Controls.RatingHandlerFactory, Devstone.Web.Blog.Controls.Rating" handlerType="Factory" />

Then add the following to the <appSettings /> section, substituting the proper values:

<!-- Devstone Settings -->
<add key="Devstone.DbConnectionString" value="..." />
<add key="Devstone.SendEmail" value="true" />
<add key="Devstone.SmtpServer" value="..." />
<add key="Devstone.Email" value="...
" />
<add key="Devstone.EmailSender" value="...
" />
<add key="Devstone.EmailSubjectHeader" value="Blog Rating" />

The following are examples as they might appear to enable a user to rate various post types:

Comments.ascx:

<devstone:ratingsummary runat=server alignment=right postType="Comment" postId="<%#((Dottext.Framework.Components.Entry)Container.DataItem).EntryID %>" visible=true />

Day.ascx:

<devstone:ratingsummary runat=server alignment=right postId="<%# ((Entry)Container.DataItem).EntryID %>" postLink="<%# ((Entry)Container.DataItem).Link %>" visible=true />

Download: RatingControl.zip

For more information, please see the previous posts:

Part I:  From Vague Concept to Less-Vague Concept
Part II:  Integrated with .Text

Have fun!

Friday, January 28, 2005 5:13:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, January 26, 2005
As others have noted, Megan Davis offers a great guide to running a utility called sysprep on virtual machines.  If you use Virtual Machines like I do (which is for just about everything), you'll not want to miss this!
Wednesday, January 26, 2005 3:31:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, January 23, 2005

I've often marvalled at this, but never really considered it or given it much thought.  As you may be aware, if you open up Sql Server's Enterprise Manager, connect to a remote database server and select 'New Database' it will allow you to designate the target location for the database (.mdf) and log (.ldf) files.  It displays a dialog box containing the drives and folders on the remote computer as though you were browsing the computer locally.

It does this even if you have no user access rights on the remote computer - Windows authentication is not required.  How does it do it?  I used to think it used some internal Sql Server magic.  Later I wondered if it might use WMI, but WMI would require you to authenticate to the remote machine to browse its directory structure.  You don't get a Windows token by logging in to a Sql Server as 'sa' ;)  Again, I didn't really consider it or give it much thought.

Well, as it turns out Sql Server has several extended stored procedures nestled neatly in the master database that the dialog uses to return a directory tree:  xp_availablemedia, xp_dirtree, et al.  The dialog is custom tailored to interpret the responses from these stored procedures and render a nice tree-view to the user.  Simply open a copy of Sql Profiler and monitor the SQL:BatchCompleted and you'll see all the calls to xp_dirtree.  This could be pretty helpful if you ever create a custom utility to creates databases on a remote computer without requiring the use of the Enterprise Manager.

I went through the trouble a while back to create one that utilized WMI to perform the same operation, but this would have been a heck of a lot easier and straightforward...I think I'm going to go back and retool a new one to use these instead.

Sunday, January 23, 2005 6:00:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback