Assembling Unable to load in shadow copy of AppDomain

I am writing a test runner xunit.net for ReSharper, and I have a problem in release 8.0 - I see assemblies that do not load in the shadow copied AppDomain. The same code and test project work fine in version 7.1. However, I do not understand why.

When running tests, ReSharper runs an executable file that loads my plugin. I use the xunit.net API to create an AppDomain with shadow copy enabled. The assembly of the test project is copied to the shadow copy cache and starts loading. It copies the dependency to the cache and loads it - an older version of FakeItEasy, which uses Assembly.LoadFile to load all the assemblies in the current directory, which is the bin \ Debug folder of the test project. Thus, FakeItEasy loads these assemblies in the context of no load. Since it uses a LoadFile, it bypasses the shadow cache copy and the files are downloaded directly from the bin \ Debug folder.

After this, the dependencies of the test project are not loaded, which throws a FileNotFoundException. Fusion binding logs show that it is trying to load them, but they are not copied to the shadow copy cache, and they are not loading. I do not understand why. Here's the communication failure:

LOG: This bind starts in default load context. LOG: No application configuration file found. LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/temp/todonancy/TodoNancyTests/bin/Debug/Nancy.Testing.DLL. LOG: Assembly download was successful. Attempting setup of file: C:\temp\todonancy\TodoNancyTests\bin\Debug\Nancy.Testing.dll LOG: Entering download cache setup phase. LOG: Assembly Name is: Nancy.Testing, Version=0.17.1.0, Culture=neutral, PublicKeyToken=null ERR: Setup failed with hr = 0x80070003. ERR: Failed to complete setup of assembly (hr = 0x80070003). Probing terminated. 

If I turn off shadow copies or use a newer version of FakeItEasy that does not use LoadFile, it all works. However, I can’t blame the older version of FakeItEasy - I have users who see the same errors with other projects and assemblies, they are all resolved by disabling the shadow cache.

In addition, this script works with ReSharper 7.1 - the same plugin code and the same test project. The only difference is the host application, but I do not see it doing anything else - for example, there are no other event handlers related to the assembly. The only real difference is that host 7.1 uses remote interaction with Visual Studio, and 8.0 uses simple TCP sockets.

Does anyone know why this fails in version 8.0, and still works with 7.1?

EDIT (08/08/2013):

I managed to execute it with a simple test:

 [Fact] public void Thing() { Assert.NotNull(Nancy.Bootstrapper.AppDomainAssemblyTypeScanner.Assemblies); } 

Using a copy of the Nancy class added directly to the project (with a ScanMode and AssemblyExtensions link). The only other content in the project is a link to xunit.dll and xunit.extensions.dll.

This does not fail every time, it is inconveniently intermittent, but I can make it throw a FileNotFoundException into this Assembly.ReflectionOnlyLoadFrom call when I try to load the test assembly from the bin \ Debug folder.

Here's the merge log from the exception:

 Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll Running under executable C:\Program Files (x86)\JetBrains\ReSharper\v8.0\Bin\JetBrains.ReSharper.TaskRunner.CLR4.MSIL.exe --- A detailed error log follows. === Pre-bind state information === LOG: Where-ref bind. Location = C:\Users\Matt\Code\scratch\WeirdXunitFailures\WeirdXunitFailures\bin\Debug\WeirdXunitFailures.dll LOG: Appbase = file:///C:/Users/Matt/Code/scratch/WeirdXunitFailures/WeirdXunitFailures/bin/Debug LOG: Initial PrivatePath = NULL Calling assembly : (Unknown). === LOG: This is an inspection only bind. LOG: No application configuration file found. LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config. LOG: Attempting download of new URL file:///C:/Users/Matt/Code/scratch/WeirdXunitFailures/WeirdXunitFailures/bin/Debug/WeirdXunitFailures.dll. ERR: Failed to complete setup of assembly (hr = 0x80070003). Probing terminated. 

Unfortunately, this does not tell me anything - the file: // url is valid, and the shadow copy cache contains xunit.dll and WeirdXunitFailures.DLL (test project). Also, the Modules window in the debugger shows me that WeitdXunitFailures.dll is already loaded from the shadow copy cache location.

And again, it’s really strange that the 7.1 runner works great.

EDIT:

In fact, I can make it fail just by calling:

 [Fact] public void Thing() { Assembly.ReflectionOnlyLoadFrom(@"C:\Users\Matt\Code\scratch\WeirdXunitFailures\WeirdXunitFailures\bin\Debug\xunit.dll"); Assembly.ReflectionOnlyLoadFrom(@"C:\Users\Matt\Code\scratch\WeirdXunitFailures\WeirdXunitFailures\bin\Debug\xunit.extensions.dll"); Assembly.ReflectionOnlyLoadFrom(@"C:\Users\Matt\Code\scratch\WeirdXunitFailures\WeirdXunitFailures\bin\Debug\WeirdXunitFailures.dll"); } 

This is a project dll and two xllit dlls. It is still very intermittent, but it seems to be most easily reproduced after a complete overhaul, although it still occurs after several successful runs (so this is not a recovery that is to blame)

+4
source share
1 answer

Phew The problem was (naturally) in a subtle change in behavior in ReSharper 8.

The test run process API has a way to tell the main ReSharper process (that is, devenv.exe) the location of the temporary folder used for the test run, the shadow copy cache. This is because the test run process usually cannot delete the cache folder because it is still in use. Then ReSharper will make several attempts to delete the folder for you, which will allow time for the process to die skillfully.

ReSharper 7.1 will delete this folder at the end of the test run or if the launch was interrupted.

ReSharper 8 deletes the folder as soon as you call the method. The nunit tester tests ReSharper about this at the end of the test run. I talked about this from the very beginning. And so ReSharper will happily come while my tests are running and remove everything it can from the shadow copy cache, making it look like the shadow copy cache was correctly broken.

I think I will log the error :)

+2
source

Source: https://habr.com/ru/post/1495432/


All Articles