Closed CCnut closed 2 years ago
Hey @CCnut
As you probably have guessed, this isn't a super common occurence, NuGet relies on Environment.SpecialFolder.LocalApplicationData
being a valid and writable path on the machine it's running on.
Are you able to set LocalAppData
on that machine?
Note that this is the behavior in all NuGet tooling, VS, dotnet.exe and nuget.exe
team triage meeting: We expect common Windows environment variables, and APIs to return without throwing. We recently had another customer who experienced a similar issue when using NuGet.Protocol in an IIS app: https://github.com/NuGet/Home/issues/11762 In their case, IIS was not configured correctly. So, our suggestion is to ensure that the machine is configured according to best practises, but the NuGet team are not experts on machine configuration.
I checked the diagnostic log. the MSBuild can read LOCALAPPDATA
correct, but the NuGet can not.
Note: Drone CI will changed USERPROFILE
path.
SettingsUtility.GetHttpCacheFolder
calls NuGetEnvironment.GetFolderPath(NuGetFolderPath.HttpCacheDirectory)
: https://github.com/NuGet/NuGet.Client/blob/cd24c74285728884cab24e6ba027d75d418c0479/src/NuGet.Core/NuGet.Configuration/Utility/SettingsUtility.cs#L349
GetNuGetEnvironment.GetFolderPath(NuGetFolderPath.HttpCacheDirectory)
calls GetFolderPath(SpecialFolder.LocalApplicationData)
: https://github.com/NuGet/NuGet.Client/blob/cd24c74285728884cab24e6ba027d75d418c0479/src/NuGet.Core/NuGet.Common/PathUtil/NuGetEnvironment.cs#L59-L61
GetFolderPath(SpecialFolder.LocalApplicationData)
calls Environment.GetEnvironmentVariable("LOCALAPPDATA")
: https://github.com/NuGet/NuGet.Client/blob/cd24c74285728884cab24e6ba027d75d418c0479/src/NuGet.Core/NuGet.Common/PathUtil/NuGetEnvironment.cs#L152
GetFolderPath(SpecialFolder.LocalApplicationData)
calls Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
:
https://github.com/NuGet/NuGet.Client/blob/cd24c74285728884cab24e6ba027d75d418c0479/src/NuGet.Core/NuGet.Common/PathUtil/NuGetEnvironment.cs#L218
Envionrment.GetFolderPath
calls InternalGetFolderPath
: https://referencesource.microsoft.com/#mscorlib/system/environment.cs,1450
InternalGetFolderPath
P/Invokes the win32 API SHGetFolderPath
: https://referencesource.microsoft.com/#mscorlib/system/environment.cs,1506
I don't know how SHGetFolder
is implemented, but this certainly was the right thing to do 11 years ago when NuGet was first written (vs looking for an environment variable), as it allowed Mono to implement Environment.GetFolderPath
in a way that made sense on Linux and Mac, so NuGet would work on those platforms without changes. This API didn't exist, however, in .NET Core 1.0, hence why NuGet checks for the platform, and uses the environment variable on windows, but this lack of Environment.GetFolderPath
has led to a bug on Linux and mac because nuget.exe on mono, and the dotnet cli, now use different paths.
So, if your solution can be built with the .NET cli, then using dotnet restore
instaed of msbuild -t:restore
might be a workaround. Otherwise, I'm afraid I don't know how to resolve the issue. In my opinion, NuGet is making the right choice in which APIs it uses (except that NuGet didn't switch to Environment.GetFolderPath
once .NET Standard introduced the API). I'm not a Windows expert, so I don't know how Windows Services should be configured to work (or if Drone CI is even installed as a WIndows Service).
In the ReactOS
source code, SHGetFolderPathW
for the current user is read from
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
.
All paths are based on USERPROFILE
.
That is why MSBuild can read, when LOCALAPPDATA
is null.
Thanks to this issue's existence I was able to solve my issue of running UTs which call "dotnet nuget ..." on windows in a python-tox isolated environment (which doesn't carry over the environment variables). What would have helped much more (and saved a lot of time) would have been a better error (e.g. 'Required LOCALAPPCONFIG environment variable is not set')...
If anyone found this issue by searching for 'tox' and the error, the solution is to add this section to your tox.ini (used in windows):
[testenv]
passenv =
LOCALAPPDATA
NuGet Product Used
dotnet.exe
Product Version
Version: 5.0.17 Commit: 6a98414363
Worked before?
No response
Impact
It bothers me. A fix would be nice
Repro Steps & Context
Build a windows app using the Drone CI. I checked the environment. The pipeline does not have
LOCALAPPDATA
.Reproduce step:
LOCALAPPDATA
environment at powershelldotnet nuget locals all -l
Verbose Logs