Mark Minasi's Reader Forum
Mark Minasi's Reader Forum
Home | Profile | Register | Active Topics | Active Polls | Members | Search | FAQ | Minasi Forum RSS Feed
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 Old, obsolete or unused
 Scripting Archive
 Last Logon Attribute for workstations
 New Topic  Reply to Topic
 Printer Friendly
Next Page
Author Previous Topic Topic Next Topic
Page: of 2

netmarcos
Honorable But Hopeless Addict

USA
2221 Posts
Status: offline

Posted - 05/27/2003 :  10:47:27 AM  Show Profile  Visit netmarcos's Homepage  Click to see netmarcos's MSN Messenger address  Look at the Skype phone address from netmarcos  Send netmarcos a Yahoo! Message  Reply with Quote
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  Show Profile  Reply with Quote
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


Go to Top of Page

netmarcos
Honorable But Hopeless Addict

USA
2221 Posts
Status: offline

Posted - 09/03/2003 :  4:31:26 PM  Show Profile  Visit netmarcos's Homepage  Click to see netmarcos's MSN Messenger address  Look at the Skype address for netmarcos  Send netmarcos a Yahoo! Message  Reply with Quote
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

Go to Top of Page

schmecky
Seasoned But Casual Onlooker

75 Posts
Status: offline

Posted - 04/28/2004 :  1:04:05 PM  Show Profile  Visit schmecky's Homepage  Reply with Quote
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
Go to Top of Page

netmarcos
Honorable But Hopeless Addict

USA
2221 Posts
Status: offline

Posted - 04/28/2004 :  8:49:40 PM  Show Profile  Visit netmarcos's Homepage  Click to see netmarcos's MSN Messenger address  Look at the Skype address for netmarcos  Send netmarcos a Yahoo! Message  Reply with Quote
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

Go to Top of Page

pappy2670
Welcome Newcomer

USA
5 Posts
Status: offline

Posted - 07/20/2004 :  09:31:17 AM  Show Profile  Reply with Quote
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.
Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 09/21/2004 :  11:11:41 AM  Show Profile  Reply with Quote
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.
Go to Top of Page

pappy2670
Welcome Newcomer

USA
5 Posts
Status: offline

Posted - 09/21/2004 :  3:24:51 PM  Show Profile  Reply with Quote
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.
Go to Top of Page

netmarcos
Honorable But Hopeless Addict

USA
2221 Posts
Status: offline

Posted - 09/21/2004 :  3:27:35 PM  Show Profile  Visit netmarcos's Homepage  Click to see netmarcos's MSN Messenger address  Look at the Skype address for netmarcos  Send netmarcos a Yahoo! Message  Reply with Quote
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

Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 09/22/2004 :  1:50:53 PM  Show Profile  Reply with Quote
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.
Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 09/23/2004 :  10:59:13 AM  Show Profile  Reply with Quote
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.
Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 09/23/2004 :  11:17:53 AM  Show Profile  Reply with Quote
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!
Go to Top of Page

netmarcos
Honorable But Hopeless Addict

USA
2221 Posts
Status: offline

Posted - 09/23/2004 :  2:27:06 PM  Show Profile  Visit netmarcos's Homepage  Click to see netmarcos's MSN Messenger address  Look at the Skype address for netmarcos  Send netmarcos a Yahoo! Message  Reply with Quote
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
Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 09/23/2004 :  3:53:06 PM  Show Profile  Reply with Quote
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.

Go to Top of Page

pappy2670
Welcome Newcomer

USA
5 Posts
Status: offline

Posted - 09/23/2004 :  5:29:11 PM  Show Profile  Reply with Quote
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...
Go to Top of Page

pappy2670
Welcome Newcomer

USA
5 Posts
Status: offline

Posted - 09/24/2004 :  12:12:53 PM  Show Profile  Reply with Quote
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.
Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 09/24/2004 :  6:44:37 PM  Show Profile  Reply with Quote
After adding the Description field I now get a stop error on the following line:

Call VBOut(struser,objList(struser))

Any ideas?

Thanks!
Go to Top of Page

photoquality
Welcome Newcomer

2 Posts
Status: offline

Posted - 10/06/2004 :  5:24:09 PM  Show Profile  Reply with Quote
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
Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 10/14/2004 :  11:23:19 AM  Show Profile  Reply with Quote
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
Go to Top of Page

wkasdo
Administrator

Netherlands
7424 Posts
Status: offline

Posted - 10/14/2004 :  11:27:08 AM  Show Profile  Click to see wkasdo's MSN Messenger address  Reply with Quote
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.

Make it as simple as you can, but not simpler -- Albert Einstein
Go to Top of Page

netmarcos
Honorable But Hopeless Addict

USA
2221 Posts
Status: offline

Posted - 10/15/2004 :  2:15:51 PM  Show Profile  Visit netmarcos's Homepage  Click to see netmarcos's MSN Messenger address  Look at the Skype address for netmarcos  Send netmarcos a Yahoo! Message  Reply with Quote
Ya just gotta love progress!

Mark M. Webster

Genius may have its limitations, but stupidity is not thus handicapped. - Elbert Hubbard

Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 10/18/2004 :  11:45:07 AM  Show Profile  Reply with Quote
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
Go to Top of Page

imakfu
Welcome Newcomer

9 Posts
Status: offline

Posted - 10/18/2004 :  5:20:13 PM  Show Profile  Reply with Quote
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.
Go to Top of Page

scripter101
Welcome Newcomer

USA
1 Posts
Status: offline

Posted - 10/19/2004 :  3:00:19 PM  Show Profile  Reply with Quote
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?

Go to Top of Page

dsmith1180
Welcome Newcomer

1 Posts
Status: offline

Posted - 10/27/2004 :  7:24:18 PM  Show Profile  Reply with Quote
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!
Go to Top of Page

netmarcos
Honorable But Hopeless Addict

USA
2221 Posts
Status: offline

Posted - 10/28/2004 :  11:06:09 AM  Show Profile  Visit netmarcos's Homepage  Click to see netmarcos's MSN Messenger address  Look at the Skype address for netmarcos  Send netmarcos a Yahoo! Message  Reply with Quote
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
Go to Top of Page

aruiz
Welcome Newcomer

USA
1 Posts
Status: offline

Posted - 11/18/2004 :  2:10:06 PM  Show Profile  Reply with Quote
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
Go to Top of Page

pappy2670
Welcome Newcomer

USA
5 Posts
Status: offline

Posted - 11/18/2004 :  3:30:48 PM  Show Profile  Reply with Quote
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.
Go to Top of Page

photoquality
Welcome Newcomer

2 Posts
Status: offline

Posted - 11/19/2004 :  3:03:30 PM  Show Profile  Reply with Quote
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
Go to Top of Page

Zeohwanz
Welcome Newcomer

1 Posts
Status: offline

Posted - 01/04/2005 :  09:34:09 AM  Show Profile  Reply with Quote
Can anyone please let me know how to get rid of subtree support?
Go to Top of Page

Matricarus
Welcome Newcomer

1 Posts
Status: offline

Posted - 04/28/2005 :  1:56:32 PM  Show Profile  Reply with Quote
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.
Go to Top of Page
Page: of 2 Previous Topic Topic Next Topic  
Next Page
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
Mark Minasi's Reader Forum © 2002-2011 Mark Minasi Go To Top Of Page
This page was generated in 0.27 seconds. Snitz Forums 2000