VS2012 Testverkenner vergrendelt native .dll, waardoor opnieuw bouwen mislukt

Ik gebruik Visual Studio 2012 voor een oplossing met een C# en een C ++/CLI .dll, waarbij de C ++/CLI dll verwijst naar native .dlls zoals boost. De C ++ -code is gecompileerd als x64.

Wanneer ik VS open, kan ik mijn project opschonen en opbouwen.

Met behulp van testverkenner kan ik mijn tests uitvoeren.

Zodra ik testverkenner eenmaal heb gebruikt om tests uit te voeren, kan ik het project niet opnieuw opbouwen. Het lijkt erop dat VS2012 Test Explorer een vergrendeling op mijn C ++/CLI-dll houdt en daar krijg ik de volgende foutmelding:

LNK1104: cannot open file 'C:\Dev\LockExample\bin\Debug\cli.dll'

Als gevolg hiervan, als ik de tests met Test Explorer heb uitgevoerd, moet ik VS2012 opnieuw opstarten voordat ik kan doorgaan met ontwikkelen. Het is duidelijk dat dit geen duurzaam ontwikkelingsproces is.

Testen en opnieuw bouwen werkt probleemloos met C# -only dll's - voor zover ik weet, doet het probleem zich alleen voor met DLL's die native x64-code gebruiken.

Na wat meer testen, vond ik dat de slechterik hier vstest.executionengine.exe is. Met handle (van SysInternals) zie ik dat vstest.executionengine.exe sloten bevat voor de .dll en de .pdb van de cli-dll. Het bevat geen vergrendeling voor managed-only dll's.

Hoe krijg ik Visual Studio Test Explorer om de vergrendelingen op de C ++/Cli-dll's vrij te geven nadat de tests zijn voltooid?

24
Vond hetzelfde probleem in VS 2017 met verwezen unmanaged DLL.
toegevoegd de auteur Slobodan Savkovic, de bron

6 antwoord

In Visual Studio 2013 this problem can easily be fixed by unchecking the option "Keep Test Execution Engine Running" under "Test -> Test Settings" in the menu.

I found the answer in another post: vstest.executionengine.x86.exe not closing

30
toegevoegd

Na wat meer zoeken, vond ik dit bericht op connect.microsoft.com . De laatste hint in oplossingen biedt een oplossing voor het probleem, hoewel het een lelijke hack is.

Ik kan opnieuw opbouwen als ik het volgende toevoeg als pre-buildgebeurtenissen aan mijn C ++/CLI-dll:

taskkill /F /IM vstest.executionengine.exe /FI "MEMUSAGE gt 1"
taskkill /F /IM vstest.executionengine.x86.exe /FI "MEMUSAGE gt 1"

Hiermee wordt het proces vstest.executionengine.exe gedood, waardoor de vergrendeling van mijn .dll-bestand wordt opgeheven.

9
toegevoegd
Deze "oplossing" werkt voor mij, ondanks de lelijkheid. Ik zal gewoon proberen er niet naar te kijken ...
toegevoegd de auteur rom99, de bron

Ik ben dit probleem ook tegengekomen tijdens het testen met native dll's. De oplossing (oplossing?) Die ik vond was om een ​​DeploymentItemAttribute toe te voegen aan de tests - niet zeker of dit in het algemeen waar is, maar het werkte zeker voor mij. Het is een beetje vervelend als er veel van zijn (ik had er 6 in mijn geval), maar eenmaal klaar was het gemakkelijk om de andere tests te kopiëren en te plakken.

Dus mijn eenheidstestklas ziet er ongeveer zo uit:

[TestClass]
public class TestMyClass
{
    [TestMethod]
    [DeploymentItem("firstnative.dll")]
    [DeploymentItem("secondnative.dll")]
    public void TestMyMethod()
    {
        //Code which (indirectly) uses the above native dlls.
    }
}
3
toegevoegd

Ik heb ook tegen dit probleem gevochten en in eerste instantie de "taskkill" -oplossing gebruikt, maar ik struikelde over een optie in de VS2013-instellingen die dit probleem eleganter lijkt op te lossen:

Verwijder het vinkje op de

Laat de testuitvoeringsengine tussen de testreeksen lopen

optie gevonden bij

Tools/Options/Web Performance Test Tools

2
toegevoegd
Werkt niet voor mij, maar ik ben geen webproject aan het bouwen - ik denk dat deze optie specifiek is voor webprojecten? Misschien is er ergens anders een optie die ik niet kan vinden.
toegevoegd de auteur rom99, de bron
Ja, ik gebruik de engine voor testuitvoering en het lijkt een vergrendeling te houden op bepaalde binaire bestanden nadat tests zijn uitgevoerd (sqlite dlls). Wanneer ik dezelfde tests voer met behulp van het opdrachtregelhulpprogramma vstest.console.exe, werkt alles zoals verwacht en zijn de binaire bestanden niet vergrendeld. Overigens lopen de testen ook VEEL sneller met behulp van de opdrachtregel (of misschien niet de tests zelf maar de testrunner is veel sneller). Maar ik dwaal af...
toegevoegd de auteur rom99, de bron
Dit lost problemen alleen op bij het gebruik van de "Testverkenner". Ik ben bezig met het testen van C# -toepassingen (niet iets webgerelateerd!) En dat loste mijn probleem op. Gebruikt u de "testuitvoeringsengine"? Als dat niet zo is, is het misschien een ander proces dat een van de binaire uitvoerbestanden in "bin" vergrendelt.
toegevoegd de auteur axeloide, de bron

Adding some stuff to the answer of @frodesto, (in case of VS2013), "Test>Test Setting>Keep Test Executin Engine running" configuration is stored in the user configuration (SUO file). This can be a bit nasty in case of this error happens in the TFS Build agent, beacause it uses a service default user.

Als u deze kwestie wilt oplossen, moet u eerst de bestaande vstest.executionengine.exe doden, de gebruiker wijzigen die door TFS Build-agent wordt gebruikt om uit te voeren met de gebruiker waarmee u bent aangemeld. Open de oplossing die is opgeslagen in de werkruimte van TFS Build-agent en deselecteer de optie. Hierna zal de TFS Build-agent de "keep test execution engine" -optie lezen, omdat het SUO-bestand voor dezelfde gebruiker is.

1
toegevoegd
Deze optie is alleen beschikbaar in nieuwe versies van VS.
toegevoegd de auteur Wilbert, de bron
Ik weet het, ik voegde alleen wat hints toe in het geval van VS2013 (ik wou antwoorden geven waar het kristalhelder is) en TFS. Maar misschien ben ik niet duidelijk genoeg geweest, ik zal mijn antwoord aanpassen.
toegevoegd de auteur Jon Ander Ortiz Durántez, de bron

Ik had een C# -hulpprogramma geschreven om native-bibliotheken in hier Ik heb het in het testproject gebruikt, zoals hieronder. Aangezien het dll in Dispose wordt verwijderd, krijg ik geen build-fouten.

public interface INativeCrypto : INativeImport
{
    [ImportFunction("mynative.dll"]
    int NativeMethod();
}


[TestClass]
public class UnitTest1
{
    public void TestMethod1()
    {
        INativeCrypto impl = NativeImport.Create("");

       //Use methods in impl
        int i = impl.NativeMethod();
        //...
    }
}
1
toegevoegd