2

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.

Richard Ward
  • 360
  • 3
  • 14
  • 1
    If you change your Exec command to `echo %TEMP%` what does it print? That should indicate whether it's an msbuild or dotnet problem. Alternative simple solution: set TEMP in the shell itself and child processes (msbuild/VS/...) will inherit it. – stijn Dec 11 '21 at 08:06
  • @stijn I'll give it a shot, but I doubt `echo %TEMP%` will work either - I think the root of the problem is that the command is generated into a randomly-named .cmd file stored in `%LOCALAPPDATA%/Temp` and my employer requires items run from there to be on a whitelist. I *might* be able to get them to whitelist `tmp*.exec.cmd` or similar, but I doubt they'd be too happy with doing that. It took me long enough to get the EF Core tools whitelisted. – Richard Ward Dec 11 '21 at 13:24
  • @stjin Nope, `echo %TEMP%` has the same thing happen. Setting UserProfile, AppDataLocal and/or Temp to a different location in the project file also has no effect. Setting the user-level environment variable has no effect either. – Richard Ward Dec 11 '21 at 14:07

1 Answers1

1

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.
stijn
  • 34,664
  • 13
  • 111
  • 163
  • Yep, this works. A bit of a nuisance that I need to fiddle with environment variables after all, and not just change some option in the project, but such is life. Perhaps I can rally enough support over on Github that it becoms a configurable option. Thank you! – Richard Ward Dec 13 '21 at 11:50
  • 1
    Yes it should ideally be configurable in another way; on the other hand, in 'defense' of msbuild: restricting a system such that it has problems writing to the temp directory is begging for problems. – stijn Dec 13 '21 at 12:12