Visual Studio Just Suddenly Stopped Working

I've run into this more than once, so I'm throwing up a quick post in case it helps someone else.

Once in a while after doing something innocuous (for instance, updating a VS extension), Visual Studio (and other parts of the system) will just stop working. Typical behavior includes a dialog box during VS startup that says something like "target of invocation threw exception". Or VS will start, but with tons of errors, like it can't load any of its components.

This might be one of Windows's most annoying weird bugs - the "path is too long" problem. It's possible for your %PATH% environment variable to get long enough that Windows can no longer parse it correctly, which leads to all kinds of strange problems in software which depends on the path being set. The smoking gun is the inability to open the System Properties dialog (on Windows 7, go to Control Panel -> System and click on the 'Advanced system settings' link on the left; normally this brings up an old XP-style dialog with a button for setting Environment Variables). If you can't open that dialog and instead get a dialog box with a weird error about not being able to find the system folder, you've probably got a %PATH% that's too long.

You would be astonished at how many installers are putting ridiculously long paths into your %PATH% variable. The SQL Server tools are really bad about this, as are the installers for the Windows Git client (which uses GUIDs at part of its paths). Anyway, you're going to need to trim down this variable for anything to work. Unfortunately, the dialog you'd normally use for this is now inaccessible.

I'm sure there are other ways to do this, either through cmd.exe or the registry, but PowerShell is what I know, so here's how I do it (disclaimer: this process is not necessarily optimized, but this will at least get you started):

  1. Run PowerShell as an admin.
  2. Check the value of $env:path. It's probably insane. You're going to need to clean that up. As near as I can figure, you want to make sure that the machine version of %PATH% and the user version of %PATH% are each under 2048 characters. I say "near as I can figure" because I've found wildly varying advice about this on the web. Either way, I'm betting that a bunch of installers have put things in the machine path which only apply to your specific user; for example, I don't share my dev machine with anyone, so there's no reason for a bunch of my personal utilities or my Git client to be in the machine-wide %PATH% variable. Before you do anything else, save the entire contents of $env:path to a file somewhere in case you screw up along the way. You've been warned.
  3. I start by getting rid of duplicates (some installers aren't courteous enough to see if a path in the %PATH% before appending it). I also clean out things like ".", which somehow made it into my path last time this happened. Here's a PS one-liner for handling this:
    $newPath = ([Environment]::GetEnvironmentVariable('Path', 'Machine').Split("`;") | group | where {$_.Name.Length -gt 1} | select -expand Name) -join "`;"
    That line takes the machine path, splits it up, and groups it together; that way, you only get each part once. If "C:\sysinternals" is in your %PATH% twice, it will only show up in the results once. The results are piped through a filter to remove anything that's only one character (the "." paths I mentioned earlier), and then everything is joined back together into one string (separated by ";").
  4. Removing the duplicates might be enough to get you under the size restrictions - if so, you can skip ahead to actually setting the new %PATH% variables. If not, you may need to do some manual cleaning. Send your scrubbed path to the clipboard:
    $newPath | clip
    (That's using the clip utility that's in Vista (and later versions of Windows). Super handy.) Open your text editor of choice and drop in the path. Clean out stuff that doesn't need to be there (things left over from programs which aren't installed are good candidates, as are things that belong in your user path).
  5. Update $newPath with your changes. Now you can update the machine path like this:
    [Environment]::SetEnvironmentVariable('Path', $newPath, 'Machine');
  6. Repeat 3-5, replacing 'Machine' with 'User' to clean up your user path. This is a good time to add the things from your machine path which should have been in the user path all along.

The %PATH% settings are inherited from the process which spawned your current process, so you won't see these changes in PowerShell until you exit and restart it; same goes for Explorer. Honestly, I just restart the whole machine. It's not elegant, but this problem only ever pops up when I have better things to worry about.

In fact, now that it's happened like three times in four years, I've added a couple of lines to my PowerShell profile which let me know when my path is getting too long and may need cleaning:

$pathThreshold = 2000;
$pathLength = ([Environment]::GetEnvironmentVariable('Path', 'Machine') | Measure-Object -Character | select -expand characters)
if($pathLength -gt $pathThreshold){ Write-Host -ForeGroundColor red "Your machine path is over $pathThreshold characters long; you might start experiencing some system problems."  }
$pathLength = ([Environment]::GetEnvironmentVariable('Path', 'User') | Measure-Object -Character | select -expand characters)
if($pathLength -gt $pathThreshold){ Write-Host -ForeGroundColor red "Your user path is over $pathThreshold characters long; you might start experiencing some system problems."  }

2000 is an arbitrary number; feel free to set it to whatever makes you comfortable.

I hope this saves someone some frustration.