问题
I have an application that runs hosted under the "w3wp.exe" process.
While debugging, I often find myself following these steps:
1 - Make some change
2 - Build the project
3 - Attach to "w3wp.exe" using the "attach to process" dialog under the Tools menu.
4 - Perform some action in the application to make my code execute, so I can step through it in the debugger
I'd like to automate step 3 in the post-build script, so that the IDE automatically attaches to the process after the build is completed. Note that I already launch the application as a part of the post-build process, so I can count on the process existing at this point.
Does anyone know a way to automate the "attach to process" command? Something from the command line would be especially nice, but a macro would do, too.
I'm using Visual Studio 2008 under Windows 7, 64 bit.
Edit @InSane basically gave me the right answer, but it does not work because I need to debug managed code, rather than native code. It seems that vsjitdebugger defaults to Native code, and thus my breakpoint is not hit. From inside the IDE, I can specify "managed code" and the debugger attaches as expected. So is there any way to point vsjitdebugger to managed code?
回答1:
I was finally able to solve this problem with an example I found elsewhere on the internet. I'm sharing it here since this was helpful to me.
1 - Create a new command line application with the below code (this example is in VB.NET).
Option Strict Off
Option Explicit Off
Imports System
'On my machine, these EnvDTE* assemblies were here:
'C:\Program Files (x86)\Common Files\microsoft shared\MSEnv\PublicAssemblies
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Imports System.Threading
Module modMain
Function AttachToProcess(ByVal processName As String, _
ByVal Timeout As Integer) As Boolean
Dim proc As EnvDTE.Process
Dim attached As Boolean
Dim DTE2 As EnvDTE80.DTE2
Try
DTE2 = _
System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.9.0")
For Each proc In DTE2.Debugger.LocalProcesses
If (Right(proc.Name, Len(processName)).ToUpper = processName.ToUpper) Then
proc.Attach()
System.Threading.Thread.Sleep(Timeout)
attached = True
End If
Next
Catch Ex As Exception
Console.Write("Unable to Attach to Debugger : " & Ex.Message)
End Try
Return attached
End Function
Sub Main()
'to call w/ Command Line arguments follow this syntax
'AttachProcess <<ProcessName>> <<TimeOut>>
'AttachProcess app.exe 2000
Dim AppName As String = "w3wp.exe"
Dim TimeOut As Integer = 20000 '20 Seconds
Try
If Environment.GetCommandLineArgs().Length > 1 Then
AppName = Environment.GetCommandLineArgs(1)
End If
If Environment.GetCommandLineArgs().Length > 2 Then
If IsNumeric(Environment.GetCommandLineArgs(2)) Then
TimeOut = Environment.GetCommandLineArgs(2)
End If
End If
Environment.GetCommandLineArgs()
AttachToProcess(AppName, TimeOut)
Console.WriteLine("Attached!!")
Catch Ex As Exception
Console.Write("Unable to Attach to Debugger : " & Ex.Message)
End Try
End Sub
End Module
2 - Open the solution you want to debug in Visual Studio
3 - At the end of your "post-build" events, enter a call to this new utility, as in:
c:\AutoAttach.exe w3wp.exe 20000
4 - Build your application
回答2:
You can try the following command from the Windows command line.
If it works as you expect, you can put it as part of your postbuild steps.
ProcessID is the ID of the process you have launched that you want to attach to.
vsjitdebugger.exe -p ProcessId
Other options for using this from the command line include :-
回答3:
Here is a PowerShell function inspired by @JosephStyons's answer. Works with any VS version without changes.
function Debug-ProcessVS([int] $processId)
{
$vsProcess = Get-Process devenv | Select-Object -First 1
if (!$vsProcess) {throw "Visual Studio is not running"}
$vsMajorVersion = $vsProcess.FileVersion -replace '^(\d+).*', '$1'
$dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE.$vsMajorVersion.0")
$debugee = $dte.Debugger.LocalProcesses | ? {$_.ProcessID -eq $processId}
if (!$debugee) {throw "Process with ID $processId does not exist."}
$debugee.Attach()
}
回答4:
Here is improved version of Joseph. I added this: -dont show console (Set on your Project in "Application" the Output Type to "Windows Application".) - i set timeout command line argument to 0 (why is it needed at all?) - added third command line arg url, which is launched with firefox, but only after site is first loaded internally in program. this is because some sites, especially dotnetnuke, take long time to load after compile. so this way firefox will bring you into foreground firefox browser only after everything is ready to test, it takes up to 1 minute on my computer. you can work on something else in the mean time. PS. this stackoverflow editor is a little dumb. thats why this text is not formatted pretty. if i add list bulletins code below doesnt show as code.
Option Strict Off
Option Explicit Off
Imports System
'On my machine, these EnvDTE* assemblies were here:
'C:\Program Files (x86)\Common Files\microsoft shared\MSEnv\PublicAssemblies
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Imports System.Threading
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Net
Module modMain
Function AttachToProcess(ByVal processName As String, _
ByVal Timeout As Integer) As Boolean
Dim proc As EnvDTE.Process
Dim attached As Boolean
Dim DTE2 As EnvDTE80.DTE2
Try
DTE2 = _
System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.11.0")
For Each proc In DTE2.Debugger.LocalProcesses
If (Right(proc.Name, Len(processName)).ToUpper = processName.ToUpper) Then
proc.Attach()
System.Threading.Thread.Sleep(Timeout)
attached = True
Exit For
End If
Next
Catch Ex As Exception
Console.Write("Unable to Attach to Debugger : " & Ex.Message)
End Try
Return attached
End Function
Sub Main()
'to call w/ Command Line arguments follow this syntax
'AttachProcess <<ProcessName>> <<TimeOut>>
'AttachProcess app.exe 2000
Dim AppName As String = "w3wp.exe"
Dim TimeOut As Integer = 20000 '20 Seconds
Dim Url As String = "http://www.dnndev.me/"
Try
If Environment.GetCommandLineArgs().Length > 1 Then
AppName = Environment.GetCommandLineArgs(1)
End If
If Environment.GetCommandLineArgs().Length > 2 Then
If IsNumeric(Environment.GetCommandLineArgs(2)) Then
TimeOut = Environment.GetCommandLineArgs(2)
End If
End If
If Environment.GetCommandLineArgs().Length > 3 Then
Url = Environment.GetCommandLineArgs(3)
End If
Environment.GetCommandLineArgs()
AttachToProcess(AppName, TimeOut)
'Console.WriteLine("Attached!!")
'load site for faster opening later
Using client = New WebClient()
Dim contents = client.DownloadString(Url)
End Using
'open site in firefox
Dim ExternalProcess As New System.Diagnostics.Process()
ExternalProcess.StartInfo.FileName = "c:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"
ExternalProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized
ExternalProcess.StartInfo.Arguments = "-url " & Url
ExternalProcess.Start()
'ExternalProcess.WaitForExit()
Catch Ex As Exception
Console.Write("Unable to Attach to Debugger : " & Ex.Message)
End Try
End Sub
End Module
来源:https://stackoverflow.com/questions/3860860/attach-to-process-as-a-post-build-event