| Author |
Topic  |
|
netmarcos
Honorable But Hopeless Addict
    
USA
1891 Posts
Status: offline |
Posted - 05/27/2003 : 10:47:27 AM
|
There has been a lot of discussion surrounding this issue. The script below is the result of the combined effort of several people.
'*******************************************************************
' ADWorkstationLastLogon.vbs
' VBScript to determine when each computer in the domain
' lastlogged on.
'
' ------------------------------------------------------------------
' Copyright (c) 2002 Richard L. Mueller
' Version 1.2 - January 23, 2003
' Modified - March 4, 2003 Kevin Buley
' - Added output lines to show that the script is processing
' (DC name, # x of y)
' Modified March 5, 2003 Mark M. Webster
' - Modified output to be fixed width for import
' - Made several structural modifications and
' additional comments
'
' Because the LastLogon attribute is not replicated, every Domain Controller
' in the domain must be queried to find the latest LastLogon date for each
' computer. The lastest date found is kept in a dictionary object. The
' program first uses ADO to search the domain for all Domain Controllers.
' The AdsPath of each Domain Controller is saved in an array. Then, for each
' Domain Controller, ADO is used to search the copy of Active Directory on
' that Domain Controller for all computer objects and return the LastLogon
' attribute. The LastLogon attribute is a 64-bit number representing the
' number of 100 nanosecond intervals since 12:00 am January 1, 1601. This
' value is converted to a date. The last logon date is in UTC (Coordinated
' Univeral Time). It must be adjusted by the Time Zone bias in the machine
' registry to convert to local time.
'
' You have a royalty-free right to use, modify, reproduce, and distribute
' this script file in any way you find useful, provided that you agree
' that the copyright owner above has no warranty, obligations, or liability
' for such use.
'************************************************************************************************
Option Explicit
Const ForAppending = 8
Dim k
Dim sDCs() 'Dynamic array to hold the path for all DCs
Dim BiasKey 'Active Time Bias from Registry
Dim Bias 'Time Bias
Dim strAdsPath 'Machine account DN
Dim strDate 'Date output string
Dim sDate 'Local machine current date
Dim lngDate 'LastLogon date
Dim strTime 'Local machine current time
Dim strLDate 'Local machine current date and time
Dim objList 'Dictionary object to track latest LastLogon for each computer
Dim objRoot 'RootDSE object
Dim strConfig 'Configuration Naming Context
Dim objDC 'Domain Controller
Dim strDNSDomain 'Default nameing context
Dim strComputer 'Computer object Name
Dim objConnection 'ADO conection
Dim objCommand 'ADO command
Dim objRecordSet 'Object to hold attributes from AD
Dim oWshShell 'Windows shell script
Dim objFSO 'File System object
Dim objFile 'File object used to open text file for output
Dim objLastLogon 'Last Logon Long Integer attribute
Dim strFilePath 'Path to current directory
Set oWshShell = CreateObject("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strFilePath = objFSO.GetAbsolutePathName(".")
sDate = Date
strTime = Now
StrLDate = DatePart("m",sDate) & "." & DatePart("d",sDate) & "." & Hour(strTime) & "." & Minute(strTime)
Set objFile = objFSO.OpenTextFile (strFilePath & "\DomainLastLogon." & strLDate & ".log",ForAppending,True)
'* Use a dictionary object to track latest LastLogon for each computer.
Set objList = CreateObject("Scripting.Dictionary")
objList.CompareMode = vbTextCompare
'* Obtain local Time Zone bias from machine registry.
BiasKey = oWshShell.RegRead("HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
If UCase(TypeName(BiasKey)) = "LONG" Then
Bias = BiasKey
ElseIf UCase(TypeName(BiasKey)) = "VARIANT()" Then
Bias = 0
For k = 0 To UBound(BiasKey)
Bias = Bias + (BiasKey(k) * 256^k)
Next
End If
'* Determine configuration context and DNS domain from RootDSE object.
Set objRoot = GetObject("LDAP://RootDSE")
strConfig = objRoot.Get("ConfigurationNamingContext")
strDNSDomain = objRoot.Get("DefaultNamingContext")
'* Use ADO to search Active Directory for ObjectClass nTDSDSA.
'* This will identify all Domain Controllers.
Set objCommand = CreateObject("ADODB.Command")
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open = "Active Directory Provider"
objCommand.ActiveConnection = objConnection
objCommand.CommandText = "<LDAP://" & strConfig & ">;(ObjectClass=nTDSDSA);AdsPath;subtree"
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 30
objCommand.Properties("Searchscope") = 2
objCommand.Properties("Cache Results") = False
Set objRecordSet = objCommand.Execute
'* Enumerate parent objects of class nTDSDSA. Save Domain Controller
'* AdsPaths in dynamic array sDCs.
k = 0
Do Until objRecordSet.EOF
Set objDC = GetObject(GetObject(objRecordSet.Fields("AdsPath")).Parent)
ReDim Preserve sDCs(k)
sDCs(k) = objDC.DNSHostName
k = k + 1
objRecordSet.MoveNext
Loop
'* Retrieve LastLogon attribute for each computer on each Domain Controller.
For k = 0 To Ubound(sDCs)
oWshShell.Popup "Checking 'lastlogon' at domain controller " & sDCs(k) & ". Controller " & k & " of " & Ubound(sDCs),2,"Checking",64
'*******************************************************************
'* Modify this line for the base of your search path depending on your own AD implementation
'*******************************************************************
objCommand.CommandText = "<LDAP://" & sDCs(k) & "/OU=Workstations," & strDNSDomain & ">;(ObjectCategory=computer);Name,LastLogon;subtree"
On Error Resume Next
Err.Clear
Set objRecordSet = objCommand.Execute
If Err.Number <> 0 Then
Err.Clear
On Error GoTo 0
oWshShell.Popup "Domain Controller not available: " & sDCs(k),2,"Notice",48
Else
On Error GoTo 0
Do Until objRecordSet.EOF
strAdsPath = objRecordSet.Fields("Name")
strDate = objRecordSet.Fields("LastLogon")
On Error Resume Next
Err.Clear
Set lngDate = strDate
If Err.Number <> 0 Then
Err.Clear
strDate = #1/1/1601#
Else
If (lngDate.HighPart = 0) And (lngDate.LowPart = 0 ) Then
strDate = #1/1/1601#
Else
strDate = #1/1/1601# + (((lngDate.HighPart * (2 ^ 32)) + lngDate.LowPart)/600000000 - Bias)/1440
End If
End If
On Error GoTo 0
If objList.Exists(strAdsPath) Then
If strDate > objList(strAdsPath) Then
objList(strAdsPath) = strDate
End If
Else
objList.Add strAdsPath, strDate
End If
objRecordSet.MoveNext
Loop
End If
Next
'* Output latest LastLogon date for each computer.
For Each strComputer In objList
Call VBOut(strComputer,objList(strComputer))
Next
objFile.WriteBlankLines (3)
objFile.Close
oWshShell.Popup "Output file " & strFilePath & "\DomainLastLogon." & strLDate & ".log created." & Chr(13)_
& " Script processing complete.",5,"Notice",64
'* Clean up.
Set objRoot = Nothing
Set objConnection = Nothing
Set objCommand = Nothing
Set objRecordSet = Nothing
Set objDC = Nothing
Set lngDate = Nothing
Set objList = Nothing
Set oWshShell = Nothing
'*******************************************************************
'* Function VBOut
'*
'* Format data and write to output file
'*
'*******************************************************************
Function VBOut(strPC,strTime)
Dim strComputerName 'Formatted computer name output string
Dim strLogonTime 'Formatted Last Logon Time output string
Dim DataOutArray(1) 'This array is used to format the output strings
'* Format computer name string
DataOutArray(0) = strPC
DataOutArray(1) = " "
strComputerName = Join(DataOutArray)
strComputerName = Left (strComputerName, 18)
'* Format Last Logon Time string
DataOutArray(0) = strTime
DataOutArray(1) = " "
strLogonTime = Join(DataOutArray)
strLogonTime = Left (strLogonTime, 24)
'* Write to output file
objFile.WriteLine strComputerName & " " & strLogonTime
End Function 'End of Script
Mark M. Webster
When people fear the government, there is tyranny. When government fears the people, there is liberty -Thomas Paine
|
Edited by - netmarcos on 12/17/2003 09:06:44 AM |
|
|
n/a
deleted
1 Posts
Status: offline |
Posted - 09/02/2003 : 2:50:17 PM
|
Hi -
I'm very new to scripting - and was wondering how to start this script off? Also, does this go out and query Each domain controller for it's time bias ? We have international locations as well so I am curious about that.
Thanks,
Tom
quote: Originally posted by netmarcos
There has been a lot of discussion surrounding this issue. The script below is the result of the combined effort of several people.
'******************************************************************* ' ADWorkstationLastLogon.vbs ' VBScript to determine when each computer in the domain ' lastlogged on. ' ' ------------------------------------------------------------------ ' Copyright (c) 2002 Richard L. Mueller ' Version 1.2 - January 23, 2003 ' Modified - March 4, 2003 Kevin Buley ' - Added output lines to show that the script is processing ' (DC name, # x of y) ' Modified March 5, 2003 Mark M. Webster ' - Modified output to be fixed width for import ' - Made several structural modifications and ' additional comments ' ' Because the LastLogon attribute is not replicated, every Domain Controller ' in the domain must be queried to find the latest LastLogon date for each ' computer. The lastest date found is kept in a dictionary object. The ' program first uses ADO to search the domain for all Domain Controllers. ' The AdsPath of each Domain Controller is saved in an array. Then, for each ' Domain Controller, ADO is used to search the copy of Active Directory on ' that Domain Controller for all computer objects and return the LastLogon ' attribute. The LastLogon attribute is a 64-bit number representing the ' number of 100 nanosecond intervals since 12:00 am January 1, 1601. This ' value is converted to a date. The last logon date is in UTC (Coordinated ' Univeral Time). It must be adjusted by the Time Zone bias in the machine ' registry to convert to local time. ' ' You have a royalty-free right to use, modify, reproduce, and distribute ' this script file in any way you find useful, provided that you agree ' that the copyright owner above has no warranty, obligations, or liability ' for such use. '************************************************************************************************
Option Explicit
Const ForAppending = 8
Dim k Dim sDCs() 'Dynamic array to hold the path for all DCs Dim BiasKey 'Active Time Bias from Registry Dim Bias 'Time Bias Dim strAdsPath 'Machine account DN Dim strDate 'Date output string Dim sDate 'Local machine current date Dim lngDate 'LastLogon date Dim strTime 'Local machine current time Dim strLDate 'Local machine current date and time Dim objList 'Dictionary object to track latest LastLogon for each computer Dim objRoot 'RootDSE object Dim strConfig 'Configuration Naming Context Dim objDC 'Domain Controller Dim strDNSDomain 'Default nameing context Dim strComputer 'Computer object Name Dim objConnection 'ADO conection Dim objCommand 'ADO command Dim objRecordSet 'Object to hold attributes from AD Dim oWshShell 'Windows shell script Dim objFSO 'File System object Dim objFile 'File object used to open text file for output Dim objLastLogon 'Last Logon Long Integer attribute Dim strFilePath 'Path to current directory
Set oWshShell = CreateObject("Wscript.Shell") Set objFSO = CreateObject("Scripting.FileSystemObject") strFilePath = objFSO.GetAbsolutePathName(".")
sDate = Date strTime = Now StrLDate = DatePart("m",sDate) & "." & DatePart("d",sDate) & "." & Hour(strTime) & "." & Minute(strTime) Set objFile = objFSO.OpenTextFile (strFilePath & "\DomainLastLogon." & strLDate & ".log",ForAppending,True)
'* Use a dictionary object to track latest LastLogon for each computer.
Set objList = CreateObject("Scripting.Dictionary") objList.CompareMode = vbTextCompare
'* Obtain local Time Zone bias from machine registry.
BiasKey = oWshShell.RegRead("HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias") If UCase(TypeName(BiasKey)) = "LONG" Then Bias = BiasKey ElseIf UCase(TypeName(BiasKey)) = "VARIANT()" Then Bias = 0 For k = 0 To UBound(BiasKey) Bias = Bias + (BiasKey(k) * 256^k) Next End If
'* Determine configuration context and DNS domain from RootDSE object.
Set objRoot = GetObject("LDAP://RootDSE") strConfig = objRoot.Get("ConfigurationNamingContext") strDNSDomain = objRoot.Get("DefaultNamingContext")
'* Use ADO to search Active Directory for ObjectClass nTDSDSA. '* This will identify all Domain Controllers.
Set objCommand = CreateObject("ADODB.Command") Set objConnection = CreateObject("ADODB.Connection") objConnection.Provider = "ADsDSOObject" objConnection.Open = "Active Directory Provider" objCommand.ActiveConnection = objConnection
objCommand.CommandText = "<LDAP://" & strConfig & ">;(ObjectClass=nTDSDSA);AdsPath;subtree" objCommand.Properties("Page Size") = 100 objCommand.Properties("Timeout") = 30 objCommand.Properties("Searchscope") = 2 objCommand.Properties("Cache Results") = False
Set objRecordSet = objCommand.Execute
'* Enumerate parent objects of class nTDSDSA. Save Domain Controller '* AdsPaths in dynamic array sDCs.
k = 0 Do Until objRecordSet.EOF Set objDC = GetObject(GetObject(objRecordSet.Fields("AdsPath")).Parent) ReDim Preserve sDCs(k) sDCs(k) = objDC.DNSHostName k = k + 1 objRecordSet.MoveNext Loop
'* Retrieve LastLogon attribute for each computer on each Domain Controller.
For k = 0 To Ubound(sDCs) oWshShell.Popup "Checking 'lastlogon' at domain controller " & sDCs(k) & ". Controller " & k & " of " & Ubound(sDCs),2,"Checking",64
'******************************************************************* '* Modify this line for the base of your search path depending on your own AD implementation '******************************************************************* objCommand.CommandText = "<LDAP://" & sDCs(k) & "/OU=Workstations," & strDNSDomain & ">;(ObjectCategory=computer);Name,LastLogon;subtree" On Error Resume Next Err.Clear Set objRecordSet = objCommand.Execute If Err.Number <> 0 Then Err.Clear On Error GoTo 0 oWshShell.Popup "Domain Controller not available: " & sDCs(k),2,"Notice",48 Else On Error GoTo 0 Do Until objRecordSet.EOF strAdsPath = objRecordSet.Fields("Name") strDate = objRecordSet.Fields("LastLogon") On Error Resume Next Err.Clear Set lngDate = strDate If Err.Number <> 0 Then Err.Clear strDate = #1/1/1601# Else If (lngDate.HighPart = 0) And (lngDate.LowPart = 0 ) Then strDate = #1/1/1601# Else strDate = #1/1/1601# + (((lngDate.HighPart * (2 ^ 32)) + lngDate.LowPart)/600000000 - Bias)/1440 End If End If On Error GoTo 0 If objList.Exists(strAdsPath) Then If strDate > objList(strAdsPath) Then objList(strAdsPath) = strDate End If Else objList.Add strAdsPath, strDate End If objRecordSet.MoveNext Loop End If Next
'* Output latest LastLogon date for each computer.
For Each strComputer In objList
Call VBOut(strComputer,objList(strComputer))
Next
objFile.WriteBlankLines (3) objFile.Close
oWshShell.Popup "Output file " & strFilePath & "\DomainLastLogon." & strLDate & ".log created." & Chr(13)_ & " Script processing complete.",5,"Notice",64
'* Clean up.
Set objRoot = Nothing Set objConnection = Nothing Set objCommand = Nothing Set objRecordSet = Nothing Set objDC = Nothing Set lngDate = Nothing Set objList = Nothing Set oWshShell = Nothing
'******************************************************************* '* Function VBOut '* '* Format data and write to output file '* '*******************************************************************
Function VBOut(strPC,strTime)
Dim strComputerName 'Formatted computer name output string Dim strLogonTime 'Formatted Last Logon Time output string
Dim DataOutArray(1) 'This array is used to format the output strings
'* Format computer name string
DataOutArray(0) = strPC DataOutArray(1) = " " strComputerName = Join(DataOutArray) strComputerName = Left (strComputerName, 18)
'* Format Last Logon Time string
DataOutArray(0) = strTime DataOutArray(1) = " " strLogonTime = Join(DataOutArray) strLogonTime = Left (strLogonTime, 24)
'* Write to output file
objFile.WriteLine strComputerName & " " & strLogonTime
End Function
'End of Script
Mark M. Webster
When people fear the government, there is tyranny. When government fears the people, there is liberty -Thomas Paine
|
 |
|
|
netmarcos
Honorable But Hopeless Addict
    
USA
1891 Posts
Status: offline |
Posted - 09/03/2003 : 4:31:26 PM
|
I suppose that could be done, but this script evaluates the last logon time based on the local machine's time bias as a single point of comparison for all machines. The value returned is based on the Julian date, so it all works out to be the same. As for running it, make sure that you modify the query base ldap string for your domains, make sure that you are running this with an account that has sufficient access to the domain, and double click the little bugger. |
Mark M. Webster
Genius may have its limitations, but stupidity is not thus handicapped. - Elbert Hubbard
 |
 |
|
|
schmecky
Seasoned But Casual Onlooker

75 Posts
Status: offline |
Posted - 04/28/2004 : 1:04:05 PM
|
Just wanted to point out that this script also works perfectly for determining USER logon times/dates
Do a search and replace and change strcomputer with struser
and on line 139 change OU=Workstations to whatever OU the users are in and change ObjectCategory=computer to ObjectCategory=user
I was surprised that there wasn't any more tweaking.. works great! thanks again netmarcos!  |
TeleData Consulting, Inc. www.tdonline.com |
 |
|
|
netmarcos
Honorable But Hopeless Addict
    
USA
1891 Posts
Status: offline |
Posted - 04/28/2004 : 8:49:40 PM
|
| No sweat, but the user lastlogon attribute is replicated and, therefore, you could simplify the script to query a single DC. Same is true for computer accounts if you are running Server 2003. |
Mark M. Webster
Genius may have its limitations, but stupidity is not thus handicapped. - Elbert Hubbard
 |
 |
|
|
pappy2670
Welcome Newcomer
USA
5 Posts
Status: offline |
Posted - 07/20/2004 : 09:31:17 AM
|
| This script is not working for me. When I run the script it finds the names of my 3 DCs, but I get "Domain Controller not available" for each one. All the DCs are W2K server. I would appricate any help troubleshooting this. |
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 09/21/2004 : 11:11:41 AM
|
I'm having the same problem. Whenever I run the script I get the "Domain controller XXXYYY not available" message for each of my DCs. Any ideas? BTW I'm trying to use it to get the USER values and not computer values.
A little background - I have used several different scripts to try to get the lastlogon value for users in my AD infrastructure, but none of my scripts query all of the DCs. They only query one of the DCs and I get invalid results as the lastlogon attribute is not replicated in my Windows 2000 implementation. This script is exactly what I'm looking for, but I can't seem to get past the error message.
Any help is greatly appreciated!
Thanks.
|
 |
|
|
pappy2670
Welcome Newcomer
USA
5 Posts
Status: offline |
Posted - 09/21/2004 : 3:24:51 PM
|
| I was able to get past my my initial problem. I was not binding to AD corectly. The items I wanted to look at were in a container (cn) not and org. unit (ou). I now need to figure out how to query another layer down. Each department has an OU containing the users. The department OU has another OU in it for all the PCs in that department. I have not been able to get the script to look into OU's more thean one layer lower than the root. |
 |
|
|
netmarcos
Honorable But Hopeless Addict
    
USA
1891 Posts
Status: offline |
Posted - 09/21/2004 : 3:27:35 PM
|
There are, potentially, two causes for this that I have encountered. The first is based in having access rights to the domain. Ensure that yiou are running this script with full privileges on the domain, and second, double-check the path in this section '*******************************************************************
'* Modify this line for the base of your search path depending on your own AD implementation
'*******************************************************************
objCommand.CommandText = "<LDAP://" & sDCs(k) & "/OU=Workstations," & strDNSDomain & ">;(ObjectCategory=computer);Name,LastLogon;subtree"
It may be helpful to add a Wscript.echo "<LDAP://" & sDCs(k) & "/OU=Workstations," & strDNSDomain & ">;(ObjectCategory=computer);Name,LastLogon;subtree" to see just what is being passed to objCommand.execute. |
Mark M. Webster
Genius may have its limitations, but stupidity is not thus handicapped. - Elbert Hubbard
 |
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 09/22/2004 : 1:50:53 PM
|
Thanks guys. I too have users in multiple OUs, but I think step one for me is getting the users from one OU returned. After that I can try to figure out the rest.
Here's what I see with the echo: <LDAP://dcname.domain.com/ou=users,OU=subOU,OU=subOU1,DC=company,DC=com>;(ObjectCategory=user);Name,LastLogon
Putting that in a web browser ends up giving me an invalid LDAP syntax message. Any ideas?
Again, your help is greatly appreciated.
|
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 09/23/2004 : 10:59:13 AM
|
OK I got it figured out - I had the domain listed twice. Its working now.
Any ideas on how I get it to return the AccountDisabled and Description fields as well (for users)?
Thanks again.
|
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 09/23/2004 : 11:17:53 AM
|
OK one more question (I promise). Like Pappy, I have my users located in more than one OU. We have them separated by country, so I'm looking for ou=users, ou=state, ou=NA for North America, and ou=users, ou=locale, ou=EU for Europe, etc. How can I get the script to query each OU as it cycles through the DCs?
Thanks! |
 |
|
|
netmarcos
Honorable But Hopeless Addict
    
USA
1891 Posts
Status: offline |
Posted - 09/23/2004 : 2:27:06 PM
|
Well, there are several possible approaches to this problem. The most basic solution would be to adjust the search path to the root of your OU structure and have it search the entire domain for accounts. Less desirable, but also effective would be to duplicate the section within the For k = 0 To Ubound(sDCs)...Nextloop for each context that you want to search. Third would be to run the sucker for each set of UOs that you wish to search, modifying the path each time.
Oh BTW: to add the Description - or any other field - create a variant (Dim sDesc) and then change this line ">;(ObjectCategory=user);Name,LastLogon,Description;subtree" and add sDesc = objRecordSet.Fields("Description") and then don't forget to add that to your output string.
As for disabled users, you need to collect userAccountControl. Some typical values include 512-enabled, 544-change password at logon, 514-disabled.
|
Mark M. Webster
Genius may have its limitations, but stupidity is not thus handicapped. - Elbert Hubbard
 |
Edited by - netmarcos on 09/23/2004 2:41:39 PM |
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 09/23/2004 : 3:53:06 PM
|
Thanks!
I'm trying your second suggestion now. I did try yesterday to go from the root using dc=company,dc=com and searching that for all user accounts, but it timed-out after about an hour.
Thanks again for you help. You're a lifesaver.
|
 |
|
|
pappy2670
Welcome Newcomer
USA
5 Posts
Status: offline |
Posted - 09/23/2004 : 5:29:11 PM
|
I'm still beating my head against the wall. I still cannot go more than 1 level deep. I replace "/OU=Workstations" the the name of one of my OU's (like Finance) and all is well. What should the syntax be to look in "Finance_PC_OU" which is in the Finance OU?
Thanx... |
 |
|
|
pappy2670
Welcome Newcomer
USA
5 Posts
Status: offline |
Posted - 09/24/2004 : 12:12:53 PM
|
| OK - I figured out my problem, I had the ou's in the path in the wrong order. I have been working blind and just guessing at what to do. Thanks to everyone for the help. |
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 09/24/2004 : 6:44:37 PM
|
After adding the Description field I now get a stop error on the following line:
Call VBOut(struser,objList(struser))
Any ideas?
Thanks! |
 |
|
|
photoquality
Welcome Newcomer
2 Posts
Status: offline |
Posted - 10/06/2004 : 5:24:09 PM
|
If you are in a large enterprise, or you have DC's that are on the other side of a slow link you may have issues.
If you log how many records each DC returns, some may return 0. This is because the timeout is 30 seconds (the default posted in most MS code examples). If you change this number to a larger number you will find great success.
objCommand.Properties("Timeout") = 30
I have changed it to 1060. You can use whatever your tolerance is. With the increased timeout I received 100% replies from over 100 DC's. At 30, I got about a 55% reply rate.
objCommand.Properties("Timeout") = 1060
|
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 10/14/2004 : 11:23:19 AM
|
Thanks.
I can succesfully get to all the DCs with just the 2 default attributes listed in the script, but when I try to add the Description attribute (which I really need) the script faults at the ilne mentioned above. Here's what I have:
Set objRecordSet = objCommand.Execute If Err.Number <> 0 Then Err.Clear On Error GoTo 0 oWshShell.Popup "Domain Controller not available: " & sDCs(k),2,"Notice",48 Else On Error GoTo 0 Do Until objRecordSet.EOF strAdsPath = objRecordSet.Fields("Name") strDate = objRecordSet.Fields("LastLogon") strDesc = objRecordSet.Fields("Description") On Error Resume Next Err.Clear Set lngDate = strDate If Err.Number <> 0 Then Err.Clear strDate = #1/1/1601# Else If (lngDate.HighPart = 0) And (lngDate.LowPart = 0 ) Then strDate = #1/1/1601# Else strDate = #1/1/1601# + (((lngDate.HighPart * (2 ^ 32)) + lngDate.LowPart)/600000000 - Bias)/1440 End If End If On Error GoTo 0 If objList.Exists(strAdsPath) Then If strDate > objList(strAdsPath) Then objList(strAdsPath) = strDate End If Else objList.Add strAdsPath, strDate End If objRecordSet.MoveNext Loop End If Next
'* Output latest LastLogon date for each computer.
For Each struser In objList
Call VBOut(struser,objList(struser))
Next
objFile.WriteBlankLines (3) objFile.Close
oWshShell.Popup "Output file " & strFilePath & "\DomainLastLogon." & strLDate & ".log created." & Chr(13)_ & " Script processing complete.",5,"Notice",64
'* Clean up.
Set objRoot = Nothing Set objConnection = Nothing Set objCommand = Nothing Set objRecordSet = Nothing Set objDC = Nothing Set lngDate = Nothing Set objList = Nothing Set oWshShell = Nothing
'******************************************************************* '* Function VBOut '* '* Format data and write to output file '* '*******************************************************************
Function VBOut(strPC,strTime,strDescription)
Dim struserName 'Formatted computer name output string Dim strLogonTime 'Formatted Last Logon Time output string Dim strDescrip
Dim DataOutArray(2) 'This array is used to format the output strings
'* Format computer name string
DataOutArray(0) = strPC DataOutArray(2) = " " struserName = Join(DataOutArray) struserName = Left (struserName, 18)
'* Format Last Logon Time string
DataOutArray(0) = strTime DataOutArray(2) = " " strLogonTime = Join(DataOutArray) strLogonTime = Left (strLogonTime, 24)
DataOutArray(0) = strDescription DataOutArray(2) = " " strDescrip = Join(DataOutArray) strDescrip = Left (strDescrip, 30)
'* Write to output file
objFile.WriteLine struserName & " " & strLogonTime & " " & strDescrip
End Function
'End of Script |
 |
|
|
wkasdo
Moderator
    
Netherlands
6140 Posts
Status: offline |
Posted - 10/14/2004 : 11:27:08 AM
|
For the lucky people with a domain in 2003 native mode: dsquery computer -inactive 10 to search for computers that have not logged on for more than 10 weeks. |
 |
|
|
netmarcos
Honorable But Hopeless Addict
    
USA
1891 Posts
Status: offline |
Posted - 10/15/2004 : 2:15:51 PM
|
| Ya just gotta love progress! |
Mark M. Webster
Genius may have its limitations, but stupidity is not thus handicapped. - Elbert Hubbard
 |
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 10/18/2004 : 11:45:07 AM
|
Thanks.
Unfortunately we aren't running a 2003 environment. Here's the error I'm getting when running the script with the Description field added.
Line: 185 Char: 5 Error: Wrong number of arguments or invalid property assignment Code: 800A01C2
Here's the code. Line 185 is the line that starts with "Call VBOut(struser,objList(struser,strDesc)) " --------------------
For Each struser In objList
Call VBOut(struser,objList(struser,strDesc))
Next
objFile.WriteBlankLines (3) objFile.Close
oWshShell.Popup "Output file " & strFilePath & "\DomainLastLogon." & strLDate & ".log created." & Chr(13)_ & " Script processing complete.",5,"Notice",64
'* Clean up.
Set objRoot = Nothing Set objConnection = Nothing Set objCommand = Nothing Set objRecordSet = Nothing Set objDC = Nothing Set lngDate = Nothing Set objList = Nothing Set oWshShell = Nothing
'******************************************************************* '* Function VBOut '* '* Format data and write to output file '* '*******************************************************************
Function VBOut(strPC,strTime,strDescription)
Dim struserName 'Formatted computer name output string Dim strLogonTime 'Formatted Last Logon Time output string Dim strDescrip
Dim DataOutArray(2) 'This array is used to format the output strings
'* Format computer name string
DataOutArray(0) = strPC DataOutArray(2) = " " struserName = Join(DataOutArray) struserName = Left (struserName, 18)
'* Format Last Logon Time string
DataOutArray(0) = strTime DataOutArray(2) = " " strLogonTime = Join(DataOutArray) strLogonTime = Left (strLogonTime, 24)
DataOutArray(0) = strDescription DataOutArray(2) = " " strDescrip = Join(DataOutArray) strDescrip = Left (strDescrip, 30)
'* Write to output file
objFile.WriteLine struserName & " " & strLogonTime & " " & strDescrip
End Function
'End of Script |
 |
|
|
imakfu
Welcome Newcomer
9 Posts
Status: offline |
Posted - 10/18/2004 : 5:20:13 PM
|
OK I throw in the towel. I don't have the mental "know how" to get this done. For the life of me I can't seem to get this script to return the Description field in the results. Nothing I have done gives me valid results, I simply get one error after the other.
Thanks to all who offered advice. |
 |
|
|
scripter101
Welcome Newcomer
USA
1 Posts
Status: offline |
Posted - 10/19/2004 : 3:00:19 PM
|
I'm getting a similar message as others. I'm tring to add the computer description to the log file but I keep getting the following error:
Error: Wrong number of arguments or invalid property assignment
Does anybody have any ideas on how to do this?
|
 |
|
|
dsmith1180
Welcome Newcomer
1 Posts
Status: offline |
Posted - 10/27/2004 : 7:24:18 PM
|
| This code is awesome , just used. May I ask how the code could be modified to allow an helpdesk tech to be prompted for a particular user they are looking for. anotherwords how could a user prompt be built into this to ask for a single username and output the login time for a single user? This would be great to use for verifying when users last logged on, esp those who fib about rebooting! |
 |
|
|
netmarcos
Honorable But Hopeless Addict
    
USA
1891 Posts
Status: offline |
Posted - 10/28/2004 : 11:06:09 AM
|
I suppose that you could do this by adding a variant(strName)for the computer name using an Inputbox to prompt for the value and modify the line that reads objCommand.CommandText = "<LDAP://" & sDCs(k) & "/OU=Workstations," & strDNSDomain & ">;(ObjectCategory=computer);Name,LastLogon;subtree" by adding an additional property to the search criteria objCommand.CommandText = "<LDAP://" & sDCs(k) & "/OU=Workstations," & strDNSDomain & ">;(ObjectCategory=computer)(Name=" & strName & ");Name,LastLogon;subtree"
For user lookup objCommand.CommandText = "<LDAP://" & sDCs(k) & "/OU=Accounts," & strDNSDomain & ">;(ObjectCategory=user)(samAccountName=" & strName & ");Name,LastLogon;subtree"
|
Mark M. Webster
Genius may have its limitations, but stupidity is not thus handicapped. - Elbert Hubbard
 |
Edited by - netmarcos on 10/28/2004 11:09:15 AM |
 |
|
|
aruiz
Welcome Newcomer
USA
1 Posts
Status: offline |
Posted - 11/18/2004 : 2:10:06 PM
|
Hi Guys,
I've been working on this script for a while and but still having trouble modifying:
objCommand.CommandText = "<LDAP://" & sDCs(k) & "/OU=Workstations," & strDNSDomain & ">;(ObjectCategory=computer);Name,LastLogon;subtree"
Can someone help with a clear example?
Thanks |
 |
|
|
pappy2670
Welcome Newcomer
USA
5 Posts
Status: offline |
Posted - 11/18/2004 : 3:30:48 PM
|
I had some problems as well. Make sure that "/OU=Workstations," reflects the name and type in your directory. In my case I had a container called Computers, so I used "/cn=computers, ". The OU (org unit) vs CN (container) thing threw me for a while so make sure you pick the correct one.
Good Luck. |
 |
|
|
photoquality
Welcome Newcomer
2 Posts
Status: offline |
Posted - 11/19/2004 : 3:03:30 PM
|
Here is a chunk of code that will give you the description w/o an error.
strdesc="" IF vartype(objRecordSet.Fields("Description")) > 8192 then strdesc=CSTR(JOIN(objRecordSet.Fields("Description"))) ELSEIF vartype(objRecordSet.Fields("Description")) = 1 then strdesc="No Description" ELSEIF vartype(objRecordSet.Fields("Description")) = 8 then strdesc=objRecordSet.Fields("Description") END IF
|
 |
|
|
Zeohwanz
Welcome Newcomer
1 Posts
Status: offline |
Posted - 01/04/2005 : 09:34:09 AM
|
Can anyone please let me know how to get rid of subtree support?
|
 |
|
|
Matricarus
Welcome Newcomer
1 Posts
Status: offline |
Posted - 04/28/2005 : 1:56:32 PM
|
Small mistake. Here's how to convert the LargeInteger to date format :
strDate = #1/1/1601# + (lngDate.highpart * 2^32 + lngDate.lowpart) / 864E9 - Bias / 1440
Hope this helps. Bye.
|
 |
|
Topic  |
|