问题描述
- Azure.DigitalTwins.Core
- Azure.Core
- Azure.Identity
必须将这些 .dll 依赖项合并到单个 .dll 中才能注册插件。我正在使用 ILMerge 批处理文件脚本将这些 dll 组合成单个 merged.dll
输出。
这是我正在使用的脚本:
@echo off
:: this script needs https://www.nuget.org/packages/ilmerge
:: Set build,used for directory. Typically Release or Debug
SET ILMERGE_BUILD=bin\Debug\ilmerge
:: set your NuGet ILMerge Version,this is the number from the package manager install,for example:
:: PM> Install-Package ilmerge -Version 3.0.29
:: to confirm it is installed for a given project,see the packages.config file
SET ILMERGE_VERSION=3.0.41
:: the full ILMerge should be found here:
SET ILMERGE_PATH=%USERPROFILE%\.nuget\packages\ilmerge\%ILMERGE_VERSION%\tools\net452
:: dir "%ILMERGE_PATH%"\ILMerge.exe
SET PROJECT_ROOT=%CD%
SET ASSEMBLY_DIR=%PROJECT_ROOT%\bin\Debug\net462
::/targetplatform:v4,"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" ^
::/target:library ^
::/copyattrs ^
::/closed ^
::/allowDup ^
echo Merging adtplugin...
:: add project DLL's starting with replacing the FirstLib with this project's DLL
"%ILMERGE_PATH%"\ILMerge.exe ^
/keyfile:%PROJECT_ROOT%\adtplugin.snk ^
/out:%ILMERGE_BUILD%\merged.dll ^
/target:library ^
/nDebug ^
/closed ^
/allowDup ^
/copyattrs ^
/targetplatform:v4,"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2" ^
%ASSEMBLY_DIR%\adtplugin.dll ^
%ASSEMBLY_DIR%\Azure.Core.dll ^
%ASSEMBLY_DIR%\Azure.DigitalTwins.Core.dll ^
%ASSEMBLY_DIR%\Azure.Identity.dll ^
%ASSEMBLY_DIR%\Microsoft.Bcl.AsyncInterfaces.dll ^
%ASSEMBLY_DIR%\Microsoft.Identity.Client.dll ^
%ASSEMBLY_DIR%\Microsoft.Identity.Client.Extensions.Msal.dll ^
%ASSEMBLY_DIR%\Microsoft.Win32.Primitives.dll ^
%ASSEMBLY_DIR%\netstandard.dll ^
%ASSEMBLY_DIR%\system.memory.dll ^
%ASSEMBLY_DIR%\System.Threading.Tasks.Extensions.dll
pause
:Done
我对传递给 ILMerge.exe 的 /option 标志进行了相当多的尝试。目前,通过显示的配置,我可以将列出的 .dll 合并到单个 merge.dll 输出中。
接下来,我尝试使用插件注册工具通过 merged.dll
输出文件注册新程序集。当我尝试注册插件时出现错误:
这是错误转储:
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault,Microsoft.Xrm.Sdk,Version=9.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35]]: Unable to load plug-in assembly.
Detail: <OrganizationServiceFault xmlns="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ActivityId>9e6ed737-8374-464e-956a-d70b46a2c686</ActivityId>
<ErrorCode>-2147204719</ErrorCode>
<ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
<keyvaluePairOfstringanyType>
<a:key>ApiExceptionSourceKey</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Plugin/Microsoft.Crm.ObjectModel.PluginAssemblyService</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiSourceActivityKey</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Microsoft.Crm.Extensibility.Pipelinestep</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiExceptioNownerKey</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">COMMONDATASERVICECDS\CDSAPI-Reliability</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiOriginalExceptionKey</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Microsoft.Crm.CrmException: Unable to load plug-in assembly. ---> Microsoft.Crm.CrmException: Unable to load plug-in assembly.
at Microsoft.Crm.ObjectModel.PluginAssemblyServiceInternal`1.LoadCrmPluginAssemblyMetadata(IBusinessEntity pluginAssembly,IExecutionContext context,Boolean loadAllMetadata)
at Microsoft.Crm.ObjectModel.PluginAssemblyServiceInternal`1.RetrieveAssemblyMetadata(IBusinessEntity pluginAssembly,ExecutionContext context,Boolean retrieveFromExisting,Boolean forSystemAssembly)
at Microsoft.Crm.ObjectModel.PluginAssemblyServiceInternal`1.ValidateOperation(String operationName,IBusinessEntity entity,ExecutionContext context)
at Microsoft.Crm.ObjectModel.SdkEntityServiceBase.CreateInternal(IBusinessEntity entity,Boolean verifyAction)
--- End of inner exception stack trace ---
at Microsoft.Crm.Extensibility.VersionedpluginProxyStepBase.Execute(PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.PipelineInstrumentationHelper.Execute(Boolean instrumentationEnabled,String stopwatchName,ExecuteWithInstrumentation action,PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.Pipeline.<>c__displayClass7_0.<RunStep>b__0()</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiStepKey</a:key>
<a:value i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">3ecabb1b-ea3e-db11-86a7-000a3a5473e8</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiDepthKey</a:key>
<a:value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiActivityIdKey</a:key>
<a:value i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">9e6ed737-8374-464e-956a-d70b46a2c686</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiPluginSolutionNameKey</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">System</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiStepSolutionNameKey</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">System</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiExceptionCategory</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">SystemFailure</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiExceptionMessageName</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">UnabletoLoadpluginAssembly</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>ApiExceptionHttpStatusCode</a:key>
<a:value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">500</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>0</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Failed to load plugin assembly with exception Microsoft.Crm.CrmException: GetAssemblyMetadata: expected mdtAssemblyRef or mdtAssembly
at Microsoft.Crm.CrmException.Assert(Boolean condition,String message)
at Microsoft.Crm.CrmPluginAssemblyMetadata.GetAssemblyMetadata(UInt32 token)
at Microsoft.Crm.CrmPluginAssemblyMetadata.ProcesstypeRef(UInt32 typeRef)
at Microsoft.Crm.CrmPluginAssemblyMetadata.Processtype(UInt32 token)
at Microsoft.Crm.CrmPluginAssemblyMetadata.ProcesstypeDef(UInt32 typeDef)
at Microsoft.Crm.CrmPluginAssemblyMetadata.Processtype(UInt32 token)
at Microsoft.Crm.CrmPluginAssemblyMetadata.LoadMetadata()
at Microsoft.Crm.CrmPluginAssemblyMetadata.LoadMetadataFromAssemblyContent(ArraySegment`1 assemblyContents,Boolean loadAllMetadata)
at Microsoft.Crm.CrmPluginAssemblyMetadata.LoadMetadataFromAssemblyContent(String content,Boolean loadAllMetadata)
at Microsoft.Crm.ObjectModel.PluginAssemblyServiceInternal`1.LoadCrmPluginAssemblyMetadata(IBusinessEntity pluginAssembly,Boolean loadAllMetadata). PluginInfo => Crm plugin assembly info : sourcetype = 0,description =,ismanaged = False,pluginassemblyid = b77380cb-8676-45b6-9e5c-63a5960ed2ac,ispasswordset = False,publickeytoken = 7F66FA42F6885FDC,name = merged,culture = neutral,isolationmode = 2,version = 1.0.0.0,</a:value>
</keyvaluePairOfstringanyType>
<keyvaluePairOfstringanyType>
<a:key>1</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Microsoft.Crm.CrmException: GetAssemblyMetadata: expected mdtAssemblyRef or mdtAssembly
at Microsoft.Crm.CrmException.Assert(Boolean condition,Boolean loadAllMetadata)</a:value>
</keyvaluePairOfstringanyType>
</ErrorDetails>
<HelpLink>http://go.microsoft.com/fwlink/?LinkID=398563&error=Microsoft.Crm.CrmException%3a80044191&client=platform</HelpLink>
<Message>Unable to load plug-in assembly.</Message>
<Timestamp>2021-04-29T17:46:08.9958593Z</Timestamp>
<ExceptionRetriable>false</ExceptionRetriable>
<ExceptionSource i:nil="true" />
<InnerFault>
<ActivityId>9e6ed737-8374-464e-956a-d70b46a2c686</ActivityId>
<ErrorCode>-2147204719</ErrorCode>
<ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<HelpLink i:nil="true" />
<Message>Unable to load plug-in assembly.</Message>
<Timestamp>2021-04-29T17:46:08.9958593Z</Timestamp>
<ExceptionRetriable>false</ExceptionRetriable>
<ExceptionSource i:nil="true" />
<InnerFault i:nil="true" />
<OriginalException i:nil="true" />
<TraceText i:nil="true" />
</InnerFault>
<OriginalException i:nil="true" />
<TraceText i:nil="true" />
</OrganizationServiceFault>
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation,ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean oneway,ProxyOperationRuntime operation,Object[] ins,Object[] outs,TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at Microsoft.Crm.Tools.Libraries.RegistrationHelper.Registerassembly(CrmOrganization org,String pathToAssembly,CrmPluginAssembly assembly) in D:\a\1\s\src\GeneralTools\PluginRegistrationV3\PluginRegistration\Crmlibraries\RegistrationHelper.cs:line 723
at Microsoft.Crm.Tools.AssemblyRegistration.PluginRegistrationviewmodel.Registerassembly() in D:\a\1\s\src\GeneralTools\PluginRegistrationV3\RegistrationTools\AssemblyRegistration\viewmodels\PluginRegistrationviewmodel.cs:line 649
如果有人成功使用 .bat 脚本运行 ILMerge、合并 .dll 文件并使用输出注册 D365 插件,请告诉我! (非常具体...我知道哈哈)
更新
我现在已经切换到 ILRepack 和 ILRepack.Lib.MSBuild.Task。我在 ILRepack.targets 文件中使用以下配置:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="ILRepacker" AfterTargets="Build">
<ItemGroup>
<InputAssemblies Include="$(OutputPath)$(TargetName)$(TargetExt)" />
<!--<InputAssemblies Include="$(OutputPath)\*.dll" />-->
<InputAssemblies Include="$(OutputPath)adtplugin.dll" />
<InputAssemblies Include="$(OutputPath)Azure.Core.dll" />
<InputAssemblies Include="$(OutputPath)Azure.DigitalTwins.Core.dll"/>
<InputAssemblies Include="$(OutputPath)Azure.Identity.dll"/>
<InputAssemblies Include="$(OutputPath)Microsoft.Bcl.AsyncInterfaces.dll"/>
<InputAssemblies Include="$(OutputPath)system.memory.dll"/>
<InputAssemblies Include="$(OutputPath)System.Threading.Tasks.Extensions.dll"/>
<!--<InputAssemblies Include="$(OutputPath)Microsoft.Identity.Client.dll"/>
<InputAssemblies Include="$(OutputPath)Microsoft.Identity.Client.Extensions.Msal.dll"/>
<InputAssemblies Include="$(OutputPath)Microsoft.Win32.Primitives.dll"/>
<InputAssemblies Include="$(OutputPath)netstandard.dll"/>-->
</ItemGroup>
<ILRepack
Parallel="true"
Internalize="false"
InternalizeExclude="@(DonotinternalizeAssemblies)"
InputAssemblies="@(InputAssemblies)"
LibraryPath="$(OutputPath)"
Wildcards="false"
TargetKind="SameAsPrimaryAssembly"
DebugInfo="false"
KeyFile="adtplugin.snk"
OutputFile="$(OutputPath)Merged\$(AssemblyName).dll"
LogFile="$(OutputPath)Merged\ILRepack.log"
/>
</Target>
</Project>
解决方法
您可能希望避免合并属于 .NET Framework 的任何内容(我假设像 System.Memory
和 System.Threading.Tasks
这样的库是)。
话虽如此,根据您要合并的 DLL,即使您注册了它,根据代码的实际作用,sandbox environment 的限制可能会阻止插件运行。
>如果情况确实如此,您可能需要查看 Azure Aware Plugin。
我曾经有一个插件,我必须在其中进行 RSA 签名验证。我尝试使用 .NET 库,但沙箱禁止运行与 RSA 相关的代码。我最终不得不使用我发现的名为 EZ-RSA 的开源 RSA 库“自行开发”。
感谢您的更新。我更仔细地查看了错误消息。我发现 this article 和 this question 中,开发人员似乎得出结论,ILMerging an Identity library 是个大杂烩。
就合并/重新打包路径而言,您可能希望使用一个空白项目并一个一个地合并 DLL,在每个 DLL 之后测试插件注册以查看哪个或哪些库破坏了注册。>
我最后一次听说,即使它有效,ILMerge 在技术上也不受支持。支持的是 Azure Aware 插件。
对于服务端点,它可以访问 Azure 服务总线队列中的各种类型的侦听器(通过连接字符串或此配置对话框)。
,尝试在构建操作后使用 Fody 包合并您的 .dll-s。首先,您需要通过 nuget 安装 Fody 和 Costura.Fody。它将添加一些引用和文件 FodyWeavers.xml,您可以通过这种方式填充
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>
然后在解决方案资源管理器中选择要合并在一起的程序集的引用,并在属性窗口中更改复制本地 strong> 到 True。对于那些您不想包含在合并过程中的程序集,请选择 Copy Local - False
重新构建您的解决方案,在输出中您将获得合并的 dll。