如何诊断 dnx 中缺失的依赖项(或其他加载程序故障)?

How can I diagnose missing dependencies (or other loader failures) in dnx?

我正在尝试使用 Kestrel 在 DNX 上为 ASP.NET vNext 运行 HelloWeb sample 的修改版本。我知道这 非常 处于最前沿,但我希望 ASP.NET 团队至少能够让最简单的网络应用程序正常运行 :)

环境:

"Web app" 代码,在 Startup.cs:

using Microsoft.AspNet.Builder;
public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseWelcomePage();
    }
}

项目配置,在project.json:

{
  "dependencies": {
    "Kestrel": "1.0.0-beta4",
    "Microsoft.AspNet.Diagnostics": "1.0.0-beta4",
    "Microsoft.AspNet.Hosting": "1.0.0-beta4",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta4",
    "Microsoft.AspNet.StaticFiles": "1.0.0-beta4",
    "Microsoft.Framework.Runtime": "1.0.0-beta4",
    "Microsoft.Framework.Runtime.Common": "1.0.0-beta4",
    "Microsoft.Framework.Runtime.Loader": "1.0.0-beta4",
    "Microsoft.Framework.Runtime.Interfaces": "1.0.0-beta4",
  },
  "commands": {
    "kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:5004"
  },
  "frameworks": {
    "dnx451": {}
  }
}

kpm restore 似乎工作正常。

但是,当我尝试 运行 时,出现异常提示无法找到 Microsoft.Framework.Runtime.IApplicationEnvironment。命令行和错误(稍微重新格式化)

.../HelloWeb$ dnx . kestrel
System.IO.FileNotFoundException: Could not load file or assembly 
'Microsoft.Framework.Runtime.IApplicationEnvironment,
  Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
or one of its dependencies.
File name: 'Microsoft.Framework.Runtime.IApplicationEnvironment,
  Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
  at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke 
    (System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke 
    (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder,
     System.Object[] parameters, System.Globalization.CultureInfo culture)
    [0x00000] in <filename unknown>:0

虽然很明显,我最迫切的需要是解决这个问题,但我也非常感谢有关如何诊断问题的建议,以便我将来可以自己解决类似的问题。 (这也可能使这个问题对其他人更有用。)

我在 Microsoft.Framework.Runtime.Interfaces assembly source, and that doesn't appear to have changed recently. It's not clear why the exception shows the name as if it's a whole assembly in itself, rather than just an interface within another assembly. I'm guessing this may be due to assembly neutral interfaces, but it's not clear from the error. ([AssemblyNeutral] is dead, so that's not it...)

中找到了 Microsoft.Framework.Runtime.IApplicationEnvironment

为了让它工作,我修改了我的 project.json .. 现在看起来像:

{
"dependencies": {
    "Kestrel": "1.0.0-*",
    "Microsoft.AspNet.Diagnostics": "1.0.0-*",
    "Microsoft.AspNet.Hosting": "1.0.0-*",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-*",
    "Microsoft.AspNet.StaticFiles": "1.0.0-*"
},
"commands": {
    "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5001",
    "kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:5004"
},
"frameworks": {
    }
}

关键似乎是框架部分。

重命名也改变了 k web 的工作方式,现在是 dnx . webdnx . kestrel

更新 - 更多信息

奇怪的是,在 运行 没有定义任何框架之后,当我定义它时,它得到了一堆额外的东西 kpm restore :

