.NET通过PowerShell操作ExChange为用户开通邮箱教程

转:http://www.cnblogs.com/gongguo/archive/2012/03/12/2392049.html

==============================================================================

要使.NET调用PowerShell组建能够管理Exchange必须在调用的时候加载管理模块,否则和Exchange相关的指令就不被支持。虽然并不是很明白这两种加载模块方式的具体区别,但是由于手动加载Exchange管理模块有两种方式,.NET(或者直接说C#)管理Exchange就有2种方式。第一种方式是将代码编译成COM+组建,注册到COM+应用程序中,以供客户机代码调用,第二种方式不需要注册COM+组建,更大程度得益于“远程管理”,第二种的调用方式五花八门,详情可以参考Exchange小组的技术博客

1.COM+:要求部署在Exchange服务器上(因为有PowerShell Modules),一般选用CAS服务器。另外COM+应用程序在没有使用的情况下会自动关闭,一有请求又开启,所以第一次调用会显得有点慢。

2.远程调用。主要是要基于Kerberos的身份验证,使用SSL加密模式也可以,但是就要配置证书,所以目前我使用的都是Kerberos模式的身份验证。可以在同一个AD上部署,或者在建立了信任关系的其他AD中部署。相比第一种来说灵活(差别不大),也干净一点。但是我尚未测试使用WEB调用的情况,所以有没有其他问题尚未明确。

 

主要原理是:(这个原理是我猜的,因为我也不太懂ExChange以及COM组件这方面的知识) 

直接用C#代码访问ExChange是不行的

微软出了一个PowerShell的命令行工具 能够用命令行来操作ExChange

可以通过把.Net类注册成COM+组件的方式来操作PowerShell

 

所以我的流程就是

WebService->.NET写的PowerShell操作类注册成的COM+组件->ExChange

环境是:

VS2010 + ExChange2010 + Windows Server 2008 64位版 + IIS7.0 

 

ps:这个COM+组件只能运行在安装ExChange的服务器上

公司的环境用的是ExChange2010, ExChange2010好像只有64位版的 只能安装在64位的系统上

所以下面会说到把COM+组件编译成64位的问题

==============================================================================

 

1 首先先创建com组件并注册

1)启动Visual Studio 2010

2)选择File ->“新建->”项目...

3)选择Windows

4)选择“类库

5)在名称框中键入“PowerShellComponent “

6)点击确定。

7)添加下列引用

System.EnterpriseServices

System.DirectoryServices

System.Management.Automation 路径:

32位系统:

C:\ProgramFiles\ReferenceAssemblies\Microsoft\WindowsPowerShell\v1.\System.Management.Automation.dll

64位系统

C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll

 

接下来有关程序集的操作

1)在解决方案资源管理器,右键单击PowerShellComponent项目,选择属性,点击签名选项,选中"为程序集签名",并创建一个新的强名称密钥称为“PowerShellComponent.snk” , 不用设置密码。如下图

 

 

 

2)还是在项目属性窗口中,选择"应用程序"选项卡,然后点击“程序集信息...”,检查框,选中"使程序集COM可见"。如图

 

 

PS:如果运行这个com组件的机器是64位系统(32位的没试过),这里需要再加一步:

把项目的运行平台设置成64位的

还是在项目属性窗口中:

"生成"选项卡->目标平台->64位

    ->   

 

 

3)打开AssemblyInfo.cs中,并添加“using System.EnterpriseServices;”,并添加

 

[assembly: ApplicationActivation(ActivationOption.Server)]  [assembly: ApplicationName("PowerShellComponent")]  [assembly: Description("Simple PowerShell Component Sample")]  [assembly: ApplicationAccessControl(             false,             AccessChecksLevel = AccessChecksLevelOption.Application,             Authentication = AuthenticationOption.None,             ImpersonationLevel = ImpersonationLevelOption.Identify)]

然后添加ManagementCommands类...

1)选择“解决方案资源管理器”查看选项卡。将Class1.cs文件重命名为“ManagementCommands.cs”。

类需要继承System.EnterpriseServices.ServicedComponent,否则不能被编译成COM+组件

