设为首页 收藏本站
查看: 1405|回复: 0

[经验分享] 一个Exchange后台管理程序(WEB)其一 用户检索

[复制链接]

尚未签到

发表于 2015-9-10 12:26:44 | 显示全部楼层 |阅读模式


引言
  如果一个Exchange的用户群按照部门的形式分散在各地,而人数又很多,让一个管理员管理工作量实在有点大。一个方式是编写一个WEB程序发布到IIS,然后让各个分部门的管理员管理各自的部门。没错,本系列文章就是围绕这个话题展开的。而这个话题的核心是如何通过.NET管理Exchange。嗯,似乎是这样。当时在实现系统的过程中,我碰到了很多其他的问题,也非常有趣。所以我决定,按照实现的流程来记叙,列出碰到的一些问题和解决方式。解决问题的过程中参考了很多网友的博客,同时得到了很多网友的帮助,会在适当的地方给出引用,方便大家参考。
  这个系统应该包括以下功能:查询,查看(指定的一些属性),禁用/启用,解锁,删除,新建,编辑(指定的一些属性),统计各个部门人数,为分部门指派管理员。总的来说就是增删查改。

用户查询
  Exchange的用户信息是和AD同步的,符合微软企业级产品的风格。所以查询用户信息可以通过查询AD进行。在.NET下可以通过System.DirectoryServices名称空间(处于System.DirectoryServices程序集中)进行活动目录查询。使用到类型是DirectorySearcher。当然System.DirectoryService.AccountManagement名称空间中的PrincipalSearcher也可以进行用户查询,但是在执行一些操作的时候,还是前者方便。所以,这里使用前一个方案。
  查询功能设计成按照用户的UPN(登录名)和姓名(环境中使用CN以方便显示)搜索,在列表中显示以下信息:登录名,CN,显示名称,所属部门,是否禁用。

分页
  要进行分页就需要获得搜索结果的总条数,我一开始没多在意DirectorySearcehr的属性,直接指定了Filter属性和根结点,然后指定搜索范围为SubTree,结果当搜索条数为1200条的时候,统计个数就要十来秒。而且我还很2X的调用GetDirectoryEntry来访问其属性,结果查询超慢。经过朋友的指点,参考了这篇博客:http://blog.sina.com.cn/s/blog_683424be0100scuz.html,才有效的缩短了查询时间。
  主要是PropertiesToLoad属性,通过向这个集合添加键,可以指定加载哪些DirectoryEntry属性,剩余属性不加载,从而缩短了时间。注意,Filter中涉及的属性是需要加载的。以下是一段脚本,和结果,可以看到差别之大。
DSC0000.png
  可用的属性键有:



msexchumenabledflags2,homemdb,legacyexchangedn,usncreated,msexchhomeservername,m
sexchrecipientdisplaytype,msexchrbacpolicylink,samaccountname,showinaddressbook,
msexchmailboxauditenable,cn,pwdlastset,whencreated,displayname,lastlogon,garbage
collperiod,samaccounttype,countrycode,objectguid,msexchmailboxsecuritydescriptor
,msexchmdbrulesquota,usnchanged,msexcharchivewarnquota,msexchversion,whenchanged
,msexchmoderationflags,name,msexchwhenmailboxcreated,protocolsettings,msexchpoli
ciesincluded,objectsid,logoncount,internetencoding,mailnickname,msexchuseraccoun
tcontrol,msexchtransportrecipientsettingsflags,msexchprovisioningflags,badpasswo
rdtime,accountexpires,msexchaddressbookflags,primarygroupid,objectcategory,userp
rincipalname,proxyaddresses,msexchdumpsterquota,useraccountcontrol,dscorepropaga
tiondata,mdbusedefaults,distinguishedname,msexchmailboxauditlogagelimit,objectcl
ass,badpwdcount,msexchrecipienttypedetails,homemta,mail,adspath,msexcharchivequo
ta,msexchumdtmfmap,msexchmailboxguid,lastlogoff,msexchbypassaudit,instancetype,c
odepage,msexchdumpsterwarningquota,

  在我的例子中,使用cn,displayname,mail,samaccountname(和UPN同名),distinguishedname(通过解析获取OU信息),useraccountcontrol。
  这里有一点需要注意,上面截图中,没有指定PageSize,所以就算指定SizeLimit,都只会最多返回1000条。

