<< July 5, 2006 | Home | July 7, 2006 >>

Shipping pdb files in release mode

I was reading an article a couple of weeks ago about shipping pdb files with the release versions of your DLLs, and thought that would be a good idea for us to do. In those cases where something unexcpected does happen (you never expect the unexpected!) having a stack trace with symbols and line numbers can be REALLY helpful. My problem is that I am lazy. I didn't want to go off and fix every single .csproj file we had, which was on the order of 60 or so across several solutions. So I took a look at the .csproj file - it is just XML, and said to myself that if I could just iterate over all the project files, and then do a replace on that one node, I would be able to do this with one command line. So I put together a few tools to make that happen.

Here is the relevant section of a .csproj file:

<VisualStudioProject>
    <CSHARP ...>
        <Build>
            <Settings … >
                <Config
                    Name = "Debug"
                    …
                    DebugSymbols = "true"
                    …
                />
                <Config
                    Name = "Release"
                    …
                    DebugSymbols = "false"
                    …
                />
            </Settings>
...

I love command line tools - they can be really useful in situations like this. In this case, here is the psuedo code for what I wanted to do:

for each .csproj file in this directory and any subdirectory
{
  change the XML at the path /VisualStudioProject/CSHARP/Build/Settings/Config[@Name='Release']/@DebugSymbols  to 'true' 
}

It did take me some time playing around with Visual XPath to get that XPath expression correct, but then all I needed was a command-line version of the nAnt xmlpoke task. So I did just that - a quick batch file called xmlpoke.bat that wraps the xmlpoke task. Another way to do this might be to use the xmlpoke task directly from C#, using something like Jeffrey Palermo's netScripter, but the batch file is my home away from home, so that is what I did. In the xmlpoke.bat, you'll see a reference to setnant.bat - this is just a batch file that adds the nant binary directory to my PATH - I could do that in my system settings, but I prefer to add it when I need it.

Here is the batch file that controls everything. I named it CreatePdbForReleaseBuilds.bat:

@echo off
for /R %%i in (*.csproj) do @xmlpoke %%i "/VisualStudioProject/CSHARP/Build/Settings/Config[@Name='Release']/@DebugSymbols" true

here is xmlpoke.bat:

@echo off
:: this is a batch file to call nant and run the xmlpoke command on an file, changing the existing value at xpath to a new value
:: parameters must be given:
::   path and name of xml file
::   xpath expression
::   new value
:: nant.exe must be on the path or setnant.bat must be on the path
setlocal
set _ERROR=
call setnant.bat > NUL
echo.
if .%1.==.. echo XML input file must be specified & set _ERROR=1
if .%2.==.. echo XPath must be specified, and might need quotes around it & set _ERROR=1
if .%3.==.. echo newvalue must be specified & set _ERROR=1
if defined _ERROR goto ERROR

if not exist %1 echo the XML input file '%1' could not be found & set _ERROR=1 if defined _ERROR goto ERROR

set xpath=%2 set xpath=%xpath:"=%

echo. echo poking value [%3] echo into xpath %xpath% echo inside file %1 echo. nant.exe -D:filename=%1 -D:xpath=%xpath% -D:value=%3 -buildfile:%~dp0xmlpoke.build | findstr /C:" [xmlpoke]" goto :EOF

:ERROR echo. echo syntax: echo xmlpoke ["input.xml"] ["xpath"] ["newvalue"] echo.

xmlpoke.bat uses a nant build file called xmlpoke.build - here is that file:

<?xml version="1.0" encoding="utf-8" ?>
<project name="xmlpoke" default="go" xmlns="http://nant.sf.net/release/0.85-rc3/nant.xsd">

<target name="go" description="run xmlpoke using properties that have to be set on the command line"> <xmlpoke file="${filename}" xpath="${xpath}" value="${value}" /> </target>

</project>

Simple but powerful. Enjoy!

I've attached all these files to this post as a zip file for your coding convenience!