2)添加引用如图并using

using System.EnterpriseServices; using System.Security; using System.Security.Principal; using System.Runtime.InteropServices; using System.Collections.ObjectModel; using System.Management.Automation; using System.Management.Automation.Host; using System.Management.Automation.Runspaces; using System.DirectoryServices; using Microsoft.PowerShell.Commands; using System.Collections;

3)拷贝下面的方法到类中

1  #region 根据登录名判断是否存在邮箱
  2 
  3         public bool IsExistMailBox(string identity)
  4 
  5         {
  6 
  7             try
  8 
  9             {
 10 
 11                 PSSnapInException PSException = null;
 12 
 13                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
 14 
 15                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
 16 
 17                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
 18 
 19                 runspace.Open();
 20 
 21 
 22 
 23                 Pipeline pipeline = runspace.CreatePipeline();
 24 
 25                 Command command = new Command("Get-Mailbox");
 26 
 27                 command.Parameters.Add("identity", identity);
 28 
 29                 pipeline.Commands.Add(command);
 30 
 31                 Collection<PSObject> result = pipeline.Invoke();
 32 
 33 
 34 
 35                 runspace.Close();
 36 
 37 
 38 
 39                 return (result != null && result.Count > 0);
 40 
 41             }
 42 
 43             catch (System.Exception ex)
 44 
 45             {
 46 
 47                 throw ex;
 48 
 49             }
 50 
 51         }
 52 
 53         #endregion
 54 
 55 
 56 
 57         #region 创建邮箱账号
 58 
 59         public bool NewMailbox(string name, string accountName, string pwd, string emailDomain, string organizationalUnit, string database)
 60 
 61         {
 62 
 63             string emailAdd = accountName + emailDomain;
 64 
 65 
 66 
 67             if (this.IsExistMailBox(emailAdd))
 68 
 69             {
 70 
 71                 throw new Exception("已经存在同名的邮箱"); 
 72 
 73             }
 74 
 75             try
 76 
 77             {
 78 
 79                 PSSnapInException PSException = null;
 80 
 81                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
 82 
 83                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
 84 
 85                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
 86 
 87                 runspace.Open();
 88 
 89                 Pipeline pipeline = runspace.CreatePipeline();
 90 
 91 
 92 
 93                 Command command = new Command("New-Mailbox");
 94 
 95                 char[] passwordChars = pwd.ToCharArray();
 96 
 97                 SecureString password = new SecureString();
 98 
 99                 foreach (char c in passwordChars)
100 
101                 {
102 
103                     password.AppendChar(c);
104 
105                 }
106 
107 
108 
109                 command.Parameters.Add("Name", name);//姓名 
110 
111 
112 
113                 command.Parameters.Add("UserPrincipalName", emailAdd);//邮箱地址
114 
115                 command.Parameters.Add("SamAccountName", accountName);//登录名
116 
117 
118 
119                 command.Parameters.Add("Password", password);//密码
120 
121 
122 
123                 command.Parameters.Add("OrganizationalUnit", organizationalUnit);//组织单元
124 
125                 command.Parameters.Add("Database", database);//数据库 
126 
127 
128 
129                 pipeline.Commands.Add(command);
130 
131                 Collection<PSObject> result = pipeline.Invoke();
132 
133                 runspace.Close();
134 
135 
136 
137                 return this.IsExistMailBox(emailAdd);
138 
139             }
140 
141             catch (Exception ex)
142 
143             {
144 
145                 throw ex;
146 
147             }
148 
149         }
150 
151         #endregion
152 
153 
154 
155         #region 删除邮箱账号(控制台和域都删除)
156 
157 
158 
159         public bool RemoveMailbox(string identity)
160 
161         {
162 
163 
164 
165             try
166 
167             {
168 
169                 PSSnapInException PSException = null;
170 
171                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
172 
173                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
174 
175                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
176 
177                 runspace.Open();
178 
179                 Pipeline pipeline = runspace.CreatePipeline();
180 
181 
182 
183                 Command command = new Command("Remove-Mailbox");
184 
185                 command.Parameters.Add("Identity", identity);
186 
187                 command.Parameters.Add("Confirm", false);
188 
189                 pipeline.Commands.Add(command);
190 
191                 Collection<PSObject> result = pipeline.Invoke();
192 
193                 runspace.Close();
194 
195 
196 
197                 return !this.IsExistMailBox(identity);
198 
199             }
200 
201             catch (System.Exception ex)
202 
203             {
204 
205                 throw ex;
206 
207             }
208 
209         }
210 
211         #endregion
212 
213 
214 
215         #region 启用邮箱账号
216 
217         public bool EnableMailbox(string identity)
218 
219         {
220 
221             try
222 
223             {
224 
225                 PSSnapInException PSException = null;
226 
227                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
228 
229                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
230 
231                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
232 
233                 runspace.Open();
234 
235                 Pipeline pipeline = runspace.CreatePipeline();
236 
237 
238 
239                 Command command = new Command("Enable-Mailbox");
240 
241                 command.Parameters.Add("Identity", identity);
242 
243                 command.Parameters.Add("Confirm", false);
244 
245                 pipeline.Commands.Add(command);
246 
247                 Collection<PSObject> result = pipeline.Invoke();
248 
249                 runspace.Close();
250 
251                 return this.IsExistMailBox(identity);
252 
253             }
254 
255             catch (Exception ex)
256 
257             {
258 
259                 throw ex;
260 
261             }
262 
263         }
264 
265         #endregion
266 
267 
268 
269         #region 禁用邮箱账号
270 
271         public bool DisableMailbox(string identity)
272 
273         {
274 
275             try
276 
277             {
278 
279                 PSSnapInException PSException = null;
280 
281                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
282 
283                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
284 
285                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
286 
287                 runspace.Open();
288 
289 
290 
291                 Pipeline pipeline = runspace.CreatePipeline();
292 
293                 Command command = new Command("Disable-Mailbox");
294 
295                 command.Parameters.Add("Identity", identity);
296 
297                 command.Parameters.Add("Confirm", false);
298 
299                 pipeline.Commands.Add(command);
300 
301                 Collection<PSObject> result = pipeline.Invoke();
302 
303                 runspace.Close();
304 
305                 return !this.IsExistMailBox(identity);
306 
307             }
308 
309             catch (Exception ex)
310 
311             {
312 
313                 throw ex;
314 
315             }
316 
317         }
318 
319         #endregion
320 
321 
322 
323         #region 判断是否存在通讯组
324 
325         public bool IsExistGroup(string identity)
326 
327         {
328 
329             try
330 
331             {
332 
333                 PSSnapInException PSException = null;
334 
335                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
336 
337                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
338 
339                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
340 
341                 runspace.Open();
342 
343 
344 
345                 Pipeline pipeline = runspace.CreatePipeline();
346 
347                 Command command = new Command("Get-DistributionGroup");
348 
349                 command.Parameters.Add("identity", identity);
350 
351                 pipeline.Commands.Add(command);
352 
353                 Collection<PSObject> result = pipeline.Invoke();
354 
355 
356 
357                 runspace.Close();
358 
359 
360 
361                 return (result != null && result.Count > 0);
362 
363             }
364 
365             catch (System.Exception ex)
366 
367             {
368 
369                 throw ex;
370 
371             }
372 
373         }
374 
375         #endregion
376 
377 
378 
379         #region 创建通讯组
380 
381         public bool NewGroup(string name)
382 
383         {
384 
385             if (this.IsExistGroup(name))
386 
387             {
388 
389                 throw new Exception("已经存在相同的通讯组"); 
390 
391             }
392 
393             try
394 
395             {
396 
397                 PSSnapInException PSException = null;
398 
399                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
400 
401                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
402 
403                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
404 
405                 runspace.Open();
406 
407 
408 
409                 Pipeline pipeline = runspace.CreatePipeline();
410 
411                 Command command = new Command("New-DistributionGroup");
412 
413                 command.Parameters.Add("Name", name);
414 
415                 pipeline.Commands.Add(command);
416 
417                 Collection<PSObject> result = pipeline.Invoke();
418 
419                 runspace.Close(); 
420 
421                 return this.IsExistGroup(name);
422 
423             }
424 
425             catch (Exception ex)
426 
427             {
428 
429                 throw ex;
430 
431             }
432 
433         }
434 
435 
436 
437         #endregion
438 
439 
440 
441         #region 删除通讯组
442 
443         public bool RemoveGroup(string identity)
444 
445         {
446 
447             try
448 
449             {
450 
451                 PSSnapInException PSException = null;
452 
453                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
454 
455                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
456 
457                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
458 
459                 runspace.Open();
460 
461 
462 
463                 Pipeline pipeline = runspace.CreatePipeline();
464 
465                 Command command = new Command("Remove-DistributionGroup");
466 
467                 command.Parameters.Add("Identity", identity);
468 
469                 command.Parameters.Add("Confirm", false);
470 
471                 pipeline.Commands.Add(command);
472 
473                 Collection<PSObject> result = pipeline.Invoke();
474 
475                 runspace.Close();
476 
477                 return !this.IsExistGroup(identity); 
478 
479             }
480 
481             catch (Exception ex)
482 
483             {
484 
485                 throw ex;
486 
487             } 
488 
489         }
490 
491         #endregion
492 
493 
494 
495         #region 添加通讯组成员
496 
497         public bool AddGroupMember(string groupIdentity, string mailIdentity)
498 
499         {
500 
501             try
502 
503             {
504 
505                 PSSnapInException PSException = null;
506 
507                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
508 
509                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
510 
511                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
512 
513                 runspace.Open();
514 
515 
516 
517                 Pipeline pipeline = runspace.CreatePipeline();
518 
519                 Command command = new Command("Add-DistributionGroupMember");
520 
521                 command.Parameters.Add("Identity", groupIdentity);
522 
523                 command.Parameters.Add("Member", mailIdentity);
524 
525                 pipeline.Commands.Add(command);
526 
527                 Collection<PSObject> result = pipeline.Invoke();
528 
529                 runspace.Close();
530 
531                 return true;
532 
533             }
534 
535             catch (Exception ex)
536 
537             {
538 
539                 throw ex;
540 
541             }
542 
543         }
544 
545         #endregion
546 
547          
548 
549         #region 删除通讯组成员
550 
551         public bool RemoveGroupMember(string groupIdentity, string mailIdentity)
552 
553         {
554 
555             try
556 
557             {
558 
559                 PSSnapInException PSException = null;
560 
561                 RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
562 
563                 runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);
564 
565                 Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
566 
567                 runspace.Open();
568 
569 
570 
571                 Pipeline pipeline = runspace.CreatePipeline();
572 
573                 Command command = new Command("Remove-DistributionGroupMember");
574 
575                 command.Parameters.Add("Identity", groupIdentity);
576 
577                 command.Parameters.Add("Member", mailIdentity);
578 
579                 command.Parameters.Add("Confirm", false);
580 
581                 pipeline.Commands.Add(command);
582 
583                 Collection<PSObject> result = pipeline.Invoke();
584 
585                 runspace.Close();
586 
587                 return true;
588 
589             }
590 
591             catch (Exception ex)
592 
593             {
594 
595                 throw ex;
596 
597             }
598 
599         }
600 
601         #endregion
602 
603  
view code

