Using the classes in the DirectoryServices namespace, I am trying to
figure out if an user's password expired (or when it's going to be
expired).
Using the LDAP provider to bind to Active Directory.
Using VB.NET/ASP.NET.
I was hoping to use the "pwdLastSet" attribute, get the value (lDate)
in a Long type (using the HighPart and LowPart), and then use the
System.DateTime.FromFileTime (lDate) to get the date when the password
was last set. However, I have not been able to do this, so far:
I have a couple of questions:
Q1:
Why are the values for "pwdLastSet" attribute different when I use the
ADSI Edit tool and when I read the value in code using
oSearchResult.Properties ("pwdLastSet").Item (0)?
Here are a couple of examples:
Both the accounts have "Password Never Expires" unchecked.
Reading through Code: 1675886196
ADSI Edit: 126881599091505776
Reading through Code: -1849430547
ADSI Edit: 126880813886336192
Q2:
Dim oli As Object = oSearchResult.Properties ("pwdLastSet").Item (0)
Dim lDate As Long = (oli.HighPart * &H100000000) + oli.LowPart
PWDLastSetDate = System.DateTime.FromFileTime (lDate)
When I use the above 3 lines, I get the following exception
"Public member 'HighPart' on type 'Long' not found."
I know I have a reference to ActiveDS.tlb. What do I need to get the
HighPart and LowPart working?
Q3:
Is there a way to read the value "MaxPwdAge" (as set in the Domain
Security Policy) using VB.NET? I need to use this to determine if the
password expired.
However, if you get PwdLastSet using the DirectoryEntry, it is returned as a
COM Object that is an IADsLargeInteger that you can read the HighPart and
LowPart members from. If you do the math to assemble the long value
yourself, you will get the correct value.
I posted a sample function that I use for converting these values that works
without having a reference to ActiveDs.dll or without using VB.NET late
binding (Option Strict On) if you are interested.
http://groups.google.com/groups?selm=Of027QwwCHA.456%40TK2MSFTNGP09&oe=UTF-8&output=gplain
Cheers,
Joe K.
"M Kancharla" <manoj_k...@yahoo.com> wrote in message
news:3705ef6c.0301...@posting.google.com...
This link discusses many of the issues involved:
http://msdn.microsoft.com/library/default.asp?
url=/library/en-us/dnclinic/html/scripting09102002.asp
The article suggests using the "PasswordLastChanged"
property of the IADsUser interface. This "property method"
maps to the PwdLastSet attribute, but returns a normal
date value.
To retrieve the domain MaxPwdAge policy, bind to the
domain and retrieve the MaxPwdAge attribute. However, this
is also an Integer8 (64-bit) value. Similar to PwdLastSet,
it represents the number of 100-nanosecond intervals.
In your message, the value you list for PwdLastSet
retrieved from your code cannot be right. It appears to be
the value for LowPart only. The ADSI Edit value looks
good. I don't use DirectoryServices, but in VBScript, I
use:
Set oUser = GetObject("LDAP://cn=Test2,dc=MyDomain,dc=com")
Set oDate = oUser.PwdLastSet
nDate = #1/1/1601" + (((oDate.HighPart * 2 ^ 32) _
+ oDate.LowPart)/600000000 - nBias)/1440
where nBias is the time zone bias from the local machine
registry in minutes.
When I use ADO to return a value I use:
sDate = oRS.Fields("PwdLastSet")
Set oDate = sDate
... etc.
This leads me to think your problem is in typing the
variables. You may need an intermediate variable, as I do
when I use ADO. I don't know what provides the HighPart
and LowPart methods, but I believe it is ADSI.
One thing not discussed in the article I linked is the
fact that PwdLastSet is not replicated. I can find no
documentation, but I assume that the PasswordLastChanged
property method retrieves a value from only one Domain
Controller. I believe an accurate method would query every
DC in the domain for the largest value. This would not be
necessary if you have only one DC, or you can be sure that
the user always authenticates to the same DC when they
logon, and this is the DC you query for
PasswordLastChanged.
As you can see, the subject can get complex.
Richard
>.
>
Tried your functions...
I get an exception "System.MissingMethodException: Method
System.Int64.HighPart not found." @ the line
highPart = CType(largeIntType.InvokeMember("HighPart",
BindingFlags.GetProperty Or BindingFlags.Public, _
Nothing, largeInteger, Nothing),
Integer).
Any suggestions?
Thanks
Manoj K
"Joe Kaplan" <ilearnedthi...@noway.com> wrote in message news:<OZjtft6xCHA.1896@TK2MSFTNGP11>...
It doesn't work with a ResultPropertyValueCollection value.
I have used this successfully with pwdLastSet this way in my code:
dim user as DirectoryEntry
'bind user object with appropriate constructor:
user = new DirectoryEntry(LDAP://myuserdnhere)
Dim pwdLastSet as Object
pwdLastSet = entry.Properties("pwdLastSet").Value
dim pwdDate as DateTime = GetDateFromLargeInteger(pwdLastSet)
I would expect the method to fail if the thing you passed in wasn't actually
an IADsLargeInteger under the hood.