This is the third post on the series “create a macro to Attach to Local IIS”. The last modification I want to implement is the ability to list all the w3wp.exe active processes, if more than one process is present, I want it to show a list of all IIS processes and let the user choose the list of processes to attach to. Clearly if I have no w3wp.exe active processes, or I have only one, there is no need to bother the user to choose the single available process.

Since I need to show a “user interface” from a macro and I’m not allowed to insert form into Visual Studio Macros Editor, I should create a Windows Forms programmatically. This is quite annoying, but creating simple interfaces without a designer is quite simple, so it is the right approach to maintain the code in a simple macro. First of all I find all IIS processes and add info about these processes inside a ListView.

   1: Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger

   2: Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")

   3: Dim processes As EnvDTE.Processes = dbg2.GetProcesses(trans, "")

   4: Dim lvProcesses As New ListView

   5: For Each proc As EnvDTE80.Process2 In processes

   6:     If (proc.Name.EndsWith("w3wp.exe")) Then

   7:         Dim lvi As New ListViewItem

   8:         lvi.Tag = proc

   9:         Dim engineList As String

  10:         lvi.Text = proc.ProcessID

  11:         lvi.SubItems.Add(proc.UserName)

  12:         lvProcesses.Items.Add(lvi)

  13:     End If

  14: Next

To keep a reference to the original EnvDTE80.Process2 object I add the reference to the Tag property of the ListViewItem. Now that I have a ListView populated with all IIS processes, I need to do some check to verify if we have processes available.

   1: If lvProcesses.Items.Count = 0 Then

   2:     Return

   3: End If

   4:  

   5: If lvProcesses.Items.Count = 1 Then

   6:     Dim proc As EnvDTE80.Process2 = lvProcesses.Items(0).Tag

   7:     proc.Attach2()

   8:     Return

   9: End If

As you can see the code is really simple, if I have no valid worker process, I simply return, but if I have a single IIS worker process available, I’ll attach the debugger to it without requiring user input. If I have more than one worker process available I need the user to select the list of the processes he want to attach to.

   1: Dim frm As New Form

   2: Dim btn As New Button

   3: btn.Text = "OK"

   4: btn.DialogResult = DialogResult.OK

   5: frm.Controls.Add(btn)

   6: frm.Width = 700

   7: frm.Text = "Choose IIS worker process to debug"

   8: btn.Dock = DockStyle.Bottom

   9: frm.Controls.Add(lvProcesses)

  10: lvProcesses.Dock = DockStyle.Fill

  11: lvProcesses.View = View.Details

  12: lvProcesses.Columns.Add("ProcessId", 100, HorizontalAlignment.Left)

  13: lvProcesses.Columns.Add("User", 300, HorizontalAlignment.Left)

  14: 'lvProcesses.Columns.Add("Type", 300, HorizontalAlignment.Left)

  15: lvProcesses.FullRowSelect = True

  16:  

  17: If frm.ShowDialog() = DialogResult.OK Then

  18:     For Each fitem As ListViewItem In lvProcesses.SelectedItems

  19:         Dim proc As EnvDTE80.Process2 = fitem.Tag

  20:         proc.Attach2()

  21:     Next

  22: End If

The code is really simple, because it is used only to create a valid Windows Forms interface to show the ListView with Processes info and an OK Button at the bottom to permit to the user to confirm the selection. Now you can start multiple IIS worker process, press the shortcut assigned to this macro and here is the result.

image

Figure 1: The list of all available IIS processes

The User Interface is minimal, I show the process Id and the user that is actually running the process; this last information is really important, because I usually use a different user for each different product I’m working to, so if I need to attach to all IIS processes of a certain product, I immediately can identify all IIS processes that are running with that credential and attach the debugger to the right list of processes.

When the user press OK button, I can iterate through all selected items of the ListView, cast the Tag property to EnvDTE80.Process2 and attach the debugger to the process. As you can see I use the overload version of the Attach2() process that accepts no parameter; this permits me to avoid to specify if I want to debug asp.net 2.0 or 4.0 code, and I can let the debugger choose the right one. Remember that you cannot debug at the same time ASP.NET 4.0 and earlier version, so you could not choose two worker process that are running two different version of the framework.

This post shows clearly that Visual Studio Macro are powerful, yet very simple to use and they can save you huge amount of time automating recurring operations.

Alk.

A file with the complete macro can be downloaded from here. (http://www.codewrecks.com/files/attachtoiis.txt)

Tags: ,