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:

1
msvsmon /allow user@computer

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:

  1. W Visual Studio otwórz Debug > Attach to Process (Ctrl+Alt+P).
  2. Ustaw Connection type na Remote (Windows).
  3. 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.
  4. 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ć.
  5. 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.
  6. 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:

StatusCo oznaczaNaprawa
Skipped loading symbolsŁadowanie symboli jest odfiltrowane przez twoje ustawieniaSprawdź 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ągalnySkopiuj 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 heksyModuł w ogóle nie ma informacji debugowychZbudowano 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.

Powiązane artykuły