Skip to content

Commit 44afe67

Browse files
authored
Merge pull request #56 from JohnCampionJr/debugging
VS Code Debugging Improvements
2 parents 71da49f + 49bd296 commit 44afe67

File tree

6 files changed

+284
-46
lines changed

6 files changed

+284
-46
lines changed

.vscode/launch.json

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,65 @@
55
"version": "0.2.0",
66
"configurations": [
77
{
8-
"name": ".NET Core Launch (web)",
8+
"name": ".NET Core & Vue Server",
99
"type": "coreclr",
1010
"request": "launch",
11-
"preLaunchTask": "build",
11+
"logging": {
12+
"moduleLoad": false
13+
},
14+
"env": {
15+
"ASPNETCORE_ENVIRONMENT": "Development",
16+
"VUE_DEV_SERVER_PROGRESS": "true"
17+
},
18+
"cwd": "${workspaceFolder}",
19+
"preLaunchTask": "build-vue-cli-serve",
1220
// If you have changed target frameworks, make sure to update the program path.
1321
"program": "${workspaceFolder}/bin/Debug/net5.0/AspNetCoreVueStarter.dll",
14-
"args": [],
15-
"cwd": "${workspaceFolder}",
22+
"args": [
23+
"/mode:attach"
24+
],
1625
"stopAtEntry": false,
26+
"sourceFileMap": {
27+
"/Views": "${workspaceFolder}/Views"
28+
},
1729
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
1830
"serverReadyAction": {
19-
"action": "openExternally",
20-
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
31+
"action": "startDebugging",
32+
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
33+
"name": "Chrome Browser"
34+
},
35+
// this will kill any stray vue-cli processes, as the .NET app can't shut them down when it is killed by the debugger
36+
"postDebugTask": "kill"
37+
},
38+
{
39+
"name": ".NET Core Web",
40+
"type": "coreclr",
41+
"request": "launch",
42+
"logging": {
43+
"moduleLoad": false
2144
},
2245
"env": {
2346
"ASPNETCORE_ENVIRONMENT": "Development"
2447
},
48+
"cwd": "${workspaceFolder}",
49+
"preLaunchTask": "build",
50+
// If you have changed target frameworks, make sure to update the program path.
51+
"program": "${workspaceFolder}/bin/Debug/net5.0/AspNetCoreVueStarter.dll",
52+
"args": [
53+
"/mode:start"
54+
],
55+
"stopAtEntry": false,
2556
"sourceFileMap": {
2657
"/Views": "${workspaceFolder}/Views"
27-
}
58+
},
59+
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
60+
"serverReadyAction": {
61+
"action": "startDebugging",
62+
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
63+
"name": "Chrome Browser"
64+
},
65+
// this will kill any stray vue-cli processes, as the .NET app can't shut them down when it is killed by the debugger
66+
"postDebugTask": "kill"
2867
},
2968
{
3069
"name": ".NET Core Attach",
@@ -33,47 +72,20 @@
3372
"processId": "${command:pickProcess}"
3473
},
3574
{
36-
"name": "Launch Chrome",
75+
"name": "Chrome Browser",
3776
"type": "chrome",
3877
"request": "launch",
3978
"url": "http://localhost:5000",
4079
"webRoot": "${workspaceFolder}/ClientApp",
4180
"breakOnLoad": true,
4281
"sourceMaps": true,
43-
"sourceMapPathOverrides": {
44-
"webpack:///*": "${webRoot}/*",
45-
"webpack:///./*": "${webRoot}/*",
46-
"webpack:///src/*": "${webRoot}/*"
47-
}
4882
},
4983
{
50-
"name": "Launch Firefox",
84+
"name": "Firefox Browser",
5185
"type": "firefox",
5286
"request": "launch",
5387
"url": "http://localhost:5000",
54-
"webRoot": "${workspaceFolder}/ClientApp",
55-
"pathMappings": [
56-
{
57-
"url": "webpack:///src/",
58-
"path": "${webRoot}/"
59-
}
60-
]
61-
}
62-
],
63-
"compounds": [
64-
{
65-
"name": "Debug SPA and API (Chrome)",
66-
"configurations": [
67-
".NET Core Launch (web)",
68-
"Launch Chrome"
69-
]
70-
},
71-
{
72-
"name": "Debug SPA and API (Firefox)",
73-
"configurations": [
74-
".NET Core Launch (web)",
75-
"Launch Firefox"
76-
]
88+
"webRoot": "${workspaceFolder}/ClientApp"
7789
}
7890
]
7991
}

