使用 DNU/DNX 和 project.json 在 VSCode 中调试 C# 控制台应用程序

Debugging C# Console Application in VSCode using DNU/DNX and project.json

问题(顺便说一句,这都在 OSX 上。):

  1. 通过 yo aspnetdnu restorednu builddnx run 创建一个新的 C# 控制台应用程序 <- 一切都很好
  2. 向项目添加依赖项(例如 Newtonsoft.JSON、Akka),dnu restorednu builddnx run <- 一切都很好
  3. 查看此站点以了解它应该如何工作。 https://code.visualstudio.com/Docs/editor/debugging#_mono-debugging(哦,通过谷歌搜索和反复试验拼凑其余部分)
  4. 在Program.cs中添加using Newtonsoft.JSON然后...实际使用它。
  5. 尝试compiling/debugging
  6. 嗯……

让我们调查一下:

mcs -debug Program.cs 无法编译 Program.cs,因为它找不到 dnu restore 安装的依赖项,它位于 ~/.dnx/packages/... 的某处。有点道理。那么使用 mcs 编译是不是可行的方法?

别人说"use xbuild or whatever"。但我不想制作 .csproj 文件。我想使用 project.json 和 DNU/DNX。 (实际上我还没有尝试过)

那你能做什么?尝试使用 fiddle 和 tasks.json 来使 dnu build 工作。

这是我得到的。

{
    "version": "0.1.0",
    "command": "dnu",
    "options": {
        "cwd": "/Users/meh/Development/code/HelloWorld"
    },
    "showOutput": "silent",
    "tasks": [
        {
            "taskName": "build",
            "isBuildCommand": true,
            "problemMatcher": "$msCompile"
        }
    ]
}

它不漂亮,但它确实完成了工作。

现在我无法开始工作的部分是调试部分。

所以 dnu build 在这样的目录中创建输出 /Users/meh/Development/code/HelloWorld/bin/Debug/dnx451/HelloWorld.dll

如果您尝试使其像 launch.json 中那样工作,它适用于生成的没有依赖项的简单 Program.cs 文件,您将一无所获。 我通过控制台尝试了它,看看它为什么不工作。所以为什么?因为mono找不到必要的依赖。为什么?因为它们不在所述目录中。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            "type": "mono",
            "request": "launch",
            "program": "/Users/meh/Development/code/HelloWorld/bin/Debug/dnx451/HelloWorld.dll",
            "args": [],
            "cwd": ".",
            "runtimeExecutable": null,
            "env": {}
        },
        {
            "name": "Attach",
            "type": "mono",
            "request": "attach",
            "address": "localhost",
            "port": 5858
        }
    ]
}

如果您使用 dnx run 或任何您配置为 运行 的编译程序,它当然可以工作。

所以环顾四周 dnx --help 我看到了一个不错的 dnx --debug 选项。如果你 运行 在控制台上你会得到这个不错的输出:

Blah:HelloWorld meh$ dnx --debug run
Process Id: 19228
Waiting for the debugger to attach...

事情是...我不知道调试器正在等待哪个端口。实际上 mono-sgenps 告诉我 PID 所属)似乎实际上并没有在任何端口上侦听。我试图通过 lsof 进行检查。

我担心的是 dnx --debug 实际上并没有真正发挥作用,因为我已经看到关于 github 问题的随机评论在这里和那里提到了一些事情。

就是这样。这就是我的进展。

所以。有人进一步了解了吗?有人试过吗?我是白痴吗试图通过 DNX/DNU 制作控制台应用程序并使用 VSCode 来编程和调试它?我只是在做一些完全错误的事情吗?

有人要吗?

编辑 1: 您必须将其添加到 project.json 以获得已编译的 DLL 文件中的入口点,以便单声道能够 运行 程序。

"compilationOptions": {
    "emitEntryPoint": true
},

编辑 2: 我尝试过的其他东西...

1. 看看dnx run实际上做了什么。

它有什么作用?

45588 s000  U+     0:02.11 mono /Users/meh/.dnx/runtimes/dnx-mono.1.0.0-rc1-update1/bin/Microsoft.Dnx.Host.Mono.dll run

