1

I am executing the following code:

public static BuildResult Compile(string projectFilePath)
{
    Nuget.NugetRestore(projectFilePath);
    ProjectCollection pc = new ProjectCollection();
    Dictionary<string, string> globalProperty = new Dictionary<string, string>();
    globalProperty.Add("nodeReuse","false");
    BuildParameters bp = new BuildParameters(pc);
    BuildRequestData buildRequest = new BuildRequestData(
        projectFilePath, globalProperty, "4.0", new string[] { "Clean", "Build" }, null);
    BuildResult buildResult = BuildManager.DefaultBuildManager.Build(bp, buildRequest);
    BuildManager.DefaultBuildManager.Dispose();
    return buildResult;
}

However when the build task is completed, when I attempt to delete the folder - I am prevented from doing so, because my application has loaded a DLL into memory from the solutions package folder.

Specifically Microsoft.Bcl.Build.Tasks.dll

Because this one file ends up getting 'in use' in my application, my application is not able to delete the temp directory until the application closes.
Chicken and the Egg - I don't want to close the application until the folder is gone, and I cannot delete the folder until the application closes.

Anyone got any solutions that are known to work?
Eg:
I know that once a DLL is loaded in the application, it is permanent and cannot be traditionally released.
However- I have heard in the past that you can create additional AppDomains within an application and then load assemblies into the AppDomains instead of the main application, then you can dispose of the AppDomain and associated references/assemblies and I am hoping... handles?

Note - I know that I am calling Nuget package restore above, but stepping through the code, I can definitively say that the locking occurs at the build step, not the nuget restore.

Buh Buh
  • 7,443
  • 1
  • 34
  • 61
Baaleos
  • 1,703
  • 12
  • 22

2 Answers2

1

I had a similar issue once but, not using BuildManager, I've used a build file and when running the msbuild process I've noticed a similar error.

When I looked in Task Manager I've noticed that there were several msbuild processes which held some files locked.

This is because msbuild has something called nodereuse that will keep some of the process active so that further builds will be faster.

If you want to disable this you can use the following msbuild parameter:

/nodeReuse:value OR /nr:value
Enable or disable the re-use of MSBuild nodes.
You can specify the following values:

  • True. Nodes remain after the build finishes so that subsequent builds can use them (default).
  • False. Nodes don't remain after the build completes.

A node corresponds to a project that’s executing. If you include the /maxcpucount switch, multiple nodes can execute concurrently.

After I set this parameter to false all my locked files issues were gone. Maybe this will help you too.

Mihail Stancescu
  • 4,088
  • 1
  • 16
  • 21
1

You might want to call BuildManager.DefaultBuildManager.EndBuild() before you dispose it, as this will signal that "no more build requests are expected (or allowed) and that the BuildManager may clean up"

Pedro Lamas
  • 7,185
  • 4
  • 27
  • 35
  • Unfortunately that did not solve the problem. The issue is not so much with the BuildManager class - it is more to do with the technicality of dll's being loaded into the host application but not unloaded. C# Discourages unloading of dlls - which makes it near impossible to cope with this Microsoft BCL dll getting locked. – Baaleos Nov 13 '17 at 10:27
  • Just an idea, but a separate AppDomain should do the trick, as you can basically load the whole thing there and destroy when you're done with it! – Pedro Lamas Nov 13 '17 at 14:06
  • Unfortunately that too did not work - I tried executing my entire build and execute process within a proxy domain. I think it is because the dll was getting loaded by the csproj as a project/targets import instead of an actual reference / assembly.load(). – Baaleos Nov 14 '17 at 14:22