Thursday, March 18, 2010

Managing multiple configurations using Virtual PC

We use Virtual PC extensively for testing in our lab. We have about 12 different configurations for each version of Windows we test. We've spent a lot of time learning how to create these configurations so that they work reliably and to create a reasonable balance between updates of individual configurations versus a global rebuild as the security updates and service packs pile up.

This blog entry describes how we create the VHDs and configure them in Virtual PC.

Layer Overview

Our VHD tree is built based on a set of defined layers. Layer 1 is comprised of single root VHD for each version of Windows, such as WinXP SP3. Layer 2 is built from differencing VHDs that use the root VHD as the parent. This means that the root VHD needs to be configured as far as possible, without requiring lower layer VHDs have to "undo" any configuration. Here is the VHD structure we use:

1. Root VHD - Contains base Windows install and common configurations
2. Configuration specific VHD - Includes apps, service packs, etc. that are different from the root. This is where configuration-dependent changes are done.
3. Working VHD - Includes temporary changes that are used over the course of several tests.
4. Undo file.

Layers are defined by how often they are changed, because when a layer changes, everything underneath it is invalidated. Layer 1 changes every six to eighteen months, usually when the number of security updates becomes overwhelming. Layer 2 changes every few months. Layer 3 is only used when a customized configuration needs to be tested for several days (or when you hit the wrong button and say "commit change.) Layer 4 changes on a minute to minute basis. It is discarded whenever a user selects "Discard changes" when a VPC is closed.

Roadblocks

Creating the VHD hierarchy is tricky. There are several problems we've seen that must be solved by making the changes in the correct order in the correct order. Some of these problems include:
  • Duplicate Ethernet MAC addresses.
  • Duplicate computer names.
  • Domain disconnects.
  • Accidental overwriting of a parent vhd file.
  • Windows Update automatically overwriting desired configurations.
The MAC address will be updated automatically by Virtual PC as long as you create a new .vmc file from the menu. In other words, use the New Virtual Machine Wizard, don't make a copy of your existing .vmc file. If you insist on copying your .vmc file, you can manually remove the MAC address from the XML file and it will automatically be recreated.
Many people are also concerned about "SID duplication" and want to use something like NewSID or SysPrep. Recent reports indicate that this is no longer a concern. Please see NewSID Retirement and the Machine SID Duplication Myth.

Create the Layer 1 Root VPC

The first task in creating the hierarchy is to create the Layer 1 VHD, which contains the OS install and will be common to all dependent virtual machines.
  1. Create the .vhd file using the Disk Wizard. Set to dynamic size, 20 to 32GB is usually a good size.
  2. Create the Virtual PC .vmc using the New Virtual Machine Wizard under the File menu. Make sure you give it enough RAM, the defaults are almost always too small.
  3. Install Windows. Install a version of Windows that includes the desired service pack. Set the system name to be something like RootWinXp so you know when you've forgotten to change it. Do not join a domain during installation.
  4. Log in as an Administrator and activate Windows, if necessary. Don't do this in a child virtual machine or you'll need an additional activation key for every child.
  5. Shut down Windows and make a backup of the VHD. Name it "Level 1 - Clean" This is a "clean machine" that's been activated. Use this VHD to create completely new configuration hierarchies.

Configure the Layer 1 Root VPC

  1. Boot the virtual machine.
  2. Install the Virtual PC Additions.
  3. Set the vpc to be part of workgroup, if it's not already. Do NOT join the root vhd to a domain! That must be done in a lower layer.
  4. Install desired Windows service pack, if any.
  5. For Windows XP, go to Windows Update in Internet Explorer and enable Microsoft Update.
  6. Install latest security updates through Windows Update. Pay attention to the following:
    • For Windows XP, go to Windows Update in Internet Explorer and check High Priority and Optional updates. The task bar "Update" icon does not show these updates.
    • Under Optional, I recommend you install Update for Root Certificates.
    • Also under Optional, install Microsoft .NET Framework, if needed.
    • Windows Update may automatically upgrade Internet Explorer if you don't do a "Custom" update and uncheck Internet Explorer. OTOH, IE8 for Windows XP is under Optional.
    • After each reboot, go back to Windows Update and check again. You'll probably need to run through Windows Update several times to get all updates.
  7. In Control Panel, set Automatic Updates to "Notify me", not to automatically download or to automatically install. Otherwise you end up fighting Windows Update every time you boot a configuration.
  8. Disable the requirement for Ctrl-Alt-Del. This can save a lot of mousing around when running the virtual PC in a window. For Windows XP, this can be found under Control Panel / User Accounts / Advanced (or use Group Policy.)
  9. Create any desired local users (as opposed to domain users.) Make sure you set them as Admin or Limited, appropriately. At a minimum, I recommend creating a "Limited" user for testing.
  10. Disable the Internet Connection Wizard if you have Windows XP virtual machines. In Group Policy, it's under User Configuration\Administrative Templates\Windows Components\Internet Explorer\Internet Settings\Advanced Settings\Internet Connection Wizard\
  11. Set firewall exceptions in Control Panel | Windows Firewall | Exceptions:
    • File and Printer Sharing must be enabled to allow access the system by name on the network.
    • Remote Desktop must be enabled to access the system remotely.
  12. If desired, enable Remote Desktop under My Computer | Properties | Remote. Note that Remote Desktop is not supported in any of the "Home" versions of Windows. Local Administrators will automatically have rights to access the system via Remote Desktop.
  13. If you use Remote Debugging in Visual Studio, start up MSVCMON.EXE and tell it unblock the firewall for your subnet. You will discover that this adds numerous exceptions to the firewall. MSVCMON.EXE can be found in:

    C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\Remote Debugger\x86\msvsmon.exe
  14. Modify options in My Computer | Tools | Folder Options | View, such as "Display the contents of system folders", "Show hidden files and folders", "Hide extensions", and Hide protected operating system files". This can also be done in the domain logon script with:

    reg add hkcu\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v Hidden /t REG_DWORD /d 1 /f

    reg add hkcu\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v HideFileExt /t REG_DWORD /d 0 /f

    reg add hkcu\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v WebViewBarricade /t REG_DWORD /d 1 /f
  15. Share any desired folders.
  16. Shut down the root vpc using the "Shutdown" from the Start menu.
  17. Commit all changes if you are using Undo disks.
  18. Set the VHD to be read-only.
  19. Create a backup of the file. Name it "Level 1 - Common".
  20. Optionally, go to the Virtual PC Console and remove this virtual machine so you don't accidently try to use it. If you don't delete it, make sure you enable Undo disks so you don't accidentally change it (Virtual PC will helpfully remove the read-only attribute.)

Create a Layer 2 VPC

  1. Use disk wizard to create a differencing hard disk to the root.
  2. Make a backup of this vhd file. Name it "Level 2 - Empty".
  3. Create the Virtual PC .vmc using the menus. Again, make sure you give it enough RAM. Turn off Undo for now.
  4. Boot the new virtual PC.
  5. Log in as an adminstrator.
  6. Change the system name.
  7. Join a domain, if desired. This can be done from the command line with the NetDom command, which is available in the Windows XP Support Tools. (This should all be on one line.)

    netdom join myvpc /domain:test.com
    /userd:Administrator
    /passwordd:<domain admin password>
  8. Give any desired domain users or groups permission to login via Remote Desktop.
  9. Log in as any domain users you plan to use frequently. This does the one-time configuration of the VPC for that user. Change Folder Options again for these users.
  10. Install any configuration-dependent software.
  11. Install updates and service packs for the software you just installed.
  12. Map network shares with a domain logon script. If a computer on a domain must map a drive on a non-domain computer, make sure the non-domain computer has an account with the same name and password as the domain computer. Alternatively, you use this command to save the username/password on the domain computer, then say "net use x: \\acme\share" in the domain logon script.

    net use x: \\acme\share
    /savecred /persistent:yes
  13. Check Windows Update one more time. On Vista and Windows 7, make sure you explicitly tell it to check again.
  14. Once everything is configured to your satisfaction, shut down Windows from the Start menu so it shuts down cleanly.
  15. Set the VHD to be read-only.
  16. Create a backup of the file. Name it "Level 2 - Configured".

Create a Layer 3 VPC

  1. Create a third vhd, differencing, whose parent is the vhd you just set to be read-only. I normally name it the same as the parent with the word "Child" appended. This is what I called the "Working VHD" earlier in this document. You will use this when you need to reuse a configuration a few times, then discard the configuration. Normally this vhd is empty.
  2. Change the settings in Virtual PC for your virtual machine to point to this working file.
  3. Enable Undo for this vhd.
  4. Backup this third VHD. Label it "Level 3 - Empty". You'll need the backup whenever you discard your current working configuration.
At this point you should have five backup files. The files labeled "Empty" in the below should be small, between 44KB and 106KB:
  • Level 1 - Clean root VHD, with a clean Windows install.
  • Level 1 - Configured root VHD, with a mostly configured Windows install.
  • Level 2 - Empty configuration VHD, which is an empty differencing disk whose parent is the Level 1 vhd.
  • Level 2 - Configured VHD, which is your fully configured test environment.
  • Level 3 - Empty VHD.

Create Remaining Configurations

  1. Copy your Level 2 - Empty vhd to a new file that will be the new configuration. Under Windows 7, you can create all of them at once using the DISKPART utility. For example: (DiskPart requires elevated privileges and so must be run from a command prompt started with Run As Administrator.)

    DISKPART < Parts.txt

    And Parts.txt is one or more lines similar to this:
    create vdisk file="c:\vpc\ParentDisks\WinXP Office 2007.vhd" parent="c:\vpc\ParentDisks\WinXP SP3 Root.vhd"
  2. Go to Step 3 under Configure a Layer 2 VPC and continue through Configure a Layer 3 VPCs.

Licensing

Licensing is also an issue. Strictly speaking, it appears that you need one Windows license per virtual PC. In practice, we have a dozen different variants of each root virtual PC, with only minor changes between each, such as whether it's a member of a workgroup or a member of a domain, or whether it's Service Pack 2 of WinXP or Service Pack 3. Since we rebuild these fairly routinely from scratch, it is hard to believe that we are supposed to own thirty different licenses and rebuy all of them every few months. Our solutions for Windows has been to use the volume licensing versions of Windows, which are available to Microsoft Certified Partners on MSDN Downloads.

Tuesday, March 9, 2010

Create separate references for Debug and Release DLLs in C++/CLR

I'm one of the crazy people who has worked with C++/CLR to make native C++ code coexist with .Net code. It runs really well, with a minimum of frustration.

Except for one thing. We rely on some components supplied by a third party. These components have both Debug and Release versions. You'll notice that the References are listed under "Common Properties" in the Properties window, so you can't create separate references for Debug and Release by simply switching to the appropriate property set.

This has been annoying me now for at least two years, and I finally found a solution, thanks Marco Beninca in this post:

http://social.msdn.microsoft.com/Forums/en-US/clr/thread/9087fb4f-149f-4d66-b33e-f2f280c65fa6

The solution is to use #using in your source code instead of defining your assembly references on the "Framework and References" page. Then you can go to the General page for C/C++ and set different directories for Debug and for Release.

The other advantage to this solution is that you don't have to reset all of your references when you get a new version of the components.

One disadvantage to this strategy is that the compiler no longer takes care of copying the appropriate DLLs to the appropriate directories. This can easily cause you to build with a different set of DLLs than you are running against, which will certainly cause a crash. My solution was to create a Pre-Link step that copies the DLLs to $(OutDir).

Monday, February 15, 2010

Online Backups - The Good, The Bad, and the Ugly

This is the third and last part in my series on doing backups for home and small office environments.

Online backup has come a long way in the past couple of years. Service has become more reliable and faster Internet connections have made backing up large quantities of data more palatable. My Internet connection is 5Mbps (30 MB/min) upstream, which is more than fast enough for overnight backup.

In spite of these advances, my opinion is that online backup is still best suited for last-ditch disaster recovery. Any online backup strategy should be paired with a primary backup strategy that includes an image and/or file backup to a USB drive or network drive. Buying 100-GB of online storage is quite expensive, much less 1-TB. The "unlimited" plans are attractive, but companies make significant compromises to make these unlimited plans affordable, including lower backup speeds, lack of geographic redundancy, and subpar technical support. My research indicates that cheap and reliable are mutually exclusive for online backup - the lower the price, the less reliable the service.

It should also be noted that it's the recovery that's most important, not the backup. Numerous people reported that Mozy could take several days (or more!) to prepare to restore a large number of files. Ordering a DVD was even worse. For me, this isn't acceptable.

Here's my experience with the various services.

Acronis. My first attempt at online backup was with Acronis, who introduced online backup in October 2009. My experience with it has been total failure. Acronis TrueImage 11 has never succeeded in creating a backup on my Windows Vista system. Acronis recently increased my backup space from 25GB to 250GB, all for $50/year. This seems like a safe choice for them, since I've never been able to backup more than 5GB to their servers.

Mozy I've been using Mozy Pro for about two months now. They charge 50 cents/GB/month for their Pro version. On the plus side, the nightly backup works quite reliably and I was easily able to select what I wanted to back up.

However, there are several downsides to Mozy. First, backup speed is only thirty to forty percent of the possible maximum. Mozy compresses data, then sends it. During compression, Mozy usually isn't transmitting data. When Mozy is transmitting, it only manages to max out my connection part of the time. So there's a lot of room for improvement in backup speed. [Updated 5/27/2010] The performance problems seem to have been resolved in Mozy Pro v2.0. I'm consistently maxing out my upstream connection at 5Mbps.

Second, numerous people have reported problems restoring data from Mozy, even from their Pro service. Former employees of Mozy confirm that Mozy has been having problems managing rapid growth.

Third, Mozy does not allow me to exclude specific extensions. While this isn't an issue for most people, it's a real problem when backing up development directories containing projects built by Microsoft Visual Studio.[Updated 5/27/2010] Mozy Pro v1.6 did allow excluding extensions, but it was difficult to use and the documentation was useless. Mozy Pro v2.0 makes it somewhat easier. See my article Configuring Mozy Pro for Visual Studio.

My final issue with Mozy is that it doesn't support multiple historical revisions. This is a feature that I consider very important in case local backups become corrupted (which, as I mentioned earlier, has been all too frequent with Acronis TrueImage.) [Updated 5/27/2010] Multiple historical revisions are definitely supported in Mozy Pro v2.0, but again the documentation is lacking. To view the historical revisions, go to My Computer, open MozyPro Remote Backup, open one of the drives, right-click on a folder, and select Change Time.

Carbonite I didn't try Carbonite, although I know several people who are happy with it.

Iron Mountain I will be trying Iron Mountain next. They are the most expensive, but, compared to the cost of losing the data, the price is cheap. They support multiple historical revisions, incremental block updates, Windows 7, and many other features. Iron Mountain makes backup systems for large companies, so I'm hopeful that their technology is more reliable. I'll keep you posted.

To recap, although online backup has been around for several years, most of the solutions still have significant shortcomings, especially with reliability. My research is that you get what you pay for, with no exceptions.

How I Backup My Windows System for Multiple Contingencies

In my last blog posting, I described the events that have lead up to my paranoia about keeping my computer backed up. In this posting I'll talk about about how I actually keep my system backed up and the challenges involved in these methods.

These backup strategies are appropriate for individuals and for small offices. For larger environments, the reasons for doing various types of backups still hold true, but the implementation strategy will change significantly.

1. DVD Backup. My first strategy is mundane - my software development directories are backed up to DVD after every release. This is more complicated than it sounds. First, Visual Studio creates hundreds of megabytes of temporary files, including .ncb, .ilk, obj, and .pch files. There generally no point in backing up these files. In Roxio Creator I can exclude all of these file types, which makes it trivial to just drag the root directory of my development structure to the DVD. Other DVD burning applications, such as CDBurnerXP, won't automatically exclude file types, so it's somewhat more complex to use them for backups. [Update 12/21/2010: CDBurnerXP now supports excluding by extension, under Edit/Filter Files. However, you can't use this filter from the command line.]

I've been careful to use high quality CDs and DVDs for these backups. I have CDs I burned over ten years ago that I can still read without difficulty. My recordable DVDs are newer, so the jury is still out on how long they'll last. The important thing to remember about CD-R and DVD-R is that, unless you buy archive-grade media, they shouldn't be expected to last more than a few years.

DVD and CD backup requires a substantial amount of effort. You have to remember to do it, it's relatively time consumering (especially if you validate the media after burning), and you have to keep all of the media labeled and filed. So it's only a good streategy if you are quite disciplined. However, DVD backups are much easier to move offsite and you have a permanent record, especially if you need an audit trail.

2. Image Backup. Image backups are the cornerstone of my backup strategy. If my computer total fails, due to a virus, a lightning strike, or user error, the image backups are what allow me to recover in a few hours instead of a few days.

For the last eight years I've created my image backups with Acronis TrueImage. This has been a mixed blessing. On the plus side, Acronis can do incremental image backups, which saves a lot of disk space. Acronis has a standalone boot CD, so you can recover the system from a raw hard drive. Acronis can do backups over the network, even when booted from the recovery disk. All of these have been invaluable.

On the minus side, Acronis has had significant difficulty with consistent quality. Their latest release, Version 11, is a total disaster and has been completely unusable for many people. Acronis also has a nasty habit of creating corrupted backups, which means that a validation phase is required.

I do image backups once a week, supplemented by file backups that are done daily. I try to keep three months of image backups because some viruses can take weeks to trigger.

[Update 12/21/2010: Because of ongoing stability problems with Acronis, I have stopped using it.]

3. File Backup. Acronis TrueImage can also do file backups. I backup my development directories and documents on a daily basis. This usually comes out to less than 5-GB, so I can store a lot of them on a 1-TB backup disk. Again, file backups are done incrementally, so the baseline file is dramatically larger than the daily incremental files.

My big problem with Acronis is the poor support for rotation management. I want to keep backup snapshots every 30 days for the last six months, every week for the past month, and every day for the past week. Acronis provides several different options, none of which can do what I want, and all of which seem to cause the frequency of corrupted backups to increase dramatically. [Update 12/21/2010: Macrium Reflect also has better support for managing archive rotation.]

File backups provide protection from accidental deletion and provide the ability to revert to an older version of a document.

4. RAID 1 Mirror drives I mentioned this in my last blog post, but it bears repeating. I use mirrored drives to handle the case of catastrophic hard drive failure, which has happened to me multiple times before. One of the two mirrored hard drives can fail completely and it won't affect the performance of the system. [Update 5/30/2010 - This happened to me again today. A hard drive failed in my primary development system. Without the RAID 1 pair I'd be looking at restoring from backup right now.]

I use software RAID (Intel Matrix Storage), which definitely has its downsides. Every time you reboot without cleanly shutting down the system, (such as a power fialure or hitting the Reset button,) the drive mirrors have to be validated. This takes six to ten hours, during which the system is almost unusable.

Hardware RAID solutions with battery backup can fix this problem, but such RAID hardware is dramatically more expensive and generally is not compatible with image backup software such as Acronis.

Note that not all RAID strategies provides protection. RAID 0 (striping) actually DECREASES reliability, because if any drive fails, your data will be completely lost.

5. Online backup. My final strategy is for last ditch disaster recovery - theft, fire, natural disaster. I'll talk about it in the third and final part of my blogs about backup.

Saturday, January 23, 2010

Six Myths About Backing Up Your Computer

This is my tale about how I got religion about backups. I played a part in all of the stories below. The amazing part is not that any one or two of them happened around me - the amazing part is that they all happened around me.

Myth #1. I have a new hard drive, my data is safe.

Five years ago I helped a friend replace his hard drive after his original drive failed and he lost everything. So he bought the new drive, spent two or three days reloading everything, and went on his way. Three months later, the new drive failed too, and again he lost everything. My friend is an optimist. He believes he's had all the bad luck he's going to have and he still doesn't do backups.

A few years later, I was overseeing putting a new server in the office and had paid a consultant a lot of money to set it up to our satisfaction. The server was backed up after the OS was installed, but before the consultant made changes. After the consultant was finished, we went home for the weekend. When we came in on Monday, the hard disk had failed. All of the money we paid for the consultant was wasted. Even more embarrassing, the CD for the backup software was sitting on top of the server.

The Reality: Hard drives have their highest failure rate when they are new.

Myth #2. Backing up once or twice a month is enough.

My neighbor conscientiously made weekly backups of his laptop. He had decided that losing a few days of work wouldn't be a big deal. Inevitably, his hard drive died hours before a sizable document was due to his largest customer. He had a four day old backup, but he'd done well over thirty hours of work on the document in the interim. I was able to recover the data with low-level tools, but recovery companies charge hundreds to thousands of dollars for that kind of work.

The Reality: Murphy's Law should never be underestimated. Nightly backups are a minimum, and software for continuous backup is easily available.

Myth #3. Backing up documents to an external drive is good enough.

Two years after I helped my optimist friend above, the primary hard drive abruptly failed in our corporate ecommerce web server. We had a backup of the database and other data, but we still had to reconfigure the operating system from scratch. It took four days to get the server running again, which was basically four days of lost sales. I learned a harsh lesson, since it cost thousands of dollars in sales and made a lot of existing customers unappy.

The Reality: To quickly recover from a catastrophic failure, you must have image backups, not data backups.

Myth #4. Having an image backup on an external drive or a NAS is good enough.

I have now been in two different offices that were burglarized and the computers were stolen. If I'd had a USB hard drive sitting on the shelf, it would have been taken too. Even if you put the backup in the safe, it just takes one flood, fire, tornado, or hurricane to destroy the sensitive platters of a hard drive.

I've also known people who whose office was served with a search warrant. The content on computers is just assumed to be relevant, so officers often take *everything* that looks like a computer or a hard drive - including what's in the safe. If you don't have off-site backups, you're done because you may not ever get that equipment back.

The Reality: You must have off-site backups.

Myth #5. I use RAID hard drives so I don't have to do backups.

My primary computer had mirrored hard drives installed right from the start. Six months later, my computer contracted the second virus I've ever had. However, RAID is protection against disk failure, not against data loss that was intentionally caused by a virus. I recovered from the failure by reloading the entire system from image-level backups, as I described in #3.

As I became increasingly paranoid about hard drives failures, I upgraded our corporate web server with a hardware RAID card and enterprise-grade SCSI hard drives to allow RAID 1 drive mirroring. SCSI hard drives generally cost several times the price of a similarly-sized IDE (consumer) drive because they are expected to be substantially more reliable.

A week after the new hardware went live, I started seeing I/O errors. Our expensive new RAID controller board had malfunctioned. As a result, it corrupted the SQL database that contained the customer support system, which contained FIVE YEARS of customer support information, including an extensive knowledgebase. The primary backup was completely missing due to a configuration error in the backup script. I ended up staying up all night to restore the database from a third-level backup that I'd been paranoid enough to perform.

The Reality: If you don't have 100% redundancy, including spare computers ready to go, downtime and possible data loss are just one hardware failure away. Also, RAID provides zero protection again viruses and user error.

Myth #6. Paying experts to do backups is good enough.

After we upgraded to RAID hard drives, we purchased Managed Backup for our corporate server. This means that experts are responsible for keeping our server backed up, and they are responsible for recovery when things go wrong.

Last summer one of our web server log files was erased accidentally. These files are critical for financial analysis and prediction, so I was pleased that we had the experts managing our backup. Except for one thing. The "experts" considered the log files low value and a waste of space, so the file I needed had not been backed up. Damn.

The Reality: Backups that haven't been verified and tested aren't backups.

Conclusion

You can't be too paranoid about backup. I have four levels of redundancy in my backups, but I still worry that it won't be good enough. If your computer contains critical information, whether it's corporate documents, baby pictures, legal documents, graduate thesis, or financial records, do yourself a favor and back it up, preferably in multiple places.

In Part 2, I'll look at how I've implemented my tiered backup strategy and what software I use to make it happen.

Thursday, November 19, 2009

Installing PHP on Windows 7

If you've wrestled with installing PHP on IIS before, there's good news. Installing PHP in Windows 7 is easy. Super easy. Microsoft has created the Web Platform Installer (WPI), which supports installing many things, PHP included.

If you look in the IIS Manager, down at the bottom of the rows of icons you should see Web Platform Installer. If you don't see it there, go to your Start menu and search for "platform".

Check off PHP and let it install. There are a couple of dependencies that will be added automatically.

There's one more change you need to make after PHP is installed, which is to add "index.php" to the list of Default Documents.

There are some other things you should know:
  • WPI correctly installs PHP even on a 64-bit system. There's no need to use cscript to separately change configurations.
  • Apparently, there's still no 64-bit version of PHP for Windows. WPI installs the 32-bit version, which works correctly even under the 64-bit version of IIS.
  • There's no uninstall option. However, everything is installed to a single directory and removing the relevant FastCGI settings is straightforward.
  • The correct strategy for upgrading to new versions of PHP isn't obvious. I'm not sure if Microsoft used the stock build of PHP or if they created a custom one.
One small gotcha - WPI installs PHP 5. If this is your first encounter with PHP 5, you need to make sure you use <?php ... ?> as opposed to <? ... ?>.

Monday, November 9, 2009

Handling Exceptions from STL

Recently I tracked down a crash to an out of bounds index in a STL vector. The strange thing was that the crash was being handled by Windows instead of by our error reporting code, which is designed to trap everything that the explicit exception handlers did not catch.

Obviously it wasn't.

I created some short test code:
vector vec;
vec[5] = 3;


When run under the debugger, I receive a helpful window that says "vector out of range" with the standard Abort/Retry/Ignore debugger options. All very well and good, but there was no exception being thrown.

I tried using set_unexpected(), which turns out didn't mean what I thought it meant. The function set_unexpected() is called when an exception is thrown through a function that doesn't declare that exception in the throw() statement in the function declaration. Visual C++ does not support these declarations, and so does not support set_unexpected(). This is discussed in the documentation.

So I tried set_terminate(), which is the only other function under Exception Handling Routines that seemed relevant. Unfortunately, my termination function was never called. Since my two line program certainly was not catching an exceptions, something else was happening.

I tried running the code again as a Release build instead of a Debug build. It still broke to the debugger, but in a separate place than the Debug build.

I tried reading the documentation, which makes no mention that operator[] can throw an exception.

Stranger and stranger. I tried walking the stack with the Release build, which looked like this:
msvcr90.dll!_crt_debugger_hook
msvcr90.dll!_invalid_parameter
msvcr90.dll!_invalid_parameter_noinfo
Exc.exe!wmain


The function _invalid_parameter() had this comment:
// No user handler is defined. Notify the debugger if attached.
So I tried running the Release build without the debugger. Which also yielded no useful information.

I don't remember exactly how I figured out what was happening, but it turns out that STL is throwing "out_of_range", which is derived from "logic_error", which is derived from class "exception". I've been using STL for twelve years. I've written articles about it. And I've never heard of these exception classes. Clearly, the authors of the documentation had never heard of them either.

Note that this behavior is different than other implementations of STL, which specifically document that only the at() functions throws an exception, not operator[]. At least "out_of_range" is defined in the standard.

[Update 8/13/2010 Visual Studio 2010 behaves according to the standard. In Release builds, vector<>::operator[] does not do bounds checking and does not throw the out_range_range exception. In Debug builds, an assertion is shown because _ITERATOR_DEBUG_LEVEL is set to 2 in yyvals.h if _DEBUG is defined.]

But the fun wasn't over. I still didn't know why set_terminate() wasn't working. The documentation for Unhandled C++ Exceptions only discusses set_terminate().

It turns out that unhandled logic_error exceptions are handled by invalid_parameter_handler and not by terminate_handler. This is broadly discussed in the documentation for Invalid Parameter Handler Routine. However, that documentation describes how errno is set, which doesn't appear to happen with STL.

The situation gets even more murky if you consider Windows SEH (Structured Exception Handling) as well as C++ exceptions. The standard way of dealing with SEH is to use SetUnhandledExceptionFilter(). However, Visual Studio 2008 changes this behavior. See a blog entry by Jochen Kalmbach. Related information about C-Runtime behavior is discussed in the MSDN forums.