【问题标题】:Debugging C# Console Application in VSCode using DNU/DNX and project.json使用 DNU/DNX 和 project.json 在 VSCode 中调试 C# 控制台应用程序
【发布时间】:2016-04-24 17:51:48
【问题描述】:

问题(顺便说一句,这都是在 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. 尝试编译/调试
  6. 嗯……

让我们调查一下:

mcs -debug Program.cs 无法编译 Program.cs,因为它找不到 dnu restore 安装的依赖项,该依赖项位于 ~/.dnx/packages/... 的某个位置。有点意思那么使用mcs 编译不就行了吗?

其他人说“使用xbuild 或其他”。但我不想制作.csproj 文件。我想使用project.json 和 DNU/DNX。 (实际上我还没有尝试过)

那你能做什么?尝试摆弄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 问题上到处看到随机 cmets 提到了一些东西。

就是这样。这就是我得到的结果。

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

有接受者吗?

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

"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调试器附加到它,命令运行,但调试器无法挂钩。我再次认为它要么没有调试器符号,要么是其他东西。

 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$ 

暂时结束。我完全没主意了。并且没有像@richardsonmarkj 建议的那样使用 gulp 或其他构建工具,我认为它不会很快发生。

【问题讨论】:

    标签: c# macos mono visual-studio-code dnx


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      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 文件复制到目录中可以解决问题,并且应用程序将运行。正如我在下面的 cmets 中提到的那样,此时调试器似乎也能正常工作。

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

      编辑:我已经验证了这一点。我将 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,这意味着项目管理将变得乏味。因此,您需要找到一种方法来将非框架依赖项收集到输出/运行时 cwd 中,以便 Mono vm 可以找到它们。似乎 Nant 或 Gulp 可能有用。

      【讨论】:

      • 这很简单。你必须添加 "compilationOptions": { "emitEntryPoint": true }, 到 project.json
      • 哦,你能分享你的launch.json吗?
      • 好的,调试器现在开始了,但是 VSCode 似乎不受控制,因为 Main() 第一行的断点没有被命中。我可以在 ReadKey() 方法中暂停程序并检查堆栈。所以现在可能是符号问题。
      • 你真的开始使用 Newtonsoft.Json 的东西了吗?在 Program.cs 中创建一个新的 JObject?
      • 我的 launch.json 和你的一样,除了路径。调试 dnx451 也比调试 dnxcore50 效果更好。
      猜你喜欢
      • 2016-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多