.vscode/tasks.json

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,72 @@
3737
"/consoleloggerparameters:NoSummary"
3838
],
3939
"problemMatcher": "$msCompile"
40+
},
41+
{
42+
"label": "kill",
43+
"command": "dotnet",
44+
"type": "process",
45+
"args": [
46+
"run",
47+
"${workspaceFolder}/bin/Debug/net5.0/AspNetCoreVueStarter.dll",
48+
"/mode:kill"
49+
],
50+
"presentation": {
51+
"echo": false,
52+
"reveal": "never",
53+
"focus": false,
54+
"panel": "shared",
55+
"showReuseMessage": true,
56+
"clear": false
57+
},
58+
"problemMatcher": []
59+
},
60+
{
61+
"label": "vue-cli-serve",
62+
"command": "npm",
63+
"type": "shell",
64+
"isBackground": true,
65+
"options": {
66+
"cwd": "${workspaceFolder}/ClientApp/",
67+
"env": {
68+
"VUE_DEV_SERVER_PROGRESS": "true"
69+
}
70+
},
71+
"args": [
72+
"run",
73+
"serve"
74+
],
75+
"presentation": {
76+
"echo": false,
77+
"reveal": "always",
78+
"focus": false,
79+
"panel": "dedicated",
80+
"showReuseMessage": false,
81+
"clear": true
82+
},
83+
"problemMatcher": [
84+
{
85+
"pattern": [
86+
{
87+
"regexp": ".",
88+
"file": 1,
89+
"location": 2,
90+
"message": 3
91+
}
92+
],
93+
"background": {
94+
"activeOnStart": true,
95+
"beginsPattern": ".",
96+
"endsPattern": "App running at",
97+
}
98+
}
99+
]
100+
},
101+
{
102+
"label": "build-vue-cli-serve",
103+
"dependsOn": ["build", "vue-cli-serve"],
104+
"dependsOrder": "sequence",
40105
}
106+
41107
]
42108
}

ClientApp/vue.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ module.exports = {
44
},
55
transpileDependencies: ['vuetify'],
66
devServer: {
7-
progress: false
7+
progress: !!process.env.VUE_DEV_SERVER_PROGRESS
88
}
99
}

