"An unexpected error ocurred" CRM 2015 本地插件

"An unexpected error ocurred" CRM2015 OnPremise Plugins

2 周以来,我们一直在使用 CRM 2015 OnPremise 中的插件遇到一个完全随机的小问题。当我们进行上传时,随机且没有多大意义(至少根据分析所有代码没有)插件向我们抛出以下异常:

The Web Service plug-in failed in OrganizationId: fb2630bc-8dc1-e411-80be-bae05bad392c; SdkMessageProcessingStepId: d2713f4e-51b7-e411-80b8-527d00dcf108; EntityName: new_serviciobase; Stage: 30; MessageName: Create; AssemblyName: Microsoft.Crm.Extensibility.InternalOperationPlugin, Microsoft.Crm.ObjectModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35; ClassName: Microsoft.Crm.Extensibility.InternalOperationPlugin; Exception: Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.

at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)

at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)

at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

at System.Web.Services.Protocols.LogicalMethodInfo.Invoke(Object target, Object[] values)

at Microsoft.Crm.Extensibility.InternalOperationPlugin.Execute(IServiceProvider serviceProvider)

at Microsoft.Crm.Extensibility.V5PluginProxyStep.ExecuteInternal(PipelineExecutionContext context)

at Microsoft.Crm.Extensibility.VersionedPluginProxyStepBase.Execute(PipelineExecutionContext context)

Inner Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.

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.Activator.CreateInstance(Type type)

at Microsoft.Crm.Extensibility.VersionedPluginProxyStepBase.InitializePlugin[T](IOrganizationContext context, StepDescription stepDescription, SecureConfigurationCache stepSecureConfigurationCache, Type type)

at Microsoft.Crm.Extensibility.V5PluginProxyStep..ctor(Guid stepId, SecureConfigurationCache stepSecureConfigurationCache, CrmEventLog eventLog, IOrganizationContext context)

at Microsoft.Crm.Extensibility.PluginStep..ctor(Guid stepId, SecureConfigurationCache stepSecureConfigurationCache, CrmEventLog eventLog, IOrganizationContext context)

at Microsoft.Crm.Extensibility.PipelineStepFactory.CreateInstance(Guid stepId, IOrganizationContext context)

at Microsoft.Crm.Caching.PipelineStepCacheLoader.LoadCacheData(Guid key, ExecutionContext context)

at Microsoft.Crm.Caching.ObjectModelCacheLoader`2.LoadCacheData(TKey key, IOrganizationContext context)

at Microsoft.Crm.Caching.CrmMultiOrgCacheBase`2.CreateEntry(TKey key, IOrganizationContext context)

at Microsoft.Crm.Caching.CrmSharedMultiOrgCache`2.LookupEntry(TKey key, IOrganizationContext context)

at Microsoft.Crm.Caching.MessageProcessorCacheLoader.GetCustomizationLevel(MessageProcessor mp, ExecutionContext context)

at Microsoft.Crm.Caching.MessageProcessorCacheLoader.LoadCacheData(MessageProcessorKey key, ExecutionContext context) at Microsoft.Crm.Caching.ObjectModelCacheLoader`2.LoadCacheData(TKey key, IOrganizationContext context)

at Microsoft.Crm.Caching.CrmSharedMultiOrgCache`2.LookupEntry(TKey key, IOrganizationContext context)

at Microsoft.Crm.Extensibility.InternalMessageDispatcher.TryGetMessageProcessor(MessageProcessorKey key, ExecutionContext context)

at Microsoft.Crm.Extensibility.ExtensiblePlatformMessageDispatcher.IsPipelineDefined(MessageProcessorKey key, ExecutionContext context)

at Microsoft.Crm.Extensibility.ExtensiblePlatformMessageDispatcher.CreateWithInvocationSource(BusinessEntity entity, Int32 invocationSource, ExecutionContext context)

at Microsoft.Crm.BusinessEntities.BusinessProcessObject.Create(IBusinessEntity entity, ExecutionContext context)

Inner Exception: System.IO.FileLoadException: Could not load file or assembly ‘SCM.CRM.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=369abd01f82b8d9d’ or one of its dependencies. Access is denied.

at SCM.CRM.Plugins.Plugin..ctor(Type childClassName)

at SCM.CRM.Plugins.PLGServicioBase..ctor()

这让人有点头疼,因为我们不明白发生了什么,只是有时会失败,有时不会...我们有一个自定义库注册插件(磁盘)"SCM.Core.dll",它说自己无法访问...有什么想法吗?

我是 Alexis 的同事,感谢 cardiagtool,现在我们有了更多的细节:

System.IO.FileLoadException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #ED0C936C: System.IO.FileLoadException: Could not load file or assembly 'SCM.CRM.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=369abd01f82b8d9d' or one of its dependencies. Access is denied. File name: 'SCM.CRM.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=369abd01f82b8d9d'

正如@Sxntk 所说,如果您在注册插件程序集时使用沙盒模式隔离模式,则需要确保将任何插件与 ilmerge 合并。

如果您的隔离模式为 'none',请确保该程序集位于 GAC 中或位于服务器上 CRM 安装目录的 bin\assembly 文件夹中。

希望这对您有所帮助。

您可以执行以下操作:

  1. 确保所有引用的程序集都将 "Copy Local" 设置为 "True"
  2. 从 visual studio
  3. 卸载项目
  4. 右键单击卸载的项目并编辑 csproj 文件
  5. 在 csproj 文件中的 "Project" 结束标记之前(文档最后一行之前)添加以下行:

    <Target Name="AfterResolveReferences">
        <ItemGroup>
          <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
            <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
          </EmbeddedResource>
        </ItemGroup>
      </Target>

  1. 将此方法添加到插件中class:

    private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
    {
    
        Assembly executingAssembly = Assembly.GetExecutingAssembly();
        AssemblyName assemblyName = new AssemblyName(args.Name);
        string path = assemblyName.Name + ".dll";
    
        if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false)
        {
            path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);
        }
    
        using (Stream stream = executingAssembly.GetManifestResourceStream(path))
        {
            if (stream == null)
                return null;
            byte[] assemblyRawBytes = new byte[stream.Length];
            stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
            return Assembly.Load(assemblyRawBytes);
        }
    }
    
  2. 将以下构造函数添加到插件 class:

    static [Constructor name]()
    {
        AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
    }
    
  3. 重建并注册您的插件

这样做,所有复制到本地 bin 文件夹的引用程序集都打包到主 dll 中。缺点是您最终可能会拥有如此庞大的 dll,以至于您无法将其注册为插件。

希望这对您有所帮助, 干杯