Remote Debugging Summary
Dmitri Leonov, Microsoft Corporation
This article summarizes and brings up to date existing information available on MSDN and in blogs related to remote debugging. The purpose of the article is to help developers understand what the supported remote debugging scenarios and limitations are and take full advantage of Visual Studio capabilities that are currently available.
Debugging applications running in production or test environments comes with additional challenges for developers. In case of a crash debugging, the process dump can help identify the code defect. Sometimes the root cause of the issue is not clear from the dump, so live debugging becomes necessary. For investigating functional defects, live debugging is usually required. However, it is not always possible or convenient to install Visual Studio on every production or test machine in question. Multi-tier application development often requires debugging processes that run on different machines at the same time.
Visual Studio remote debugging has a client-server architecture with the Visual Studio IDE (devenv.exe) on the client (local) side and Visual Studio Remote Debugging Monitor (MSVSMON.exe) on the server (remote) side. The latter serves requests, such as launch or attach to a remote process, from Visual Studio IDE. Native, managed, mixed and T-SQL debugging are supported for remote processes with x86, x64 and ia64 architectures. MSVSMon comes in three different versions: x86, x64 and IA64 to match the target platform of the process being debugged (target process).
Communication between Visual Studio IDE and Remote Debugging Monitor is done using one of two possible transport types:
Default transport (that uses authentication and encryption and works with all supported debug engines). It uses TCP port 135 (DCOM).
No-authentication transport that works only for native debugging. Uses TCP connection (dynamic ports).
No-authentication transport can present a security risk, especially when used outside of an isolated network. When enabling the no-authentication transport, the maximum idle time is set to 900 seconds (15 minutes). If no connection is made during that time, MSVSMon will exit.
It is important to note that for either of the transport types, network connection is initiated from both sides: first from the Visual Studio IDE to the remote machine, then MSVSMon initiates another connection back to the local machine.
To enable remote debugging, the Remote Debugging Monitor (msvsmon.exe) needs to be running on the remote machine.
Msvsmon.exe, and the [Obsolete] Remote Debugging Components, can be found on the client machine in this folder:
InstallPath\Microsoft Visual Studio 10.0\Common7\IDE\Remote Debugger
This folder can be shared to the remote machine.
Running the Remote Debugging Monitor from a file share is the easiest way to enable remote debugging. Certain scenarios however require running MSVSMon as a service, which is done by installing the remote debugging components. The Remote Debugging installer is located in the Remote Debugger folder on the Visual Studio installation media. It creates a copy of the components and installs the Remote Debugging configuration wizard. The wizard configures the firewall for remote debugging and allows the Remote Debugging monitor to run as a service. This installation step is needed even when Visual Studio is installed on the remote machine (Remote Debugging installation is not part of the Visual Studio 2010 installation).
Remote Debugging monitor normally should run with elevated permissions so that it can debug other elevated processes or processes run by other users, such as Local Service or other Windows built-in identity.
There can be several instances of MSVSMon with different server names running on the same remote machine. This is needed, for example, when both x64 and x86 processes need to be debugged on an x64 machine. When msvsmon.exe starts, it tries to get the default server name that has the form <username>@<machine name> in the default transport case. If the default server name is taken, the user is prompted to enter a unique name. The machine part of the name does not change; it has to be the actual machine name:
In no-authentication mode, the port number can be changed from the default value (4015) to a different value.
Remote Debugging uses TCP port 135 (DCOM) by default. In addition, UDP ports 4500 and 500 must be opened on both machines if they are in a domain with IPSec. Visual Studio (devenv.exe) and the Remote Debugging Monitor (msvsmon.exe) need to be added to firewall exceptions lists. On the remote machine, File and Printer Sharing need to be allowed (the following ports: TCP 139, TCP 445, UDP 137, and UDP 138).
Visual Studio Setup does not configure firewall for remote debugging, so when first attempt is made to connect to a remote machine (such as attach to a remote process), the OS would bring up a warning dialog like this:
After confirmation from the user, the ports get opened and the connection should be established immediately. To configure the firewall in advance, the user can set up Remote Debugging Components and run Remote Debugger Configuration Wizard (it runs automatically during initial setup) which makes the necessary changes in the firewall settings. These changes are the same for the client and remote machine.
If for some reason this does not work (due to OS configuration or third-party software), the firewall needs to be configured manually to open the above ports and add exceptions for devenv.exe on the client machine and msvsmon.exe on the remote machine. For more information, see How to: Configure the Windows 7 Firewall for Remote Debugging.
Remote Debugging Functionality can be divided into these major types of scenarios:
Attaching to a remote process
Launching a remote process
Auto attach scenarios:
Automatically attaching to a hosted service called from a WCF client.
Automatically attaching to IIS worker process when starting debugging a Web project.
Attaching to a remote process
This can be done using Visual Studio’s Attach to Process command from the Tools menu. In the dialog box, the Qualifier field corresponds to the Server name that identifies an instance of Remote Debugging Monitor (msvsmon.exe) on the remote machine.
Launching a remote process
This basically means that the remote process gets launched on the remote machine when you press F5 on the client machine. The Start Debugging command is done by changing project’s Debug properties where "Remote Server Name" or "remote machine" again correspond to an instance of msvsmon.exe, and "Remote Command" or "external program" contain the path (on the remote machine) to the executable that will be launched. For Visual C++ projects, the connection (transport type) is also specified:
When debugging a project that implements a WCF client, the debugger allows stepping into service code by automatically attaching to the service process (usually IIS worker process). This feature works both locally and remotely. As a result, a logical call stack is shown that contains server and client frames on top of each other:
Also, when debugging an ASP.NET Web project that is part of the solution, the debugger automatically attaches to the IIS worker process on Start Debugging (F5) command.
To enable these scenarios, MSVSMon needs to run as a service on the remote machine, which can be done by running the Remote Debugging Configuration Wizard (see above). The service instance of MSVSMon is not intended to co-exist with task instances on the same machine. Also, it is not intended to be used for manual launching or attaching.
Debugging outside of network isolated by IPSec.
Remote debugging between domains without two-way trust is, in general, supported by using local user accounts (see Troubleshooting Steps). However, Internet protocol Security (IPSec) may interfere with this scenario due to the bi-directional communication in remote debugging. So, when the local machine is in an isolated network (where IPSec prevents inbound connections from untrusted sources), and the remote machine is outside of it, remote debugging will not work unless some workaround is in place, such as VPN or a boundary zone.
Debugging across local networks.
Network connections with high latency (50 millisecond and longer ping times) are poorly supported due to the synchronous communication between the IDE and MSVSMon. So for example, stepping will be slow on such connections due to multiple round-trip communications performed for every stepping command.
No-authentication transport over IPv6 network.
No-authentication transport relies on IPv4 protocol and is not supported on pure-IPv6 networks. Default transport is supported on IPv6.
Local Symbol loading.
The symbols are loaded and cached on the remote machine for managed debugging and on the client machine for native debugging. In mixed debugging, symbols for mixed-mode binaries are loaded and cached on both machines.
Firewall is not configured correctly.
When trying to launch or attach to a remote process, the following error messages indicate that the firewall is not configured correctly on the remote machine:
Sometimes the firewall on the local machine prevents MSVSMon from connecting back to it:
To configure the firewall on the local or on the remote machine, follow the steps in How to: Configure the Windows Vista Firewall for Remote Debugging.
Debugging without domain accounts.
In cases when there are no domain accounts that can authenticate on both machines, local user accounts must be used. In order for authenticated transport to work, the users running devenv and MSVSMon should have identical usernames and identical passwords. (MSVSMon must be run by a local user account, devenv may be run by a domain account but local account still needs to be present on the client machine.)
Debugging a process run by a different user.
The user running Visual Studio IDE is trying to attach to a remote process running by a different user. The following error appears when the first user does not have the permissions to debug on the remote machine. The error appears when trying to get the list of available processes:
After explicitly adding the permissions, the list of processes gets populated but it may still be impossible to attach to the process:
This is because MSVSMon is not running with elevated privileges (as Administrator). This happens for example when using the runas command.
"Security package error" when trying to connect to a Windows XP machine.
On a domain-joined Windows XP machine you may experience this issue. When using default transport and trying to connect to MSVSMon, connection fails with an error message like this:
"Unable to connect to the Microsoft Visual Studio Remote Debugging Monitor named 'DOMAIN\username@MACHINE'. A security package specific error occurred." This is a Windows bug for which a hotfix was released in 2009. If a workaround is still needed, local user accounts can be used. These steps do that:
Visual Studio box: net user <your_alias> <your_password> /add
Target box: net user <your_alias> <your_password> /add
Target box: net localgroup administrators <computer_name>\<your_alias> /add
Target box: runas /user:<computer_name>\<your_alias> <path_to_msvsmon>
Visual Studio box: enter <your_alias>@<target_computer_name> (instead of just the target computer name)
Auto-attaching to IIS worker process on newer OS’s.
Windows 7 and Windows Server 2008 R2 introduced a change in the default configuration of Internet Information Services (IIS). On these OS’s IIS worker process (w3wp.exe) by default runs under a unique identity that corresponds to the application pool. This change interferes with Visual Studio’s auto-attach functionality. When the user attempts to step into server code, a security warning appears.
To avoid this warning, IIS can be reconfigured to run under a Windows built-in identity such as NETWORKSERVICE.
Remote debugging in Visual Studio 2010 allows you to debug processes that run on different computers at the same time. With the information in this white paper, you can correctly configure your computers for remote debugging, as well as learn how to trouble-shoot common remote debugging errors.