Bug odtwarza się na serwerze testowym, a nie na twoim laptopie. Serwer testowy nie ma Visual Studio, a instalowanie tam pełnego IDE, żeby ustawić jeden breakpoint, nie wchodzi w grę. Debugowanie zdalne jest zrobione właśnie na taki przypadek. Mały samodzielny program działa na maszynie docelowej, twoje lokalne Visual Studio łączy się z nim przez sieć, a ty dostajesz breakpointy i podgląd zmiennych na procesie, który nie działa nigdzie w pobliżu twojego biurka.
Są trzy kroki: uruchomienie remote debuggera na celu, podpięcie się z Visual Studio i załadowanie pasujących symboli. Każdy z nich zawodzi na swój specyficzny sposób. Po nich omówione są dwa cele zdalne, na które trafisz najczęściej w praktyce: proces w kontenerze Docker i aplikacja na Azure App Service.
Jak zainstalować i uruchomić Visual Studio Remote Debugger (msvsmon)
Program nazywa się msvsmon.exe, Visual Studio Remote Debugger. Na maszynę
docelową możesz go przenieść na dwa sposoby.
Jeśli na celu jest już zainstalowane Visual Studio Community, Professional
albo Enterprise, msvsmon.exe już tam jest, w
<folder instalacji Visual Studio>\Common7\IDE\Remote Debugger\x64\ (albo
x86\, zależnie od architektury, którą debugujesz). Uruchom go bezpośrednio.
W przeciwnym razie pobierz samodzielny pakiet remote tools ze strony Microsoftu z remote tools dla twojej wersji Visual Studio i weź jego najnowszy update. Kompatybilność działa tylko w jedną stronę: nowsze remote tools współpracują ze starszym Visual Studio, ale starsze remote tools mogą odmówić współpracy z nowszym. Wybierz architekturę systemu docelowego (x86, x64 albo ARM64), nie architekturę aplikacji, którą debugujesz.
Pierwsze uruchomienie otwiera kreatora konfiguracji, który dodaje regułę Windows Firewall dla typu sieci, na jakiej jesteś (domenowa, prywatna albo publiczna). Gdy skończy, okno Remote Debuggera pokazuje nazwę serwera i port. Ten adres wpiszesz potem w Visual Studio. Zostaw okno otwarte; zamknięcie go (File > Exit) kończy sesję.
Porty i uwierzytelnianie remote debuggera: co blokuje połączenie
Reguła firewalla dodana przez kreatora otwiera tylko port TCP przychodzący, a ten port zmienia się wraz z wersją Visual Studio. Dla Visual Studio 2022 to 4026; starsze wersje używają innych numerów. Jeśli cel siedzi za firewallem, którego kreator nie skonfigurował, na przykład za firmowym appliance’em albo cloudową security group, otwórz ten konkretny port sam. Zgadywanie “portu debuggera” bez sprawdzenia swojej wersji to strata czasu.
UDP 3702 wychodzący jest opcjonalny. Pozwala celowi pojawić się w oknie Find w Visual Studio. Bez niego nadal możesz się połączyć — po prostu wpisujesz adres ręcznie.
Tryb uwierzytelniania musi być zgodny po obu stronach. Domyślnie remote
debugger używa Windows Authentication, więc konto Windows, na którym działa
Visual Studio, potrzebuje uprawnień na remote debuggerze. Nadaj je z
Tools > Permissions w oknie Remote Debuggera (wymagane uprawnienia
administratora) albo uruchom msvsmon z linii komend, od razu z
dopuszczonym kontem:
| |
Przełączenie na No Authentication (Tools > Options w oknie Remote Debuggera) pomija to wszystko i na jednorazowej maszynie wirtualnej kusi. Rób to tylko w sieci, której ufasz w pełni. Każdy, kto dosięgnie ten port, może podpiąć się pod dowolny proces działający na tym samym koncie: bez pytania, bez hasła.
Jak podpiąć się pod zdalny proces z Visual Studio
Mając uruchomiony i osiągalny remote debugger:
- W Visual Studio otwórz Debug > Attach to Process (
Ctrl+Alt+P). - Ustaw Connection type na Remote (Windows).
- W Connection target wpisz adres w formacie, jaki pokazuje samo okno
remote debuggera, zwykle
<nazwa-maszyny>:<port>. Jeśli nazwa maszyny się nie rozwiązuje, użyj IP:10.0.0.15:4026. - Kliknij Refresh, żeby pobrać listę procesów ze zdalnej maszyny, potem znajdź i wybierz swój proces. Jeśli nie działa na twoim koncie, zaznacz Show processes from all users. Visual Studio pokazuje ostrzeżenie bezpieczeństwa przed podpięciem się pod proces należący do kogoś innego — przeczytaj je, zamiast od razu odklikiwać.
- Zostaw Code type na Automatic. Wyjątkiem jest proces z mieszanym kodem, gdzie podpięcie się cicho zawodzi dla jednego języka: wybierz wtedy ten język jawnie i podepnij się ponownie, a dostaniesz konkretny błąd zamiast niczego.
- Kliknij Attach.
Dla aplikacji ASP.NET hostowanej na IIS proces, którego szukasz, to
w3wp.exe. Dla aplikacji .NET z własnym serwerem Kestrel to dotnet.exe
albo nazwa własnego pliku wykonywalnego aplikacji. IIS często uruchamia
kilka identycznych procesów w3wp.exe obok siebie. Kolumna Command Line
na liście procesów mówi, który jest który.
Jak naprawić “no symbols loaded” przy debugowaniu zdalnym
Podpięcie się nie znaczy jeszcze, że możesz debugować. Otwórz Debug > Windows > Modules i sprawdź kolumnę Symbol Status przy swoim binarce. Pusty czerwony okrąg zamiast wypełnionego przy breakpoincie mówi to samo z poziomu edytora: debugger nie ma symboli, do których mógłby zmapować ten breakpoint.
W praktyce pojawiają się trzy statusy:
| Status | Co oznacza | Naprawa |
|---|---|---|
Skipped loading symbols | Ładowanie symboli jest odfiltrowane przez twoje ustawienia | Sprawdź Debug > Options > Symbols pod kątem reguły include/exclude blokującej ten moduł |
Cannot find or open the PDB file | Żaden pasujący plik .pdb nie jest osiągalny | Skopiuj dokładny .pdb z builda, który wyprodukował wdrożoną binarkę, na maszynę zdalną, albo wskaż go ręcznie w Visual Studio |
| Brak wpisu / same surowe heksy | Moduł w ogóle nie ma informacji debugowych | Zbudowano go w Release bez .pdb, albo to systemowa DLL, której nie musisz debugować |
Większość straconego tu czasu bierze się z jednej zasady: debugger
akceptuje wyłącznie .pdb, który dokładnie pasuje do binarki. Nie “tę samą
wersję”. Plik z tego konkretnego builda. Jeśli maszynę zdalną wdrożono
ponownie po twoim ostatnim lokalnym buildzie, twój lokalny .pdb już nie
pasuje. Gdy automatyczne ładowanie go nie znajdzie, kliknij prawym na moduł
w oknie Modules, wybierz Load Symbols i wskaż folder wyjściowy tego
konkretnego wdrożenia.
Nawyk, który temu wszystkiemu zapobiega: wysyłaj .pdb razem z binarką przy
każdym wdrożeniu, które możesz potrzebować debugować. Odtworzenie pasującego
pliku po fakcie rzadko się udaje.
Jak debugować proces w kontenerze Docker
Wszystko powyżej zakłada maszynę z Windows, na której możesz instalować
oprogramowanie. Kontener to co innego. Nie wrzucasz msvsmon do produkcyjnego
obrazu, a zależnie od konfiguracji
sieci Docker
kontener może nawet nie być osiągalny z hosta po nazwie.
Jeśli projekt ma włączone wsparcie Dockera (Add > Docker Support, albo
projekt już wcześniej zbudowany z Dockerfile), narzędzia kontenerowe
Visual Studio robią całą robotę: F5 buduje obraz skonfigurowany do
debugowania, startuje kontener i podpina się. Dla kontenera, którego nie
uruchomiłeś z Visual Studio, otwórz Debug > Attach to Process, ustaw
Connection type na Docker (Linux Container) albo
Docker (Windows Container), dopasowując do obrazu, i wybierz kontener z
listy. Visual Studio idzie przez daemon Dockera i wstawia własny debugger do
działającego kontenera, więc sam nigdy nie dodajesz go do obrazu.
Jak debugować zdalnie aplikację na Azure App Service
Dla aplikacji wdrożonej na Azure App Service pomiń ręczną konfigurację remote debuggera. Kliknij prawym na projekt w Solution Explorer, wybierz Publish, a potem z menu … profilu publikacji wybierz Attach Debugger. Visual Studio włącza endpoint debugowania zdalnego na instancji App Service i obsługuje za ciebie połączenie i uwierzytelnianie. Po podpięciu się zasady symboli z poprzednich sekcji nadal obowiązują. Sprawdź okno Modules, zanim zaufasz breakpointowi.
Remote debugger czy git bisect: czego użyć najpierw
Remote debugger mówi, co robi konkretna linia kodu w tej chwili, na
konkretnej maszynie. Nie powie ci, który commit wprowadził problem.
git bisect
odpowiada właśnie na to, przez binarne przeszukiwanie historii zamiast
przeszukiwania własnej pamięci.
Przy regresji uruchamiaj je w tej kolejności. Jeśli jeszcze nie wiesz, który commit coś zepsuł, zacznij od bisecta. Gdy masz już commit i maszynę, na której bug się odtwarza, ustaw tam remote debugger i sprawdź dlaczego.