VS Code似乎有一个名为Launch.json的文件,可以自定义调试应用程序时发生的情况。那么对于Visual Studio,我们该如何做呢?我的目标是在没有使用VS Docker工具的情况下运行docker-compose,然后在容器启动后,告诉VS附加到容器上。
我的问题并不特定于该情况,它可能是另一种自定义Run with debugger场景。理想情况下,我可以运行一些命令来构建项目,运行项目,然后告诉VS附加到它并将该逻辑与VS关联起来。
VS Code似乎有一个名为Launch.json的文件,可以自定义调试应用程序时发生的情况。那么对于Visual Studio,我们该如何做呢?我的目标是在没有使用VS Docker工具的情况下运行docker-compose,然后在容器启动后,告诉VS附加到容器上。
我的问题并不特定于该情况,它可能是另一种自定义Run with debugger场景。理想情况下,我可以运行一些命令来构建项目,运行项目,然后告诉VS附加到它并将该逻辑与VS关联起来。
根据Vlad和Jack的答案,我想出了以下解决方案。 为了在按下“运行”按钮时运行自己的代码,我设置了一个带有自定义启动设置的空白命令行项目。
{
"profiles": {
"Build": {
"commandName": "Executable",
"executablePath": "powershell",
"commandLineArgs": ".\\DebugRun.ps1",
"workingDirectory": "."
}
}
}
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
dotnet.exe
进程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];
}
}
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];
}
}
在解决方案资源管理器中右键单击项目,选择“属性”。 选择“调试”节点。填写“命令”、“命令参数”(如果需要),并将“附加”设置为true。
[System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE.15.0")
获取 VS 实例,但我无法将其转换为 DTE2
,这意味着我无法访问远程调试脚本的 Debugger2.Transports
。我更喜欢使用 PowerShell,但我认为我必须编写一个控制台应用程序来解决它。 - Swimburger