从Visual Studio 2010中发布报表错误-”Loading this assembly would produce a different grant set from other instances“

 

问题描述:

从Dynamics AX 2012 R2 的AOT / Visual Studio Projects/ 打开一个VS.NET 报表项目,这样VS.NET就打开了,编译部署该报表报如下错误:

The "GenerateRdlTask" task failed unexpectedly.

System.IO.FileLoadException: Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401)

   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)

   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)

   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)

  at System.Activator.CreateInstance(Type type, Boolean nonPublic)

   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)

   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)

   at System.Activator.CreateInstance(String assemblyString, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark)

   at System.Activator.CreateInstance(String assemblyName, String typeName)

   at System.AppDomain.CreateInstance(String assemblyName, String typeName)

   at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)

   at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)

   at Microsoft.Dynamics.Framework.Deployment.Reports.DomainBound.PrepareTask(AppDomain tempAppDomain)

   at Microsoft.Dynamics.Framework.Deployment.Reports.GenerateRdlTask.GetBusinessLogicAssemblyReferences(String assemblyPath)

   at Microsoft.Dynamics.Framework.Deployment.Reports.GenerateRdlTask.Execute()

   at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()

   at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__20.MoveNext() C:\Program Files (x86)\MSBuild\Microsoft\DynamicsTools\Microsoft.Dynamics.Framework.Design.Reporting.Modeling.targets 103 6 FreeTextInvoiceReport

 

原因:

“Loading this assembly would produce a different grant set from other instances”是一常见错误,从CLR角度来看是如下assembly 被加载到多个AppDomain中,而security context不同:

Microsoft.Dynamics.Framework.ReportsDeployment, Version=6.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

AX 定制了一个单独的VS.NET project template, 在发布项目时候为了实现能够unload/load 会建立一个临时的AppDomain, 调用AppDomain.CreateIntanceAndUnWrap()执行 Microsoft.Dynamics.Framework.ReportsDeployment.dll中的类型:

Microsoft.Dynamics.Framework.Deployment.Reports.DomainBoundHelper

深层次的原因目前不清楚,目前只在一个客户那里发生该问题,无法在内部重现跟踪排错。

如果用Process Explore查看DevEnv.exe (VS.NET)加载的assembly, 可以看到Microsoft.Dynamics.Framework.ReportsDeployment.dll被加载到多个AppDomain中,包括Shared AppDomain. 但是Microsoft.Dynamics.Framework.ReportsDeployment.dll实际上是被安装到GAC里的,而且有强签名的,所以不应该会出现在多个AppDomain中的。

解决办法:

目前来看可以采用如下办法绕过该问题:

设置操作系统级别的环境变量 COMPLUS_LoaderOptimization =1, 关于COMPLUS_LoaderOptimization 的说明参看

image

COMPLUS_LoaderOptimization Environment Variable

http://msdn.microsoft.com/en-us/library/dn449122.aspx