Visual Studio has an interesting way of caching source files retrieved from source servers. In fact, it has two different ways of caching source server-served files:
- .NET Framework source files (Reference Source)
- Custom source files (source files from your own custom source server)
.NET Framework Source Files
For the .NET Framework source server (see screenshot below), Visual Studio caches the source files under the symbols server cache that you provide.
The following screenshot shows the Symbols options page located under: Tools –> Options –> Debugging:
For example, in the screenshot above, the symbols cache folder is C:\Symbols. So, the .NET Framework source drops to the “src” sub-folder under C:\Symbols. So, if you have debugged a WinForms application, chances are that you probably stepped into the Application.cs source file. In that case, and with the cache path specified above, the cache location of Application.cs would be:
C:\Symbols\src\source\dotnetfx35sp1_3053\1.3\DEVDIV\depot\DevDiv\releases\whidbey\netfxsp\ndp\fx\src\WinForms
\Managed\System\WinForms\Application.cs\9\Application.cs
The long path structure has to do a little bit with the way source trees are structured. Notice though the use of short folder names like ndp, fx, src. This is mainly to help avoid running into long path issues.
So, what are those long path issues?
The short answer is that MAX_PATH (defined as 260 characters) is still the limit used by many Windows APIs for storing paths. So, if you have a path that is deeper than 260 characters, then chances are that you will notice some weird and inconsistent behavior when files under that path are accessed. For example, you might be able to write a file under such path but not be able to read it. I won’t elaborate more on describing the problems with long paths as there are folks that have done a great job detailing those problems. Here are some resources:
Custom (Your) Source Files
If you have set up your own internal source server for your organization to use, you might have noticed that the source files are not copied over to the same cache location as the symbols cache – this is unlike the behavior you notice with the reference source for the .NET Framework. You will notice that the source will be cached under your user profile. If you are on a pre-Vista OS, then your path is already too deep (something like C:\Documents and Settings\MyUserName\Local Settings\Application Data\SourceServer). So, if your source tree is too long or if you have been using long verbose folder and file names, then chances are you will notice the same weird behavior that I noticed.
When you are downloading the source file, those files will actually get successfully written under the longer-than-260-characters path. However, when Visual Studio tries to load the source files into the debugger and step through them, it fails to find the files due to the long path. It seems that the debugger uses one of those file I/O APIs that still rely on buffers that are MAX_PATH long.
It is interesting how so many people still do not believe that there are still APIs present even in Vista and Windows 7 that use MAX_PATH. I had a discussion a while back with someone who insisted that this is not a problem anymore and that we do not need to guard against it in one of our applications. Have we naively listened to him, we would have run into some weird behaviors that are the result of long paths.
How do we work around this problem?
First, notice that there is no option under the Debugging options pane in Visual Studio for setting the source server cache. So, how do you specify the path then?
The first time I saw the solution to this problem was in John Robbins’ book “Debugging .NET 2.0 Applications”. Later, I heard it again when John mentioned it in the internal Debugging .NET Applications class that he teaches at Microsoft. John ran into the same problem and ended up figuring out the following solution and creating the HiddenSettings add-in that allows you to set this option:
- Override the default value of SourceServerExtractToDirectory (REG_SZ) from under the following registry key:
- VS2005 (Whidbey): HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Debugger
- VS2008 (Orcas): HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Debugger
- VS2010 (Dev10/Rosario): HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\Debugger
- Note that the default value is typically as follows:
- On Pre-Vista OS’s: “C:\Documents and Settings\MyUserName\Local Settings\Application Data\SourceServer”.
- On Vista/Windows 7/Windows 2008/Windows 2008 R2: “C:\Users\MyUserName\AppData\Local\SourceServer”.
- Set SourceServerExtractToDirectory to the desired value. You can set it to the same folder as the symbols cache (e.g. C:\Symbols).
- It seems that Dev10 (VS2010) still does not expose this setting in any of the Debugger options pages.
What about WinDBG?
It so happens that WinDBG does not have this problem since it relies on the _NT_SOURCE_PATH environment variable. It also allows you to override that value by specifying the path in .srcpath. WinDBG defaults to the the path to the home directory, i.e. the directory where the Debugging Tools for Windows in installed. Note that you would want to change that value as well to point to a shorted path since the typical path is something like: C:\Program Files\Debugging Tools for Windows (x86). The winDBG documentation provides more details on the various options that WinDBG provides for configuring the source path.