Program Visual Studio blokuje plik wyjściowy podczas kompilacji

80

Mam proste rozwiązanie WinForms w VS 2010. Za każdym razem, gdy je buduję, plik wyjściowy (bin \ debug \ app.exe) zostaje zablokowany, a kolejne kompilacje kończą się niepowodzeniem z komunikatem typu "The process cannot access the file 'bin\Debug\app.exe' because it is being used by another process." Jedynym sposobem na zbudowanie projektu jest ponowne uruchomienie VS po każdą kompilację, co jest bardzo niezręczne.

Znalazłem ten stary wpis na blogu http://blogs.geekdojo.net/brian/archive/2006/02/17/VS2005FileLocking.aspx - wygląda na to, że problem jest naprawdę stary. Czy ktoś wie, co się tutaj dzieje, a przynajmniej jakieś obejście?

Aktualizacja

W rzeczywistości nie uruchamiam pliku. Blokowanie następuje po kompilacji, a nie po debugowaniu (tj. Uruchomieniu VS - kompilacja - kompilacja - niepowodzenie!). Próbowałem wyłączyć program antywirusowy. To nie pomaga.

Zaktualizuj 2

Process Explorer pokazuje, że devenv.exe załadował plik (w bibliotekach DLL, a nie w uchwytach). Wygląda na to, że jakiś błąd podczas kompilacji uniemożliwił wyładowanie, ale (pierwsza) kompilacja kończy się bez żadnych komunikatów innych niż „1 powiodło się, o nie powiodło się” /

Nieważne
źródło
czasami mam podobny problem; używasz systemu Windows 7? W moim przypadku to nie VS blokuje plik: mogę go po prostu usunąć w eksploratorze i kompilacja działa poprawnie. Zauważyłem, że problem występuje częściej, jeśli mam otwarte okno eksploratora w katalogu wyjściowym. Przy okazji nie używam skanera antywirusowego.
stijn
Ten sam problem pojawia się sporadycznie w Win7, gdy używasz NUnit, co jest niezwykle irytujące, gdy robisz jakieś TDD.
Mathias
@stijn: Nie używasz skanera antywirusowego podczas uzyskiwania dostępu? Doooh ...
TheBlastOne
Dzieje się tak również w przypadku VS 2013, kiedy debuguję testy jednostkowe i zatrzymuję kod, zanim VS zakończy wykonywanie testu. Jeśli poczekam kilka dodatkowych sekund, aż VS zwolni testowy biegacz, to się nie stanie.
StingyJack
Może to pomoże: sevenforums.com/tutorials/…
Saturn Technologies

Odpowiedzi:

69

Miałem ten sam problem, ale znalazłem rozwiązanie (dzięki Keyvan Nayyeri ):

Ale jak to rozwiązać? Istnieją różne sposoby w zależności od typu projektu, ale jednym prostym rozwiązaniem, które polecam programistom dodatków programu Visual Studio, jest dodanie prostego kodu do zdarzeń kompilacji projektu.

Możesz dodać następujące wiersze kodu do wiersza polecenia zdarzenia przed kompilacją projektu.

if exist "$(TargetPath).locked" del "$(TargetPath).locked"
if exist "$(TargetPath)" if not exist "$(TargetPath).locked" move "$(TargetPath)" "$(TargetPath).locked"
Stormenet
źródło
U mnie też zadziałało. Miałem ten problem już od jakiegoś czasu.
ritcoder
To działa dla mnie. Wypróbowałem wersję% random% według Vladimira Datsyuka poniżej, ale stwierdziłem, że w moim przypadku jedyny blokowany plik pochodzi z pierwszej kompilacji po uruchomieniu VS, więc wystarczy, że zadziała tylko raz. Jestem na VS 2013 i nie używam też projektanta GUI, tylko duże rozwiązanie z dużą ilością referencji i projektów szablonów T4.
Davos,
5
Musiałem zmienić nazwę WPB też, jak to zostało zablokowane również: if exist "$(TargetDir)$(TargetName).pdb.locked" del "$(TargetDir)$(TargetName).pdb.locked" ,if exist "$(TargetDir)$(TargetName).pdb" if not exist "$(TargetDir)$(TargetName).pdb.locked" move "$(TargetDir)$(TargetName).pdb" "$(TargetDir)$(TargetName).pdb.locked"
Tobias J
U mnie działa również (Visual Studio 2013). Dzięki
Anonimowy
Nadal pracuje nad VS2017. Zaskakujące jest to, że problem nadal występuje w VS2017!
Carvo Loco
24

