You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨源场景下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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:15:31