ILMERGE合并DLL后OrganizationServiceProxy初始化失败求助
这个空引用异常的核心原因是ILMerge合并程序集后,Microsoft.Xrm.Sdk库无法正确读取自身的程序集版本信息。
具体来说,ServiceMetadataUtility.GetSDKVersionNumberFromAssembly()方法会尝试加载Microsoft.Xrm.Sdk程序集并获取其版本号,但ILMerge将该DLL的代码合并到主EXE后,原来的独立程序集标识已经消失,导致方法找不到预期的程序集资源,最终抛出NullReferenceException。
下面提供几种可行的解决办法,按推荐程度排序:
1. 使用Costura.Fody替代ILMerge(最推荐)
Costura.Fody是一个专门用于将依赖DLL内嵌到.NET程序集的工具,它能更好地处理这类需要读取自身程序集信息的库,比ILMerge兼容性更强。
- 步骤:
- 通过NuGet安装Costura.Fody到你的Windows Forms项目:
Install-Package Costura.Fody - 重新编译项目,生成的EXE会自动内嵌
Microsoft.Xrm.Sdk.dll和Microsoft.Crm.Sdk.Proxy.dll,无需手动执行ILMerge命令 - 直接运行生成的EXE即可正常连接Dynamics 365
- 通过NuGet安装Costura.Fody到你的Windows Forms项目:
2. 修改ILMerge命令,保留程序集元数据(可选)
如果你坚持使用ILMerge,可以尝试添加/internalize:exclude=Microsoft.Xrm.Sdk,Microsoft.Crm.Sdk.Proxy参数,避免ILMerge将这两个库的类型标记为内部类型,同时保留它们的程序集信息:
"$(SolutionDir)ILMERGE/IlMerge.exe" /target:winexe /targetplatform:"v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319" /internalize:exclude=Microsoft.Xrm.Sdk,Microsoft.Crm.Sdk.Proxy /out:"$(SolutionDir)..\Output\ConnectToCRM.exe" "$(TargetDir)ConnectToCRM.exe" "$(TargetDir)Microsoft.Crm.Sdk.Proxy.dll" "$(TargetDir)Microsoft.Xrm.Sdk.dll"
不过这种方法不一定能完全解决问题,因为ILMerge的合并方式还是会改变程序集的加载逻辑,部分场景下仍可能出现异常。
3. 避免合并DLL,随EXE一同分发(最简单)
如果合并不是硬性要求,最稳妥的方式是直接将Microsoft.Xrm.Sdk.dll和Microsoft.Crm.Sdk.Proxy.dll放在EXE同一目录下分发,这样程序能正常加载原始程序集,不会出现版本读取问题。
Dynamics 365的SDK库(尤其是Microsoft.Xrm.Sdk)在设计时依赖自身的程序集元数据进行版本校验和服务端点匹配,合并工具如果破坏了这些元数据的可访问性,就会引发这类异常。Costura.Fody在处理内嵌时会模拟原始程序集的加载行为,因此能很好地适配这类场景。
内容的提问来源于stack exchange,提问作者Indie.Dev

