Re: List Users Accounts That are Locked Out
  Home FAQ Contact Sign in
microsoft.public.windows.server.scripting only
 
Advanced search
POPULAR GROUPS

more...

 Up
Re: List Users Accounts That are Locked Out         

Group: microsoft.public.windows.server.scripting · Group Profile
Author: Richard Mueller [MVP]
Date: Jul 31, 2007 03:27

If the error is on the "Set objTrans" line, then the only explanation I can
think of is that the client is Windows 95 or 98 or NT and DSClient is not
installed.

If the error is on "objTrans.Init", then the client was unable to contact a
Global Catalog.

If the error was on "objTrans.Set", then strDNSDomain is wrong, but that was
retrieved from the objRootDSE object. Either you are not joined to a domain,
or no DC is available. This makes no sense if you are running the program on
a DC.

The "objTrans.Get" statement only raises an error if there is no NetBIOS
name for the domain, which is not possible.

What error message do you get, and on which line exactly? The only realistic
explanation I can see is that the client (the computer you are running the
script on) cannot find a Global Catalog.

As a last resort you could hard code the NetBIOS name of the domain. You
would replace the code you posted with:

strNetBIOSDomain = "MyDomain"

where "MyDomain" is the NetBIOS name of your domain. However, the error
makes me think something serious is wrong.

--
Richard Mueller
Microsoft MVP Scripting and ADSI
Hilltop Lab - http://www.rlmueller.net
--

