在使用vs2017开发.net core应用时,通过项目引用的程序集可以正常编译和运行,但是通过直接引用dll的方式引用程序集时,编译可以通过,在运行时总是提示找不到程序集:
看到这个问题后直观的认为是dll没有放到指定的路径,但是尝试过把dll丢到程序运行目录,system32,c:\windows\users\特定用户文件夹下,都不行。通过用dotnet 命令执行程序,开启procmon跟踪了下,发现运行的时候根本没有去加载这个dll,而通过项目引用的dll却能清楚的看到被加载的记录。
由此看来,感觉像是dll根本没有加载到运行时,导致了最终执行到对应代码时挂了。顺着这个思路,在程序启动后反射加载下dll,问题解决。代码中的TryLoadAssembly方法
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //尝试加载下程序集 6 //TryLoadAssembly(); 7 DoSomeThing(); 8 Console.ReadKey(); 9 } 10 private static void DoSomeThing() 11 { 12 //项目引用 13 ProjectReference.Class1.SayHello(); 14 //直接引用 15 DirectReference.Class1.SayHello(); 16 } 17 private static void TryLoadAssembly() 18 { 19 Assembly entry = Assembly.GetEntryAssembly(); 20 //找到当前执行文件所在路径 21 string dir = Path.GetDirectoryName(entry.Location); 22 string entryName = entry.GetName().Name; 23 //获取执行文件同一目录下的其他dll 24 foreach (string dll in Directory.GetFiles(dir, "*.dll")) 25 { 26 if (entryName.Equals(Path.GetFileNameWithoutExtension(dll))) { continue; } 27 //非程序集类型的关联load时会报错 28 try 29 { 30 AssemblyLoadContext.Default.LoadFromAssemblyPath(dll); 31 } 32 catch (Exception ex) 33 { 34 35 } 36 } 37 } 38 }
但是这不是我想要的方式,因为这样随着引用的第三方dll的增多,需要维护一个清单来进行这个引用。
不知道是否存在一个什么在csproj文件中的配置,或者生成dll时的一个什么选项设置得不对,因为不管怎么着,允许我引用但是不让执行是让人无法理解的,毕竟是微软出品,应该不会有这么容易发现的问题。
在网上搜索到的解决方案是将这类dll打包成nuget的包,放在本地,然后还是通过加载包的方式来加载,微软官方指引中也是推荐的这种方式,但目前不想使用这种方式。
所以现在的问题是,有没有一种办法,让手工添加引用后的程序集可以编译通过并运行,不借助nuget和代码执行前反射加载,望各位大神支招。
最好能提供一个可运行的示例项目。
感谢你的关注,示例项目已经打包放置在了百度网盘 链接: http://pan.baidu.com/s/1pKAhy7x 密码: fyvi
@HaiZL:
测试结果如下:
1、直接用VS(2017 preview 15.3.0 Preview 3.0)打开,设置DllReference为主项目,直接运行,没问题,正常输出。
2、进入到bin目录,通过 dotnet DllReference.dll ,提示无法加载DirectReference。
3、通过dotnet publish 生成项目,再通过 dotnet DllReference.dll,和2无差别。
4、我在VS中,将DirectReference.dll 包含到项目中,然后设置属性(总是拷贝到输出目录),然后再生成,接着使用dotnet DllReference.dll ,就能加载到了。
综上,我觉得应该是生成路径的问题。如果不按照4这个步骤,最终的结构是不一样的。
2017-7-14 09:55:48 补充
抱歉,由于我之前的测试步骤较多,导致相互之间有干扰,得出了不对的结论。
我重新解压你提供的压缩包,然后清空DllReference\bin\Debug目录,接着重新编译一次。就能直接通过dotnet DllReference.dll 运行。
可运行的Dll: http://files.cnblogs.com/files/humin/netcoreapp1.1.zip
我的dotnet --version 2.0.0-preview1-005977
@幻天芒: 非常感谢,我安装了2.0预览版的运行时后,果然可以直接运行你附件中的dll了,vs的话暂未升级,公司的网络太慢了,周末在家升级了试试。
@HaiZL: 2.x相对1.x还是有较多变化。部署docker也容易遇到问题,感觉还是不够稳定。
@HaiZL: https://q.cnblogs.com/q/111338/ 程序集引用可以参考
就接触这么久netcore来,只有你说的方式:1.指向项目引用 2.nuget 3.反射 ; dll在vs2017是不允许直接添加引用的,因此直接复制到bin目录也没效果;
哎,这真是一个悲伤的故事,在我这边vs2017中是可以直接添加引用的,所以才报这个希望。
这是我vs的版本。
你是要引用一个预先生成好的dll么, 如果是引用最新版本的DirectReference一般用项目引用, 不然无法保证项目的生成顺序和预期的一致.
另外我用dotnet 2.0.0-preview2-006497(需要搭配VS2017>= 15.3.0 Preview3食用, 最新版本15.3.0 Preview4)是能直接正常运行DllReference的(已清理bin文件夹下除了), dotnet 1.x应该不能直接引Dll(你用的VS正式版可能不支持2.x).你更新下试试.
另外下面这几行是并不需要的(加了会复制出一层多余的dll文件夹)
<ItemGroup> <Content Include="bin\DirectReference.deps.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup> <ItemGroup> <None Include="bin\DirectReference.dll"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup>
非常感谢,原来高版本时该问题已经得到解决,奈何vs太重型了,当初找解决方案时就没有往vs升级这个方向走。
项目文件中确实包含了不需要包含的文件,非常感谢指出。