为什么要创建List<>来自GAC的汇编在沙盒插件中失败了吗?

时间:2012-11-29 18:22:41

标签: c# dynamics-crm-2011

我正在尝试编写一个MSWare CRM 2011插件,以在沙盒模式下运行,但使用GAC程序集中的类。我遇到了一个问题,即从GAC程序集中创建一个类型的List会产生错误,我不明白为什么。生成的异常类型为System.MethodAccessException,并显示以下消息:

Attempt by method 'IsolatedModeExceptionsTestingPlugin.Plugin.Execute(System.IServiceProvider)' to access method 'System.Collections.Generic.List`1<System.__Canon>..ctor()' failed.

有人可以解释为什么会失败,以便我可以修改我的代码/环境以解决失败问题吗?

我在下面的一组简单的类中重新创建了场景。

我在运行Dynamics 2011 Rollup 7的Win2008 R2服务器上运行测试,然后再在Rollup 11上运行。 我的程序集都是针对.Net 4.0构建的,而动态IIS AppPool是针对.Net 4配置的。两个程序集都是签名的(使用相同的密钥对)。

请注意,如果我将插件的隔离模式从“沙盒”更改为“无”,插件工作正常 - 仅在沙盒模式下才会发生这种情况,这意味着在生成List&lt;&gt;时会出现某种安全违规行为。 。另请注意,创建List(或其他.Net类型)的工作正常,创建List&lt;&gt;也是如此。我自己的程序集中的类。它似乎特定于GAC的组件。

我放在GAC中的程序集名为“ClassLibrary1”,只包含一个类:

namespace ClassLibrary1
{    
    public class MyCustomAssemblyClass
    {
        public string GetAString()
        {
            return "The current time is " + System.DateTime.Now.ToString();
        }
    }
} 

我通过在服务器(安装了Windows SDK v7.1)上运行以下命令将其放在GAC中:"c:\program files\Windows SDKs\Windows\v7.1\bin\NETFX 4.0 Tools\gacutil.exe" -i classlibrary1.dll

我的插件代码如下所示:

using System.Collections.Generic;
using System.Text;
using System;
using ClassLibrary1;
using Microsoft.Xrm.Sdk;

namespace IsolatedModeExceptionsTestingPlugin
{
    public class Plugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {            
            var pluginExecutionContext = (IPluginExecutionContext) serviceProvider.GetService(typeof (IPluginExecutionContext));
            var tracingService = (ITracingService) serviceProvider.GetService(typeof (ITracingService));

            try
            {
                tracingService.Trace("Entered Plugin.Execute()");
                tracingService.Trace(string.Format("Isolation Mode: {0}, Mode: {1}\n\n",
                                                   pluginExecutionContext.IsolationMode,
                                                   pluginExecutionContext.Mode));

                try
                {                    
                    tracingService.Trace(string.Format("*** Creating List<{0}>", typeof (MyCustomAssemblyClass)));
                    var list = new List<MyCustomAssemblyClass>(); //XXX Exception thrown here!!
                    tracingService.Trace("    Success");
                }
                catch (Exception ex)
                {                    
                    tracingService.Trace(GetExpectionTraceMessage(ex));
                    throw new Exception("An error occurred in one of the tests", ex);
                }
                finally
                {
                    tracingService.Trace("*** Finished TestListOfGACClassCxtr\n\n");
                }

                //This will force a failure to allow viewing of the trace file
                //    throw new Exception("TEST SUCCESSFULL");                

            }           
            finally
            {
                tracingService.Trace("Exiting Plugin.Execute()");
            }
        }


        private string GetExpectionTraceMessage(Exception ex)
        {
            var message = new StringBuilder();
            message.AppendFormat("EXCEPTION: {0}\n", ex.GetType());
            message.AppendFormat("\tMessage: {0}\n", ex.Message);
            message.AppendFormat("\tStack: {0}\n", ex.StackTrace);

            if (ex.InnerException != null)
            {
                message.AppendLine("---- INNER EXCEPTION ----");
                message.AppendLine(GetExpectionTraceMessage(ex.InnerException));
            }

            return message.ToString();
        }

    }
}

当实体更新时,我注册了插件以从数据库中以沙箱模式运行。执行插件后,我通过“业务流程错误”对话框的“下载日志文件”获得以下输出:

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Unexpected exception from plug-in (Execute): IsolatedModeExceptionsTestingPlugin.Plugin: System.Exception: An error occurred in one of the testsDetail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ErrorCode>-2147220956</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>Unexpected exception from plug-in (Execute): IsolatedModeExceptionsTestingPlugin.Plugin: System.Exception: An error occurred in one of the tests</Message>
  <Timestamp>2012-11-29T18:09:26.5671559Z</Timestamp>
  <InnerFault i:nil="true" />
  <TraceText>

[IsolatedModeExceptionsTestingPlugin: IsolatedModeExceptionsTestingPlugin.Plugin]
[6d245108-b638-e211-bae5-000c29d5e4ba: IsolatedModeExceptionsTestingPlugin.Plugin: Update of new_insurancequote]

Entered Plugin.Execute()
Isolation Mode: 2, Mode: 0


*** Creating List&lt;ClassLibrary1.MyCustomAssemblyClass&gt;
EXCEPTION: System.MethodAccessException
    Message: Attempt by method 'IsolatedModeExceptionsTestingPlugin.Plugin.Execute(System.IServiceProvider)' to access method 'System.Collections.Generic.List`1&lt;System.__Canon&gt;..ctor()' failed.
    Stack:    at IsolatedModeExceptionsTestingPlugin.Plugin.Execute(IServiceProvider serviceProvider)

*** Finished TestListOfGACClassCxtr


Exiting Plugin.Execute()


</TraceText>
</OrganizationServiceFault>

作为参考,.Net框架似乎使用System .__ Canon类型在JIT为所有泛型创建可重用代码。请参阅:http://www.marklio.com/marklio/PermaLink,guid,1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9.aspx

2 个答案:

答案 0 :(得分:1)

隔离模式模仿CRM Online。在CRM Online中,您无法在不检查低级别原因的情况下从根本上添加到GAC,我相信这就是您的代码失败的原因。

(因此我猜测List<>是一个红色的鲱鱼,甚至实例化一个GACed Type的单个实例也会失败)

修改

默认情况下,GAC会向程序集授予完全信任。在沙盒/隔离模式下运行的插件在部分信任中运行 - 这就是为什么我不相信您在沙盒模式下运行时能够实例化MyCustomAssemblyClass(这就是为什么我认为{{1}无关紧要)。

根据我自己在下面的评论 - 我认为这样总结了它:

  

我认为这个问题基本上是一个提升 - 即a   部分受信任的程序集(即插件,受限制)   它应该可以信任运行一个完全受信任的插件   (可以做任何事情)。如果部分信任,似乎合乎逻辑   代码被允许运行完全受信任的代码,它会有效   因此,提升部分受信任程序集的权限   创建漏洞。

答案 1 :(得分:0)

查看this link并尝试将允许部分信任的来电者属性添加到您的GAC。

当天结束时,CRM正在使用.NET 4中的AppDomain类(link on AppDomain)并使用AppDomain运行沙盒插件。

我遇到的挑战是,我找不到任何明确说明CRM Sandbox服务应用于它正在创建执行插件的AppDomain的规则的Microsoft文档。这使得在GAC中配置类以使其可以通过沙盒代码调用时,基本上是试错了。