How can I make a Visual Studio Macro to attach the debugger to all instances of w3wp.exe?
-
03-07-2019 - |
Question
I'm normally developing web apps, and a surprisingly large amount of my work time is spent doing "Ctrl + Alt + P", sorting by Process Name, and picking w3wp.exe to attach my debugger.
To make matters worse, I'm working on an app that spans several application pools, so I normally have 2 or 3 instances of w3wp.exe, and it's impossible to know which one to attach to, so I normally end up attaching to all of them, which is overkill but works.
All in all, this is pretty annoying...
My colleague figured out a way to have a VS Macro to automatically attach to w3wp.exe (he basically recorded this):
Sub AttachMacro()
Try
Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
Dim dbgeng(3) As EnvDTE80.Engine
dbgeng(0) = trans.Engines.Item("T-SQL")
dbgeng(1) = trans.Engines.Item("T-SQL")
dbgeng(2) = trans.Engines.Item("Managed")
Dim proc2 As EnvDTE80.Process2 = dbg2.GetProcesses(trans, "ENIAC").Item("w3wp.exe")
proc2.Attach2(dbgeng)
Catch ex As System.Exception
MsgBox(ex.Message)
End Try
End Sub
I'm not really sure whether all that is necessary, or anything, I have never made a macro for VS, I don't really know where to start.
Would there be a way to modify this macro so that instead of attaching itself to an instance of w3wp.exe, it will attach itself to all instances of w3wp.exe?
Solution
Sub MacroAttachToAllProcesses()
Try
Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
Dim dbgeng(3) As EnvDTE80.Engine
dbgeng(0) = trans.Engines.Item("T-SQL")
dbgeng(1) = trans.Engines.Item("T-SQL")
dbgeng(2) = trans.Engines.Item("Managed")
For Each theProcess As EnvDTE80.Process2 In dbg2.GetProcesses(trans, "COMPUTERNAME")
If theProcess.Name.Contains("w3wp.exe") Then
theProcess.Attach2(dbgeng)
End If
Next
Catch ex As System.Exception
MsgBox(ex.Message)
End Try
End Sub
OTHER TIPS
I know that you are looking for a Macro for this task, and I have similar macros. However I would like to explain a way to attach the debugger to the projects in your solution when you start to debug.
It's a little known feature - if you right-click on your solution file in the solution browser, Choose properties, you can then define multiple startup projects and their action. Your debugger will attach to the listed projects when you run it.
Note: If you have a web-service it will open a browser window, however you can disable that in the properties of the project by telling it not to open a window.
This is how I attach to a remote w3wp process. It runs a bit quicker than DanC's solution and has some extra error handling.
Private Sub AttachToW3wp(ByVal machineName As String)
' In order for this to work, you have to be running the Visual Studio 2010 Remote Debugging Monitor
' as your (domain) user.
' It won't work if the remote debugger is running as a service. I've tried every permutation of
' domain and username in the the transport qualifier, tried the obvious local system username,
' even tried looking at the network traffic
' in WireShark, I can't figure it out how to make it work if you are running as a service.
' If you are running the debugger as a service, even running the macro that gets created by VS's
' macro recorder when you attach to a process doesn't work.
Dim transportQualifier = machineName
Try
Dim processToAttachTo As String = "w3wp.exe"
Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
Dim dbgeng(2) As EnvDTE80.Engine
dbgeng(0) = trans.Engines.Item("T-SQL")
dbgeng(1) = trans.Engines.Item("Managed (v2.0, v1.1, v1.0)")
Dim processesRemote = dbg2.GetProcesses(trans, transportQualifier)
Dim attached As Boolean = False
Dim processRemote As EnvDTE80.Process2
For Each processRemote In processesRemote
' For some reason it takes a much longer time to get the remote process names then it
' does the user name, so let's skip over all the processes that have the wrong UserName.
If processRemote.UserName = "NETWORK SERVICE" AndAlso _
(Right(processRemote.Name, Len(processToAttachTo)) = processToAttachTo) Then
If processRemote.IsBeingDebugged Then
MsgBox(processToAttachTo & " on " & machineName & " is already being debugged")
Else
processRemote.Attach2(dbgeng)
End If
attached = True
End If
Next
If Not attached Then
MsgBox(processToAttachTo & " is not running on " & machineName & ".")
End If
Catch ex As System.Exception
MsgBox("Exception attempting to attach to " & transportQualifier & ": " & ex.Message)
End Try
End Sub
You may want to check out gflags.exe. One of its options is a debugger to run attached to every invocation of a particular executable.