作为一个后期构建事件,“Attach to Process”是什么意思?

7
我有一个应用程序,运行在“w3wp.exe”进程下。
调试时,我经常按照以下步骤操作:
1- 进行一些更改
2- 构建项目
3- 在“工具”菜单下的“附加到进程”对话框中附加到“w3wp.exe”。
4- 执行某些操作使我的代码执行,以便我可以在调试器中逐步执行它。
我想在后期构建脚本中自动化第3步,以便IDE在构建完成后自动附加到该进程。请注意,我已经在后期构建过程中启动了应用程序,因此我可以保证此时该进程存在。
有人知道如何自动化“附加到进程”命令吗?从命令行中获取信息会非常好,但宏也可以。
我正在使用Windows 7,64位下的Visual Studio 2008。
编辑: @InSane基本上给出了正确答案,但它不起作用,因为我需要调试托管代码而不是本机代码。看起来vsjitdebugger默认为本机代码,因此我的断点没有被触发。从IDE内部,我可以指定“托管代码”,调试器会按预期附加。那么有没有办法将vsjitdebugger指向托管代码?
4个回答

7

我最终在网上找到一个例子解决了这个问题。我在这里分享它,因为它对我很有帮助。

1 - 使用以下代码创建一个新的命令行应用程序(此示例使用 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 - 在Visual Studio中打开您想要调试的解决方案。

3 - 在“后生成”事件的末尾,输入对这个新实用程序的调用,如下所示:

c:\AutoAttach.exe w3wp.exe 20000

4 - 构建您的应用程序


2
我们需要根据相应的Visual Studio版本更新字符串“VisualStudio.DTE.9.0”。对于Visual Studio 2012,它将是“VisualStudio.DTE.11.0”。 - NavaRajan
对于Visual Studio 2015,它将是“VisualStudio.DTE.14.0”。 - bluray

2
你可以尝试从Windows命令行执行以下命令。如果符合您的预期,您可以将其作为后构建步骤的一部分。ProcessID是您要附加到已启动的进程的ID。
vsjitdebugger.exe -p ProcessId 

使用命令行的其他选项包括:- alt text


1
点赞支持这个好建议,但它并不完全有效。如果我使用那个命令,它会问我是否要使用当前的调试器还是启动一个新的调试器。我选择当前的调试器,它会花费一些时间来思考,但随后我设置的任何断点都会出现“当前不会触发断点。此文档尚未加载任何符号。” 如果我在IDE中手动选择相同的进程,则断点会正确设置。有什么想法吗? - JosephStyons
@JosephStyons - 我不确定这是否有效,但你是否可以在VS中事先指定调试符号文件夹 --> 选项 --> 调试 --> 符号 --> 符号文件位置 --> <你的.pdb文件所在的文件夹>。这可能有助于调试器知道在哪里查找符号... - Jagmag
同样的问题,我正在使用在后期构建事件中执行的PowerShell脚本,并且它要求我使用当前调试器或新调试器,但是然后断点没有被命中。 - Luis Molina

1
这是一段受@JosephStyons答案启发的PowerShell函数。可适用于任何版本的VS,无需更改。
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()
}

0
这是改进版的Joseph。我添加了以下内容: - 不显示控制台(在“应用程序”中将输出类型设置为“Windows应用程序”)。 - 我将超时命令行参数设置为0(为什么需要它?) - 添加了第三个命令行参数url,它会在程序内部首次加载网站后使用firefox启动,但只有在网站编译后长时间加载时才会出现,特别是dotnetnuke等网站。因此,这种方式可以在一切准备就绪后将您带入前台的firefox浏览器,这需要在我的计算机上花费多达1分钟。在此期间,您可以处理其他事情。 PS. 这个stackoverflow编辑器有点傻。这就是为什么这段文字没有很好地格式化。如果我添加列表符号代码,下面的代码就不会显示为代码。
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

这对我不起作用。使用VS2015,可能是原因吗?基本上使用构建事件运行程序,然后该程序进行“附加”。我在我的主项目中添加了一个断点,但它没有被触发。我可以手动完成它而没有问题。 - AbstractDissonance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接