MSBuild has an <Exec> task for calling external programs, but (bafflingly) it doesn’t allow you to set the environment the program runs in. In my case, I need to run a Python script with certain directories in the PYTHONPATH.
The Short Way
On Unix machines, this is trivial:
PYTHONPATH=”~/foo” python script.py
For Windows’ wonderful cmd.exe shell (which MSBuild uses to run Exec) it’s a little longer:
(set PYTHONPATH=C:\Foo) & python script.py
If you want, you can chain multiple set commands together to set multiple variables:
(set PYTHONPATH=C:\Foo) & (set FOO=42) & python script.py
To actually use this in the MSBuild file, you’ll need to escape it like so:
<Exec Command=”(set PYTHONPATH=C:\Foo) & python script.py” />
Getting the quoting right for <Exec> can be tricky; I use the <Message> task for debugging the command line. Remember to use " instead of double quotes.
The Long Way
This method takes more typing but is a bit more clear, especially if you have multiple variables to set. Actually, it can be used to store whole batch files inside the MSBuild file, if necessary.
<PropertyGroup> <PythonExec><![CDATA[ set PYTHONPATH=C:\Foo set FOO=42 python script.py ]]></PythonExec> </PropertyGroup> <Exec Command="$(PythonExec)" />
A CDATA section is required because the newlines need to be preserved. When running an <Exec> task, all MSBuild does is write the contents of Command to a temporary batch file an execute. This just provides more than the usual single line command.