Wednesday, April 30, 2008

A more robust way of converting a string to an enumerated value (enum)

A while back, I had blogged about a tip that Mark Wagner had posted about converting a string to an enumerated value.  Tim Sneath posted a similar tip even earlier, except his had some additional error logging.  Tim's post made it to DotNetKicks, which is good because having the additional error handling is just good coding practice. 

enum Sushi
{
Ika,
Hirameh,
Tako
}

// ...
Sushi lunch = (Sushi) Enum.Parse(typeof(Colour), "Tako", true);
Console.WriteLine("Sushi Value: {0}", lunch.ToString());

// To avoid an ArgumentException for strings that do have
// corresponding enumerate values, call Enum.IsDefined()
// first.

string NotSushi = "pizza";

if (Enum.IsDefined(typeof(Sushi), NotSushi))
{
lunch = (Sushi) Enum.Parse(typeof(Sushi), NotSushi, true);
}
else
{
// Add your error logic here
}

Mucho gracias to Tim & Mark...

Troubleshooting SQL Server connectivity issues

Xinwei Hong (MSFT) wrote a great troubleshooting guide on how to identify and resolve SQL Server connectivity issues on the SQL Protocols blog.

Xinwei broke it down to 6 possible causes:

  1. Network issue.
  2. SQL Server configuration issue.
  3. Firewall issue.
  4. Client driver issue.
  5. Application configuration issue.
  6. Authentication and logon issue.

For each cause. Xinwei lists some background on why that cause could a problem along with specific commands to run to help diagnose the problem.  For example, to determine if #2, SQL Server configuration issue, is the root cause of the problem; the following steps are listed:

You need to make sure the target SQL Server is running and is listening on appropriate protocols. You can use SQL Server Configuration Manager (SCM) to enable protocols on the server machine. SQL Server supports Shared Memory, Named Pipes, and TCP protocols (and VIA which needs special hardware and is rarely used). For remote connection, NP and/or TCP protocols must be enabled. Once you enabled protocols in SCM, please make sure restart the SQL Server.

 

You can open errorlog file to see if the server is successfully listening on any of the protocol. The location of errorlog file is usually under:

%ProgramFile%Microsoft SQL Server/MSSQLxx.xxx/MSSQL/Log

If the target SQL instance is a named instance, you also need to make sure SQL Browser is running on the target machine. If you are not able to access the remote SQL Server, please ask your admin to make sure all these happen.

 

This guide is definitely worth keeping bookmarked.  When a client calls and they can't connect to their database, having a list like the one Xinwei provide should make it easy to resolve the problem.  Or at the very least, rule out the usual suspects.

Tuesday, April 29, 2008

I just installed the PowerCommands for Visual Studio 2008

I just installed the PowerCommands 1.1 for Visual Studio 2008.  This is a set of extensions to the VS 2008 IDE that provide some additional functionality.  The available commands are listed here.  The Collapse Projects command sounds pretty basic, but it's something I've always wanted and it's great for large solutions. 

The best part of PowerCommands?  You get the source code, which would be handy if you ever want to write your own VS extension.

My "Windows Feedback" copy of Office 2007 Ultimate just came in

I just received a NFR copy of Microsoft Office 2007 Ultimate in the mail.  Last December, I signed up for the 2008 Microsoft Windows Feedback Program Sweepstakes.  This was a three month program run out of the Windows Feedback Program.  As part of the program, I installed some software on one of my home PC's that recorded some basic metrics such as Windows settings, hardware details, how the common document folders are being used, changes to the system, and problems that may occur.

This information was sent back to Microsoft to provide information on how our PC was being used.  In return for allowing MS to collect this data for 3 months, I was given a choice of several different products from Microsoft (Vista Ultimate, Office Ultimate, Money Plus Premium, Encarta Premium, or Streets and Trips).  I opted for Office 2007 Ultimate.  I didn't need another copy of Office right now, but it would handy the next time I get a new machine.   Apparently the response to this offer was so huge that Microsoft closed the program to new entrants after only a day or so.

