Search code examples
msbuildenvironment-variablescsproj

How can I change the folder that Exec tasks in a csproj file generates its temporary exec.cmd files in?


I have a .NET 6 project that includes some Exec nodes, and those commands are failing because (as in this discussion on the msbuild repo) the paths of the generated tmp<blah>.exec.cmd files are not whitelisted.

The suggested fix in there is

The location of this file is controlled by the environment variable TEMP. Can you set that to a custom value before invoking MSBuild?

Which I'm sure would work - but I don't know how to do that. According to this question (which is for C++ not C#, but it's the best I can find) you can use EnvironmentVariables="<blah>" in that same node, but the files are still generated in %LOCALAPPDATA% despite my trying to set TEMP to something else. A failing example is below - what am I doing wrong?

<Target Name="ToolRestore" BeforeTargets="PreBuildEvent">
  <Exec Command="dotnet tool restore" StandardOutputImportance="high" EnvironmentVariables="TEMP=C:\MSBuildTemp" />
</Target>

An answer should ideally be valid for building/debugging in Visual Studio and via dotnet build/test/publish. Even better would be a method of making the value of TEMP be variable per-user, but that's not necessary.


Solution

  • According to the code for the Exec task it does use the standard GetTempPath function, which means it really should react to user-level environment variables. However that function is documented like:

    This method checks for the existence of environment variables in the following order and uses the first path found:

    The path specified by the TMP environment variable.
    The path specified by the TEMP environment variable.
    ...
    

    so the suggested fix you found is not entirely correct: you might need TMP not TEMP. And indeed on my machine I have TMP set and msbuild uses it for its temporary batch files which can be seen using a target which prints the path of the batch file Exec uses:

    <Target Name="TempTest">
      <Exec Command="echo %~dp0"/>
    </Target>
    

    Running on cmd.exe:

    >set TMP=c:\temp
    
    >msbuild temptest.proj /t:TempTest /v:m /nologo
      c:\temp\
    
    >set TMP=c:\Users
    
    >msbuild temptest.proj /t:TempTest /v:m /nologo
    temptest.proj(7,5): error MSB6003: The specified task executable "
    cmd.exe" could not be run. Failed to create a temporary file. Temporary files folder is full or its path is incorrect.
    Access to the path 'c:\Users\tmpb31f9faffaab49e9b3bd5479a6823550.exec.cmd' is denied.