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

Jon*_*eet 130 c# dnx asp.net-core

我正在尝试使用Kestrel在DNX上为ASP.NET vNext 运行HelloWeb示例的修改版本.我明白,这是非常对的前沿不多,但我希望这对ASP.NET团队至少会保持尽可能简单的Web应用程序的工作:)

环境:

  • Linux(Ubuntu,非常多)
  • 单声道3.12.1
  • DNX 1.0.0-beta4-11257(我也有11249可用)

"Web应用程序"代码,位于Startup.cs:

using Microsoft.AspNet.Builder;
public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseWelcomePage();
    }
}
Run Code Online (Sandbox Code Playgroud)

项目配置,在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": {}
  }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

显然,我最迫切的需要是解决这个问题,我也很欣赏有关如何确定问题的建议,以便我将来能够自行解决类似的问题.(这也可能使这个问题对其他人更有用.)

Microsoft.Framework.Runtime.IApplicationEnvironmentMicrosoft.Framework.Runtime.Interfaces汇编源代码中找到了,最近似乎没有改变.目前尚不清楚为什么异常将名称显示为整个程序集本身,而不仅仅是另一个程序集中的接口.我猜这可能是由于汇编中性接口,但从错误中不清楚.([AssemblyNeutral]死了,所以不是......)

dav*_*owl 144

好问题.对于您的特定问题,您似乎在已解决的依赖项中存在不匹配.当这样的事情发生时,可能是因为你在不兼容的dnx上运行你的应用程序.我们仍然会进行非常大的改变,所以如果你看到缺少类型丢失的方法,你很可能最终运行betaX包和betaYdnx,反之亦然.

更具体地说,在beta4中删除了程序集中性接口,但看起来你正在运行的应用程序仍在使用它们.

我们计划将其设置为使包可以标记运行所需的最小dnx,以使错误消息更加清晰.随着时间的推移,破裂的变化将会消失.

总的来说,我觉得是时候编写一本关于如何在使用dnx时诊断这样的问题的指南(因为它与现有的.NET非常不同).

您投入的依赖关系project.json仅限顶级.版本也总是最小的(它就像一个NuGet包).这意味着当您指定Foo 1.0.0-beta4您真正指定时Foo >= 1.0.0-beta4.这意味着如果您要求MVC 0.0.1并且已配置的Feed上的最低版本是MVC 3.0.0,您将获得该版本.除非您指定,否则我们也永远不会浮动您的版本.如果你要求1.0.0并且它存在,即使存在更新的版本,你也会获得1.0.0.指定空版本总是很糟糕,在以后的版本中将不允许这样做.

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

1.0.0-*- means给我匹配前缀的最高版本(根据语义版本规则)或者如果没有匹配该前缀的版本,使用正常行为并获得LOWEST版本> =指定版本.

在最新版本中运行还原时,它将写出一个名为的文件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
Run Code Online (Sandbox Code Playgroud)

*表示直接依赖.

如果你有一个工作的visual studio(现在它与DNX打破),你可以查看references节点.它具有相同的视觉数据:

引用节点

让我们看一下依赖失败的样子:

这是project.json

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

    "frameworks" : {
        "dnx451" : { 
            "dependencies": {
            }
        },
        "dnxcore50" : { 
            "dependencies": {
                "System.Runtime": "4.0.20-beta-22709"
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Newtonsoft.Json 8.0.0不存在.所以运行kpm restore会显示以下内容:

在此输入图像描述

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

KPM恢复--no-cache

这些错误也会在包管理器日志输出窗口中显示在Visual Studio中:

在此输入图像描述

边注!

包装来源

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

在这里阅读有关NuGet.config的更多信息

回到现实:

当依赖关系未解析时,运行应用程序将为您提供:

> 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)
Run Code Online (Sandbox Code Playgroud)

运行时基本上尝试在尝试运行之前验证整个依赖关系图是否已解析.如果它建议运行kpm restore它是因为它找不到列出的依赖项.

你可能会遇到这个错误的另一个原因是你运行了错误的dnx风格.如果您的应用程序仅指定dnx451并且您尝试运行CoreCLR dnx,则可能会看到类似的问题.密切注意错误消息中的目标框架:

用于运行:

dnx4x - runs on dnx-clr-{etc}
dnxcore50 - runs on dnx-coreclr-{etc}
Run Code Online (Sandbox Code Playgroud)

当你试图运行时,你应该记住从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\4.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\4.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\4.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\4.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\4.0.10-beta-22231
    File: lib\contract\System.Threading.Tasks.dll
Run Code Online (Sandbox Code Playgroud)

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

这是一个在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"
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

缺少dnxcore50上的程序集

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

这结束了我的大脑转储


Jon*_*eet 17

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

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

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

rm -rf ~/.dnx/packages && rm -rf ~/.dnx/runtimes && dnvm upgrade && kpm restore && dnx . kestrel
Run Code Online (Sandbox Code Playgroud)

看起来我的问题确实是由于安装的依赖项版本错误.版本号"1.0.0-beta4"显然与...完全不同"1.0.0-beta4-*".例如,Kestrel依赖安装版本1.0.0-beta4-11185时刚刚指定为1.0.0-beta4,但版本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": {}
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是因为` - *`总是为您提供最新的预发行版本,而没有它你会得到满足所有依赖项的最低版本(与NuGet一样).[本测试](https://github.com/aspnet/DNX/blob/1cd7c16acf86f202b260e3da5f200f43967a4be2/test/Microsoft.Framework.Runtime.Tests/ProjectFacts.cs#L57-L94)有几个例子. (6认同)
  • `"frameworks":{"dnx451":{}}`为我修好了,不需要`dnxcore50` (4认同)
  • @AlexanderKöplinger:谢谢,这是有道理的.所以...... beta4是最早的beta4,而beta4-*是最新的beta4,对吧? (2认同)

Eil*_*lon 8

您可以设置一个名为的环境变量DNX_TRACE1看看一吨多的诊断信息.被警告,这是一个很大的详细信息!