.NET Core 9调用Get-ExoMailbox遇程序集不匹配错误求助
.NET Core调用PowerShell执行Get-ExoMailbox时程序集不匹配错误
环境与现象
- 在服务器PowerShell ISE中运行以下脚本可正常执行:
# Connect to Exchange Online $CertThumbPrint = "111" $AppID = "222" $Org = "333.onmicrosoft.com" Connect-ExchangeOnline -CertificateThumbPrint $CertThumbPrint -AppID $AppID -Organization $Org # Get Mailboxes $Mailboxes = Get-Mailbox -ResultSize 5 Write-Output $Mailboxes | format-table
- 同一服务器上,IIS托管的.NET Core 9应用通过以下C#代码调用PowerShell时,执行到
Get-ExoMailbox -ResultSize Unlimited出现0x80131040程序集不匹配错误,提示无法加载Microsoft.Identity.Client.dll,其清单定义与引用不匹配。 - 前置命令(设置执行策略、导入模块、连接Exchange Online)均正常运行,仅该命令报错。
- 已确认:
- 执行策略设为Unrestricted(Process范围)
- 仅安装ExchangeOnlineManagement 3.8.0模块
- C#项目已安装Microsoft.PowerShell.SDK和System.Management.Automation NuGet包
- 目标版本4.66.1的Microsoft.Identity.Client.dll存在
.NET Core出错的C#代码
var mailboxes = new List<IrMailBox>(); using var runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); using var pipeline = runspace.CreatePipeline(); string script = @" Set-ExecutionPolicy Unrestricted -Scope Process; Import-Module ExchangeOnlineManagement; Connect-ExchangeOnline -AppId '123' -CertificateThumbprint '123' -Organization '123.onmicrosoft.com'; Get-ExoMailbox -ResultSize Unlimited "; pipeline.Commands.AddScript(script); var results = pipeline.Invoke(); foreach (var result in results) { var psObject = result.BaseObject as PSObject; if (psObject != null) { mailboxes.Add(new IrMailBox { DisplayName = psObject.Properties["DisplayName"]?.Value?.ToString(), PrimarySmtpAddress = psObject.Properties["PrimarySmtpAddress"]?.Value?.ToString() }); } } runspace.Close(); return mailboxes;
解决方案
方案1:添加程序集绑定重定向
在PowerShell脚本中添加临时配置文件,强制模块使用指定版本的Microsoft.Identity.Client:
string script = @" Set-ExecutionPolicy Unrestricted -Scope Process -Force; # 创建程序集绑定重定向配置 $bindingConfig = @' <configuration> <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-4.66.1.0"" newVersion=""4.66.1.0"" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration> '@ $configPath = Join-Path $env:TEMP 'powershell.config.json' Set-Content -Path $configPath -Value $bindingConfig -Encoding utf8 Import-Module ExchangeOnlineManagement; Connect-ExchangeOnline -AppId '123' -CertificateThumbprint '123' -Organization '123.onmicrosoft.com'; Get-ExoMailbox -ResultSize Unlimited # 清理临时配置文件 Remove-Item $configPath -Force ";
原理:PowerShell会读取临时目录下的powershell.config.json,通过绑定重定向统一程序集版本,避免冲突。
方案2:启动独立PowerShell进程执行脚本
绕过进程内程序集冲突,通过启动独立的PowerShell进程执行脚本,再通过JSON传递结果:
var mailboxes = new List<IrMailBox>(); var scriptContent = @" Set-ExecutionPolicy Unrestricted -Scope Process -Force; Import-Module ExchangeOnlineManagement; Connect-ExchangeOnline -AppId '123' -CertificateThumbprint '123' -Organization '123.onmicrosoft.com'; Get-ExoMailbox -ResultSize Unlimited | Select-Object DisplayName, PrimarySmtpAddress | ConvertTo-Json "; var psi = new ProcessStartInfo { FileName = "pwsh.exe", // 服务器装的是Windows PowerShell则用powershell.exe Arguments = $"-NoProfile -Command \"{scriptContent}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process = Process.Start(psi); process.WaitForExit(); var output = process.StandardOutput.ReadToEnd(); var error = process.StandardError.ReadToEnd(); if (!string.IsNullOrEmpty(error)) { throw new Exception($"PowerShell执行错误: {error}"); } if (!string.IsNullOrEmpty(output)) { var mailboxList = System.Text.Json.JsonSerializer.Deserialize<List<IrMailBox>>(output); if (mailboxList != null) { mailboxes.AddRange(mailboxList); } } return mailboxes;
原理:独立进程的PowerShell使用自身的程序集上下文,不会与.NET Core应用的程序集产生冲突,通过JSON序列化/反序列化传递数据。
方案3:同步模块与NuGet包版本
尝试升级ExchangeOnlineManagement模块到最新稳定版,或调整C#项目中Microsoft.PowerShell.SDK、System.Management.Automation的版本,确保模块依赖的程序集版本与项目引用版本兼容。
内容的提问来源于stack exchange,提问作者soomon
相关产品推荐
相关产品推荐