...
Installing Microsoft.Framework.Logging 1.0.0-beta4-11001
Installing Microsoft.Framework.Logging.Interfaces 1.0.0-beta4-11001
Installing Microsoft.Framework.DependencyInjection.Interfaces 1.0.0-beta4-11010
Installing Microsoft.Framework.DependencyInjection 1.0.0-beta4-11010
Installing Microsoft.Framework.ConfigurationModel 1.0.0-beta4-10976
Installing Microsoft.Framework.ConfigurationModel.Interfaces 1.0.0-beta4-10976
Installing Microsoft.AspNet.Hosting.Interfaces 1.0.0-beta4-11328
Installing Microsoft.AspNet.FeatureModel 1.0.0-beta4-11104
Installing Microsoft.AspNet.Http 1.0.0-beta4-11104
Installing Microsoft.AspNet.FileProviders.Interfaces 1.0.0-beta4-11006
Installing Microsoft.Framework.Caching.Interfaces 1.0.0-beta4-10981
Installing Microsoft.AspNet.FileProviders 1.0.0-beta4-11006
Installing Microsoft.AspNet.Http.Core 1.0.0-beta4-11104
Installing Microsoft.AspNet.WebUtilities 1.0.0-beta4-11104
Installing Microsoft.Net.Http.Headers 1.0.0-beta4-11104
Installing Microsoft.AspNet.Http.Interfaces 1.0.0-beta4-11104
Installing Microsoft.Framework.Runtime.Interfaces 1.0.0-beta4-11257
Installing Microsoft.AspNet.Server.Kestrel 1.0.0-beta4-11262
Installing Microsoft.Net.Http.Server 1.0.0-beta4-11698
Installing Microsoft.Net.WebSockets 1.0.0-beta4-11698
Installing Microsoft.Net.WebSocketAbstractions 1.0.0-beta4-10915
Installing Microsoft.Framework.WebEncoders 1.0.0-beta4-11104
Installing Microsoft.Framework.OptionsModel 1.0.0-beta4-10984
Installing Microsoft.AspNet.Http.Extensions 1.0.0-beta4-11104
Installing Microsoft.AspNet.Diagnostics.Interfaces 1.0.0-beta4-12451
Installing Microsoft.AspNet.RequestContainer 1.0.0-beta4-11328

.. 然后它 运行 很好。然后我在框架部分切换回来

"frameworks": {
    "dnx451": {}
}

.. 它仍然有效,而之前它会抛出错误!

很奇怪!

(我运行 1.0.0-beta4-11257)

进一步更新

我启动了一个新的 Ubuntu 实例,得到了和你一样的错误。我的想法是这个问题可能是因为它只是试图从 nuget.org 获取包而不是myget.org(它有更新的东西)所以我把 NuGet.Config 放入项目的根目录中..

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="AspNetVNext" value="https://www.myget.org/F/aspnetvnext/" />
    <add key="NuGet" value="https://nuget.org/api/v2/" />
  </packageSources>
</configuration>

.. 这似乎已经通过获取正确的版本(在另一个 kpm restore 之后)为我修复了它。

我仍然完全不知道哪里出了问题,但我现在有一系列步骤至少可以让尝试变得更容易:

  • 如有疑问,请重新安装 dnx
    • 清除包缓存可能会有帮助
  • 检查 ~/.config/NuGet.config 以确保您使用的是正确的 NuGet 源

我最终使用以下命令行以相当干净的方式测试各种选项:

rm -rf ~/.dnx/packages && rm -rf ~/.dnx/runtimes && dnvm upgrade && kpm restore && dnx . kestrel

看来我的问题真的是因为安装了错误的依赖项版本。 "1.0.0-beta4" 的版本号显然与 "1.0.0-beta4-*" 完全不同。例如,Kestrel 依赖项在刚指定为 1.0.0-beta4 时安装版本 1.0.0-beta4-11185,但版本 1.0.0-beta4-11262 在末尾带有 -*。我想明确指定 beta4 以避免意外使用带有

的 beta3 版本

以下项目配置工作正常:

{
  "dependencies": {
    "Kestrel": "1.0.0-beta4-*",
    "Microsoft.AspNet.Diagnostics": "1.0.0-beta4-*",
    "Microsoft.AspNet.Hosting": "1.0.0-beta4-*",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta4-*",
  },
  "commands": {
    "kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:5004"
  },
  "frameworks": {
    "dnx451": {}
  }
}

您可以将名为 DNX_TRACE 的环境变量设置为 1 以查看更多诊断信息。请注意,很多 更多信息!

好问题。对于您的特定问题,看起来您的已解决依赖项不匹配。发生这种情况很可能是因为您 运行 在不兼容的 dnx 上运行您的应用程序。我们仍在进行非常大的突破性更改,因此如果您看到类型缺失的方法缺失,您最终可能会 运行ning betaX 包和 betaY dnx,反之亦然。

更具体地说,Assembly Neutral Interfaces 在 beta4 中被删除了,但看起来您正在 运行ning 的应用程序仍在使用它们。

我们计划这样做,以便软件包可以标记它们所需的最小 dnx 运行 使错误消息更加清晰。而且随着时间的推移,破坏性的变化也会逐渐消失。

不过,总的来说,我觉得是时候写一篇指南,介绍如何在使用 dnx 时诊断此类问题(因为它与现有的 .NET 截然不同)。