CommandLine.cs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// original source: https://www.codeproject.com/Articles/3111/C-NET-Command-Line-Arguments-Parser
2+
3+
using System;
4+
using System.Collections.Specialized;
5+
using System.Text.RegularExpressions;
6+
7+
namespace CommandLine
8+
{
9+
public static class Arguments
10+
{
11+
12+
public static bool TryGetOptions(string[] args, bool inConsole, out string mode, out ushort port, out bool https)
13+
{
14+
var arguments = Parse(args);
15+
var validArgs = true;
16+
17+
mode = arguments["m"] ?? arguments["mode"] ?? "start";
18+
https = arguments["http"] == null && arguments["https"] != null;
19+
var portString = arguments["p"] ?? arguments["port"] ?? "8080";
20+
21+
if (mode != "start" && mode != "attach" && mode != "kill")
22+
{
23+
if (inConsole)
24+
{
25+
Console.ForegroundColor = ConsoleColor.Red;
26+
Console.WriteLine("Invalid mode; Allowed values are start | attach | kill");
27+
Console.ResetColor();
28+
}
29+
validArgs = false;
30+
}
31+
32+
if (!ushort.TryParse(portString, out port) || port < 80)
33+
{
34+
if (inConsole)
35+
{
36+
Console.ForegroundColor = ConsoleColor.Red;
37+
Console.WriteLine("Invalid port number specified.");
38+
Console.ResetColor();
39+
}
40+
validArgs = false;
41+
}
42+
43+
if (arguments["h"] != null || arguments["help"] != null) validArgs = false;
44+
45+
if (inConsole && !validArgs)
46+
{
47+
Console.WriteLine();
48+
Console.WriteLine(" Mode Argument Options (Defaults to start)");
49+
Console.WriteLine(" -m | --mode start -> Start the SPA server and proxy to that.");
50+
Console.WriteLine(" -m | --mode attach -> Attach to existing SPA server");
51+
Console.WriteLine(" -m | --mode kill -> Shutdown any existing SPA server on the specified port (used after debugging in VS Code)");
52+
Console.WriteLine();
53+
Console.WriteLine(" Port Argument (Defaults to 8080)");
54+
Console.WriteLine(" -p | --port 8080 -> Specify what port to start or attach to, minimum of 80");
55+
Console.WriteLine();
56+
Console.WriteLine(" HTTPS (Defaults to false)");
57+
Console.WriteLine(" -https -> Uses HTTPS");
58+
Console.WriteLine();
59+
60+
}
61+
62+
return validArgs;
63+
64+
}
65+
66+
public static StringDictionary Parse(string[] args)
67+
{
68+
var parameters = new StringDictionary();
69+
Regex splitter = new Regex(@"^-{1,2}|^/|=|:",
70+
RegexOptions.IgnoreCase | RegexOptions.Compiled);
71+
72+
Regex remover = new Regex(@"^['""]?(.*?)['""]?$",
73+
RegexOptions.IgnoreCase | RegexOptions.Compiled);
74+
75+
string parameter = null;
76+
string[] parts;
77+
78+
// Valid parameters forms:
79+
// {-,/,--}param{ ,=,:}((",')value(",'))
80+
// Examples:
81+
// -param1 value1 --param2 /param3:"Test-:-work"
82+
// /param4=happy -param5 '--=nice=--'
83+
foreach (string txt in args)
84+
{
85+
// Look for new parameters (-,/ or --) and a
86+
// possible enclosed value (=,:)
87+
parts = splitter.Split(txt, 3);
88+
89+
switch (parts.Length)
90+
{
91+
// Found a value (for the last parameter
92+
// found (space separator))
93+
case 1:
94+
if (parameter != null)
95+
{
96+
if (!parameters.ContainsKey(parameter))
97+
{
98+
parts[0] =
99+
remover.Replace(parts[0], "$1");
100+
101+
parameters.Add(parameter, parts[0]);
102+
}
103+
parameter = null;
104+
}
105+
// else Error: no parameter waiting for a value (skipped)
106+
break;
107+
108+
// Found just a parameter
109+
case 2:
110+
// The last parameter is still waiting.
111+
// With no value, set it to true.
112+
if (parameter != null && !parameters.ContainsKey(parameter))
113+
parameters.Add(parameter, "true");
114+
115+
parameter = parts[1];
116+
break;
117+
118+
// Parameter with enclosed value
119+
case 3:
120+
// The last parameter is still waiting.
121+
// With no value, set it to true.
122+
if (parameter != null && !parameters.ContainsKey(parameter))
123+
parameters.Add(parameter, "true");
124+
125+
parameter = parts[1];
126+
127+
// Remove possible enclosing characters (",')
128+
if (!parameters.ContainsKey(parameter))
129+
{
130+
parts[2] = remover.Replace(parts[2], "$1");
131+
parameters.Add(parameter, parts[2]);
132+
}
133+
134+
parameter = null;
135+
break;
136+
}
137+
}
138+
// In case a parameter is still waiting
139+
if (parameter != null && !parameters.ContainsKey(parameter))
140+
parameters.Add(parameter, "true");
141+
142+
return parameters;
143+
}
144+
}
145+
}

Program.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Threading.Tasks;
52
using Microsoft.AspNetCore.Hosting;
6-
using Microsoft.Extensions.Configuration;
73
using Microsoft.Extensions.Hosting;
8-
using Microsoft.Extensions.Logging;
4+
using VueCliMiddleware;
95

106
namespace AspNetCoreVueStarter
117
{
128
public class Program
139
{
1410
public static void Main(string[] args)
1511
{
12+
if (!CommandLine.Arguments.TryGetOptions(args, true, out string mode, out ushort port, out bool https)) return;
13+
14+
if (mode == "kill") {
15+
Console.WriteLine($"Killing process serving port {port}...");
16+
PidUtils.KillPort(port, true, true);
17+
return;
18+
}
19+
1620
CreateHostBuilder(args).Build().Run();
1721
}
1822

0 commit comments

Comments
 (0)