In addition to the monitoring software, I was required to answer at least one survey during that time period.  Oddly enough, I was only prompted once during the 3 month period to answer a survey.  At this point, I'm no longer obligated to run the monitoring software and I haven't decided whether or not to uninstall it.  I'm not a big fan of monitoring software, but I'm not seeing any performance impact and I'm satisfied with the privacy issues with the data being sent back.  I know some people roaming the series of tubes were calling this spyware, but technically the WFP software isn't spyware.  Most definitions of spware define it as software that collects data or controls a computer surreptitiously and was installed without informed concept.  I knew what it was doing and I opted in, which means it's not spyware.  At most, Microsoft now knows how much time my kids spend at Webkinz World.

It would be nice to see what data was being sent back to the mothership, but if MS is following their own Terms of Use for this program, my privacy concerns have been satisfied.  This is in strong contrast to a program launched by Sears Holding Corp (SHC). at roughly the same time, where they wanted to install some software that would be a lot closer to the definition of spyware.  The software that Sears wanted to install was a web proxy from ComScore (never identified as such by Sears) that would track all of your web usage and sent that data to Sears.

The software used by SHC is a web proxy program supplied by Comscore.  It redirects all of your web browser activity through the Comscore software and that data can be sent to Sears.  SHC notifies the user that the user is about to install some software, but it does not go into full detail about what data is being collected and what is being sent to Sears.  At no point during the installation process or preliminary email is the software identified or it's functionality  described.  A person with computer security experience would realize what is going on, but the average computer user would have no idea what they just installed.

With the security breaches on Sears web site earlier this year, I would be very hesitant with letting Sears have access to my personal information.  I understand why Sears would want to know what I shop for online, and I don't mind sharing that information.   Sears has no business knowing how I pay for those items and has no business viewing my email.  Comscore's tracking software would monitor all of that.  All privacy issues aside, that's a horribly inefficient means of tracking online shopping.

It also looks a little funny that the guy in charge of this program, Rob Harles, was a former senior vice president at Comscore.  Comscore is the vendor for the tracking software that the SHC wants to install. Ben Edelman, assistant professor at the Harvard Business School who focuses on spyware practices, did a great write up about the SHC sofware.  He documented in clear detail (with screenshots and video) that the installation steps violate FTC guidelines.  If you Google for Sears & spyware, you'll get close to a quarter of million hits.  That's not what you call good publicity, but I digress.  When I participate any sort of consumer feedback program, I take a close look at what would be installed and what will be collected.  I also check to make sure that the company collecting the data is collecting the right data and will respect my privacy.  Microsoft met those concerns.

Friday, April 25, 2008

How to identify who has a terminal session and how to kill it

Having the ability to use a terminal service (aka Remote Desktop) session to manage a Windows Server (2000, 2003, and 2008) is very useful.  If you don't have a Terminal Services license installed, you are limited to to two active sessions (plus a bonus connection that I'll get to in a minute).  If a person disconnects from a session without logging out, it can leave that session running.  That allows you to start a long running task and come back to it later, but it does use up one of the available connections.  If both sessions are being used, you will not be able to create a new terminal service connection to the server.  At this point, you have three options:

Yell down the hallway and ask "Who has a connection to server XYZ".  This never works because either the person who left the connect forgot about it or didn't realize that he (or she) was supposed to logout.  The other problem is that you could be working from home and the only thing that the yelling accomplishes will be to attract your dog and your child, both of which will be looking for cookies.

Use the command line tools to identify the open sessions and kill one of them.  There are two tools, qwinsta and rwinsta.  If you run "qwinsta /?" from a command shell, you will get the following:

qwinsta /?
Display information about Terminal Sessions.
QUERY SESSION [sessionname | username | sessionid]
              [/SERVER:servername] [/MODE] [/FLOW] [/CONNECT] [/COUNTER]
  sessionname         Identifies the session named sessionname.
  username            Identifies the session with user username.
  sessionid           Identifies the session with ID sessionid.
  /SERVER:servername  The server to be queried (default is current).
  /MODE               Display current line settings.
  /FLOW               Display current flow control settings.
  /CONNECT            Display current connect settings.
  /COUNTER            Display current Terminal Services counters information.

                                


If you run "rwinsta /?", you get the following:


rwinsta /?
Reset the session subsytem hardware and software to known initial values.

RESET SESSION {sessionname | sessionid} [/SERVER:servername] [/V]

  sessionname         Identifies the session with name sessionname.
  sessionid           Identifies the session with ID sessionid.
  /SERVER:servername  The server containing the session (default is current).
  /V                  Display additional information.



For the sample server XYZ, you would run "qwinsta /server:xyz"  That will return something like:


 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