您放入 project.json 的依赖项仅为顶级。版本也始终是最低的(它就像一个 NuGet 包)。这意味着当您指定 Foo 1.0.0-beta4 时,您实际上是在指定 Foo >= 1.0.0-beta4。这意味着如果您要求 MVC 0.0.1 并且您配置的提要的最低版本是 MVC 3.0.0,您将得到那个。我们也 NEVER 浮动您的版本,除非您指定它。如果您要求 1.0.0 并且它存在,即使存在更新版本,您也会得到 1.0.0。指定空版本 总是 不好,在以后的构建中将被禁止。

我们向 nuget 引入了一项名为浮动版本的新功能。今天它只适用于预发布标签,但在下一个版本中它将适用于该版本的更多部分。这类似于 npm 和 gem 用于在包规范文件中指定版本范围的语法。

1.0.0-* - 意味着给我匹配前缀的最高版本(根据 semantic versioning rules)或者如果没有匹配该前缀的版本,使用正常行为并给我最低版本 >=指定的版本。

当您 运行 在最新版本中恢复时,它会写出一个名为 project.lock.json 的文件。此文件将包含 project.json.

中定义的所有目标框架的依赖项的传递闭包

当这样的事情失败时,您可以执行以下操作:

使用 kpm list 查看已解决的依赖项。这将向您显示项目引用的包的已解析版本以及将其引入的依赖项。例如如果 A -> B,它将显示:

A
  -> B
B
 ->

实际 KPM 列表输出:

列出 ClassLibrary39 的依赖项(C:\Users\davifowl\Documents\Visual Studio 14\Projects\ClassLibrary39\src\ClassLibrary39\project.json)

[Target framework DNX,Version=v4.5.1 (dnx451)]

 framework/Microsoft.CSharp 4.0.0.0
    -> ClassLibrary39 1.0.0
 framework/mscorlib 4.0.0.0
    -> ClassLibrary39 1.0.0
 framework/System 4.0.0.0
    -> ClassLibrary39 1.0.0
 framework/System.Core 4.0.0.0
    -> ClassLibrary39 1.0.0
*Newtonsoft.Json 6.0.1
    -> ClassLibrary39 1.0.0

[Target framework DNXCore,Version=v5.0 (dnxcore50)]

*Newtonsoft.Json 6.0.1
    -> ClassLibrary39 1.0.0
 System.Runtime 4.0.20-beta-22709
    -> ClassLibrary39 1.0.0

* 表示直接依赖。

如果你有一个工作 visual studio(现在与 DNX 中断),你可以查看参考节点。它具有相同的可视化数据:

让我们看看依赖失败是什么样的:

这是project.json

{
    "version": "1.0.0-*",
    "dependencies": {
        "Newtonsoft.Json": "8.0.0"
    },

    "frameworks" : {
        "dnx451" : { 
            "dependencies": {
            }
        },
        "dnxcore50" : { 
            "dependencies": {
                "System.Runtime": "4.0.20-beta-22709"
            }
        }
    }
}

Newtonsoft.Json 8.0.0 不存在。所以 运行ning kpm restore 显示如下:

诊断恢复可能失败时,查看发出的 HTTP 请求,它们会告诉您 kpm 查看了哪些配置的包源。请注意上图中,有一个 CACHE 请求。这是基于资源类型(nupkg 或 nuspec)的内置缓存,并且具有可配置的 TTL(查看 kpm restore --help)。如果要强制 kpm 命中远程 NuGet 源,请使用 --no-cache 标志:

这些错误也出现在包管理器日志输出 Visual Studio 中 window:

旁注!

包源

我将描述 NuGet.config 现在的工作方式(将来可能会改变)。默认情况下,您有一个 NuGet.config,在 %appdata%\NuGet\NuGet.Config 中全局配置了默认 NuGet.org 源。您可以在 visual studio 内或使用 NuGet 命令行工具管理这些全局资源。在尝试诊断故障时,您应该始终查看您的有效来源(kpm 输出中列出的来源)。

阅读更多关于 NuGet.config here

回到现实:

当依赖关系未解决时,运行应用程序会给你这个:

> dnx . run
System.InvalidOperationException: Failed to resolve the following dependencies for target framework 'DNX,Version=v4.5.1':
   Newtonsoft.Json 8.0.0

Searched Locations:
  C:\Users\davifowl\Documents\Visual Studio 14\Projects\ClassLibrary39\src\{name}\project.json
  C:\Users\davifowl\Documents\Visual Studio 14\Projects\ClassLibrary39\test\{name}\project.json
  C:\Users\davifowl\.dnx\packages\{name}\{version}\{name}.nuspec
  C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\{name}.dll
  C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\Facades\{name}.dll
  C:\WINDOWS\Microsoft.NET\assembly\GAC_32\{name}\{version}\{name}.dll
  C:\WINDOWS\Microsoft.NET\assembly\GAC_64\{name}\{version}\{name}.dll
  C:\WINDOWS\Microsoft.NET\assembly\GAC_MSIL\{name}\{version}\{name}.dll

