Finding Those Errors in CodeSmith
CodeSmith is a great tool. From the samples and the feedback it looks like it has two main groups of users. The first group are those that use it to create typed collections - these may be disappearing soon with .NET 2 coming around the corner. The second group are the database OR mapping crowd. Dynamically creating data access code and business state objects populated from the database. A lot of samples and a lot of the support questions seem to revolve around this problem domain.
The problem for me is writing and managing your own templates. The templates are the files that look like ASP code. If there's an error in this file then the custom tool reports the error, the problem is that the error report refers to the output file (which is empty if there's any error) and the line number is the number of the line in the resulting compiled file generated from your template.
The way CodeSmith works (well, at least this is my assumption) is that the template is taken from your property file. The file contents outside the "<% ... %>" sections are replaced with individual "Response.Write" and the code inside the "<% .. %>" is placed directly into a code file. Some additional entry point and header code is added and the file is compiled, with the output captured. The resulting DLL is run with the parameters taken from the property file. The output of this file is sent to the output of the custom tool.
To find out what really went wrong in your CodeSmith template would require checking the compiler output from the merged code file. This is what the CodeSmith studio does - but wouldn't it be nice to get this output in the VS IDE.
One way to do this is to run the CodeSmith console application which has the handy little option to keep the temporary files and not delete them - (use "/tempfiles+"). Unfortunately this option doesn't seem to work - at least all the time. I found this out by running the sysinternals filemon and regardless of the command line options the temporary files are cleaned up each time I run it.
So, the problem is : - run CodeSmithConsole from the VS IDE and redirect the error output to the output pane so that you can double-click to find the error in your template. To do this prevent the temporary files from being deleted and locate the filename of the most recent temporary file in that directory so that you can load it to the output pane.
So, sticking to good old batch files. Problem #1 - preventing CodeSmithConsole from cleaning itself up. The solution here is to redirect the temporary files to a directory where the running user does not have delete permissions. CodeSmithConsole uses the TMP env variable to locate the temporary files. Creating a special directory called something like "nodel" and forcing TMP to this is easy, the code is something like this:
@echo off
set OLDTMP=%TMP%
set TMP=c:\temp\nodel
CodeSmithConsole /p:%1
set TMP=%OLDTMP%
The parameter to the batch file is the property file (the XML file). Turn the echo off because we're using the batch file output to redirect to the output pane. Also note, that CodeSmithConsole crashes without delete permission - this is fair enough. The app does its job anyway, just fails on the last step when it tries to tidy up.
So simple enough so far, next problem#2 : - now to locate the last file in that directory. The output files end with .out. You cannot rely on their position in the directory file structure so a for loop with a environment variable won't always work:
for %%f in (c:\temp\nodel\*.out) do set OUTFILE=%%f
type %OUTFILE%
We need to be able to iterate over the files in date order. You can do this using the new "for /F" option. With this you can iterate over the result of a command. Luckily "dir /b" provides a list of files in raw format, and "dir /b/od" will list them in date order. So the following should always output the contents of the most recent file in this directory:
for /F "usebackq delims==" %%f in (`dir /b/od c:\temp\nodel\*.out`) do set OUTFILE=%%f
type %OUTFILE%
So that completes the batch file. You can run this from the Tools menu and redirect the output to the output pane. This will now bring up the temporary file where your codesmith error is.
There are probably easier ways of doing this. Use a little VBScript, even clean the temporary directory first so that there's only one .out file. But there's nothing like a plain old batch file.
Now, what would be really nice is for Eric J Smith to add a feature to parse the compiler output. It would be great to keep a map between template line numbers and code line numbers. When the compiler outputs its error lines he could substitute each line number with the corresponding 'source' line number. Then rename the compiler source file with the template file name. This way the error being reported will take the user straight to their .CST file, right to the line where the error is.