pondělí 18. července 2011

Visual Studio 2010: "The process cannot access the file because it is being used by another process." (2. část)

(1. část)

Pokračování příspěvku, který nastiňoval některá možná řešení velice nepříjemné chyby ve Visual Studiu 2010.


Pokud můžeme vyloučit za původce chyby kód, ve kterém se snažíme pracovat se souborem, který jsme zapomněli dříve uvolnit (viz první ukázka kódu), jedná se pravděpodobně o Visual Studio 2010 (v jiných verzích nebyl tento problém zaznamenán).
FileStream fs = File.Create(cestaKSouboru);
using (StreamWriter sw = File.AppendText(cestaKSouboru))
{
// neco delej
}
// Protoze jsme volali File.Create, meli bysme zavolat i File.Close
// nebo vyuzit using
using (FileStream fs = File.Create(cestaKSouboru, 1024))
{
// neco delej
}

Podle názorů na fórech se tedy jedná o situaci, kdy si Visual Studio pod rukama zamyká soubory. Vypíšu zde postupy, které jsem popořadě zkoušel.
  1. Vypnout ručně Read-Only přepínač na adresářích bin u všech projektů.
Ve chvíli, kdy jsem provedl Build a zkontrolova přepínač, byl opět nastaven na True. Visual Studio si jej tedy přepíná (je možné, že to způsobuje TFS). Řekl jsem si, že nastavím Pre-Build event, ve které vypnu Read-Only:
  1. Vypnout Read-Only pomocí Pre-Build Event.

Jak název napovídá, jedná se o události (akce), které se provedou před samotným buildem. Je třeba mít na paměti, že pokud se žádný soubor z projektu, u kterého máme pre-build akci nastavenou, nezměnil, a není tedy třeba projekt rebuildovat, akce nebude provedena.
Vytvořil jsem bat soubor RemReadOnly.bat s jedním parametrem:
@echo off
attrib -r "%1*.*"
Příkazem attrib můžeme zobrazit nebo nastavit příznaky u souborů a adresářů. Samotná pre-build akce vypadala následovně:Zde je potřeba se všimnout několika věcí. Call na začátku akce způsobí zavolání příkazu, který následuje (ve skutečnosti není v tomto případě potřeba). Cesta k bat souboru je v uvozovkách. Bat soubor je nakopírován v adresáři Debug/Release (v závislosti na aktuálním režimu). Bere jeden argument, který je specifikován v těle bat souboru jako %1. Jsou použita dvě makra.
  • $(TargetDir) je cesta do adresáře, kam se daný projekt builduje. Defaultně to je adresář bin/Debug nebo bin/Release (v závislosti na režimu).
  • $(SolutionDir) je cesta do adresáře celého solution.
Nicméně ani když jsem nastavil tyto akce u všech projektů, problému jsem se nezbavil. Hledal jsem tedy dál a našel jsem tento blog, kde nenastavují Read-Only příznak, ale řeší samotné zamykání souborů.
  1. Pre-build akce s lock soubory
Doporučená pre-build akce vypadá následovně:
if exist "$(ProjectDir)bin\$(TargetFileName).locked" del "$(ProjectDir)bin\$(TargetFileName).locked"
if exist "$(ProjectDir)bin\$(TargetFileName)" if not exist "$(ProjectDir)bin\$(TargetFileName).locked" move "$(ProjectDir)bin\$(TargetFileName)" "$(ProjectDir)bin\$(TargetFileName).locked"
Pro jistotu jsem v Pre-Build akcích nechal i svůj bat file. Problém nezmizel.
  1. Modifikace souboru Microsoft.Common.targets
Tento postup už je docela hardcore, ale v těžkých chvílích jsem vyzkoušel i to. Dopředu říkám, že to nevyřešilo problém. Soubor je defaultně na tomto umístění:
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets"
Pro jistotu si soubor zálohujte. Visual Studio si jej hlídá, takže nelze upravit. Musíte ho překopírovat do jiného adresáře, upravit, na původním umístění smazat a nakopírovat zpět upravenou verzi. Ještě jednou upozorňuji, abyste někde měli zálohu původního souboru. Najděte následující část kódu:
<!-- Copy the build product (.dll or .exe). -->
A v tagu copy změňte hodnoty u těchto položek:
Retries="60"
RetryDelayMilliseconds="500"
Problém jsem obešel tím, že jsem knihovny buildoval zvlášť ve správném pořadí, tak aby žádnému projektu nechyběly zbuildované referencované knihovny, a spustitelný projekt byl jediný, který se buildoval po zmáčknutí F5. To jsem nastavil ve vlastnostech solution v Configuration Properties.


Microsoft o problému ví,ale bude prý vyřešen až s Visual Studiem 2012. Ještě přidám odkazy na vlákna, kde je tento error rozebírán:
Zpět na 1.část.

Žádné komentáře:

Okomentovat