使用Microsoft Graph发邮件遇System.IO.FileLoadException问题求助
本地VS2019环境中使用Microsoft Graph发送邮件功能运行正常,但部署到生产环境后邮件模块崩溃,抛出
System.IO.FileLoadException异常。Windows日志精简信息如下:Toepassing: CIP.WindowsClient.exe Framework-versie: v4.0.30319 Beschrijving: het proces is beëindigd als gevolg van een onverwerkte uitzondering. Uitzonderingsinformatie: System.IO.FileLoadException bij Microsoft.Identity.Client.ApplicationConfiguration..ctor() bij Microsoft.Identity.Client.ConfidentialClientApplicationBuilder.Create(System.String) bij CIP.Helper.Mail.GraphMail+<已确认部署所有相关DLL文件、配置中的TenantId/ClientId加载正常,替换过DLL文件但问题仍未解决,需要排查建议。
相关代码
using Microsoft.Graph; using Microsoft.Identity.Client; using System; using System.Linq; using System.Collections.Generic; using System.Configuration; using System.Net.Http.Headers; namespace CIP.Helper.Mail { public class GraphMail { private static GraphServiceClient _userClient; private static User _user; public GraphMail() { InitializeGraphForUserAuth(); } private async static void InitializeGraphForUserAuth() { string auth = string.Concat("https://login.microsoftonline.com/", ConfigurationManager.AppSettings["TenantId"]); IConfidentialClientApplication application = ConfidentialClientApplicationBuilder.Create(ConfigurationManager.AppSettings["ClientId"]) .WithClientSecret(ConfigurationManager.AppSettings["ClientSecret"]) .WithAuthority(new Uri(auth)) .Build(); System.Windows.MessageBox.Show(string.Format(ConfigurationManager.AppSettings["TenantId"].ToString())); try { _userClient = new GraphServiceClient("https://graph.microsoft.com/v1.0", new DelegateAuthenticationProvider(async (requestMessage) => { AuthenticationResult AuthToken = await application.AcquireTokenForClient(new string[] { "https://graph.microsoft.com/.default" }).ExecuteAsync(); requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", AuthToken.AccessToken); } )); } catch (MsalUiRequiredException ex) { // The application doesn't have sufficient permissions. // - Did you declare enough app permissions during app creation? // - Did the tenant admin grant permissions to the application? Console.WriteLine("Exception: {0}", ex.Message); } catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011")) { // Invalid scope. The scope has to be in the form "https://resourceurl/.default" // Mitigation: Change the scope to be as expected. Console.WriteLine("Scope provided is not supported"); } catch (Exception ex) { Console.WriteLine(ex.InnerException); } //} //catch (FileLoadException ex) //{ // System.Windows.MessageBox.Show(ex.InnerException.ToString()); //} //catch(Exception ex) //{ // System.Windows.MessageBox.Show(ex.InnerException.ToString()); //} } } }
app.config配置
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.net> <defaultProxy> <proxy bypassonlocal="true" usesystemdefault="false" /> </defaultProxy> </system.net> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /> </startup> <appSettings> <add key="TenantId" value="<guid>"/> <add key="ClientId" value="<guid>"/> <add key="ClientSecret" value="<value>"/> </appSettings> </configuration>
排查建议
检查程序集版本冲突
使用fuslogvw.exe(程序集绑定日志查看器)捕获程序集加载失败的详细日志,确认是否存在Microsoft.Identity.Client(MSAL)或Microsoft.Graph的版本不匹配问题。同时在app.config中添加程序集绑定重定向,强制指定使用的版本:<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0a613f4dd989e8ae" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-[当前使用版本]" newVersion="[当前使用版本]" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Graph" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-[当前使用版本]" newVersion="[当前使用版本]" /> </dependentAssembly> </assemblyBinding> </runtime>确认.NET Framework版本一致性
检查生产环境服务器上的.NET Framework版本是否为4.6.2,若版本低于该版本,升级至对应版本,确保与开发环境一致。验证文件权限
确认应用程序运行账户对DLL所在目录有读取权限,避免因权限不足导致程序集无法加载。修复异步方法调用问题
代码中InitializeGraphForUserAuth为async static void方法,会导致异常无法被上层捕获且可能引发上下文问题。改为async Task并使用异步工厂模式调用:public static async Task<GraphMail> CreateAsync() { var instance = new GraphMail(); await instance.InitializeGraphForUserAuthAsync(); return instance; } private async Task InitializeGraphForUserAuthAsync() { // 原方法逻辑保持不变 }检查MSAL依赖项完整性
核对MSAL的所有依赖程序集(如Microsoft.Identity.Client.Extensions.dll等)是否都已部署到生产环境,可通过NuGet包管理器查看依赖列表逐一确认。启用详细异常日志
在生产环境中添加FileLoadException的捕获逻辑,输出完整异常信息定位问题:catch (FileLoadException ex) { System.Windows.MessageBox.Show($"无法加载程序集:{ex.FileName}\n错误信息:{ex.Message}\n内部异常:{ex.InnerException?.Message}"); }
内容的提问来源于stack exchange,提问作者JeroenZenM

