跨源场景下C#连接Exchange Server无报错失效问题求助
跨域环境下Exchange Server连接代码无报错但无法工作
我的项目中有一段获取Exchange邮箱容量的代码,当应用服务器和Exchange处于同源环境时运行正常,但在应用服务器池和Exchange跨域的场景下,代码没有抛出任何异常,却无法正常获取数据。无法提供邮箱相关信息,求解决办法。
public int GetMailBoxSize(string mail) { int percent = -1; if (HttpContext.Current.Cache["MailSize" + mail] != null) { percent = (Convert.ToInt32(HttpContext.Current.Cache["MailSize" + mail])); } else { try { string un = @"foresty\activedirectory.update"; System.Security.SecureString pw = new System.Security.SecureString(); string password = "passsword"; string exchangeServerName = "http://xxx.xxx.xx/powershell"; foreach (char ch in password) { pw.AppendChar(ch); } using (PowerShell _powerShell = PowerShell.Create()) { var credential = new PSCredential(un, pw); _powerShell.Runspace.SessionStateProxy.SetVariable("Credential", credential); _powerShell.AddScript($"$Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri {exchangeServerName} -Credential $Credential -Authentication Kerberos -AllowRedirection"); _powerShell.AddScript("Import-PSSession $Session"); _powerShell.Invoke(); _powerShell.AddScript(@"get-mailbox -identity " + mail + " | Select-Object ProhibitSendReceiveQuota"); var results = _powerShell.Invoke(); string size = ""; string used = ""; string size2 = ""; foreach (PSObject obj in results) { size = (obj.Properties["ProhibitSendReceiveQuota"].Value.ToString()); } _powerShell.AddScript(@"Get-MailboxStatistics -Identity " + mail + " | Select-Object Totalitemsize,DatabaseProhibitSendQuota"); var results2 = _powerShell.Invoke(); _powerShell.AddScript("Remove-PSSession $Session"); _powerShell.Invoke(); foreach (PSObject obj in results2) { used = (obj.Properties["Totalitemsize"].Value.ToString()); size2 = (obj.Properties["DatabaseProhibitSendQuota"].Value.ToString()); } if (size != "Unlimited") { if (used.Contains("KB")) { percent = Convert.ToInt32((Convert.ToDouble(used.Split()[0].Replace('.', ','))) * 100 / ((Convert.ToDouble(size.Split()[0].Replace('.', ',')) * 1024 * 1024))); } else if (used.Contains("MB")) { percent = Convert.ToInt32((Convert.ToDouble(used.Split()[0].Replace('.', ','))) * 100 / ((Convert.ToDouble(size.Split()[0].Replace('.', ',')) * 1024))); } else if (used.Contains("GB")) { percent = Convert.ToInt32((Convert.ToDouble(used.Split()[0].Replace('.', ','))) * 100 / (Convert.ToDouble(size.Split()[0].Replace('.', ',')))); } } else { if (used.Contains("KB")) { percent = Convert.ToInt32((Convert.ToDouble(used.Split()[0].Replace('.', ','))) * 100 / ((Convert.ToDouble(size2.Split()[0].Replace('.', ',')) * 1024 * 1024))); } else if (used.Contains("MB")) { percent = Convert.ToInt32((Convert.ToDouble(used.Split()[0].Replace('.', ','))) * 100 / ((Convert.ToDouble(size2.Split()[0].Replace('.', ',')) * 1024))); } else if (used.Contains("GB")) { percent = Convert.ToInt32((Convert.ToDouble(used.Split()[0].Replace('.', ','))) * 100 / (Convert.ToDouble(size2.Split()[0].Replace('.', ',')))); } } } } catch (Exception ex) { return percent; } HttpContext.Current.Cache.Insert("MailSize" + mail, percent, null, DateTime.Now.AddHours(1), System.Web.Caching.Cache.NoSlidingExpiration); } return percent; }
排查与修复建议
- Kerberos跨域认证配置:当前代码使用Kerberos认证,跨域场景下需确保运行应用池的账户已配置对Exchange服务器的约束委派权限,允许访问Exchange的HTTP服务类。
- 捕获PowerShell执行错误:C#的
try/catch不会捕获PowerShell命令执行的内部错误,需主动检查_powerShell.Streams.Error集合获取具体失败原因,比如认证失败、连接拒绝等。可在每次Invoke()后添加检查:if (_powerShell.Streams.Error.Count > 0) { var errorDetails = _powerShell.Streams.Error[0].ToString(); // 记录错误日志或抛出自定义异常 } - Exchange端点跨域设置:检查Exchange服务器上的PowerShell虚拟目录配置,确保允许跨域访问,可通过Exchange Management Shell执行:
Set-PowerShellVirtualDirectory -Identity "ExchangeServerName\PowerShell (Default Web Site)" -AllowCrossDomainAccess $true - 切换认证方式:如果Kerberos跨域配置复杂,可尝试改用Basic认证(需配合HTTPS保障安全),修改
New-PSSession的-Authentication参数为Basic,并确保Exchange服务器开启Basic认证支持。 - 缓存逻辑优化:当前代码无论是否成功获取数据都会更新缓存,若执行失败会把
-1存入缓存,导致后续请求持续返回错误值。建议仅在成功计算出有效百分比(非-1)时才更新缓存。
内容的提问来源于stack exchange,提问作者witchqueen
相关产品推荐
相关产品推荐