To nie jest problem z wirusami. Jest to błąd programu Visual Studio 2010. Wygląda na to, że problem jest związany z korzystaniem z Visual Studio GUI Designer.

Sposób obejścia tego problemu polega na przeniesieniu zablokowanego pliku wyjściowego do innego tymczasowego w zdarzeniu przed kompilacją. Sensowne jest losowe generowanie tymczasowej nazwy pliku.

del "$(TargetPath).locked.*" /q 
if exist "$(TargetPath)"  move "$(TargetPath)" "$(TargetPath).locked.%random%"
exit /B 0

W przypadku używania stałych tymczasowych nazw plików po prostu odłożysz blokady:

To obejście działa dokładnie raz

 if exist "$(TargetPath).locked" del "$(TargetPath).locked"
    if exist "$(TargetPath)" if not exist "$(TargetPath).locked" move "$(TargetPath)" "$(TargetPath).locked"

Znalazłem również rozwiązanie z 2 plikami tymczasowymi, które działa dokładnie 2 razy.

Vladimir Datsyuk
źródło
1
Mnie też się to zdarza, ale tylko wtedy, gdy uruchomię aplikację. Podejrzewam, że to system operacyjny pilnuje pliku wykonywalnego w celu buforowania lub z innych powodów. Ponadto wydaje się, że dzieje się tak tylko w przypadku aplikacji, które wywołują System.Reflection.Assembly.GetExecutingAssembly (), przynajmniej w moim przypadku.
TheBlastOne
2
OK, wygląda na to, że dzieje się tak tylko wtedy, gdy ostatnie uruchomienie o nazwie System.Reflection.Assembly.GetExecutingAssembly lub - i to jest nowość - jeśli kod źródłowy dowolnego komponentu czasu projektowania (kod źródłowy dowolnego komponentu czasu projektowania, który jest aktywny na pasku narzędzi komponentu) która wywołuje System.Reflection.Assembly.GetExecutingAssembly w czasie projektowania była otwarta w edytorze, gdy rozpoczęło się ostatnie uruchomienie. Rozumiem?
TheBlastOne
1
Myślę, że ten problem pojawił się nagle ... Teraz zmarnowałem 30 minut swojego życia na próbę zbudowania konfiguracji projektu ... ponieważ mam problemy z blokowaniem! Nawet nie uruchamiam aplikacji ..
GorillaApe
1
stackoverflow.com/questions/3312646/… który dla mnie
zadziałał
1
Dodatkowo dla pliku pbd: del "$(TargetPath).locked.*" /q if exist "$(TargetPath)" move "$(TargetPath)" "$(TargetPath).locked.%random%" del "$(TargetDir)$(TargetName).pdb.locked.*" /q if exist "$(TargetDir)$(TargetName).pdb" move "$(TargetDir)$(TargetName).pdb" "$(TargetDir)$(TargetName).pdb.locked.%random%" exit /B 0
Marv
6

Problem też przyszedł mi do głowy.

Mój scenariusz był taki: Uruchamianie systemu Windows 7 (ale mogło się to również zdarzyć w systemie Windows XP) i podczas pracy nad projektem z kontrolą użytkownika WPF mogłem budować cały czas, aż do otwarcia pliku XAML kontroli użytkownika - stamtąd, ja ' Mam jedną kompilację, a następnie pliki są zablokowane.

Zauważyłem również, że jako administrator uruchomiłem Visual Studio (Devenv.exe), zacząłem uruchamiać Visual Studio bez uprawnień administratora i problem zniknął! .

Daj mi znać, jeśli tobie też pomogło. Powodzenia.

Shani Elharrar
źródło
1
Miałem dokładnie ten sam problem we wszystkich wersjach VS11, ale nie udało mi się jeszcze znaleźć rozwiązania (niestety bez uprawnień administratora nie pomogło). Wszelkie pomysły mile widziane!
Dan Nolan
4

Widziałem to na chciwym oprogramowaniu do skanowania antywirusowego lub jeśli app.exe nie zamyka się poprawnie. Upewnij się, że proces nie jest nadal uruchomiony.

