我有一个调用.Net assembly built from a Matlab function的C#类。我可以从一个简单的C#控制台应用程序调用此函数,没有任何问题。
但是如果我尝试从NUnit运行单元测试,我会得到以下异常:
ClassLibrary1.Tests.UnitTests.TestPerformOptimization: System.Reflection.TargetInvocationException:异常已经发生 由调用目标抛出。 ----> System.Exception: 编组.NET对象时出错。 '消息:无法找到程序集 ' ClassLibrary1,Version = 1.0.0.0,Culture = neutral, 公钥=空&#39 ;.来源:mscorlib HelpLink:'
如果我尝试从独立的NUnit控制台,ReSharper的测试运行器调用该类,或者如果我尝试从Excel中调用该函数(使用Excel-DNA),则会出现相同的错误。
当调用我编译的Matlab组件时,我实际上将C#方法(在MWObjectArray对象中)包装起来并将其注入。我认为当编译的Matlab组件尝试调用这个注入方法时,问题就出现了。
我发现的唯一解决方法是将我的类的副本(包含注入的方法)放在与NUnit测试运行器,ReSharper测试运行器或Excel相同的位置。然而,由于我需要将此应用程序安装到用户计算机上,因此这不是一个实际的解决方案。我无法使用的另一个选项是将文件复制到我的%DEVPATH%,原因相同。
有没有办法可以告诉Matlab组件在哪里找到我注入的方法/类的程序集?
示例项目下载
有一个示例项目可供下载here。只需按照zip文件中的README.txt文件中的说明操作即可。
更新1
我设法让我的单元测试通过修改我的类以在其构造函数中包含以下内容来识别我的程序集:
AppDomain.CurrentDomain.AssemblyResolve +=
(sender, args) => typeof(OptimizationFunction).Assembly;
但是现在我得到以下例外:
异常:System.Reflection.TargetInvocationException:异常有 被调用的目标抛出。 ---> System.Exception的: 编组.NET对象时出错。 '消息:无法加载文件或 assembly' dotnetcli,Version = 1.0.5488.33915,Culture = neutral, 公钥= da1231a838c93da4'或其中一个依赖项。一个 强名命的装配是必需的。 (HRESULT的例外情况: 0x80131044)来源:mscorlib HelpLink:'在 dotnetcli.throwNetExceptionID(BaseMsgID * msgId)at dotnetcli.DeployedDataConversion.GetMxArrayFromObject(Object data)
---内部异常堆栈跟踪的结束---在System.RuntimeMethodHandle.InvokeMethod(Object target,Object [] arguments,Signature sig,Boolean constructor)
所以现在解决dotnetclli.dll问题(请参阅下面的Fusion日志/例外),据我所知,这应该只存在于C:\ Program Files(x86)\ MATLAB \ MATLAB Runtime \ v85 \ bin \的win32。
以下是Fusion Log的摘录:
===预绑定状态信息===
日志:DisplayName = ClassLibrary1(部分) 警告:程序集名称:ClassLibrary1 |域ID:1 警告:仅提供部分程序集显示名称时发生部分绑定。 警告:这可能导致装订器装入错误的装配。 警告:建议为程序集提供完全指定的文本标识, 警告:它由简单的名称,版本,文化和公钥令牌组成。 >警告:有关此问题的更多信息和常见解决方案,请参阅白皮书http://go.microsoft.com/fwlink/?LinkId=109270。 日志:Appbase = file:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ 日志:初始PrivatePath = NULL 日志:动态Base = NULL 日志:缓存基数= NULL 日志:AppName = nunit-agent-x86.exe 调用程序集:(未知)。
=== 日志:此绑定在默认加载上下文中启动。 日志:使用应用程序配置文件: C:\洞察\ TFS \ ASG \ ConsoleApplication4 \包\ NUnit.Runners.2.6.3 \工具\ NUnit的代理,x86.exe.Config 日志:使用主机配置文件:日志:使用C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ config \ machine.config中的计算机配置文件。 日志:此时策略未应用于引用(私有,自定义,部分或基于位置的程序集绑定)。日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication4/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1.DLL。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1/ClassLibrary1.DLL。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1.DLL。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1/ClassLibrary1.DLL。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1.DLL。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1/ClassLibrary1.DLL。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1.EXE。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1/ClassLibrary1.EXE。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1.EXE。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1/ClassLibrary1.EXE。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1.EXE。 日志:尝试下载新网址 文件:/// C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1/ClassLibrary1.EXE。 日志:所有探测URL都已尝试失败。
警告:为程序集提供了部分绑定信息:为什么我的控制台应用程序可以通过我的NUnit测试来解析此程序集?
更新2
当我联系他们时,我从Matlab得到了以下回复:
据我所知,这是默认的.NET行为 deserializations。反序列化该类的应用程序看起来 对于自己当前文件夹和GAC中的程序集,它不能 找到它。它类似于(当你读到这个替换MATLAB时 NUnit的)
您的示例并不代表涉及MATLAB的情况。 MATLAB通过APPDomains发送类。你的例子不行 这一点。
使用Fuslogvw查看绑定。你会看到它 不是MATLAB,它找不到它是调用应用程序的程序集 无法解决依赖关系(在您的情况下 NUnit的代理-x86.exe程序)。
答案 0 :(得分:4)
确保所有需要的文件都是由ConsoleApplication4的编译生成的,并放在可执行文件之外(例如任何需要的程序集DLL,运行时DLL,.config文件等)。
一旦确定发生了这种情况,请使用--no-shadow-copy命令行开关启动NUnit,或者将其设置为GUI工具中的配置参数。正如布什所说,NUnit通常会将测试中的文件复制到一个单独的目录中,并可能留下重要文件。
如果Matlab创建的类需要某种特定的运行时,请确保它在运行测试的计算机中正确安装/使用Excel / ReSharper。
在这个级别上,我不会试图通过大会决议程序来捣乱:请总结你所链接文章的内容,因为它已付款,并尝试使用NUnit的无阴影 - 复制设置。
答案 1 :(得分:4)
提出第一个问题:
它会记录您的应用查找程序集的位置以及失败的方式。这可能意味着nunit的工作目录与控制台应用程序使用的工作目录不同。
提出第二个错误:强烈命名的程序集是必需的表示您尝试使用的库未签名。如果它是你的组件,你只需要使用visual studio从项目属性中签署程序集。如果它不是您的程序集,您可以对其进行反编译并使用强名称(with this method)进行编译,但第三方dll的提供者应该为您提供一个强名称的程序集。
答案 2 :(得分:4)
我猜这个问题来自.NET CLR版本不兼容。某些客户端(我的意思是调用您的程序集的客户端)加载不同版本的CLE,然后解析的程序集可能与加载的CLR不兼容。这可能会导致 not 发现错误,因为找不到兼容的程序集。
尝试检查/播放客户端版本(控制台应用程序)和服务器版本(您的程序集)并诊断正在发生变化的内容。
同时检查你的程序集引用是否有"复制到输出目录"在所有项目中检查
答案 3 :(得分:3)
您将需要研究在.NET加载时如何进行探测操作。以下是其中的规则:https://msdn.microsoft.com/en-us/library/yx7xezcf(v=vs.110).aspx
除了正在发布的程序集中包含bin之外,它是决定DLL的支持程序是否可加载的加载程序。如果使用上述规则找不到它,那么你就是运气不好。
我们在过去看到类似的问题,一些开发人员对系统管理员说,这里是运行应用程序所需的Dll。系统管理员遵循说明和繁荣,应用程序在加载时失败。
原因:程序集中某个孩子的某个孩子根据探测规则提到了系统上没有的dll。
解 1)获取(孩子的孩子)dll以在其程序集中包含所有依赖项 2)更改较新的主程序集以包括所有依赖项(如果无法更改子程序集)。 3)手动复制它们。 4)创建一个完成所有操作的安装程序。
答案 4 :(得分:2)
是否在全局程序集缓存(GAC)中的程序集或可能覆盖您认为正在加载的程序集的任何位置?这通常是加载错误程序集的结果,对我而言,这意味着我通常在GAC中有一些内容覆盖了bin / Debug中的版本。
答案 5 :(得分:0)
我猜这个问题来自于.NET CLR版本的不兼容性。某些客户端(我的意思是调用您的程序集的客户端)加载不同版本的CLE,然后解析的程序集可能与加载的CLR不兼容。这可能导致找不到错误,因为找不到兼容的程序集。
尝试检查/播放客户端版本(控制台应用程序)和服务器版本(程序集),并诊断正在发生变化的内容。
同时检查您的装配参考是否已在所有项目中选中“复制到输出目录”