"Gustavo" discussions.microsoft.com> wrote in message
news:7E914145-456F-4792-A212-19370DC78C46@microsoft.com...
> Hi Richard, It's me again:
>
> I getting error messages when I run the script on DC, and is in these
> lines
> Set objTrans = CreateObject("NameTranslate")
> objTrans.Init ADS_NAME_INITTYPE_GC, ""
> objTrans.Set ADS_NAME_TYPE_1779, strDNSDomain
> strNetBIOSDomain = objTrans.Get(ADS_NAME_TYPE_NT4)
> I do not know what's the problem is, please can you help me?, and thanks.
>
> "Richard Mueller [MVP]" wrote:
>
>> Gustavo wrote:
>>
>>> Thanks again Richard, just to clear my mind, yuor code has this:
>>>
>>> ' Determine DNS domain name.
>>> Set objRootDSE = GetObject("LDAP://RootDSE")
>>> strDNSDomain = objRootDSE.Get("defaultNamingContext")
>>>
>>> *********
>>> ' Find locked out user accounts in domain
>>> ' create array of sAMAccountName's
>>> Set objDomain = GetObject("WinNT://" & strNetBIOSDomain)
>>> objDomain.Filter = Array("user")
>>>
>>> where can I change the connection string?
>>>
>>> and where do I change the provider, 'cos I could not find it.
>>>
>>> "Richard Mueller [MVP]" wrote:
>>>
>>
>> The line in the program LockedUsers.vbs that I meant to replace is
>> further
>> down, in the "For" loop that loops through the DC's. The complete code
>> could
>> look similar to below. This assumes the ou of interest is "ou=Sales":
>> ==================
>> Option Explicit
>>
>> Dim objRootDSE, strConfig, adoConnection, adoCommand, strQuery
>> Dim adoRecordset, objDC
>> Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
>> Dim strDN, dtmDate, objDate, strUser, strNTName
>> Dim objList1, objList2, objList3, j, intBadCount
>> Dim strBase, strFilter, strAttributes, objWinNTUser
>> Dim objTrans, strNetBIOSDomain, objDomain, arrstrNTNames()
>> Dim lngHigh, lngLow
>>
>> ' Constants for the NameTranslate object.
>> Const ADS_NAME_INITTYPE_GC = 3
>> Const ADS_NAME_TYPE_NT4 = 3
>> Const ADS_NAME_TYPE_1779 = 1
>>
>> ' Determine DNS domain name.
>> Set objRootDSE = GetObject("LDAP://RootDSE")
>> strDNSDomain = objRootDSE.Get("defaultNamingContext")
>>
>> ' Use the NameTranslate object to convert the DNS domain name
>> ' to the NetBIOS domain name.
>> Set objTrans = CreateObject("NameTranslate")
>> objTrans.Init ADS_NAME_INITTYPE_GC, ""
>> objTrans.Set ADS_NAME_TYPE_1779, strDNSDomain
>> strNetBIOSDomain = objTrans.Get(ADS_NAME_TYPE_NT4)
>> ' Remove trailing backslash.
>> strNetBIOSDomain = Left(strNetBIOSDomain, Len(strNetBIOSDomain) - 1)
>>
>> ' Find locked out user accounts in domain
>> ' create array of sAMAccountName's
>> Set objDomain = GetObject("WinNT://" & strNetBIOSDomain)
>> objDomain.Filter = Array("user")
>> k = 0
>> For Each objWinNTUser In objDomain
>> If (objWinNTUser.IsAccountLocked = True) Then
>> ReDim Preserve arrstrNTNames(k)
>> arrstrNTNames(k) = objWinNTUser.name
>> k = k + 1
>> End If
>> Next
>>
>> If (k = 0) Then
>> Wscript.Echo "No user accounts locked out in domain"
>> Wscript.Quit
>> End If
>>
>> ' Use dictionary objects to track latest badPasswordTime,
>> ' badPwdCount, and Domain Controller for each locked out user.
>> Set objList1 = CreateObject("Scripting.Dictionary")
>> objList1.CompareMode = vbTextCompare
>> Set objList2 = CreateObject("Scripting.Dictionary")
>> objList2.CompareMode = vbTextCompare
>> Set objList3 = CreateObject("Scripting.Dictionary")
>> objList3.CompareMode = vbTextCompare
>>
>> ' Obtain local Time Zone bias from machine registry.
>> Set objShell = CreateObject("Wscript.Shell")
>> lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" _
>> & "TimeZoneInformation\ActiveTimeBias")
>> If (UCase(TypeName(lngBiasKey)) = "LONG") Then
>> lngBias = lngBiasKey
>> ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
>> lngBias = 0
>> For k = 0 To UBound(lngBiasKey)
>> lngBias = lngBias + (lngBiasKey(k) * 256^k)
>> Next
>> End If
>>
>> ' Determine configuration context.
>> strConfig = objRootDSE.Get("configurationNamingContext")
>>
>> ' Use ADO to search Active Directory for ObjectClass nTDSDSA.
>> ' This will identify all Domain Controllers.
>> Set adoCommand = CreateObject("ADODB.Command")
>> Set adoConnection = CreateObject("ADODB.Connection")
>> adoConnection.Provider = "ADsDSOObject"
>> adoConnection.Open = "Active Directory Provider"
>> adoCommand.ActiveConnection = adoConnection
>>
>> strBase = ""
>> strFilter = "(objectClass=nTDSDSA)"
>> strAttributes = "AdsPath"
>> strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
>>
>> adoCommand.CommandText = strQuery
>> adoCommand.Properties("Page Size") = 100
>> adoCommand.Properties("Timeout") = 60
>> adoCommand.Properties("Cache Results") = False
>>
>> Set adoRecordset = adoCommand.Execute
>>
>> ' Enumerate parent objects of class nTDSDSA. Save Domain Controller
>> ' DNS host names in dynamic array arrstrDCs.
>> k = 0
>> Do Until adoRecordset.EOF
>> Set objDC = _
>> GetObject(GetObject(adoRecordset.Fields("AdsPath").Value).Parent)
>> ReDim Preserve arrstrDCs(k)
>> arrstrDCs(k) = objDC.DNSHostName
>> k = k + 1
>> adoRecordset.MoveNext
>> Loop
>> adoRecordset.Close
>>
>> ' Use ADO to retrieve all user objects from each Domain Controller.
>> strFilter = "(&(objectCategory=person)(objectClass=user))"
>> strAttributes = "distinguishedName,sAMAccountName," _
>> & "badPasswordTime,badPwdCount"
>> For k = 0 To Ubound(arrstrDCs)
>> strBase = " >> ">"
>> strQuery = strBase & ";" & strFilter & ";" & strAttributes _
>> & ";subtree"
>> adoCommand.CommandText = strQuery
>> On Error Resume Next
>> Set adoRecordset = adoCommand.Execute
>> If (Err.Number <> 0) Then
>> On Error GoTo 0
>> Wscript.Echo "Domain Controller not available: " & arrstrDCs(k)
>> Else
>> On Error GoTo 0
>> Do Until adoRecordset.EOF
>> strNTName = adoRecordset.Fields("sAMAccountName").Value
>> ' Check each user to see if in array of locked out accounts.
>> For j = 0 To UBound(arrstrNTNames)
>> If (UCase(strNTName) = UCase(arrstrNTNames(j))) Then
>> ' User locked out, retrieve badPasswordTime.
>> strDN =
>> adoRecordset.Fields("distinguishedName").Value
>> intBadCount =
>> adoRecordset.Fields("badPwdCount").Value
>> On Error Resume Next
>> Set objDate =
>> adoRecordset.Fields("badPasswordTime").Value
>> If (Err.Number <> 0) Then
>> On Error GoTo 0
>> dtmDate = #1/1/1601#
>> Else
>> On Error GoTo 0
>> lngHigh = objDate.HighPart
>> lngLow = objDate.LowPart
>> If (lngLow < 0) Then
>> lngHigh = lngHigh + 1
>> End If
>> If (lngHigh = 0) And (lngLow = 0 ) Then
>> dtmDate = #1/1/1601#
>> Else
>> dtmDate = #1/1/1601# + (((lngHigh * (2 ^ 32))
>> _
>> + lngLow)/600000000 - lngBias)/1440
>> End If
>> End If
>> If (objList1.Exists(strDN) = True) Then
>> If (dtmDate > objList1.Item(strDN)) Then
>> ' Later badBadPasswordTime found, save info
>> from
>> this DC.
>> objList1.Item(strDN) = dtmDate
>> objList2.Item(strDN) = intBadCount
>> objList3.Item(strDN) = arrstrDCs(k)
>> End If
>> Else
>> ' First time user found, save info from this DC.
>> objList1.Add strDN, dtmDate
>> objList2.Add strDN, intBadCount
>> objList3.Add strDN, arrstrDCs(k)
>> End If
>> End If
>> Next
>> adoRecordset.MoveNext
>> Loop
>> adoRecordset.Close
>> End If
>> Next
>>
>> ' Output information on each locked out user.
>> For Each strUser In objList1.Keys
>> Wscript.Echo strUser & " ; " & objList1.Item(strUser) & " ; " _
>> & objList2.Item(strUser) & " ; " & objList3.Item(strUser)
>> Next
>>
>> ' Clean up.
>> adoConnection.Close
>> Set objRootDSE = Nothing
>> Set adoConnection = Nothing
>> Set adoCommand = Nothing
>> Set adoRecordset = Nothing
>> Set objTrans = Nothing
>> Set objDomain = Nothing
>> Set objWinNTUser = Nothing
>> Set objDC = Nothing
>> Set objDate = Nothing
>> Set objList1 = Nothing
>> Set objList2 = Nothing
>> Set objList3 = Nothing
>> Set objShell = Nothing
>> ===============
>> In the statement:
>>
>> strBase = ""
>>
>> you need to modify "ou=Sales" to match the OU you are interested in.
>> Everything else should stay the same.
>>
>> --
>> Richard Mueller
>> Microsoft MVP Scripting and ADSI
>> Hilltop Lab - http://www.rlmueller.net
>> --
>>
>>
>>
no comments
diggit! del.icio.us! reddit!