VBScript Bit-wise Operators
Working with Active Directory userAccountControl and VBScript (.vbs files) to check for a disabled account. This is a much better alternative to checking if the account is equal to "514"or "546". Read on to understand why!
(Full VBScript included at the very bottom)
Since userAccountControl in AD is represented as a long ugly hexadecimal number, i.e. "0x00000002", finding out if a user is disabled is a very unintuitive task that requires expanding the value to binary and checking for a "1" or a "0" in the 2nd most right position (thanks to Bit-wise operators, we'll never have to do this, but rather it's provided as an explanation).
The bitwise operator known as a "Logical OR" treats a number, such as "512", "514" or "2" as binary and returns only the binary matches between the two numbers being compared.
I had a hard time finding how to do logical "AND" logical "OR" in VBScript. These operators are usually represented with "&" (AND) "|" (OR) in C based languages such as Java, C++, but VBScript simply uses the word "AND" and the word "OR" in-between numbers.
More on bitwise "OR" can be found here: http://en.wikipedia.org/wiki/Bitwise_operation#OR
Test this out with 512, 544, etc. This is the RIGHT way to check account status. For more account status codes, look here (Scroll down to remarks): http://msdn.microsoft.com/en-us/library/windows/desktop/ms680832(v=vs.85).aspx
-Tres
(Full VBScript included at the very bottom)
ADS_UF_ACCOUNTDISABLE = 2The "AND" operator has two meanings in VBScript, depending on how it's used. "AND" is normally used for Boolean Logic, such as True AND False; however in VBScript, when used between two numbers, "AND"/"OR" is used as a "Bit-wise Logical Operator", which is essential for comparing 1's and 0's underlying your decimal values. The tricky part was knowing to use the parenthesis around the "AND". statement. Without it, order of operations will evaluate the Equals sign first, and the AND statement second. Keep reading to understand more.
UserAccountControl = 514
If (UserAccountControl AND ADS_UF_ACCOUNTDISABLE) = ADS_UF_ACCOUNTDISABLE Then
MsgBox UserAccountControl & " = Is Disabled!"
Else
MsgBox UserAccountControl & " = Is NOT Disabled!"
End If
Since userAccountControl in AD is represented as a long ugly hexadecimal number, i.e. "0x00000002", finding out if a user is disabled is a very unintuitive task that requires expanding the value to binary and checking for a "1" or a "0" in the 2nd most right position (thanks to Bit-wise operators, we'll never have to do this, but rather it's provided as an explanation).
Decimal: 512Since expanding decimal to binary is a lot of work, computers have native support for these operations known as "Bit-wise Operators", sometimes referred to as "DWORD" calculations.
Binary: 1000000000
*Note: Red "0" indicates enabled account.
Decimal: 514
Binary: 1000000010
*Note: Red "1 "indicates disabled account.
The bitwise operator known as a "Logical OR" treats a number, such as "512", "514" or "2" as binary and returns only the binary matches between the two numbers being compared.
Decimal: 2
Binary: 0000000010---------------------------
Decimal: 512
Binary: 1000000010
*Note: 0 "OR" 1 is always "0".
---------------------------
Result: 0000000010
- So, 514 "OR" 2 is always 2!
- This means 512 "OR" 2 is always 0!
- This works for any number stored for user account control!
I had a hard time finding how to do logical "AND" logical "OR" in VBScript. These operators are usually represented with "&" (AND) "|" (OR) in C based languages such as Java, C++, but VBScript simply uses the word "AND" and the word "OR" in-between numbers.
More on bitwise "OR" can be found here: http://en.wikipedia.org/wiki/Bitwise_operation#OR
Test this out with 512, 544, etc. This is the RIGHT way to check account status. For more account status codes, look here (Scroll down to remarks): http://msdn.microsoft.com/en-us/library/windows/desktop/ms680832(v=vs.85).aspx
On Error Resume Next
Const ADS_SCOPE_SUBTREE = 2
Const ADS_UF_ACCOUNTDISABLE = 2
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
Set fso = CreateObject("Scripting.FileSystemObject")
Set oStream = fso.CreateTextFile("DisabledUsers.csv", True)
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objCommandProperties("Sort On") = "Name"
objCommand.CommandText = _ "SELECT 'Name', 'userAccountControl' FROM 'LDAP://dc=AD_DOMAIN,dc=YOURCOMPANY,dc=COM_NET_ETC' WHERE objectCategory='user'"
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
'oStream.Write(objRecordSet.Fields("Name").Value & ",")
'objRecordSet.MoveNext
If (objRecordSet.Fields("userAccountControl").Value AND ADS_UF_ACCOUNTDISABLE) = ADS_UF_ACCOUNTDISABLE Then oStream.WriteLine(objRecordSet.Fields("Name").Value & ",")
End If
objRecordSet.MoveNext
Loop
WScript.Quit
-Tres
Comments