console                                     0  Conn    wdcon
rdp-tcp                                 65536  Listen  rdpwd
                   gatesb                    1  Disc    rdpwd
rdp-tcp#93        jobss                    3  Active  rdpwd


From that output, we can take one of the IDs that was returned for the remote sessions and use rwinsta to kill that session.  You would use something like:


rwinsta 1 /SERVER:xyz


And that will terminate that session, allowing you to open a new session.  You will need admin rights to run that command, but if you are using the admin terminal service connections to the server, then you would already have the necessary access rights to the server.


There is a third option, you can connect to the console session.  This is the bonus option that I had referred to earlier.  This is the session that you would get if you were physically in front of the server and were logging in on the server's mouse and keyboard.  You can specify the console session as a command line parameter to the remote desktop client, mstsc.exe.  The following syntax can be used to connect to the console session of a server:


mstsc /console

That feature will work with Server 2003 and later.  On some machines, qwinsta and rwinsta may have been renamed to query.exe and reset.exe, respectively.


[Updated at 2:42 pm]
Steve listed an alternative to qwinsta and rwinsta on his blog.  He uses quser.exe and logoff.exe, which provide pretty much the same functionality.  On my machine, quser.exe was buried in c:\windows\system32\dllcache, which was odd.  I wonder why it wasn't in system32?  quser has an advantage over qwinsta, it lists the logon time and idle time for each session.  That gives you a little more data when you have to kill someone session and you can't determine which one must die.

Saturday, April 19, 2008

System Restore and Vista

After reading the comments posted to my blog entries for USB issues caused by KB938371, I can't over emphasis how valuable it is to have System Restore enabled.  While trying to find a work around for the mouse problems that I reported here, here, here, and starting at here; I noted that a few of the people who had posted responses or had sent private email did not have System Restore available.

I was surprised by that as System Restore is enabled in all SKU's of Vista by default and it's greatly improved over the System Restore feature in XP.  If you are not familiar with System Restore, I'm going to borrow the following from the Wikipedia entry

it's a feature that periodically takes a snaphot of the current state of the operating system, typically referred to as a restore point.  Windows uses Shadow Copy (aka Volume Snapshot Service or Previous version) to create a file that contains system files, registry settings, drivers, installed programs and stores the data in a single compressed file.  User settings and files are typically not covered.

This restore point will be generated under the following conditions:

  • when a piece of software is installed
  • when Windows Update installs new updates to Windows
  • when the user installs a driver that is not digitally signed by Windows Hardware Quality Labs
  • every 24 hours of computer use , or every 24 hours of calendar time, whichever happens first
  • when the operating system starts after being off for more than 24 hours
  • when the user requests it.

When Windows Update pushed KB983371 down to my machine, System Restore created a restore point of the current state of the OS just prior to the installation.  This allowed me to easily roll back the installation of the update.  Since 938371 does not allow itself to be uninstalled, roll back the system via System Update was the only documented way of removing 938371, short of reinstalling Vista.