PS: 这些都是ExChange的命令,暂时只封装了这么多,如果想实现更多的功能,只需要照着上面的例子把实现相应的ExChange命令就行了

在微软的官网上有ExChange的命令文档 http://msdn.microsoft.com/zh-cn/library/aa997174.aspx

 https://msdn.microsoft.com/zh-cn/library/aa998225.aspx

另:还有远程调用方法,其实不一定要通过注册COM+组件的方式来完成任务,PowerShell支持远程管理,使用.NET也可以得益于这个功能。

// <summary>
        /// 邮箱管理员凭证  
        /// </summary>
        /// <returns></returns>
        static WSManConnectionInfo OpenWSManConnInfo()
        {
            //Lync管理webservice地址  邮箱地址
            //string uri = "http://sss-ex01.dev.com/PowerShell";
            string uri = ConfigUtils.GetLocalParamValue("EmailAddress");
            //命令解析uri
            string shellUri = "http://schemas.microsoft.com/powershell/Microsoft.Exchange";
            //管理账户
            //string userName = @"dev\devadmin";
            string DomainName = ConfigUtils.GetLocalParamValue("DomainName");//
            string AdminName = ConfigUtils.GetLocalParamValue("AdminName");

            string adminName = AdminName + "\\" + DomainName;

            //管理密码
            //string userPassWord = "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;
    

/********

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);//邮箱地址
                command.Parameters.Add("SamAccountName", accountName);//登录名
                command.Parameters.Add("Password", password);//密码
                //command.Parameters.Add("OrganizationalUnit", "");//组织单元
                command.Parameters.Add("DisplayName", userName);
                //command.Parameters.Add("Database", "Mailbox Database 1406924081");//数据库 
                pipeLine.Commands.Add(command);

                Collection<PSObject> result = pipeLine.Invoke();
                runspace.Close();

                return IsExistMailBox(emailAdd);

*******/
 
        }
