Ad account operation C # sample code (2) -- check the user whose password will expire

Source: Internet
Author: User
Tags filetime list of attributes samaccountname

This article will share with you the operations on the ad account. This time, we will develop a simple tool to check for expired users.

First, create a new user entity class. The attribute is the user information we want to obtain.

Public class userinfo {// <summary> // Sam account name // </Summary> Public String samaccountname {Get; set ;} /// <summary> /// name /// </Summary> Public string name {Get; set ;} /// <summary> /// email /// </Summary> Public String mail {Get; set ;} /// <summary> /// disabled /// </Summary> Public bool isdisabled {Get; set ;} /// <summary> /// set the password to never expire /// </Summary> Public bool ispasswordneverexpire {Ge T; Set ;}/// <summary> /// you do not need a password. // </Summary> Public bool isnopasswordrequired {Get; set ;} /// <summary> /// Number of days when the system password expires /// </Summary> Public long maxPasswordAge {Get; set ;} /// <summary> /// remaining days overdue /// </Summary> Public double? Surpluspasswordexpirationdays {get {If (! Passwordexpirationdate. hasvalue) {return default (double ?);} Double days = passwordexpirationdate. value. subtract (datetime. now ). totaldays; If (days <= 0) {return 0;} return math. round (days, 2) ;}/// <summary> /// last password modification time /// </Summary> Public datetime passwordlastset {Get; set ;} /// <summary> /// password expiration time /// </Summary> Public datetime? Passwordexpirationdate {Get; Set ;}}

Then, you can search for user information.

Private ienumerable <userinfo> searchusers (string path, string username, string password, string samaccountname, string displayname, bool isdisabled, bool ispasswordneverexpire, long [] surplusexpirationdays) {using (directoryentry = new directoryentry (path, username, password) {using (directorysearcher = new directorysearcher (directoryentry, @ "& (objectcategory = Person) (objectclass = user) ", new string [] {" name "," samaccountname "," useraccountcontrol "," pwdlastset "," mail "}, searchscope. subtree) {pagesize = 1000}) {using (searchresultcollection userresultcollection = directorysearcher. findall () {foreach (searchresult userresult in userresultcollection) {userinfo = new userinfo (); // todo: Value: yield return userinfo ;}}}}}

This time, we mainly use the directorysearcher class: searchroot is the root node of the directoryentry to be searched, searchscope attribute is the search range, and searchscope enumeration: Base (limited to the base object), onelevel (search for the direct sub-objects of the base object, but not the Base Object), and subtree (search for the entire sub-tree, including the base object and all its sub-objects ). To search for users under the specified ou, select the subtree.

The filter attribute of the directorysearcher class is a filter condition, and the Search user is "& (objectcategory = person) (objectclass = user ))". Note: "&", "|", and "!" of and or not Prefix these condition expressions instead of between them. If you want to use wildcard characters * for fuzzy search, you can use "=", "> =", "<=", and "~". = "(Approximately equal to), but"> "and" <"cannot be used;" pwdlastset "must be converted to Windows file time, because a long is stored, there is also the merge operation for "useraccountcontrol". Here we use ": 1.2.840.113556.1.4.803: = ". We can put some query conditions in the filter to reduce the number of rows returned by the search results:

                    directorySearcher.SearchScope = SearchScope.Subtree;                    List<string> filterItems = new List<string>();                    if (!string.IsNullOrEmpty(sAMAccountName))                    {                        filterItems.Add(string.Format(@"(sAMAccountName={0})", sAMAccountName));                    }                    if (!string.IsNullOrEmpty(displayName))                    {                        filterItems.Add(string.Format(@"(name={0})", displayName));                    }                    if (!containsDisabled)                    {                        filterItems.Add(@"(!(userAccountControl:1.2.840.113556.1.4.803:=2))");                    }                    if (!containsPasswordNeverExpire)                    {                        filterItems.Add(@"(!(userAccountControl:1.2.840.113556.1.4.803:=65536))");                    }                    if (!containsNoPasswordRequired)                    {                        filterItems.Add(@"(!(userAccountControl:1.2.840.113556.1.4.803:=32))");                    }                    if (surplusExpirationDays != null && surplusExpirationDays.Length > 0)                    {                        StringBuilder surplusExpirationDaysFilter = new StringBuilder(@"(|");                        DateTime now = DateTime.Now;                        foreach (long surplusExpirationDay in surplusExpirationDays)                        {                            DateTime passwordExpirationDate = now.AddDays(surplusExpirationDay);                            DateTime passwordLastSet = passwordExpirationDate.AddDays(-1 * maxPwdAge);                            if (surplusExpirationDay != 0)                            {                                surplusExpirationDaysFilter.AppendFormat("(&(pwdLastSet>={0})(pwdLastSet<={1}))", passwordLastSet.ToFileTime().ToString(), passwordLastSet.AddDays(1).AddSeconds(-1).ToFileTime().ToString());                            }                            else                            {                                surplusExpirationDaysFilter.AppendFormat("(pwdLastSet<={0})(pwdLastSet=0)", passwordLastSet.AddDays(1).AddSeconds(-1).ToFileTime().ToString());                            }                        }                        surplusExpirationDaysFilter.Append(@")");                        filterItems.Add(surplusExpirationDaysFilter.ToString());                    }                    directorySearcher.Filter = string.Format(@"(&{0}(objectCategory=person)(objectClass=user))", string.Concat(filterItems));

For the filter syntax, see: Filters.

For the useraccountcontrol flag, see examples (vs.85). aspx, http://technet.microsoft.com/library/ee198831.aspx.

The propertiestoload attribute of the directorysearcher class is the list of attributes to be retrieved. This is equivalent to the items following the SELECT statement in the SQL statement when we access the database. It is best to specify the parameter as needed, and try not to write "select *"; note that the pagesize attribute of the directorysearcher class can be set to 1000 if you want to return all data. By default, only 1000 entries are returned.

 directorySearcher.PropertiesToLoad.AddRange(new string[] { "name", "sAMAccountName", "userAccountcontrol", "pwdLastSet", "mail" }); directorySearcher.PageSize = 1000;

For more directorysearcher class properties, see: http://msdn.microsoft.com/zh-cn/library/System.DirectoryServices.DirectorySearcher_properties (V = vs.80). aspx

The expiration date of the user's password can be obtained through the invokeget method of the directoryentry object. However, it is a waste to load the directoryentry once!

    using (DirectoryEntry resultDirectoryEntry = userResult.GetDirectoryEntry())    {        userInfo.PasswordExpirationDate = DateTime.Parse(resultDirectoryEntry.InvokeGet("PasswordExpirationDate").ToString());    }

So I still want to calculate it by myself. Use the last password setting time + the Password Expiration days set by the system. The last password setting time corresponds to "pwdlastset". If you use the properties of the directoryentry object, it is a "system. _ comobject "type value. Fortunately, the" pwdlastset "of the searchresult object can be directly taken as long. This value is the Windows file time and can be converted to the local time.

long fileTime = (userResult.Properties["pwdLastSet"][0] as long?).GetValueOrDefault();userInfo.PasswordLastSet = DateTime.FromFileTime(fileTime);

The System Password Expiration days are set through the Group Policy and can be obtained through the "maxpwdage" attribute in the ou path. The "maxpwdage" of the searchresult object can also be directly set to long.

 directorySearcher.SearchScope = SearchScope.Base; directorySearcher.Filter = @"(objectClass=*)"; directorySearcher.PropertiesToLoad.Add("maxPwdAge"); SearchResult ouResult = directorySearcher.FindOne(); long maxPwdAge = 0; if (ouResult.Properties.Contains("maxPwdAge")) {      maxPwdAge = TimeSpan.FromTicks((long)ouResult.Properties["maxPwdAge"][0]).Days * -1; }

Finally, the user's password expires!

 userInfo.MaxPasswordAge = maxPwdAge; if (!userInfo.IsPasswordNeverExpire) {      userInfo.PasswordExpirationDate = userInfo.PasswordLastSet.AddDays(userInfo.MaxPasswordAge); }

Query user information OK. The code for exporting User information to excel is as follows:

View code

The code for sending emails using smtpclient allows you to customize HTML files as template content:

View code

 

Finally, the Code is integrated to check that the user's password has expired! Due to the limited level of the author, there will inevitably be some omissions and errors in this article, and the code needs to be constantly optimized. You are welcome to give valuable suggestions!

References:

Directoryentry class uses http://msdn.microsoft.com/zh-cn/library/z9cddzaa (V = vs.110). aspx

Directorysearcher class uses http://msdn.microsoft.com/zh-cn/library/System.DirectoryServices.DirectorySearcher (V = vs.90). aspx

Simple Directory Access Protocol (LDAP) http://msdn.microsoft.com/en-us/library/aa367008 (vs.85). aspx

Checking password will expire user gadgets: http://files.cnblogs.com/CSharpDevelopers/UserPasswordSetChecker.zip

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.