McAden
źródło
3

A co ze skanerami antywirusowymi na twoim komputerze? Czy widzisz procesy, które trzymają uchwyty do twojego pliku (użyj Process Explorer, aby się tego dowiedzieć)?

Może na liście procesów widoczny jest plik „app.exe”, tj. Ostatnia wersja, którą debugowałeś, nadal działa? Podczas tworzenia aplikacji, które mają wiele wątków, może się tak zdarzyć, jeśli nie joinwszystkie z nich.

naiwistów
źródło
3

Miałem ten sam problem i dowiedziałem się, że VS blokuje exe tylko wtedy, gdy otworzyłem Formularz lub UserControl w VS przed budowaniem. Rozwiązanie było dość łatwe, po prostu musiałem zamknąć dowolny Form / UserControl przed zbudowaniem rozwiązania i zadziałało.

Enyra
źródło
3

Oprzyj się na wspaniałej odpowiedzi Stormenet , kładę się mały skrypt, który powinien działać we wszystkich przypadkach.

Oto kod, który należy umieścić w polu tekstowym zdarzenia przed kompilacją

$(SolutionDir)\BuildProcess\PreBuildEvents.bat  "$(TargetPath)"  "$(TargetFileName)"  "$(TargetDir)"  "$(TargetName)"

Wydarzenie przed kompilacją

Oto skrypt do skopiowania w pliku $(SolutionDir)\BuildProcess\PreBuildEvents.bat (oczywiście możesz zmodyfikować tę ścieżkę):

REM This script is invoked before compiling an assembly, and if the target file exist, it moves it to a temporary location
REM The file-move works even if the existing assembly file is currently locked-by/in-use-in any process.
REM This way we can be sure that the compilation won't end up claiming the assembly cannot be erased!

echo PreBuildEvents 
echo  $(TargetPath) is %1
echo  $(TargetFileName) is %2 
echo  $(TargetDir) is %3   
echo  $(TargetName) is %4

set dir=C:\temp\LockedAssemblies

if not exist %dir% (mkdir %dir%)

REM delete all assemblies moved not really locked by a process
del "%dir%\*" /q

REM assembly file (.exe / .dll) - .pdb file - eventually .xml file (documentation) are concerned
REM use %random% to let coexists several process that hold several versions of locked assemblies
if exist "%1"  move "%1" "%dir%\%2.locked.%random%"
if exist "%3%4.pdb" move "%3%4.pdb" "%dir%\%4.pdb.locked%random%"
if exist "%3%4.xml.locked" del "%dir%\%4.xml.locked%random%"

REM Code with Macros
REM   if exist "$(TargetPath)"  move "$(TargetPath)" "C:\temp\LockedAssemblies\$(TargetFileName).locked.%random%"
REM   if exist "$(TargetDir)$(TargetName).pdb" move "C:\temp\LockedAssemblies\$(TargetName).pdb" "$(TargetDir)$(TargetName).pdb.locked%random%"
REM   if exist "$(TargetDir)$(TargetName).xml.locked" del "C:\temp\LockedAssemblies\$(TargetName).xml.locked%random%"
Patrick z zespołu NDepend
źródło
2

Istnieje również znany problem 533411, w którym użycie automatycznej aktualizacji numerów kompilacji może spowodować problem z blokowaniem. Obejście problemu z raportu o błędzie

Tymczasowe obejście polegałoby na wyłączeniu aktualizacji wersji zestawu po przebudowie. W pliku AssemblyInfo.cs usuń symbol wieloznaczny z atrybutu AssemblyVersion, na przykład:
zamień to:
[assembly: AssemblyVersion ("1.4. *")]
[Assembly: AssemblyFileVersion ("1.4")] na
to:
[assembly: AssemblyVersion ("1.4.0.0")]
[zespół: AssemblyFileVersion ("1.4.0.0")]

Robert MacLean
źródło
2

Miałem ten problem i rozwiązałem go za pomocą niestandardowego kodu. Zobacz tutaj: Problemy z blokowaniem plików kompilacji programu Visual Studio 2010

Skompiluj narzędzie w zaakceptowanej odpowiedzi i odwołaj się do niego podczas kroku kompilacji zgodnie z opisem, aby obejść problem. Nadal wyłączam VS 2010 w porze lunchu, żeby posprzątać poranną pracę.