View Code

 

最后运行生成项目,得到PowerShellComponent.dll,COM组件就创建好了。

接下来就是注册这个组件了:  

步骤一: 【控制面板】→【管理工具】→【组件服务】

 
 步骤二: 出现窗口后,【组件服务】→【计算机】→【我的电脑】→【COM+ 应用程序】单击右键 →新建→ 应用程序→安装向导下一步→创建空应用程序→输入空应用程序名称:PowerShellComponent,并选择激活类型为服务器应用程序→设置应用程序标示(账号选择下列用户 账号和密码是该服务器登录用户名和密码)→完成。

右键单击创建出来的PowerShellComoponent,选择属性,找到"标志"选项卡,选择 ”下列用户“ 填入计算机的登录用户名和密码,确定 

 

 步骤三: 创建好应用程序后 打开PowerShellComponent 出现 【组件】【旧版组件】【角色】 在【组件】上单击右键  →新建→组件 

 步骤三: 点下一步,出现如下窗口,选择【安装新组件】:

选择前面项目生成的PowerShellComponent.dll文件→【打开】点下一步,选择完成。

 步骤四:

为刚刚注册的PowerShellComponent组件添加用户权限

打开PowerShellComponent 下面的【角色】-【CreatorOwner】-【用户】右键  【新建】 - 【用户】

 

 

