Friday, May 23, 2008 10:21 AM
Remote debugging ASP.NET applications using Visual Studio 2008
If you have recently upgraded a Visual Studio .NET 2003 ASP.NET application project or a Visual Studio 2005 Web Application project to a Visual Studio 2008 ASP.NET Web Application project you may have noticed the following popup. Needless to say this makes it a little more difficult to connect remotely to your project in order to run and debug it:
At this point I can only guess as to why connecting to a remote web application project no longer seems to work. I do have a few guesses but I won't bother mentioning what they are because inevitably somebody will tell me my guesses are wrong. Instead I thought I would share with you a relatively simple way to get back to work and remotely debug anyway.
In a nutshell, to remotely debug we want to run two instances of Visual Studio. One will be the "debugger" instance, and the other will be the "editor/compiler" instance.
Here are the steps.
- Install the Visual Studio 2008 Remote Debugger on your remote machine. You can find the installation file in the Remote Debugger folder on your Visual Studio 2008 installation disk.
- Once you have the remote debugger installed, run Visual Studio 2008 Remote Debugger Configuration Wizard from the start menu of the remote machine.
- Choose Run the "Visual Studio 2008 Remote Debugger" service. You could try running individual instances of the debugger but you may run into user rights or permissions related issues. Personally I prefer easy versus difficult. Your choice though.
- Leave the service user as LocalSystem and leave the password blank then click Next.
- If you see a Configure the Windows Firewall for Debugging option, choose the available option to suit your needs then click Next then Finished.
- Next in order to prepare your old project to be opened with minimal problems, open your vbproj or csproj file in notepad and remove the "IISUrl" related settings then save the project file.
- Back on your local workstation, open Visual Studio 2008 then click File --> Open --> Project\Solution... and browse to the UNC path where the project or solution file resides.
You can leave the Web settings for the project properties set to Use Visual Studio Development Server or Use IIS Web server. It does not matter since we aren't going to be launching the project that way. If you do choose to create a virtual directory you will to create it locally on your workstation of course to avoid the error mentioned above. This will actually create a virtual directory that points to the UNC path where your content lives.
This first instance of Visual Studio will be used to edit source files and compile the application as necessary.
From your local workstation, open a second instance of Visual Studio 2008 but do not open any projects.
Click Tools --> Attach to process...
Enter the appropriate remote server name in the Qualifier textbox then click the Refresh button near the bottom.
Choose the correct remote process (aspnet_wp.exe or w3wp.exe for example) and click Attach
- Example: \\someserver\C$\inetpub\wwwroot\RemoveWebApp\myapp.csproj
- Note: If you are not an administrator on the remote machine then you cannot use the adminitrative "C$" share. Instead you will need to ask the administrator to create a share for you.
- Note: If you are not an administrator on the remote machine you will also need to ask the administrator to add you to the "Debugger Users" group.
Click File --> Open --> File and open the source file that you want to debug from your UNC path.
- If there are multiple w3wp.exe processes running and you aren't sure which to pick you can run "cscript c:\Windows\System32\iisapp.vbs" on the remote machine to get the right PID. iisapp.vbs simply lists the running W3WP.exe processes along with their Application Pool name and PID.
- If there are *no* processes running that you know you need to attach to, then you should make at least one request to http://someServer/RemoteWebApp" in order to spawn the worker process.
- To make retrieving the PID a little easier I have included some sample VBS code below to get it for you.
Set a breakpoint somewhere.
This second instance of Visual Studio will be used to "debug" your project
Open IE and request your page and you should break at the desired location.
- Example: \\remotemachine\C$\inetpub/wwwroot\RemoveWebApp\Default.aspx.cs
NOTE: Something you might want to do to avoid the need to attach over and over while writing your code is to disable the idle timeout settings and possibly the recycling settings of the application pool that your ASP.NET application is using in IIS. To find which application pool your application is using you need to go to the remote server and open the IIS manager. Then go into your application's properties and look at either the "[Virtual] Directory" tab or "Home Directory" tab depending on whether it is a web site or directory level application.
To find the application pool name go into the properties of your application.
To disable the AppPool idle timeout go into the properties of the correct AppPool:
And finally... here is a script I wrote to make obtaining your remote PID a little easier. To use this:
- Copy/paste the text below into notepad
- Save the file with a VBS extension
- Edit the first 3 variables machineName, appPoolName, and url so they are correct for your remote server.
- Run this from your workstation.
machineName = "remoteMachineName" 'This to your remote machine.
appPoolName = "DefaultAppPool" 'This is the AppPool your ASP.NET is using.
url = "http://remoteMachineName/" 'This is the URL that will launch your AppPool
wmiPath = "winmgmts://" & machineName & "/root/cimv2"
wmiQuery = "SELECT * FROM Win32_Process WHERE Name='w3wp.exe'"
' Code execution begins
Set wmiObj = GetObject(wmiPath)
Set wpList = wmiObj.ExecQuery(wmiQuery)
response = AskAboutRequestingPage()
If (response = vbYes) Then
MsgBox "Unable to locate PID for '" & appPoolName & "'"
message = ""
For Each wp In wpList
name = GetAppPoolId(wp.CommandLine)
If (UCase(appPoolName) = UCase(name)) Then
message = message & vbCrLf & " " & wp.ProcessID
If (message <> "") Then
MsgBox "'" & appPoolName & "' is running under the following PID(s):" & message
On Error Resume Next
Set re = New RegExp
re.Pattern = "-ap ""(.+)"""
re.IgnoreCase = True
Set Matches = re.Execute(strArg)
Set SubMatches = Matches(0).Submatches
strPoolId = Submatches(0)
GetAppPoolId = strPoolId
message = "'" & appPoolName & "' is not currently running on '" & machineName & "'. Would you like to make a request to '" & url & "' in order to spawn the process?"
style = vbYesNo + vbCritical + vbDefaultButton2
title = "AppPool not running"
AskAboutRequestingPage = MsgBox(message, style, title)
Dim ie: Set ie = WScript.CreateObject("InternetExplorer.Application", "Ie_")
ie.Visible = True
Set ie = Nothing
Sub Ie_NavigateComplete2(ByVal pDisp, URL)