Jimm Chen
Jimm Chen

Reputation: 3777

How to pass env-var to MSBuild Task and make it effective for all sub-process? (concrete code)

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.

enter image description here

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

Answers (1)

Jonathan Dodds
Jonathan Dodds

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)" />

Example

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

Related Questions