Try running 'kpm restore'.

   at Microsoft.Framework.Runtime.DefaultHost.GetEntryPoint(String applicationName)
   at Microsoft.Framework.ApplicationHost.Program.ExecuteMain(DefaultHost host, String applicationName, String[] args)
   at Microsoft.Framework.ApplicationHost.Program.Main(String[] args)

运行时间基本上会尝试在尝试 运行 之前验证整个依赖关系图是否已解析。如果它提示 运行ning kpm restore 那是因为它找不到列出的依赖项。

您可能会收到此错误的另一个原因是,如果您 运行 使用了错误的 dnx 风格。如果您的应用程序仅指定 dnx451 并且您尝试 运行 CoreCLR dnx,您可能会看到类似的问题。密切关注报错信息中的目标框架:

对于运行宁:

dnx4x - runs on dnx-clr-{etc}
dnxcore50 - runs on dnx-coreclr-{etc}

当您尝试 运行 时,您应该记住从 clr 到 project.json 中定义的目标框架的心理映射。

这也显示在 Visual Studio 的引用节点下:

标记为黄色的节点未解析。

这些也出现在错误列表中:

建筑

构建时也会出现这些错误。从命令行构建时,输出非常冗长,在诊断问题时非常有用:

> kpm build

Building ClassLibrary39 for DNX,Version=v4.5.1
  Using Project dependency ClassLibrary39 1.0.0
    Source: C:\Users\davifowl\Documents\Visual Studio 14\Projects\ClassLibrary39\src\ClassLibrary39\project.json

  Using Assembly dependency framework/mscorlib 4.0.0.0
    Source: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\mscorlib.dll

  Using Assembly dependency framework/System 4.0.0.0
    Source: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\System.dll

  Using Assembly dependency framework/System.Core 4.0.0.0
    Source: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\System.Core.dll

  Using Assembly dependency framework/Microsoft.CSharp 4.0.0.0
    Source: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\Microsoft.CSharp.dll


Building ClassLibrary39 for DNXCore,Version=v5.0
  Using Project dependency ClassLibrary39 1.0.0
    Source: C:\Users\davifowl\Documents\Visual Studio 14\Projects\ClassLibrary39\src\ClassLibrary39\project.json

  Using Package dependency System.Console 4.0.0-beta-22709
    Source: C:\Users\davifowl\.dnx\packages\System.Console.0.0-beta-22709
    File: lib\contract\System.Console.dll

  Using Package dependency System.IO 4.0.10-beta-22231
    Source: C:\Users\davifowl\.dnx\packages\System.IO.0.10-beta-22231
    File: lib\contract\System.IO.dll

  Using Package dependency System.Runtime 4.0.20-beta-22231
    Source: C:\Users\davifowl\.dnx\packages\System.Runtime.0.20-beta-22231
    File: lib\contract\System.Runtime.dll

  Using Package dependency System.Text.Encoding 4.0.10-beta-22231
    Source: C:\Users\davifowl\.dnx\packages\System.Text.Encoding.0.10-beta-22231
    File: lib\contract\System.Text.Encoding.dll

  Using Package dependency System.Threading.Tasks 4.0.10-beta-22231
    Source: C:\Users\davifowl\.dnx\packages\System.Threading.Tasks.0.10-beta-22231
    File: lib\contract\System.Threading.Tasks.dll

输出显示了从包和项目引用传递到编译器的所有程序集。当您开始遇到构建失败时,查看此处以确保您使用的包在该目标平台上确实有效是很有用的。

这是一个不适用于 dnxcore50 的软件包示例:

{
    "version": "1.0.0-*",
    "dependencies": {
        "Microsoft.Owin.Host.SystemWeb": "3.0.0"
    },

    "frameworks": {
        "dnx451": {
            "dependencies": {
            }
        },
        "dnxcore50": {
            "dependencies": {
                "System.Console": "4.0.0-beta-22709"
            }
        }
    }
}

Microsoft.Owin.Host.SystemWeb 版本 3.0.0 在 dnxcore50 上没有 运行 的任何程序集(查看解压包的 lib 文件夹)。当我们 运行 kpm build:

注意它说 "using Package Microsoft.Owin.Host.SystemWeb" 但没有 "File:"。这可能是构建失败的原因。