在出来的窗口点[高级]-[位置]-选择[整个目录]-[立即查找]

 

 

因为WebServicce是发布在IIS上面的 所以我的IIS需要有权限来操作这个COM组件 所以我添加的是IIS的用户

在搜索出来的结果里面 选择IIS_IUSRS并添加,  如果是用winform来调用这个COM+组件 则应该要添加管理员帐号Administrator

 

 

用户添加完了  组件就注册成功了。

把PowerShellComponent.dll拷到测试项目中 

测试项目添加对 PowerShellComponent.dll 的引用   就能被调用了

  

如果你的COM+组件被启用了 在调试过程中如果你需要重新编译你的DLL文件 那么需要先关闭COM+组件  dll才能被重新编译

如果在调用的过程中发生异常,可能是两个方面的原因:

1  如果com+组件在64位的环境下运行 是否有被编译成64位

2 权限问题

 

还有一个 

因为操作的是ExChange2010  所以代码中是

 

PSSnapInInfo info = runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out PSException);

 

如果你的ExChange是2007的  那么这行代码可能需要被改成

 

PSSnapInInfo info = runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Admin", out PSException);

 

http://ishare.iask.sina.com.cn/f/23481273.html

这是我的源代码,赚点积分,勿怪

 

另外的参考资料:http://www.cnblogs.com/lightluomeng/archive/2013/01/20/2868028.html

http://www.cnblogs.com/lightluomeng/archive/2013/01/20/2868028.html

 

posted @ 2015-11-04 18:24  bxzjzg  阅读(1174)  评论(0编辑  收藏  举报