Edit (July 7, 2010): Get the latest version of this script here. 

A while ago, I wrote a PowerShell script that sets up the _NT_SYMBOL_PATH environment variable as well as Visual Studio 2008 so all the debuggers or tools that access symbols you use to shared the same symbol cache. Numerous people said they found useful so I thought I’d post the VS 2010 version of the same script. I’m sure one of you brilliant PowerShell scripters can tweak this script so it’s even cooler. Please do!

Hope this helps someone out.

#requires -version 2.0

# Wintellect .NET Debugging Code
# (c) 2009 by John RobbinsWintellect – Do whatever you want to do with it
# as long as you give credit.

<#.SYNOPSIS
Sets up a computer with symbol server values in both the environment and in
VS 2010.
.DESCRIPTION
Sets up both the _NT_SYMBOL_PATH environment variable and Visual Studio 2010
to use a common symbol cache directory as well as common symbol servers.
.PARAMETER Internal
Sets the symbol server to use to \SYMBOLSSYMBOLS. Visual Studio will not use
the public symbol servers. This will turn off the .NET Framework Source Stepping
You must specify either -Internal or -Public to the script.
.PARAMETER Public
Sets the symbol server to use as the two public symbol servers from Microsoft.
All the appropriate settings are configured to properly have .NET Reference
Source stepping working.
.PARAMETER CacheDirectory
Defaults to C:SYMBOLSPUBLIC for -Public and C:SYMBOLSINTERNAL for -Internal.
Note that if -Public is set, the public symbols will go into
<CacheDirectory>MicrosoftPublicSymbols because Visual Studio 2010 is hard coded to
use that location.
.PARAMETER SymbolServers
A string array of additional symbol servers to use. If -Internal is set, these
additional symbol servers will appear after \SYMBOLSSYMBOLS. If -Public is
set, these symbol servers will appear after the public symbol servers so both
the environment variable and Visual Studio have the same search order
#>

[CmdLetBinding(SupportsShouldProcess=$true)]
param
( [switch] $Internal ,
   
[switch] $Public ,
   
[string] $CacheDirectory ,
   
[string[]] $SymbolServers )

# Creates the cache directory if it does not exist.
function
CreateCacheDirectory ( [string] $cacheDirectory )
{
    if ( ! $(Test-path $cacheDirectory -type “Container” ))
    {
        if ($PSCmdLet.ShouldProcess(“Destination: $cacheDirectory” ,
“Create Directory”
))
        {
            New-Item -type directory -Path $cacheDirectory > $null
        }
    }
}

function Set-ItemPropertyScript ( $path , $name , $value , $type )
{
    if ( $path -eq $null )
    {
        Write-Error “Set-ItemPropertyScript path param cannot be null!”
        exit
    }
    if ( $name -eq $null )
    {
        Write-Error “Set-ItemPropertyScript name param cannot be null!”
        exit
    }
    $propString = “Item: “ + $path.ToString() + ” Property: “ + $name
   
if ($PSCmdLet.ShouldProcess($propString ,“Set Property”))
    {
        if ($type -eq $null)
        {
             Set-ItemProperty -Path $path -Name $name -Value $value
        }
        else
        {
             Set-ItemProperty -Path $path -Name $name -Value $value -Type $type
        }
    }
}

# Do the parameter checking.
if
( $Internal -eq $Public )
{
    Write-Error “You must specify either -Internal or -Public”
    exit
}

# Check if VS is running.
if
(Get-Process ‘devenv’ -ea SilentlyContinue)
{
    Write-Error “Visual Studio is running. Please close all instances before running this script”
    exit
}

$dbgRegKey = “HKCU:SoftwareMicrosoftVisualStudio10.0Debugger”