它从您的项目目录中调用名为 Microsoft.Dnx.Host.Mono.dll 的东西,该目录用于调用所有内容。

遗憾的是,没有真正的方法将该命令放入 launch.json 条目中以使其 a) 从正确的目录开始并且 b) 从命令中省略 .DLL 文件名。

这是我能从 launch.json 中得到的最好结果。

cd '/Users/meh/Development/code/HelloWorld/bin/Debug/dnx451';  'mono' '--debug' '--debugger-agent=transport=dt_socket,server=y,address=127.0.0.1:61396' '/Users/meh/.dnx/runtimes/dnx-mono.1.0.0-rc1-update1/bin/Microsoft.Dnx.Host.Mono.dll' 'HelloWorld.dll' 'run'

很明显,从 Microsoft.Dnx.Host.Mono.dll 到 运行 的目录是错误的,你不能让它省略 HelloWorld.dll 参数。

另一件事是。即使您可以使 VSCode 生成正确的命令行,它也不起作用。打开一个终端并执行这样的命令让你进入调试模式:

cd '/Users/meh/Development/code/HelloWorld/';  'mono' '--debug' '--debugger-agent=transport=dt_socket,server=y,address=127.0.0.1:61396' '/Users/meh/.dnx/runtimes/dnx-mono.1.0.0-rc1-update1/bin/Microsoft.Dnx.Host.Mono.dll' 'run'

然后通过 launch.json 中的附加配置从 VSCode 附加到调试器,如上所示(当然端口需要匹配),运行 是程序但是调试器无法进入。我猜那是因为你没有真正调试 HelloWorld.dll。或者 dnx build 不输出调试符号。应该是最后一个吧

2. 告诉 mono 在哪里调整依赖项。

所以我研究了 man mono 并发现您可以通过 $MONO_PATH 告诉 mono 去哪里寻找库。

但是制作一个脚本并拍打在 ~/.dnx/packages 中找到的所有路径是不好的,因为那里包含了你曾经拥有的所有库 dnu restored。他们的每个版本。

那么如何只获取 project.json 引用的库呢?好吧,我在 dnu 周围挖掘了一下,发现了 dnu publish。这会在 bin 内生成一个 output 目录,其中包含许多内容。其中之一是名为 packages 的文件夹,其中包含您所有的项目依赖项。

是吗?没有!

因为 dnu publish 不做的是创建一个已编译的 .DLL 文件。相反,它创建了一个 shell 脚本,似乎可以即时编译您的内容。但是无所谓。无论如何,我们只是想要 DLL。

那么我们有什么。我们有一个 dnu build 来获得一个不错的 .DLL 文件。我们有一个 dnu publish 为我们收集依赖项。

现在您可以使用一点shell魔法以$MONO_PATH友好的方式为我们收集路径。

ls -d $PWD/bin/output/approot/packages/*/*/lib/net45 | tr '\n' ':'

问题又出在launch.json。它有一个很好的 属性,叫做 env : {},但是 VSCode,在生成启动调试器的实际命令时,将您放入其中的所有内容用单引号引起来。这被解释为文字字符串。所以你实际上不能把上面的小命令之类的东西放进去。 悲伤的长号

