If there are files that are needed to build the project (e.g. XML files) and those files are generated by an external tool, it can be very annoying to remember to run that tool before every build. We end up wasting a lot of time running the external tool, and we forget to run the tool then we waste even more time with strange behaviors.
We would like to automate the process of running the tool before each build. Obviously, we’d just run the tool and generate the file before running starting the build in a script. It is a little bit tricky in Visual Studio since we’d just like to hit F5 and go into another debugging session. If the tool generates an error, it should also halt the build process and notify of the error.
Here, I’ll go into how to create a project build configuration in Visual Studio so that you can just forget about the pre-build step. When any of the dependent input files to the pre-build step changes, it will run the pre-build script. It will copy the relevant files. If the pre-build steps fails then it will notify as an error rather than silently failing.
The pre-build dependent file will be
data.xml which will be generated by a
XMLData project and this data.xml file is needed by our main program
XMLMain. There are two command line executable projects and we will run
XMLData as part of the build process and copy the files over to
The project structure is that
data.xml which is used by
XMLMain to display the XML data. So, if we modify
input.txt, it should automatically run
XMLData and generate the
data.xml and copy it to the
XMLMain project. If there is an error when creating
data.xml, the build process should fail and notify the user.
Post Build Steps
XMLData and then copy data.xml to
XMLMain project directory, the following post build script works.
$(TargetPath) copy /y $(TargetDir)data.xml $(SolutionDir)XMLMain
This works fine until there is an error in
XMLData and it won’t pick up the error. It will show the exception in the output but thinks the build process went successfully.
Catching Build Errors
The post-build event command line is essentially a batch script. So, we can use batch file commands to detect the return value of
XMLData.exe and then produce an error if it is not equal to 0.
The next step is to figure out how Visual Studio detects that there are errors in the build process and notifies the user.
- If the output of a build tool matches a pattern, Visual Studio will show as an error as discussed in the SOF thread and MSBuild blog.
- If the batch script exits with an error level, the build process will fail with
MSB3073error and show the set error code.
In batch files, you query the return value of the last program using
%ERRORLEVEL%. The convention is that if there is no error, then error-level is 0, otherwise is something else defined by the application.
A strange side effect of querying the error-level is that now Visual Studio thinks the post-build step failed with the
MSB3073 error. If you don’t query for the error-level, Visual Studio thinks everything is fine. As soon as you query for it, it produces an error. The following code would produce an error when
XMLData throws an exception.
$(TargetPath) if %ERRORLEVEL% == 0 (goto copyxml) ELSE (goto end) :copyxml copy /y $(TargetDir)data.xml $(SolutionDir)XMLMain :end
The exit code of -532462766 is the error level set by
Custom Build Error
We’d like to make a little bit nicer build error so that someone building the project know that
XMLData has failed and it’s not a mysterious error. We will echo out a custom message.
The following code outputs a custom error message.
$(TargetPath) if %ERRORLEVEL% == 0 (goto copyxml) ELSE (goto showerror) :showerror echo XMLData.cs : error XMLData001: Exception thrown by XMLData. goto end :copyxml copy /y $(TargetDir)data.xml $(SolutionDir)XMLMain :end
It still throws the MSB3073 error in the error log and I can’t seem to get rid of it by resetting the error-level.
However, it does the trick of notifying the user that there is an error with
XMLData that they should check.
A cooler solution would be remove the
MSB3073 and just show the exception from
The error message string allows you to specify the file and line number. Since we have only a single file, we can specify that file and if you double click, it will take you to that file. It would also be great to parse out the exception being thrown and print the line number in the error so you can just double click on it and get to the line that caused the exception. For projects with multiple files, it would be great to have the file that caused the exception.
Right now, we just want to make sure build fails when the
XMLData fails and there is an error message that points to