How to run custom code when “Start Debugging” in Visual Studio and attach to debugger

浪子不回头ぞ 提交于 2020-01-23 03:08:04

问题


VS Code seems to have a file called Launch.json to customize what happens when you run your app for debugging. How do we go about that for Visual Studio? My goals is to run docker-compose without the VS Docker Tools, and then after the containers are up, telling VS to attach to the container.

My question is not specific to that case though, it could just as well be another custom way of Run with debugger scenario. Ideally I could just run some commands to build the project, run the project, and then tell VS to attach to it and associate that logic with VS.


回答1:


Right-click the project in your solution explorer; select "Properties". Choose "Debugging" node. Fill in "Command", "Command Arguments" (if needed), and set "Attach" to true.




回答2:


Based on the answers of Vlad and Jack, I came up with the following solution. To have my own code run when I press the Run button, I set up a blank Command Line project with custom launch settings.

{
  "profiles": {
    "Build": {
      "commandName": "Executable",
      "executablePath": "powershell",
      "commandLineArgs": ".\\DebugRun.ps1",
      "workingDirectory": "."
    }
  }
}

Whenever I press Run, it will run the DebugRun.ps1 script using PowerShell. Here's what I put in the DebugRun.ps1.

docker-compose -f "./docker-compose.debug.yml" --no-ansi up -d --force-recreate --build

Start-Sleep -Seconds 5

$appId = ((docker ps --filter "ancestor=employeemapapp:debug")[1] -split " ")[0]
$apiId = ((docker ps --filter "ancestor=employeemapapi:debug")[1] -split " ")[0]

$appIp = (docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $appId)
$apiIp = (docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $apiId)

docker exec -d $appId C:\\remote_debugger\\x64\\msvsmon.exe /noauth /anyuser /silent /nostatus /noclrwarn /nosecuritywarn /nofirewallwarn /nowowwarn /timeout:214748364
docker exec -d $apiId C:\\remote_debugger\\x64\\msvsmon.exe /noauth /anyuser /silent /nostatus /noclrwarn /nosecuritywarn /nofirewallwarn /nowowwarn /timeout:214748364

$appTarget = $appId + ":4022"
$apiTarget = $apiId + ":4022"

#Parameters
## 1: Solution Name is used to run the code only to the VS instance that has the Solution open
## 2: Transportation method for remote debugger
## 3: Target is the hostname/IP/... to the target where remote debugging is running
## 4: The process name you want to attach tos
./RemoteDebugAttach.exe "EmployeeMap.sln" "Remote (no authentication)" $appTarget "dotnet.exe"
./RemoteDebugAttach.exe "EmployeeMap.sln" "Remote (no authentication)" $apiTarget "dotnet.exe"

Write-Host "Api:" $apiIp
Write-Host "App:" $appIp
$apiUrl = "http://$apiIp/api/employees"
$appUrl = "http://$appIp"

start $apiUrl
start $appUrl

Read-Host "Press any key to quit"

./RemoteDebugDetach.exe EmployeeMap.sln "dotnet.exe"

docker exec -d $appId C:\\remote_debugger\\x64\\utils\\KillProcess.exe msvsmon.exe
docker exec -d $apiId C:\\remote_debugger\\x64\\utils\\KillProcess.exe msvsmon.exe

docker-compose -f "./docker-compose.debug.yml" --no-ansi down 

This script does the following:

  • Bring up my docker containers via docker-compose
  • Grab the container id's, ip's, etc
  • Start the remote debugger instance inside of the container
  • Attach to the dotnet.exe processes inside of the container using a custom executable (RemoteDebugAttach)
  • Open the browsers to browse to the websites served from the containers
  • Wait for any keypress to bring down infrastructure
  • Detach from processes using custom executable
  • Kill remote debugger on docker container
  • Bring down containers

The custom executables come from a separate solution where I just built some Command Line Applications. I used the code from this source to get all VS instances running on the machine. And combined it with this code to attach:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        string solutionName = Ask(args, 0, "Solution name?");
        string transportName = Ask(args, 1, "Transport name?");
        string target = Ask(args, 2, "Target machine?");
        string processName = Ask(args, 3, "Process Name?");


        var instances = Msdev.GetIDEInstances(true);
        var dte = (DTE2)instances.Find(d => d.Solution.FullName.EndsWith(solutionName, StringComparison.InvariantCultureIgnoreCase));
        var debugger = dte.Debugger as Debugger2;
        var transports = debugger.Transports;
        Transport transport = null;
        foreach(Transport loopTransport in transports)
        {
            if(loopTransport.Name.Equals(transportName, StringComparison.InvariantCultureIgnoreCase)) // "Remote (no authentication)")
            {
                transport = loopTransport;
                break;
            }
        }

        Processes processes = debugger.GetProcesses(transport, target); // "172.24.50.15:4022");
        foreach(Process process in processes)
        {
            if(process.Name.EndsWith(processName, StringComparison.InvariantCultureIgnoreCase))
            {
                process.Attach();
            }
        }
    }

    static string Ask(string[] args, int index, string question)
    {
        if(args.Length <= index)
        {
            Console.WriteLine(question);
            return Console.ReadLine();
        }

        return args[index];
    }
}

And the following to Detach:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        string solutionName = Ask(args, 0, "Solution name");
        string processName = Ask(args, 1, "Process Name?");

        var instances = Msdev.GetIDEInstances(true);

        var dte = (DTE2)instances.Find(d => d.Solution.FullName.EndsWith(solutionName, StringComparison.InvariantCultureIgnoreCase));
        var debugger = dte.Debugger as Debugger2;

        Processes processes = debugger.DebuggedProcesses;
        foreach (Process2 process in processes)
        {
            if (process.Name.EndsWith(processName, StringComparison.InvariantCultureIgnoreCase))
            {
                process.Detach(false);
            }
        }
    }

    static string Ask(string[] args, int index, string question)
    {
        if (args.Length <= index)
        {
            Console.WriteLine(question);
            return Console.ReadLine();
        }

        return args[index];
    }
}

I would have preferred to have this code in PowerShell because it would be easier to copy to other project + edit. Though in PowerShell, I was simply not able to get the right code to execute, even when using reflection to apply certain code the COM objects.

I hope it helps some people who want to have their own custom flow build into VS. Thank you Vlad and Jack.




回答3:


If you want to attach to process debugging with script, you could think about using the powershell.

Or as far as I know, we could custom the code to attach to process.

Attach debugger in C# to another process

But if you have to use the VS IDE debugging feature, we often use the remote debugging tool: https://msdn.microsoft.com/library/y7f5zaaa.aspx.



来源:https://stackoverflow.com/questions/49660094/how-to-run-custom-code-when-start-debugging-in-visual-studio-and-attach-to-deb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!