If for some reason you have disabled System Restore, you really should consider turning it back on.  I have seen a few sites mention how to turn it off (but for the most part they do warn you of the consequences), but you really want to leave it on.  I have had to use System Restore a couple of times and it really got me out of jam.  If you need to re-enable System Restore, the following steps should work for you:

  1. Click on the Start button.
  2. Right click on "Computer" ,and then select Properties. (Also reachable as the "System" applet on the Control Panel.
  3. On the left hand side of the Control panel->System dialog, click Advanced Settings.  If the User Access Control dialog rears it's ugly head and propmtps you to permit the action, click on Continue (or OK) to allow you to continue.
  4. Click on the System Protection tab.
  5. In the group box labeled "Automatic Restore Points", check the checkboxes listed for your hard drives.  Some PC's come with special partitions used for vendor specific diagnostic and restore functionality (Dell PC's typically have a special partition labeled "RECOVERY", leave those partitions unchecked.
  6. Press OK to save the changes.

There's rarely a free lunch in this business, and there is a cost to using System Restore.  This cost is pretty simple, it will use up to 15% of the space on the drive, with 300MB as a minimum.  You also need to have a drive larger than 1GB to use System Restore.  With the huge drives now available to today, the benefit clearly out weighs the cost.

Friday, April 18, 2008

Dealing with the "Cannot generate SSPI context" error message

One of our sales engineers came up to me with with a problem that I had not come across before.  He was getting the error "Cannot generate SSPI context" when he tried to back up a database. Before getting too deep into the problem, I'll lay out the background of how the problem occurred.

Our applications work with SQL Server 2000 and 2005.  Our desktop applications have the ability to back up the SQL Server database and store the backup on the local machine.  The backup command is issued to the database server, typically on it's own server.  The account that SQL Server runs under typically can only access the local file systems.  You can get around that by running SQL Server under an account with network access, but as a shrink wrapped application, we want to under the default installation of SQL Server.

To get around the file system access, I wrote a win32 service that runs on the same machine as SQL Server.  Our applications back up the database through my agent service.  When the agent receives a backup request from a client, it does the following:

  1. Performs some preventative maintenance on the database
  2. Defragments the log file
  3. Backs up the database to local path
  4. Compresses the database backup to a .zip file
  5. Sends the compressed backup to the client
  6. Deletes the backup and compressed backup from the server.

It does a few other things, but those steps are the highlights of the backup process.  Our engineer was getting the "Cannot generate SSPI context" error right at step one.  I have never come across that error so it was time to fire up Google and go searching.  One of the top hits for goggling that error message was a KB article, 811889.  It was informative, but not especially helpful for me.  The top hit was much more helpful, “Cannot generate SSPI context” error message, when connect to local SQL Server outside domain, on the SQL Protocols blog.  Who knew that SQL Protocols had it's own blog.  This post had all of the good details of what was happening and suggestions on how to resolve it.  I like that.

In short that error can occur when all of the following are true:

  1. The hosting machine of SQL Server is connected to a network, including home network or dialup connection, but it is disconnected from its domain.
  2. The OS of the hosting machine is Windows XP or 2000. Not windows 2003.
  3. The connection is to a local SQL Server.
  4. Connection configuration causes network library to choose TCP/IP provider.

The root cause is that agent service is using integrated security to connect to the local server over TCP/IP.  The SSPI in the error message stands for Security Support Provider Interface.  SSPI is a set of Windows API that handle delegation and authentication over data transport layers (TCP, Named Pipes, etc).  With TCP/IP and SSPI, the Kerberos protocol is used to authenticate the user account.  This will attempt to access the Active Directory services of the domain that the user is logged into.  If that domain is not accessible, the authentication attempt will fail.  This check will only occur if SSPI detects that it is on a network.  If it's not on a network, it will use NTLM, which for our situation will work just fine.

In our case, the engineer has a laptop and he logs into it with a domain account.  If he's demoing the products at a clients site, he may have a network connection, but not be connected to our domain.  The immediate work around was for him to close his network connection and do his backup.  Literally all he needed to do was to press a button on his laptop to turn off his wireless adapter.

The long term solution will be for me to change conditions #3 or #4.  The code is currently hard coded to connect to a sever named "(local)", I may try replacing that with the TCP/IP loopback address 127.0.0.1.  If that doesn't work, I add a setting that allows the agent service to connect with the Shared Memory or Named Pipes providers.

Looking forward to stackoverflow

Not an actual stack overflow, but the new site, stackoverflow.com, run by Jeff Atwood and Joel Spolsky.  Their aim is to provide some sort of programming Q&A site.  Accurate and up to date information that's easy to find by having programmers ask questions and other programmers answer them.  I hope that they can pull it off.  My usual method of learning something programming related is by what Joel referred to as "page-fault" learning.  I start out with a Google or forum search, get the basics, and start implementing until I hit an error or a mental block.  Then I jump back on the Intertubes to research a little deeper.

I'm so tired of hitting Experts-exchange when I google a topic.  So much that I'll specifically exclude it from my Google searches by tacking on  "-site:www.experts-exchange.com" to the search string.  There's something about that site that just rubs me the wrong way.  it's like "We'll tease you with the question, now pay up for the answer".  And you'll have no way of knowing if the answer is correct or applicable to your need until after you have paid them.  No sir, I don't like it.

Right now, the only thing up on the site is a podcast of a conversation between Jeff and Joel.  I've been listening to it and it's pretty good.  I can't wait for the site to take form and I hope to be able to contribute to it in some small form.

Thursday, April 17, 2008

There's no privacy with infant video monitors

We still have a video baby monitor on our youngest, Laura.  She's 5, but we never got around to taking it down.  At bedtime, Laura and her older sister Kathryn will perform for each other in front of the camera while the other one is watching the monitor.

Last night when the girls went to bed, I turned on the monitor.  All I could see was static and some form of interference. The camera to monitor connection is wireless.  You can pick one of two channels and fiddle around with the antenna, but that's about it.  It's very much like watching TV on a B&W portable, circa 1976.

As I fiddled around with the antenna, the view on Laura's room disappeared and I could see an infant lying in a bed with a pacifier in his mouth.  I called out to my wife, "Look, they canceled the Laura Show and replaced it with a new one."  We think this baby is our next door neighbor's baby.  They just had a baby boy a couple of months ago.  I'm going to over and talk to them on the weekend and let him know that we are picking up their video signal.

For now, we have stopped using the monitor.  Laura is will past the age of needing a monitor, and it feels too much like voyeurism to be watching and listening to someone else's baby.  

Wednesday, April 16, 2008

Handy tip for debugging a Windows Service

Debugging a Windows Service is always a pain. You can't run a service like a regular application, you have to run it from Windows Service Control Manager (SCM) and then have your debugger attach to the process while it's running. The problem is that it's difficult to debug problems with the service startup as the debugger can't attach to the service in time.

I came across a tip on the .NET Tip of The Day site, "How to debug Windows Service startup". Basically, you just add a line that calls Debugger.Launch() or Debugger.Break() in your startup code. When your code hits one of those lines, the Visual Studio Just-In-Time Debugger dialog will be invoked and you can select your debugger to handle the error. That will allow you to continue along in the code and debug until the cows come home.

That works better than a service debugging tip I posted a couple of years back, calling the Sleep API in your startup code to allow enough time to attach a debugger to the service. That was a hack, this is much cleaner.

All in all, I still prefer to separate the functional code from the service specific code. I can then run that code from a desktop app, making it much easier to debug. That works about 99.9% of time. Every now and then, I do need to run the actual service code and the Debugger.XXXX() calls will make that task much easier.

Microsoft admits that KB 938371 kills USB Devices

Various reports on the Intertubes are reporting that Microsoft has acknowledge that last weeks Vista Update, 938371, has been causing "problems" with USB devices.  The money quote:

“We are aware of concerns that a recent Microsoft update may be causing problems with USB devices. We are investigating the matter, and at this time, do not have any information to share.”

Supposedly this was an update to fix a security hole in Windows Defender.  Read about more people hit by 938371 in MS's own forums.

This is starting to feel like an endless series of misadventures with 938371.  See Work around for KB938371 disabling HID-compliant input devices , KB 938371 woes continue and the first post, Vista update KB938371 disabled my mouse.

I just want to know when a permanent fix will be available.  Come on Microsoft, there is enough people reporting this problem that you should be able to reach out for more information to help diagnose and fix this problem.

Know your SQL Server version

There are times where you need to know what version of SQL Server is installed.  Usually you want to know which version and which service pack has been applied.  There have been a few isolated cases over the years where we saw bugs go away or significant performance boosts by merely installing the latest service pack.  It's less of an issue with 2005, but with SQL Server 2000, we wanted to make sure the user installed the latest service packs to block against stuff like the "Slammer" worm.

The following bit of T-SQL will send back the version information in easy to process pieces

SELECT SERVERPROPERTY('productversion') AS ProductVersion, SERVERPROPERTY ('productlevel') AS ProductLevel, SERVERPROPERTY ('edition') AS Edition

For SQL Server 2005, you could get back something like this:

ProductVersion  ProductLevel  Edition
--------------- ------------- ----------------
9.00.2047.00    SP1           Standard Edition

Which indicates the Standard Edition of SQL Server 2005, with Service Pack 1 installed.  You can also get most of that information with


select @@version


But you would have to parse out the version from a block of text like this:

----------------------------------------------------------------------
Microsoft SQL Server 2005 - 9.00.2047.00 (Intel X86)
Apr 14 2006 01:12:25
Copyright (c) 1988-2005 Microsoft Corporation
Standard Edition on Windows NT 5.2 (Build 3790: Service Pack 2)

Using SERVERPROPERTY (2000, 2005 or 2008) is much easier than parsing that block of text.  To determine which version is running based just on the version number, Microsoft has a KB article that lists all of the releases under KB321185.

Sunday, April 13, 2008

Work around for KB938371 disabling HID-compliant input devices

After a few days of non-working mice, someone found a work around for KB938371. As I noted here and here, Vista Update 938371 disabled two the three mice I have I on my main home machine. Here's the work around that actually worked for me:

  • Just go to device manager -> HID-devices -> Unknown Device and search for drivers.
  • When prompted for how to search for driver software, select "Browse my computer for driver software"
  • Enter "C:\windows\winsxs" for the driver location and press the "Next" button.
  • If you get a popup saying "this is an unsigned driver...", just allow Windows to install the driver.

At this point, Windows should select the appropriate driver and your mouse will start working again.  When I tried this, only had one of the non-working mice plugged in.  When I followed those steps, the mouse started working.  I plugged the other mouse in and Windows enabled it without any prompting.

I went in to Device Manage and both mice were listed as "HID-compliant mouse" under "Mice and other pointing devices".  Just to be safe, I selected one the mice, right-clicked into "Properties, selected the "Driver" tab on the dialog that opened up.  I clicked the "Driver Details" button and the mouse was using mouclass.sys and mouhid.sys drivers, located in c:\windows\system32\drivers, which is what they were supposed to be using.

This tip was originally posted here and I came across it here.  I'm happy that I have my mouse functionality back, but how did this get past Microsoft's testing?  I saw too many people reporting this, it's not an isolated case.  I have a mouse that comes with my Wacom table that wasn't affected by this snafu, but what about the people who just had regular USB mice?  They were/are pretty much screwed by an update that can't be uninstalled with running System Restore. 

I still want to know what happened and why 938371 toasted my HID-compliant hardware.  Was there something broken already with my Vista installation and 938371 was just a symptom of the problem, or did 938371 actually break something?

I'm not allowing MS to automatically update my PC anymore.  That requires a certain level of trust that MS is going to push down updates that will be beneficial.  They just blew that trust.  I'll take the updates, but I'm going to decide if and when they get installed.

I was asked offline why I have three mice.  It's pretty simple (almost makes sense).  My day to day mouse is a Logitech MX™700.  It's a cordless mouse that uses rechargeable batteries.  It's been the best mouse that I have ever used and I continue to use it under Vista even though Logitech never ported the MX700 drivers to Vista.  It has a little dock that charges the batteries.  I almost always forget to put the mouse back in it's dock and a every few days, the batteries give out.  When that happens, I place it back in it's dock and use a Dell USB optical mouse while the MX700 is charging.   The third mouse is a digitizer mouse that comes with my Wacom Bamboo Fun tablet.  That mouse works, but only on it's little pad.  It was OK enough to use while tracking down this problem, but I wouldn't want it to be my everyday mouse.

Update: 2/22/2010
I repaved this machine with Windows 7 about 6 months ago and replaced the MX700 with a Logitech mouse that is supported under Windows 7.  For anyone that is still having this problem, consider Windows 7.  It’s much nicer than Vista.

Friday, April 11, 2008

KB 938371 woes continue

I still haven't been able to fix the problem that I reported yesterday.  After blogging about how Vista update KB 938371 disabled the mouse on my PC, I have found other people reporting the same problem.  The mouse shows up in the Device Manage as "unknown device".  If I try to install a device driver for it, it fails with the error dialog "Found New Hardware - Unknown Device) and displaying the following text:


Windows encountered a problem installing the driver software for your device

Windows found driver software for your device but encountered an error while attempting to install it.

     HID-compliant device


An error occurred during the installation of the device

The driver installation file for this device is missing a necessary entry.  This may because the INF was written for Windows 95 or later.  Contact your hardware vendor.

This occurs with any USB port on my machine and with both of my mice.  I have a Logitech wireless mouse and a basic Dell USB Optical mouse.  I have a mouse with my Wacom tablet that still works.  It has it's own drivers and MS didn't touch them.  I even took the Microsoft Optical mouse off my wife's Vista machine (which is working fine with 938371) and plugged into my machine.  It didn't work either.

If I do a System Restore and rollback to the point just before 938371 was installed, the mice work.  As soon as I install 938371, I lose the mice. This is really frustrating as 938371 is a prerequisite for SP1.

I've been posting this tale on a new message boards and blogs.  I'm not the only person having the problem, but we have yet to identify what we have in common that is triggering this.  My machine is running Vista Home Premium, 32-bit, on an ASUS M2N-SLI Deluxe motherboard. The M2N is NVidia NForce based and I have an AMD Athlon X2 processor in it.  You can read about other peoples symptoms in this MSDN Forum thread,  this thread I started on an NVidia fan site, and a message that I posed in the Windows Vista Blog.

Thursday, April 10, 2008

Vista update KB938371 disabled my mouse

Windows Update just pushed down an update, KB938371 on to my main home PC, as a prerequisite for Vista Service Pack 1.  After that update was installed and Vista rebooted, I lost all mouse functionality.  The only way I could get mouse functionality back was to run System Restore and restore the OS to the point to just before 938371 was installed.  For me, selecting the recommended restore point was as far back as I needed to go.

I have installed 938371 twice now by itself, each time I lose mouse function.  My machine was custom built for Visa Home Premium, but it uses a pretty standard motherboard, an ASUS M2N-SLI Deluxe, which uses the NVidia NForce chipset.  I have a Logitech MX™700, which uses the Vista input drivers and mouse that comes with the Wacom Bamboo Fun tablet, which has it's own Vista drivers.  I also have Dell USB mouse which I use when I'm recharging the batteries in the MX700.  None of them worked after 938371 was installed.  I think it would be a fair assumption that other features are broken, but I didn't bother to check.  The machine was unusable without a working pointing device, I concentrated my efforts on rolling back 938371.

938371 is an non-removable update.  It wont show up in the "Uninstall or change a program" list under "Control Panel\Programs and Features".  System Restore is the only way that I know to yank it out.  I don't think I'm only one having this problem.  I posted a message about this on an NVidia enthusiasts board and saw an immediate reply on this blog as a comment to a non-related post.

Service Pack 1 for Vista is out now and it requires 938371 as a  prerequisite.  Which means I can't install SP1 without running a mouse killing update.  I'm trying to decide if I can install SP1 and hope for the best.  If it fails, I'm without a pointing device and makes Windows somewhat less than usuable.  I would prefer to resolve 938371 before installing anything else.  The advantage of trying SP1 would be that Microsoft is providing free support for SP1 and this is definitely a SP1 support issue.

This could be the final straw that pushes me back Windows XP.  After using Vista for nearly a year, I'm tempted to repave with XP.  I have another Vista box at home that the family shares.  It's a Dell and while it has less functionality (my box has RAID 5), it has had any of the weird Vista problems that this machine has had.  I do wonder how many other people have had their mice disabled by this update.  If we can discover what we have in common, we get closer to determining what the root cause is and what fix there may be.

[Updated on 4/17/08]
If this is your first visit to my blog, please read this post for a work around that may work for you.

Monday, April 07, 2008

Fun with CoInitialize

I was tracking down a error in one of the command line apps that I use to save web.config settings over upgrades.  It was a strange error, If I stepped through the code, everything executed correctly, but I would get an access violation when I left a specific method call.  The fun part was that all of the code in that method call executed normally.  The app is written in Delphi 2007 and is Win32 unmanaged code.  The code looked something like this:

function TSaveConfig.UpdateWebConfig(const srcfile, destfile: string): boolean;
var
fsrcDoc, fDestDoc: IXMLDocument;
begin
CoInitialize(nil);

result := true;

fsrcDoc := LoadXMLDocument(srcFile);
fDestDoc := LoadXMLDocument(DestFile);

UpdateNode(fsrcDoc, fDestDoc, 'configuration\system.web\httpRuntime', 'executionTimeout', '', '');
UpdateNode(fsrcDoc, fDestDoc, 'configuration\system.web\sessionState', 'timeout', '', '');

if fDestdoc.Modified then begin
fDestdoc.SaveToFile(DestFile);
end;

CoUninitialize;
end;



Not much to it.  My Spidey sense started tingling at the calls to CoInitialize/CoUninitialize.  CoInitialize is needed to initialize the COM library on the current thread.  And COM is needed because I am using MS XML COM objects to work with the web.config files.  I was initializing COM, using COM, then uninitializing COM.  The problem was that I was using interfaces to the COM objects and Delphi is managing the lifetime of interfaces.  At the end of the method call, those objects go out of scope and Delphi calls their cleanup code.  In my case this happens after the the call to CoUninitialize.  My IXMLDocument interfaces were being garbage collected by the Delphi runtime and they were referencing a COM library that had been already closed.


In this case, the fix was easy.  I just moved the calls to CoInitialize/CoUninitialize to the code that calls UpdateWebConfig.  Once I did that, my odd little access violation was fixed.  That's one of those bugs that seems obvious after you fix it.  What clued me in to what was going on was a post by Chris Bensen that explained it all.  Thanks Chris!

Thursday, April 03, 2008

Wireshark reaches 1.0

Image:Wireshark Icon.svg

It looks like Wireshark has made it to version 1.0.  Wireshark has been my favorite tool for diagnosing TCP problems in the socket code that I have worked on.  I've been using it since it used to be called Ethereal®.  Wireshark is a free an open source packet sniffer.  If you are trying to see what is coming over the wire, you want this tool whether you are running Windows, Unix, Linux. or Mac.

Tuesday, April 01, 2008

Saving application settings over installs

We have been using Windows Installer (WI) based setups for all of our newer applications.  I used to use Wise, but I have migrated our installers to InstallAware.  Why I made that change will be another blog post, but needless to say I had very good reasons to make the switch.  When we release a new version or upgrade for one of our applications, we do full installs.  We don't do patches.

WI technology supports the distribution of patch files.  If you are only updating one or two files, the patch file will only contain what has changed, greatly reducing the size of the installable bits needed to be distributed.  I did use patch files when I first started doing WI based setups, but I abandoned the practice early on.  Patches were hard to automate as part of the build process and they had to account for cumulative changes.  The other drawback was that they could add files, but not remove them.  Another drawback was that it yet another file extension, .msp instead of .msi, to explain to the users.

I decide to have the installers upgrade in place. When a new version was installed over a previous version, the previous version would be silently uninstalled, then the new version would be installed.  This basically gives you a clean slate per install, which is great because you only install the files that are needed and the dependant objects will be up to date.  The bad part is that the user settings will be removed as part of the previous versions uninstall.

What I needed to do was to persist the user defined settings.  Consider a web application, if all of the settings are in the web.config file, then you just need to keep that web.config file around.  The simple solution is to tell the installer not to delete that file on the uninstall.  There's a couple of problems with that approach.  The first one is that the new install is a full install and the user gets to pick the destination.  They may want to put the web application in a different folder or drive and I didn't want to take that option away just to make my job easier.

The other drawback was far more serious.  I could keep the web.config around between installs, but what if the new version added content to the web.config file?  You don't want to save the old settings and lose the new settings.  That could cause hard to diagnose bad things to happen.   What was needed was the ability to merge selected content from the old web.confile and into the new web.config.  You can do many things with WI technology and InstallAware provides powerful functions, but this is a task best left outside the installer code.

I decided to write a Win32 command line app that would be able to save the old web.config and merge selected values from that file into the new one.  The installer would be include that file and be able to run it without permanently installing it.  I could have used C# with .NET (and I even had most of the code already written), but I didn't want to deal with .NET security issues or make the .NET Framework a prerequisite for non .NET based installs.  Delphi 2007 provided everything that I needed.

From the installer, I call this app just before the previous version is uninstalled with a command line parameter to designate which app is being installed.  It will locate the current web.config file for that application and copy it to a folder in the user's temp directory.  I always have our installers write the location of the install folder to the registry, it makes tasks like this much simpler.  After the new version has been installed, I run the app one more time, with a "-restore" command line parameter.  It locates the cached copy of the old web.config and the new web.config and updates the new web.config file with the settings that need to be persisted across installs.  Once that task is complete, it removes that temporary folder.

The app knows what settings to use from rules encoded into the source code.  I could have used a file to store a list of settings to persist, but that would have made the installer a bit more complicated.  It's fairly easy to run an app from the installer without actually installing it, but if you want it to have it read an external file, then you need to make sure that file is in a place where it can be read from.  That comes one more part of the installer to be tested and the mechanism for handling that would be specific to installer tool used.  By making the app contain the rules it needed to follow, running it from the installer becomes a trivial task.

The other advantage of having a separate app to handle to the saving of the user settings is that the code is much easier to test and debug.   It becomes a modular piece of the install and can even be unit tested in a scriptable manner.  This type of code can be easily adapted to the types of application.  I use a similar type of program to persist settings and current run start for some of our Win32 service applications.