顺便说一句。如果您再次打开终端,并将上述脚本的输出导出到 $MONO_PATH,然后像在其他尝试中那样手动将 运行 命令导出到 mono,您可以再次尝试附加VSCode 调试器,命令 运行s 但调试器无法挂接到它。我再次认为它要么没有调试器符号,要么是其他东西。

 Flash:HelloWorld meh$ export MONO_PATH=$(ls -d $PWD/bin/output/approot/packages/*/*/lib/net45 | tr '\n' ':')
 Flash:HelloWorld meh$ echo $MONO_PATH 
 /Users/meh/Development/code/HelloWorld/bin/output/approot/packages/Akka/1.0.5/lib/net45:/Users/meh/Development/code/HelloWorld/bin/output/approot/packages/Microsoft.CSharp/4.0.1-beta-23516/lib/net45:/Users/meh/Development/code/HelloWorld/bin/output/approot/packages/Newtonsoft.Json/8.0.1-beta3/lib/net45:/Users/meh/Development/code/HelloWorld/bin/output/approot/packages/System.Collections/4.0.11-beta-23516/lib/net45:/Users/meh/Development/code/HelloWorld/bin/output/approot/packages/System.Linq/4.0.1-beta-23516/lib/net45:/Users/meh/Development/code/HelloWorld/bin/output/approot/packages/System.Threading/4.0.11-beta-23516/lib/net45:
 Flash:HelloWorld meh$ cd '/Users/meh/Development/code/HelloWorld/bin/Debug/dnx451';  'mono' '--debug' '--debugger-agent=transport=dt_socket,server=y,address=127.0.0.1:61396' 'HelloWorld.dll'
 Meh
 Hello World
 {
   "blah": "blub"
 }
 From ConsoleActor: blah blub
 From ConsoleActor: blubberblub

 Flash:dnx451 meh$ 

暂时得出结论。我完全没有想法。如果不使用 gulp 或其他构建工具,就像@richardsonmarkj 建议的那样,我认为它不会很快发生。

我也一直在努力理解这种情况。我走过你的脚步,最终来到了一个不同的地方。我没有看到依赖性问题。当我尝试从 VSCode 进行调试时,我在终端 window-

中得到了这个
cd '/Users/markr/Projects/ConsoleApplication/bin/Debug/dnxcore50';  'mono' '--debug' '--debugger-agent=transport=dt_socket,server=y,address=127.0.0.1:58907' 'ConsoleApplication.dll'
Assembly '/Users/markr/Projects/ConsoleApplication/bin/Debug/dnxcore50/ConsoleApplication.dll' doesn't have an entry point.

不同的可能是我的依赖添加了Newtonsoft.JSON之后-

 "dependencies": {
  "Newtonsoft.Json": "8.0.2"
},

在我的 project.json 文件中,我确实做了一个 dnu restore

编辑:"compilationOptions": { "emitEntryPoint": true }, 添加到我的 project.json 文件确实解决了我的入口点问题。

这是我的代码:-

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace ConsoleApplication
{
public class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Hello World");

        JArray array = new JArray();
        array.Add("Manual text");
        array.Add(new DateTime(2000, 5, 23));

        JObject o = new JObject();
        o["MyArray"] = array;

        string json = o.ToString();
        Console.WriteLine(json);

        Console.Read();
    }
}
}

我认为调试器遇到的问题与您在 mcs -debug 中看到的问题相同。 运行 该应用程序通过 mono ConsoleApplication.dll 从命令行给出此

Unhandled Exception:
System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies.
File name: 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'
[ERROR] FATAL UNHANDLED EXCEPTION: System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies.
File name: 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'

将 Newtonsoft.Json.dll 文件复制到目录中可解决问题,应用程序将 运行。同样在那时,调试器似乎像我在下面的评论中提到的那样工作。

我想我们需要一个构建步骤来收集依赖项并将它们放在输出目录中。

编辑: 我已经验证过了。我将 Newtonsoft.Json.dll 拉入根目录并将 tasks.json 更改为 -

{
    "version": "0.1.0",
    "command": "mcs",
    "options": {
        "cwd": "/Users/markr/Projects/ConsoleApplication"
    },
    "args": [
        "*.cs",
        "-debug",
        "-r:Newtonsoft.Json.dll"
    ],
    "showOutput": "always",
    "tasks": [
        {
            "taskName": "build",
            "suppressTaskName": true,
            "isBuildCommand": true,
            "problemMatcher": "$msCompile"
        }
    ]
}

当指向新 Program.exe 时,调试按预期进行。这实际上是在删除 dnu/dnx,这意味着项目管理将变得乏味。因此,您需要找到一种方法来将 non-framework 依赖项收集到 output/runtime cwd 中,以便 Mono vm 可以找到它们。似乎 Nant 或 Gulp 可能有用。

DNX 已弃用,所以这个问题现在没有实际意义。

将此 link 留在这里,以显示使用 vscode 进行实验性 .net 核心调试。