我的脑洞到此结束

我在尝试安抚 dnxcore50 和 dnx451 引用时也遇到了依赖项缺失问题。

如果我没理解错 "dependencies":{} 在框架之间共享。

然后 "dependencies":{} 在 "frameworks" 中:特定于该框架。

dnxcore50 是一个模块化的 运行time(自包含),因此它基本上包含 运行times 需要的所有核心 运行 一个不同于经典 .net 框架的程序,您拥有核心依赖项分散在其他地方。

因此我想坚持使用最小方法,以防我决定在某个时候在 mac 或 linux 上主持。

更新 运行 遇到 cshtml 视图的奇怪依赖问题,现在只使用 dnx451。

这是我的project.json

{
"webroot": "wwwroot",
"version": "1.0.0-*",

"dependencies": {
    "System.Runtime": "4.0.10",
    "Microsoft.AspNet.Hosting": "1.0.0-beta4",
    "Microsoft.AspNet.Mvc": "6.0.0-beta4",
    "Microsoft.AspNet.Server.IIS": "1.0.0-beta6-12075",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta6-12457",
    "Microsoft.Framework.DependencyInjection": "1.0.0-beta4",
    "Microsoft.Framework.DependencyInjection.Interfaces": "1.0.0-beta5"
 },

"commands": {
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://admin.heartlegacylocal.com"  },

"frameworks": {
"dnx451": { }
 }
},

"publishExclude": [
"node_modules",
"bower_components",
"**.xproj",
"**.user",
"**.vspscc"
],
"exclude": [
  "wwwroot",
  "node_modules",
  "bower_components"
  ]
}

这些天,我所有的 package.json 版本都以 "-rc2-*"

结尾

(到目前为止我看到的唯一例外是 Microsoft.Framework.Configuration 包,它们必须是 "1.0.0-rc1-*""1.0.0-*"

关于@davidfowl 提到的 "version trains",似乎在 beta8 和 rc2 之间已经消除了很多痛苦。

dnvm upgrade -u -arch x64 -r coreclr

我在 coreclr 上最幸运的是这两个 NuGet 提要:

"https://www.myget.org/F/aspnetvnext/"
"https://nuget.org/api/v2/"

当我 遇到包裹丢失问题时,90% 的时间都是这些相同的罪魁祸首:

Newtonsoft.Json
Ix-Async
Remotion.Linq

大多数时候,我可以通过强制主要 NuGet.org 提要来解决这些问题:

dnu restore;
dnu restore -s https://nuget.org/api/v2

这是我的作品config.json:

{
"dependencies": {
    "Microsoft.AspNet.Diagnostics": "1.0.0-rc2-*",
    "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-rc2-*",
    "Microsoft.AspNet.Hosting": "1.0.0-rc2-*",
    "Microsoft.AspNet.Http": "1.0.0-rc2-*",
    "Microsoft.AspNet.Http.Abstractions": "1.0.0-rc2-*",
    "Microsoft.AspNet.Mvc.Core": "6.0.0-rc2-*",
    "Microsoft.AspNet.Mvc.Razor": "6.0.0-rc2-*",
    "Microsoft.AspNet.Owin": "1.0.0-rc2-*",
    "Microsoft.AspNet.Routing": "1.0.0-rc2-*",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc2-*",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-rc2-*",
    "Microsoft.AspNet.Session": "1.0.0-rc2-*",
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc2-*",
    "EntityFramework.Commands": "7.0.0-rc2-*",
    "EntityFramework.Core": "7.0.0-rc2-*",
    "EntityFramework.InMemory": "7.0.0-rc2-*",
    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc2-*",
    "EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc2-*",
    "EntityFramework.Relational": "7.0.0-rc2-*",
    "EntityFramework7.Npgsql": "3.1.0-beta8-2",
    "Microsoft.Extensions.Logging.Abstractions": "1.0.0-rc2-*",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-*",
    "Microsoft.Extensions.DependencyInjection": "1.0.0-rc2-*",
    "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-rc2-*",
    "Microsoft.Framework.Configuration.CommandLine": "1.0.0-*",
    "Microsoft.Framework.Configuration.EnvironmentVariables": "1.0.0-*",
    "Microsoft.Framework.Configuration.Json": "1.0.0-*"
},
"commands": {
    "ef": "EntityFramework.Commands",
    "dev": "Microsoft.AspNet.Hosting --ASPNET_ENV Development --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5004"
},
"frameworks": {
    "dnxcore50": {}
}
}