oleg-shilo / cs-script

C# scripting platform
http://www.cs-script.net
MIT License
1.56k stars 234 forks source link

Locked NuGet assemblies #331

Open UweKeim opened 1 year ago

UweKeim commented 1 year ago

This is a rather vague posting. It is driving me nuts since several days and maybe you can give me an idea on what might be the issue.

✅ Scenario 1, everything working correctly

  1. Having a CMD file "one.cmd".
  2. "one.cmd" calling css 4.7.1 (installed as a global .NET tool) on a .CS script file "one.cs".
  3. "one.cs" references a NuGet package "Foo".
  4. "one.cs" does a Process.Start to dotnet build example.sln. The "example.sln" contains a .NET 7 app that also references the NuGet package "Foo".

This works just as expected. The CS script runs, does the compilation and ends successfully.

⛔ Scenario 2, failing with a locked Foo.dll file

Similar to scenario 1 but with one more redirection.

  1. Having a CMD file "one.cmd".
  2. "one.cmd" calling css 4.7.1 (installed as a global .NET tool) on a .CS script file "one.cs".
  3. "one.cs" references a NuGet package "Foo".
  4. "one.cs" does a Process.Start to another CMD file "two.cmd".
  5. "two.cmd" uses css 4.7.1 to run "two.cs".
  6. "two.cs" references a NuGet package "Foo".
  7. "two.cs" does a Process.Start to dotnet build example.sln. The "example.sln" contains a .NET 7 app that also references the NuGet package "Foo".

In this scenario, the dotnet build fails with an error message similar to:

C:\Program Files\dotnet\sdk\7.0.300-preview.23179.2\NuGet.targets(156,5): error : Access to the path 'Foo.dll' is denied. [C:\my\example.sln]

This error occurs when dotnet build is trying to restore the NuGet packages referenced by the "example.sln" project.

In a broader context, this is the log output (manually translated to English by me):

MSBuild version 17.6.0-preview-23179-01+dd5d9f746 for .NET
Projects to be restored are determined...
C:\Program Files\dotnet\sdk\7.0.300-preview.23179.2\NuGet.targets(156,5): warning : The folder "C:\Users\ukeim.nuget\packages\foo\foo.3.3.2" contains an invalid version. [C:\my\example.sln]
C:\Program Files\dotnet\sdk\7.0.300-preview.23179.2\NuGet.targets(156,5): error : Access to the path 'Foo.dll' is denied. [C:\my\example.sln]

Error during build.

(The "contains an invalid version" also makes me scratch my head).

What I've tried

I've already tried the use Process Monitor to sniff during the CMD run to see which process is accessing the file, but I still get no real idea what I'm doing wrong here.

My question

Could you throw any wild guesses at me, what might be going on here?

oleg-shilo commented 1 year ago

I repeated your experiment and found that two.cmd process hangs after completion. Meaning that most likely it locked some files (e.g. foo.dll).

There is something interesting about how dotnet handles termination for a child process.

I found that I can fix it by waiting in one.cs for completion of the child two.cmd. This way both parent and child processes exit gracefully:

Process.Start(@"D:\dev\Galos\support\cs-script_#331\two.cmd").WaitForExit(); 

image

I have attached the whole sample: cs-script_#331.zip

UweKeim commented 1 year ago

Thank you very much, Oleg!

In my scripts, I already do call .WaitForExit(). Confusing to me that it works in your experiment but not in mine.

I'll try to investigate further. Maybe it is because I'm doing more than just a simple Process.Start; I'm also doing EnableRaisingEvents, BeginOutputReadLine, BeginErrorReadLine and stuff like this. Maybe this hinders my script from waiting until the process exited completely.

oleg-shilo commented 1 year ago

Interestingly enough even if the file is locked (e.g. loaded by the hanging script), it should not be a problem. Any other NuGet client (e.g. script, VS, dotnet) simply references this dll, which is OK even for the locked file.

Unless dotnet.exe it trying to do something mote aggressive.

oleg-shilo commented 1 year ago

Mind you it was one difference in my experiment. I was using CSS installed by choco. Though I do not see how it can be different...