C#操作AD及Exchange Server总结(二)
转http://www.cnblogs.com/renzh/p/AD-Exchange.html
上一节C#操作AD及Exchange Server总结(一)写了对AD的操作,新建AD用户后,通常都需要为此用户开启Exchange邮箱,接下来写如何远程操作Exchange。
三、对Exchange Server操作
操作exchange会用到新的DLL,需要安装Windows power shell,安装后在路径:C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0(测试机为64位)下找到System.Management.Automation.dll,在项目中引入。
1、为AD用户新建邮箱
上一节我们在AD中加入并启用了一个用户Employee01,下面我们继续在上一节创建的项目中编写代码,为该用户开启邮箱。
PowerShell支持远程管理
新建一个ExchangeMange.cs文件,添加下面的方法:

public void AddExchangeUser(string identity, string alias) { string runasUsername = @"contoso\管理员账号"; string runasPassword = "管理员密码"; SecureString ssRunasPassword = new SecureString(); foreach (char x in runasPassword) { ssRunasPassword.AppendChar(x); } PSCredential credentials = new PSCredential(runasUsername, ssRunasPassword); var connInfo = new WSManConnectionInfo(new Uri("http://exchange服务器IP/PowerShell"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credentials); connInfo.AuthenticationMechanism = AuthenticationMechanism.Basic; var runspace = RunspaceFactory.CreateRunspace(connInfo); var command = new Command("Enable-Mailbox"); command.Parameters.Add("Identity", identity); command.Parameters.Add("Alias", alias); runspace.Open(); var pipeline = runspace.CreatePipeline(); pipeline.Commands.Add(command); var results = pipeline.Invoke(); Console.WriteLine("通道错误数:" + pipeline.Error.Count); runspace.Dispose(); } AddExchangeUser
代码解释:
- 首先需要生成管理员凭据,此管理员必须有管理exchange服务器的权限
- 生成一个连接类型,传入exchange服务器IP、将要使用的Scheme以及管理员凭据
- 打开一个命令空间,创建管线通道,传入要运行的powershell命令,执行命令
- 释放连接资源
域和exchange配套使用同一数据库,添加了域用户,在新建邮箱时,用New-Mailbox不成功,只需要用激活命令,Enable-Mailbox;
这段代码对应的powershell命令相当于本地运行的“Enable-Mailbox -Identity 'rzh.com/CompanyA/Employee01' -Alias 'Employee01'”
Get-Mailbox -Identity 'a322' |fl 可以在任何返回语句后面,加上 |FL 可以查看到他的全部属性
批量隐藏邮箱
Get-Mailbox -OrganizationalUnit 'OU=test,OU=CN_Disable,OU=Disabled Accounts,DC=abc,DC=local' | Set-Mailbox -HiddenFromAddressListsEnabled $True
特定用户取消隐藏
Set-Mailbox -Identity mailbox@domain.com -HiddenFromAddressListsEnabled $False
http://blog.sina.com.cn/s/articlelist_1458355033_1_1.html
编写测试代码:

static void Main(string[] args) { ExchangeMange manage = new ExchangeMange(); Console.WriteLine("Start to enable user maibox..."); try { manage.AddExchangeUser("Employee01@contoso.com", "Employee01"); } catch (System.Management.Automation.RuntimeException ex) { Console.WriteLine("enable user maibox error..."); Console.WriteLine(ex); Console.ReadLine(); } Console.WriteLine("Finish to enable user maibox..."); Console.ReadLine(); } 测试代码
此时运行代码会报出下面的错误
错误信息很详细,说明了出错的原因,服务器不支持客户端请求的身份验证机制。
需要对客户端和服务器端进行一些配置。
在项目使用到的代码:(修改好像有点问题) https://technet.microsoft.com/zh-CN/library/bb123981(v=exchg.80).aspx

static void TestExchange(string userName, string accountName, string userPassWord) { var sb = new System.Text.StringBuilder(); sb.AppendLine("请输入命令:"); sb.AppendLine("0:退出;1:创建;2:启用 3 禁用 4 修改 5 判断是否存在 6 删除"); Console.Write(sb.ToString()); bool flag= false; string cmd = Console.ReadLine(); Console.Write("执行开始" + "\r\n"); string strUPNName = accountName + "@dev.com"; switch (cmd) { case "0": break; case "1": flag = NewMailBox(userName, accountName, userPassWord); break; case "2": flag = EnableMailbox(accountName); break; case "3": flag = DisableMailbox(accountName); break; case "4": flag = SetMailbox("ceshi110402", userName + "aa", accountName + "aa", userPassWord); break; case "5": flag = IsExistMailBox(strUPNName); break; case "6": flag = RemoveMailbox(accountName); break; default: break; } Console.Write(flag); Console.Write("\r\n执行完成"); Console.ReadLine(); } #region Exchange #region 远程调用 /// <summary> /// 邮箱管理员凭证 /// </summary> /// <returns></returns> static WSManConnectionInfo OpenWSManConnInfo() { //Lync管理webservice地址 string uri = "http://test-ex01.dev.com/PowerShell"; //string uri = ConfigUtils.GetLocalParamValue("EmailAddress"); //命令解析uri string shellUri = "http://schemas.microsoft.com/powershell/Microsoft.Exchange"; //管理账户 string adminName = @"dev\admin"; //string DomainName = ConfigUtils.GetLocalParamValue("DomainName");//域 //string AdminName = ConfigUtils.GetLocalParamValue("AdminName"); //string adminName = AdminName + "\\" + DomainName; //管理密码 string adminPassWord = "admin"; //string adminPassWord = ConfigUtils.GetLocalParamValue("AdminPassword"); //UPN后缀名 //string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); System.Security.SecureString secPwd = new SecureString(); char[] adminPwds = adminPassWord.ToCharArray(); foreach (char c in adminPwds) { secPwd.AppendChar(c); } //下面这句屏蔽服务器证书验证,防止页面报“根据验证过程,远程证书无效”的错误 //ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; }; //RunspaceConfiguration config = RunspaceConfiguration.Create(); PSCredential psc = new PSCredential(adminName, secPwd); WSManConnectionInfo wsManConnInfo = new WSManConnectionInfo(new Uri(uri), shellUri, psc); wsManConnInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos;//计算机加入了域 return wsManConnInfo; } #endregion #region 根据登录名判断是否存在邮箱 /// <summary> /// 是否存在邮箱--UPN名 /// </summary> /// <param name="identity">UPN名(唯一)</param> /// <returns></returns> public static bool IsExistMailBox(string identity) { try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo); if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Get-Mailbox"); command.Parameters.Add("identity", identity); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); runspace.Close(); return (result != null && result.Count > 0); } catch (System.Exception ex) { throw ex; } } #endregion #region 创建邮箱 /// <summary> /// 创建邮箱 /// </summary> /// <param name="userName">用户名</param> /// <param name="accountName">登录名唯一(域账户)</param> /// <param name="userPassWord">用户密码</param> public static bool NewMailBox(string userName, string accountName,string userPassWord) { //UPN后缀名 //string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); string SuffixName = "@dev.com"; //string emailAdd = accountName + "@dev.com"; string emailAdd = accountName + SuffixName; #region MyRegion if (IsExistMailBox(emailAdd)) { throw new Exception("已经存在同名的邮箱"); } try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo); if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } //PowerShell powerShell = PowerShell.Create(); //powerShell.Runspace = runspace; //PSCommand psCommand = new PSCommand(); Pipeline pipeLine = runspace.CreatePipeline(); Command command = new Command("New-Mailbox"); //New-Mailbox 邮箱命令 char[] passwordChars = userPassWord.ToCharArray(); SecureString password = new SecureString(); foreach (char c in passwordChars) { password.AppendChar(c); } command.Parameters.Add("Name", userName);//姓名 command.Parameters.Add("UserPrincipalName", emailAdd);//邮箱UPN command.Parameters.Add("SamAccountName", accountName);//登录名 command.Parameters.Add("Password", password);//密码 //command.Parameters.Add("OrganizationalUnit", "");//组织单元 //command.Parameters.Add("proxyAddresses", emailAdd);//邮箱地址 //command.Parameters.Add("Database", "Mailbox Database 1406924081");//数据库 command.Parameters.Add("DisplayName", userName); pipeLine.Commands.Add(command); Collection<PSObject> result = pipeLine.Invoke(); runspace.Close(); return IsExistMailBox(emailAdd); } catch (Exception ex) { throw ex; } #endregion } #endregion #region 删除邮箱账号(控制台和域都删除) /// <summary> /// 删除邮箱账号(控制台和域都删除) /// </summary> /// <param name="identity">参数标识要删除的邮箱。可以使用任何能够唯一标识该邮箱的值</param> /// <returns></returns> /// Identity 参数标识要删除的邮箱。可以使用任何能够唯一标识该邮箱的值。 /// 例如:名称,显示名称,别名,可分辨名称 (DN),规范 DN,<域名>\<帐户名称>,电子邮件地址,GUID,LegacyExchangeDN,SamAccountName /// ,用户 ID 或用户主体名称 (UPN),此参数不能与 Database 参数一起使用。 public static bool RemoveMailbox(string identity) { try { //UPN后缀名 //string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); string SuffixName = "@dev.com"; string emailAdd = identity + SuffixName; WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo); if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } Pipeline pipeLine = runspace.CreatePipeline(); Command command = new Command("Remove-Mailbox"); //Remove-Mailbox 邮箱命令 command.Parameters.Add("Identity", identity); command.Parameters.Add("Confirm", false); pipeLine.Commands.Add(command); Collection<PSObject> result = pipeLine.Invoke(); runspace.Close(); return !IsExistMailBox(identity); } catch (Exception ex) { throw ex; } } #endregion #region 修改邮箱 /// <summary> /// 修改邮箱 /// </summary> /// <param name="identity">参数标识要删除的邮箱。可以使用任何能够唯一标识该邮箱的值(UPN的名字)</param> /// <param name="userName">用户名</param> /// <param name="accountName">登录名</param> /// <param name="userPassWord">密码</param> /// <returns></returns> public static bool SetMailbox(string identity, string userName, string accountName, string userPassWord) { try { //UPN后缀名 //string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); string SuffixName = "@dev.com"; string emailUPN = accountName + SuffixName; string emailAdd = identity + SuffixName; if (!IsExistMailBox(emailAdd)) { throw new Exception("不存在邮箱!"); } WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo); if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } char[] passwordChars = userPassWord.ToCharArray(); SecureString password = new SecureString(); foreach (char c in passwordChars) { password.AppendChar(c); } Pipeline pipeLine = runspace.CreatePipeline(); Command command = new Command("Set-Mailbox"); //邮箱命令 command.Parameters.Add("Identity", emailAdd); //邮箱地址--旧的UPN名字 command.Parameters.Add("Name", userName);//姓名 command.Parameters.Add("UserPrincipalName", emailUPN);//邮箱地址--新的UPN名字 command.Parameters.Add("SamAccountName", accountName);//登录名 command.Parameters.Add("Password", password);//密码 command.Parameters.Add("DisplayName", userName); command.Parameters.Add("Confirm", false); pipeLine.Commands.Add(command); Collection<PSObject> result = pipeLine.Invoke(); runspace.Close(); return IsExistMailBox(emailUPN); } catch (Exception ex) { throw ex; } } #endregion #region 启用邮箱账号 public static bool EnableMailbox(string identity) { try { //UPN后缀名 //string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); string SuffixName = "@dev.com"; string emailAdd = identity + SuffixName; WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo); if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } Pipeline pipeLine = runspace.CreatePipeline(); Command command = new Command("Enable-Mailbox"); //邮箱命令 command.Parameters.Add("Identity", identity); command.Parameters.Add("Confirm", false); pipeLine.Commands.Add(command); Collection<PSObject> result = pipeLine.Invoke(); runspace.Close(); return IsExistMailBox(identity); } catch (Exception ex) { throw ex; } } #endregion #region 禁用邮箱账号 public static bool DisableMailbox(string identity) { try { //UPN后缀名 //string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); string SuffixName = "@dev.com"; string emailAdd = identity + SuffixName; WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo); if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } Pipeline pipeLine = runspace.CreatePipeline(); Command command = new Command("Disable-Mailbox"); //邮箱命令 command.Parameters.Add("Identity", identity); command.Parameters.Add("Confirm", false); pipeLine.Commands.Add(command); Collection<PSObject> result = pipeLine.Invoke(); runspace.Close(); return !IsExistMailBox(identity); } catch (Exception ex) { throw ex; } } #endregion #endregion public static void OpenRunspace(string uri, string userName, string password) { //命令解析uri string shellUri = "http://schemas.microsoft.com/powershell/Microsoft.Exchange"; try { System.Security.SecureString secPwd = new SecureString(); char[] userPwds = password.ToCharArray(); foreach (char c in userPwds) { secPwd.AppendChar(c); } //下面这句屏蔽服务器证书验证,防止页面报“根据验证过程,远程证书无效”的错误 //ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; }; //RunspaceConfiguration config = RunspaceConfiguration.Create(); PSCredential psc = new PSCredential(userName, secPwd); WSManConnectionInfo connInfo = new WSManConnectionInfo(new Uri(uri), shellUri, psc); connInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos; Runspace runspace = RunspaceFactory.CreateRunspace(connInfo); if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } PowerShell powerShell = PowerShell.Create(); powerShell.Runspace = runspace; PSCommand psCommand = new PSCommand(); } catch (Exception) { throw; } }
在AD域里建好了部门用户,然后显示到exchange,操作通讯录的,组在AD域中的作用域:全局,否则不显示到exchange中; 显示如图
在使用修改命令的时候一直result =0,但是在界面查看成功了;
在激活邮箱(Enable-Mailbox)时,在正式环境遇到一个问题,identity使用邮箱名称加后缀名一直失败,取消后缀名成功了;
代码:

#region 汉字转化为拼音首字母 /// <summary> /// 汉字转化为拼音首字母 /// </summary> /// <param name="str">汉字</param> /// <returns>首字母</returns> public static string GetFirstPinyin(string str) { string r = string.Empty; foreach (char obj in str) { try { ChineseChar chineseChar = new ChineseChar(obj); string t = chineseChar.Pinyins[0].ToString(); r += t.Substring(0, 1).ToLower(); } catch { r += obj.ToString(); } } return r; } #endregion #region 判断是否存在通讯组 public bool IsExistGroup(string identity) { try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Get-DistributionGroup"); command.Parameters.Add("identity", identity); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); //runspace.Close(); bool flag = (result != null && result.Count > 0); return flag; } } catch (Exception ex) { throw new Exception("判断是否存在通讯组,错误消息:" + ex.Message); } } #endregion #region 创建通讯组 /// <summary> /// 创建通讯组 /// </summary> /// <param name="name">参数指定新通讯组的名称。如果未指定 DisplayName 参数,则在 Name 参数中指定的值还将用于 DisplayName 参数。</param> /// <param name="alias">别名,也就映射到邮箱</param> /// <param name="disPlayName">通讯录名</param> /// <param name="organizationalUnit">路径</param> /// <returns></returns> public void NewDistributionGroup(string name, string disPlayName, string organizationalUnit) { if (this.IsExistGroup(name)) { throw new Exception("已经存在相同的通讯组"); } string adDomainName = ConfigUtils.GetLocalParamValue("AD_DomainName"); //AD域 organizationalUnit = adDomainName+"/" + organizationalUnit; string alias = "ztzs_" + GetFirstPinyin(name); try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } //CN=测试部门111603,OU=测试部门111603,OU=中天精装,DC=dev,DC=com string distinguishedName = "CN=" + name + ","+ organizationalUnit; Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("New-DistributionGroup"); command.Parameters.Add("Name", name); command.Parameters.Add("Alias", alias); //command.Parameters.Add("distinguishedName", distinguishedName); //command.Parameters.Add("OrganizationalUnit", organizationalUnit); command.Parameters.Add("DisplayName", disPlayName); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); //bool flag = (result != null && result.Count > 0); //return flag; } } catch (Exception ex) { throw new Exception("创建通讯组,错误消息:" + ex.Message); } } #endregion #region Set-DistributionGroup public void SetDistributionGroup(string identity, string name, string disPlayName) { //if (this.IsExistGroup(identity)) //{ // throw new Exception("已经存在相同的通讯组"); //} try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } string alias = "ztzs_" + GetFirstPinyin(name); Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Set-DistributionGroup"); command.Parameters.Add("Identity", identity); command.Parameters.Add("Name", name); command.Parameters.Add("Alias", alias); command.Parameters.Add("DisplayName", disPlayName); command.Parameters.Add("Confirm", false); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); } } catch (Exception ex) { throw new Exception("修改通讯组,错误消息:" + ex.Message); } } #endregion #region RemoveDistributionGroup public void RemoveDistributionGroup(string identity) { //if (this.IsExistGroup(identity)) //{ // throw new Exception("已经存在相同的通讯组"); //} try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Remove-DistributionGroup"); command.Parameters.Add("Identity", identity); command.Parameters.Add("Confirm", false); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); } } catch (Exception ex) { throw new Exception("删除通讯组,错误消息:" + ex.Message); } } #endregion #region Enable-DistributionGroup Disable-DistributionGroup public void EnableDistributionGroup(string name, string disPlayName) { //if (this.IsExistGroup(name)) //{ // throw new Exception("已经存在相同的通讯组"); //} try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } ////邮箱后缀 //string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); //string primarySmtpAddress = "ztzs_" + GetFirstPinyin(name) + SuffixName; string alias = "ztzs_" + GetFirstPinyin(name); Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Enable-DistributionGroup"); command.Parameters.Add("Identity", name); command.Parameters.Add("Alias", alias); //command.Parameters.Add("PrimarySmtpAddress", primarySmtpAddress); //CN=测试部门111603,OU=测试部门111603,OU=中天精装,DC=dev,DC=com //command.Parameters.Add("distinguishedName", distinguishedName); //command.Parameters.Add("WindowsEmailAddress", alias); //command.Parameters.Add("OrganizationalUnit", organizationalUnit); command.Parameters.Add("DisplayName", disPlayName); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); } } catch (Exception ex) { throw new Exception("激活通讯组,错误消息:" + ex.Message); } } public void DisableDistributionGroup(string name) { //if (this.IsExistGroup(name)) //{ // throw new Exception("已经存在相同的通讯组"); //} try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } string alias = "ztzs_" + GetFirstPinyin(name); Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Disable-DistributionGroup"); command.Parameters.Add("Identity", name); //command.Parameters.Add("Alias", alias); //command.Parameters.Add("WindowsEmailAddress", alias); set-group //CN=测试部门111603,OU=测试部门111603,OU=中天精装,DC=dev,DC=com //command.Parameters.Add("distinguishedName", distinguishedName); //command.Parameters.Add("OrganizationalUnit", organizationalUnit); //command.Parameters.Add("DisplayName", disPlayName); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); } } catch (Exception ex) { throw new Exception("禁用通讯组,错误消息:" + ex.Message); } } #endregion #region 添加通讯组成员 public void AddDistributionGroupMember(string groupIdentity, string mailIdentity) { if (!this.IsExistGroup(groupIdentity)) { throw new Exception("不存在通讯组"); } //邮箱后缀 string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); mailIdentity = mailIdentity + SuffixName;//UPN try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Add-DistributionGroupMember"); command.Parameters.Add("Identity", groupIdentity); command.Parameters.Add("Member", mailIdentity); command.Parameters.Add("Confirm", false); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); } } catch (Exception ex) { throw new Exception("添加通讯组成员,错误消息:" + ex.Message); } } #endregion #region 删除通讯组成员 public void RemoveDistributionGroupMember(string groupIdentity, string mailIdentity) { if (!this.IsExistGroup(groupIdentity)) { throw new Exception("不存在通讯组"); } //邮箱后缀 string SuffixName = ConfigUtils.GetLocalParamValue("UserPrincipalName"); mailIdentity = mailIdentity + SuffixName;//UPN try { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Remove-DistributionGroupMember"); command.Parameters.Add("Identity", groupIdentity); command.Parameters.Add("Member", mailIdentity); command.Parameters.Add("Confirm", false); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); } } catch (Exception ex) { throw new Exception("删除通讯组成员,错误消息:" + ex.Message); } } #endregion #region 通讯录修改显示名,排序 /// <summary> /// 通讯录修改显示名,排序 /// </summary> /// <param name="name"></param> public void OperaDistributionGroup() { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } using (var db = ZTZS.DAL.Platform.Organ.Platform_OrganContext.Create()) { //var ModDepts = db.vDeptTreeSimple.Where(p=>p.DeptName==name).OrderBy(p=>p.DeptNo); //片区和职能部门 var ModDepts = db.vDeptTreeSimple.Where(p => p.FatherNo == "ZZ00001").OrderBy(p => p.DeptNo); int m = 1000000; foreach (var item in ModDepts) { m = m + 10000; int n = 0; //1.在exchange中查找该部门,如果存在,对比编号,若不同,更新部门及子部门编号 Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Get-DistributionGroup"); command.Parameters.Add("identity", item.DeptName); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); if (result != null && result.Count > 0) { string disPlayName = result[0].Properties["DisplayName"].Value.ToString(); bool flag = disPlayName.StartsWith(m.ToString()); //string str = disPlayName.Substring(0, 5); //若编号不相等,修改 if (!flag) { SetDistributionGroup(item.DeptName, item.DeptName, m + n + item.DeptName); ////该节点下所有项目 //var ModDept = db.vDeptTreeSimple.Where(p => p.FatherNo == item.DeptNo).OrderBy(p => p.DeptNo); //foreach (var ChildDept in ModDept) //{ // n = n + 1; // SetDistributionGroup(ChildDept.DeptName, ChildDept.DeptName, m + n + ChildDept.DeptName); //} } OperaChildDistributionGroup(m, item.DeptNo); } } } } //return dic; } //该节点下所有项目 public void OperaChildDistributionGroup(int m, string deptNo) { WSManConnectionInfo wsManConnInfo = OpenWSManConnInfo(); using (Runspace runspace = RunspaceFactory.CreateRunspace(wsManConnInfo)) { if ((runspace.RunspaceStateInfo.State == RunspaceState.Closed) || (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)) { runspace.Open(); } else if (runspace.RunspaceStateInfo.State == RunspaceState.Broken) { runspace.Open(); } using (var db = ZTZS.DAL.Platform.Organ.Platform_OrganContext.Create()) { int n = 0; int k = m + 1000; //该节点下所有部门项目 var ModDept = db.vDeptRelation.Where(p => p.FatherNo == deptNo).OrderBy(p => p.DeptNo); int n = 0; //该节点下所有部门项目 var ModDept = db.vDeptTreeSimple.Where(p => p.FatherNo == deptNo).OrderBy(p => p.DeptNo); foreach (var ChildDept in ModDept) { //没有邮箱先空着,后面编号不修改 n = n + 1; Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Get-DistributionGroup"); command.Parameters.Add("identity", ChildDept.DeptName); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); if (result != null && result.Count > 0) { string disPlayName = result[0].Properties["DisplayName"].Value.ToString(); bool flag = disPlayName.StartsWith((m + n).ToString()); //若编号不相等,修改 if (!flag) { SetDistributionGroup(ChildDept.DeptName, ChildDept.DeptName, m + n + ChildDept.DeptName); } } OperaChildDistributionGroup(m + 1000, ChildDept.DeptNo);//1000,二级职能部门 } } } }
更改排序的需求,显示名的排序中间有空缺的序号,新加的自动加到空缺的位置;
部分代码如下:

Pipeline pipeline = runspace.CreatePipeline(); Command command = new Command("Get-DistributionGroup"); command.Parameters.Add("identity", item.DeptName); pipeline.Commands.Add(command); Collection<PSObject> result = pipeline.Invoke(); if (result != null && result.Count > 0) { //string disPlayName = result[0].Properties["DisplayName"].Value.ToString(); foreach (var res in result) { dicDistributionGroup[res.Properties["Name"].Value.ToString()] = res.Properties["DisplayName"].Value.ToString().Substring(0, 2); } } ictionary<int, string> dicDept = new Dictionary<int, string>(); //新增 for (int i = 60; i < 100; i++) { dicDept[i] = i.ToString(); if (!dicDistributionGroup.ContainsValue(i.ToString())) { SetDistributionGroup(strDeptName, strDeptName, i + "." + strDeptName); //OperaChildDistributionGroup(i, strDeptNo); break; } }

New-Mailbox -UserPrincipalName confmbx@contoso.com -Alias confmbx -Name ConfRoomMailbox -Database "Mailbox Database 1" -OrganizationalUnit Users -Room -ResetPasswordOnNextLogon $true //下次登录是否需修改密码 alias 别名 displayName 1.UPN邮箱地址 2.别名 3.名称 4 数据库 5 组织单元 6 下次登录是否需修改密码 Get-Mailbox -Identity ceshi110402@dev.com | Set-Mailbox -SamAccountName ceshi110402aa Set-Mailbox -Identity ceshi110402@dev.com -UserPrincipalName ceshi110402bb@dev.com -SamAccountName ceshi110402bb

调用exe 执行pdf 转换的 try { Process proc = new Process(); string resource = HttpContext.Current.Server.MapPath("~/Content/wkhtmltopdf/bin"); string dllstr = string.Format(resource + "\\wkhtmltopdf.exe"); if (System.IO.File.Exists(dllstr)) { proc.StartInfo.FileName = dllstr; string strArguments = IsNoHead?string.Empty:" --margin-top 20 --margin-bottom 20 --header-spacing 2 --footer-spacing 1 --footer-font-size 7 --footer-center \"第[page]页/共[topage]页\" "; strArguments += parms; proc.StartInfo.Arguments = strArguments; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardInput = true; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardError = true; proc.StartInfo.CreateNoWindow = true; proc.Start(); proc.WaitForExit(); } else { throw new Exception("wkhtmltopdf.exe启动异常!"); } } catch (Exception) { throw; }
2、配置客户端和服务器
客户端配置:
运行gpedit.msc进入本地组策略管理器,计算机配置》管理模版》Windows组件》WinRM》WinRM客户端
启用允许为加密通信,启用受信任的主机并添加exchange服务器IP地址到TrustedHostsList
服务器端配置:
启用IIS基本身份验证
SSL设置中不要求SSL
再次运行代码
用以上示例可以看到如何利用System.Management.Automation的类型和方法对Exchange进行操作的整个过程,其他的操作唯一不同的就是command命令,只要我们知道Powershell的命令,就可以替换上面代码中的Command段,进行操作。
三、总结归纳
1、AD操作总结
- 了解DirectoryEntry类型
- 学会创建AD各种类型的方法
- 学会设置AD类型的属性
2、Exchange操作总结
- 了解System.Management.Automation下的类型和方法
- 配置客户端和服务器端
- 掌握powershell命令
exchange2010 帮助文档,网上搜索exchangeHelp ADHelp文件看看;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~