内存分页?LINQ迭代?
  对1000条进行测试,速度上,两个区别不是很大。我最开始是用内存分页的,就是转换了(select)之后转为数组(ToArray),后来改为Skip,和Take的查询。在代码中进行测试的时候,设置好PageSize属性,然后使用foreach迭代输出,可以发现输出结果是一段一段的,输出若干个(页长)停顿一小会儿。所以使用Skip和Take方式最好,网上已经有LINQ to AD查询的实现了(LINQ Provider)。

用户操作
  操作用户信息的时候有几个小点,这里直接列出。
  #更改CN。使用DirectoryEntry修改对象的CN的属性的时候应该使用以下方式。
  DirectoryEntry.Rename("CN=" + cmname),需要注意参数的格式。
  #如何判断用户是否禁用。
  1.通过DirecotryEntry.Properties["UserAccountControl"]的值和2进行位与(&)操作,然后转为bool,含义是Disabled(512&2的结果为0代表正常)
  2.通过获取UserPrincipal,然后访问其Enabled属性。
  #判断用户是否锁定。
  DirectoryEntry.InvokeGet(“IsAccountLocked”)
  #重置密码。重置密码后如何把用户置为“下次登录必须修改密码”。
  1.通过DirectoryEntry获取UserPrincipal对象,调用ExpirePasswordNow()方法。
  2.通过DirectoryEntry自身来处理应该也可行,但是尚未尝试。
  #修改属性的正确的方式(防止异常)。这里把键和值对应了一下,不是必要的。



         foreach (var kv in propertyValues)
{
if (!string.IsNullOrEmpty(kv.Value))
if (entry.Properties.Contains(kv.Key))
entry.Properties[kv.Key][0] = kv.Value;
else
entry.Properties[kv.Key].Add(kv.Value);
}
entry.CommitChanges();   

分页窗口
  由于以前学过一点C(都不好意思说出口),考虑问题的时候总是面向过程。就算知道建立类型,一些思考方向还是没有转过来。这里表现的就很明显。面对的问题是:让分页栏保持定长(如果有足够多页的数据)。
  #CStyle
  获取当前页,获取窗口长度。计算左右距离,验证左侧,验证右侧。然后在不同的情况下取不同的值。比如:



protected int[] getPagerWindow(int current, int max, int width)
{
//获取分页窗口
int left = (width - 1) / 2;
int right = width - left - 1;
//左右索引
int rindex;
int lindex;
List<int> window = new List<int>();
//计算
if (current - left <= 0)
{
//获取分页窗口左右索引
lindex = 1;
rindex = Math.Min(width, max);
}
else if (current + right >= max)
{
//获取左右索引
rindex = max;
lindex = Math.Max(1, max - width + 1);
}
else
{
rindex = current + right;
lindex = current - left;
}
for (int i = lindex; i < rindex + 1; i++)
window.Add(i);
return window.ToArray();
}

  #OOPStyle
  将窗口想象成窗口,将页码想象成长胶卷。那么,如果胶卷长度比窗口小,就取所有页码,否则计算窗口中心的位移,然后移动窗口。比如:



        public static IEnumerable<int> ComputePageWindow(int count, int current, int size)
{
current = current < 1 ? 1 : current;
count = count < 1 ? 1 : count;
var fixedIndex = size%2 == 0 ? size/2 : (size + 1)/2;
var offset = current - fixedIndex;
offset = current < fixedIndex ? 0 : offset;
offset = count - current < fixedIndex ? count - size : offset;
var windowStart = 1 + offset;
return Enumerable.Range(windowStart, size).Where(i => i > 0 && i <= count);
}
  #以及数据绑定



<asp:Repeater ID="rptPager" runat="server"
DataSource='<%#getPagerWindow(searcher.CurrentIndex,searcher.PageCount,5)  %>'
OnItemCommand="rptPager_ItemCommand">
</asp:Repeater>

  很明显,第二种思路简洁很多。这里记下来提醒自己。各位朋友就当是听一个初学者的喃喃自语吧。
  自此,AD信息管理的内容结束,其实主要是为了解决搜索的问题。这里贴一个运行截图。由于操作中有数据转换,所以执行搜索花了2~3秒,但是作为一个管理系统还可以接受。下一篇的内容是.net调用PowerShell组件以达到管理Exchange的目的。
DSC0001.png
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-111942-1-1.html 上篇帖子: WebDAV方式访问Exchange 2003收件箱程序 下篇帖子: Exchange常见问题大全
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表