if ( $Internal )
{
    $CacheDirectory = “C:SYMBOLSINTERNAL”
    CreateCacheDirectory $CacheDirectory
    # Default to \SYMBOLSSYMBOLS and add any additional symbol servers to
    # the end of the string.
    $symPath = “SRV*$CacheDirectory*\SYMBOLSSYMBOLS”
    $vsPaths = “”
    $pathState = “”

    for ( $i = 0 ; $i -lt $SymbolServers.Length ; $i++ )
    {
        $symPath += “*”
        $symPath += $SymbolServers[$i]
   
    $vsPaths += $SymbolServers[$i]

        $vsPaths += “;”
        $pathState += “1”
    }
    $symPath += “;”
    Set-ItemPropertyScript HKCU:Environment _NT_SYMBOL_PATH $symPath

    # Turn off .NET Framework Source stepping.
    Set-ItemPropertyScript $dbgRegKey FrameworkSourceStepping 0 DWORD
    # Turn off using the Microsoft symbol servers.
    Set-ItemPropertyScript $dbgRegKey SymbolUseMSSymbolServers 0 DWORD
    # Set the symbol cache dir to the same value as used in the environment
    # variable.
    Set-ItemPropertyScript $dbgRegKey SymbolCacheDir $CacheDirectory
    # Set the VS symbol path to any additional values
    Set-ItemPropertyScript $dbgRegKey SymbolPath $vsPaths
    # Tell VS that to the additional servers specified.
    Set-ItemPropertyScript $dbgRegKey SymbolPathState $pathState
}
else
{
    $CacheDirectory = “C:SYMBOLSPUBLIC”
    CreateCacheDirectory $CacheDirectory
    # It’s public so we have a little different processing to do. I have to
    # add the MicrosoftPublicSymbols as VS hardcodes that onto the path.
   
# This way both WinDBG and VS are using the same paths for public
    # symbols.
    $refSrcPath = “$CacheDirectoryMicrosoftPublicSymbolshttp://referencesource.microsoft.com/symbols”
    $msdlPath = “$CacheDirectoryMicrosoftPublicSymbolshttp://msdl.microsoft.com/download/symbols”
    $extraPaths = “”
   
$enabledPDBLocations =“11”

    # Poke on any additional symbol servers. I’ve keeping everything the
    # same between VS as WinDBG.
   
for ( $i = 0 ; $i -lt $SymbolServers.Length ; $i++ )
    {
        $extraPaths += “;”
        $extraPaths += $SymbolServers[$i]
        $enabledPDBLocations += “1”
    }
    $envPath = “SRV$refSrcPath;SRV$msdlPath$extraPaths”

    Set-ItemPropertyScript HKCU:Environment _NT_SYMBOL_PATH $envPath

    # Turn off Just My Code.
    Set-ItemPropertyScript $dbgRegKey JustMyCode 0 DWORD
    # Turn on .NET Framework Source stepping.
    Set-ItemPropertyScript $dbgRegKey FrameworkSourceStepping 1 DWORD
    # Turn on Source Server Support.
    Set-ItemPropertyScript $dbgRegKey UseSourceServer 1 DWORD
    # Turn on Source Server Diagnostics as that’s a good thing. 🙂
    Set-ItemPropertyScript $dbgRegKey ShowSourceServerDiagnostics 1 DWORD
    # It’s very important to turn off requiring the source to match exactly.
    # With this flag on, .NET Reference Source Stepping doesn’t work.
    Set-ItemPropertyScript $dbgRegKey UseDocumentChecksum 0 DWORD
    # Turn on using the Microsoft symbol servers.
    Set-ItemPropertyScript $dbgRegKey SymbolUseMSSymbolServers 1 DWORD
    # Set the VS SymbolPath setting.
    $vsSymPath =” $refSrcPath;$msdlPath$extraPaths”
    Set-ItemPropertyScript $dbgRegKey SymbolPath $vsSymPath
    # Tell VS that all paths set are active (you see those as check boxes in
    # the Options dialog, DebuggingSymbols page.)
    Set-ItemPropertyScript $dbgRegKey SymbolPathState $enabledPDBLocations
    # Set the symbol cache dir to the same value as used in the environment
    # variable.
    Set-ItemPropertyScript $dbgRegKey SymbolCacheDir $CacheDirectory
}
“”
“Please log out to activate the new symbol server settings”

“”