Reputation: 3777
I have a question about passing environment variables to MSBuild
Task. See my code below:
a.proj
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="A1">
<Target Name="A0">
<Message Text="A0 start."/>
<MSBuild Projects="b.proj" Properties="myvar=000" />
<Message Text="A0 end."/>
</Target>
<Target Name="A1" DependsOnTargets="A0">
<Message Text="A1 start."/>
<MSBuild Projects="b.proj" Properties="myvar=111" />
<Message Text="A1 end."/>
</Target>
</Project>
b.proj
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="B">
<Message Text="B start."/>
<Exec command="c.bat" />
</Target>
</Project>
c.bat
echo [C]myvar=%myvar%
I hope that c.bat
can see myvar
's value passed from a.proj
. My code above failed to do that.
Consider(Assume) a running <MSBuild> Task a process on the OS, then, I'd like to pre-set environment variable myvar
for that process, so that its subprocesses(no matter how deep) can all see myvar
's value.
How can I achieve that? Thank you.
Upvotes: 0
Views: 1060
Reputation: 5068
When MSBuild starts, it maps the environment variables in its process to MSBuild Properties. For example the environment variable COMPUTERNAME
is available in an MSBuild project as the $(COMPUTERNAME)
property.
But Properties are not added to the environment variables.
The Exec
task creates a new process. The new process will inherit the environment variables of the 'parent' process and Exec
has a parameter for passing additional environment variable definitions that will either add to or override the existing environment variables. The parameter is EnvironmentVariables
.
Modify your Exec
task as follows:
<Exec command="c.bat" EnvironmentVariables="myvar=$(myvar)" />
The following is a full example of the environment variable passing.
Given a file 'test.proj':
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="TestExecPassVar">
<MSBuild Projects="$(MSBuildThisFile)" Targets="ExecPassVar" Properties="myvar=000" />
<MSBuild Projects="$(MSBuildThisFile)" Targets="ExecPassVar" Properties="myvar=111" />
<MSBuild Projects="$(MSBuildThisFile)" Targets="ExecPassVar" />
</Target>
<Target Name="ExecPassVar">
<Exec Command="test.bat" EnvironmentVariables="myvar=$(myvar)" EchoOff="true" />
</Target>
</Project>
And given a file 'test.bat':
@echo running test.bat
@echo %myvar%
Running the command
set myvar=222
and then
msbuild test.proj
will produce output like the following (which has been edited to remove paths and other noise):
Project "test.proj" on node 1 (TestExecPassVar target(s)).
Project "test.proj" (1) is building "test.proj" (1:2) on node 1 (ExecPassVar target(s)).
ExecPassVar:
running test.bat
000
Done Building Project "test.proj" (ExecPassVar target(s)).
Project "test.proj" (1) is building "test.proj" (1:3) on node 1 (ExecPassVar target(s)).
ExecPassVar:
running test.bat
111
Done Building Project "test.proj" (ExecPassVar target(s)).
Project "test.proj" (1) is building "test.proj" (1:4) on node 1 (ExecPassVar target(s)).
ExecPassVar:
running test.bat
222
Done Building Project "test.proj" (ExecPassVar target(s)).
Done Building Project "test.proj" (TestExecPassVar target(s)).
The test project invokes its own ExecPassVar
target three times. The first two times it passes Properties
that define a $(myvar)
property. The third time no property is passed and the $(myvar)
property is undefined.
The Exec
task uses the EnvironmentVariables
parameter.
When the $(myvar)
property is defined, the batch file sees a myvar
environment variable with the passed value.
When the $(myvar)
property is not defined, the EnvironmentVariables
parameter value evaluates to "myvar="
. This doesn't override or clear the value of myvar
and the value of 222
, that was set before the msbuild command, is seen by the batch file.
Upvotes: 1