Przyczyną powstania kodu niestandardowego było to, że często zalecane rozwiązanie działało tylko raz, a następnie pliki o zmienionych nazwach zostały również zablokowane, uniemożliwiając zmianę nazwy. Tutaj po prostu dołączamy informacje o czasie do pliku, aby wersje o zmienionych nazwach nie powodowały konfliktów.

Godeke
źródło
0

Jedyną rzeczą, która zadziałała, było zamknięcie programu Visual Studio 2012, usunięcie folderów BIN i OBJ dla projektu, w którym występują problemy, i ponowne otwarcie programu Visual Studio.

Problem rozwiązany ... Do następnego razu.

willem
źródło
0

Jeśli $ (TargetPath) wskazuje na bibliotekę DLL, która używa modelu COM, upewnij się, że masz domyślny konstruktor. Nie wiem, dlaczego domyślny konstruktor nie jest tam wywnioskowany. Dodanie domyślnego konstruktora zadziałało w tym scenariuszu.

Onyximo
źródło
0

Zamknięcie Visual Studio, ponowne otwarcie i ponowne załadowanie najnowszego rozwiązania rozwiązuje ten problem. (Visual Studio 2013 Ultimate)

Sójka
źródło
1
Tak, muszę to robić za każdym razem. to nie jest rozwiązanie
John Demetriou
0

Natknąłem się na to samo, tworząc aplikacje Xamarin w VS2017.

Zdarzyło się, że program Windows Defender blokował exe / dll za pomocą devenv.exe.

Możesz przejść do Win Defender i dodać

devenv.exe
msbuild.exe

do listy wykluczeń procesów.

michael g
źródło
jak się dowiedziałeś, że to obrońca systemu Windows?
Mike
moje rozwiązanie działało przez chwilę, ale okazało się, że jest to w rzeczywistości poważny błąd w nowej wersji aktualizacji VS2017. developercommunity.visualstudio.com/content/problem/54945/…
michael g
0

To jest rozwiązanie, które znalazłem

  1. Usuń zaznaczenie procesu hostingu programu Visual Studio w ustawieniach projektu, jak pokazano poniżej

wprowadź opis obrazu tutaj

  1. Zabij exe. będzie to nazwa_aplikacji.vshost.exe z menedżera zadań

wprowadź opis obrazu tutaj

  1. Teraz możesz przebudować swoją aplikację i uruchomić ją.

Uwaga: możesz ponownie włączyć tę opcję bez żadnych problemów.

Ramankingdom
źródło
0

Udało mi się rozwiązać ten problem, wyłączając skanowanie w czasie rzeczywistym za pomocą McAfee LiveSafe. Mój plik .exe blokował się, jak opisuje OP, i nie miałbym możliwości usunięcia pliku, co oznaczało, że nie mogłem zbudować rozwiązania. Po wyłączeniu funkcji McAfee problem zniknął.

Następnie oczywiście całkowicie odinstalowałem McAfee, który został zainstalowany tylko dlatego, że mój komputer jest nowy i miał już zainstalowany program.

Konrad Skagerberg
źródło
-8

Utworzyłem nowe, puste rozwiązanie i dodałem do niego wszystkie stare pliki. To jakoś rozwiązało problem.

Nieważne
źródło
To nie może być odpowiedź. Inni podali o wiele wyraźniejsze powody problemu i odpowiednie obejścia, które nie wymagają tworzenia nowego pliku rozwiązania, co jest niedopuszczalne podczas pracy z kontrolą wersji, ponieważ historia zostałaby utracona.
Bernhard Hofmann
Tak, to zła odpowiedź. Inni są jeszcze gorsi. Zmiana nazw plików wyjściowych nie jest rozwiązaniem, jest to nieporęczne obejście. Jeśli masz lepsze pomysły, dlaczego nie opublikować odpowiedzi?
Nevermind,
Stworzenie nowego rozwiązania tylko tymczasowo rozwiązało problem za mnie. Wydaje się, że najlepszą odpowiedzią jest Vladimir Datsyuk.
user492238
1
Czy to Twoje rozwiązanie byłoby optymalne, gdybyś miał 15 projektów w jednym rozwiązaniu?
Shittu Joseph Olugbenga