none
Erro - Lista todos usuários do AD 2003 e último logon em txt RRS feed

  • Pergunta

  • Bom dia Pessoal,

     

    Se alguém souber pode me ajudar com o problema abaixo?

     

    Estou criando um Script para buscar todos os usuários do AD 2003 e seus úlitmos Logons e exportar para um TXT, estou com o script abaixo e está me apresentando um erro na linha ,    Set objLogon = objUser.Get("lastLogonTimeStamp")  erro : The directory property cannot be found in the cache   Code: 8000500D.

     

     

    Option Explicit

    Const ADS_SCOPE_SUBTREE = 2

    Dim objRootDSE
    Dim objConnection, objCommand, objRecordSet, objFSO, objFolder, objShell, objTextFile, objFile, strSheet, objExcel, objSpread, data, horario
    Dim UserDN, objUser, strDNSDomain, strQuery, strDirectory, strFile, strText
    Dim objLogon, strWeeks, strDays, intLogonTime, strCN, strUserDN, strAcao
    Dim intLLTS, intReqCompare

    data = replace(date(),"/","")
    horario = replace(time(),":","")


    strDirectory = "c:\ADScripts\ConsultaUsuáriosBase\UsuariosBaseAD\"
    strFile = data +"_" + horario + ".txt"


    ' Determine DNS domain name from RootDSE object.
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")


    ' Create the File System Object
    Set objFSO = CreateObject("Scripting.FileSystemObject")

    ' Check that the strDirectory folder exists
    If objFSO.FolderExists(strDirectory) Then
       Set objFolder = objFSO.GetFolder(strDirectory)
    Else
       Set objFolder = objFSO.CreateFolder(strDirectory)
       WScript.Echo "Just created " & strDirectory
    End If

    ' Note If..Exists. Then, Else ... End If construction
    If objFSO.FolderExists(strDirectory) Then
       Set objFolder = objFSO.GetFolder(strDirectory)
       WScript.Echo strDirectory & " already created "
    Else
       Set objFolder = objFSO.CreateFolder(strDirectory)
    WScript.Echo "Just created " & strDirectory
    End If


    set objFile = nothing
    set objFolder = nothing
    ' OpenTextFile Method needs a Const value
    'ForAppending = 8 ForReading = 1, ForWriting = 2
    Const ForAppending = 8

    Set objTextFile = objFSO.OpenTextFile _
    (strDirectory & strFile, ForAppending, True)

     

    ' Use ADO to search Active Directory for all Users.

    Set objConnection      = CreateObject("ADODB.Connection")
    Set objCommand         = CreateObject("ADODB.Command")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    Set objCommand.ActiveConnection = objConnection

    objCommand.Properties("Page Size") = 1000
    objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE

    strQuery = "SELECT distinguishedName FROM 'LDAP://" & strDNSDomain & "' WHERE objectCategory = 'User'"

    objCommand.CommandText = strQuery
    Set objRecordSet = objCommand.Execute


    objRecordSet.MoveFirst
    Do Until objRecordSet.EOF
       UserDN = objRecordSet.Fields("distinguishedName").Value
       Set objUser = GetObject("LDAP://" & UserDN)

       ' Begin calculation

       Set objLogon = objUser.Get("lastLogonTimeStamp")
       intLogonTime = objLogon.HighPart * (2^32) + objLogon.LowPart
       intLogonTime = intLogonTime / (60 * 10000000)
       intLogonTime = intLogonTime / 1440
       intLLTS = intLogonTime + #1/1/1601#
       strDays = strWeeks * 7
       intReqCompare = Now - strDays
       If intLLTS < intReqCompare Then
                      objTextFile.WriteLine(objUser.Name) & ";" & intLLTS
       End If

       objRecordSet.MoveNext
    Loop
    WScript.Quit

     

     

     

    Podem me ajudar por gentileza??

     

    Obrigado pessoal!

    segunda-feira, 25 de fevereiro de 2008 12:12

Respostas

  • Diego, mil perdões te passei um script errado, esse aqui que funciona

     

    Dim objRootDSE, strConfig, adoConnection, adoCommand, strQuery
    Dim adoRecordset, objDC
    Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
    Dim strDN, dtmDate, objDate, objList, strUser
    Dim strBase, strFilter, strAttributes, lngHigh, lngLow

    set objFSO = CreateObject("scripting.FilesystemObject")
    set arq = OBjFSO.CreateTextFile("C:\LastLogon.txt",2)
    arq.close
    Set arquivo = objFSO.OpenTextFile("C:\LastLogon.txt", 8)

     

    Set objList = CreateObject("Scripting.Dictionary")
    objList.CompareMode = vbTextCompare

     

    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

     

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strConfig = objRootDSE.Get("configurationNamingContext")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")

     

    Set adoCommand = CreateObject("ADODB.Command")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"
    adoCommand.ActiveConnection = adoConnection

    strBase = "<LDAP://" & strConfig & ">"
    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

     

    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

     

    For k = 0 To Ubound(arrstrDCs)
        strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
        strFilter = "(&(objectCategory=person)(objectClass=user))"
        strAttributes = "sAMAccountName,lastLogon"
        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
                strDN = adoRecordset.Fields("sAMAccountName").Value
                On Error Resume Next
                Set objDate = adoRecordset.Fields("lastLogon").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 (objList.Exists(strDN) = True) Then
                    If (dtmDate > objList(strDN)) Then
                        objList.Item(strDN) = dtmDate
                    End If
                Else
                 arquivo.writeline strDN & " " & dtmDate
                End If
                adoRecordset.MoveNext
            Loop
            adoRecordset.Close
        End If
    Next


     

    adoConnection.Close
    Set objRootDSE = Nothing
    Set adoConnection = Nothing
    Set adoCommand = Nothing
    Set adoRecordset = Nothing
    Set objDC = Nothing
    Set objDate = Nothing
    Set objList = Nothing
    Set objShell = Nothing

    ele salva o arquivo  LastLogon.txt no C: Wink

     

    ps: quanto aos eu script, parece ser problema com cache, vou dar uma olhada melhor nele depois, testei ele com 1000 usuários e realmente deu problema, espero te retornar o problema logo Wink

    terça-feira, 26 de fevereiro de 2008 22:42
  • É Laerte...

    Tem forças do mal agindo contra mim, heauheauaeh....

    No seu códio faltava apenas um End IF, coloquei e segue abaixo, como o anteiror, na VM funciona perfeitamente, inclusive neste abaixo ele busca já o nome do usuário e o campo UserAccountControl, que eu estava pensando em usar para tentar determinar se o usuário está ativo ou não, porém no ambiente de produção ele continua pegando lixo dos últimos 5 logons + data default (como se nunca tivesse logado), o pior é que ele não pega na ordem exata dos últimos logons, caso fosse eu podia pegar e validar se o usuário já existisse na lista para descartar, porém ele pega a sequencia aleatória dos últimos logons.

    Tá dificil imaginar onde está o problema, realmente é muito estranho.

    Não sei se você tem outra idéia de correção, porém de qualquer maneira até o momento muitissimo obrigado pela ajuda.

     

     

     

    Dim objRootDSE, strConfig, adoConnection, adoCommand, strQuery
    Dim adoRecordset, objDC
    Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
    Dim strDN, dtmDate, objDate, objList, strUser, objUser,objNames
    Dim strBase, strFilter, strAttributes, lngHigh, lngLow

    set objFSO = CreateObject("scripting.FilesystemObject")
    set arq = OBjFSO.CreateTextFile("C:\LastLogon.txt",2)
    arq.close
    Set arquivo = objFSO.OpenTextFile("C:\LastLogon.txt", 8)

     

    Set objList = CreateObject("Scripting.Dictionary")
    objList.CompareMode = vbTextCompare

    strDN = ""

    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

     

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strConfig = objRootDSE.Get("configurationNamingContext")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")

     

    Set adoCommand = CreateObject("ADODB.Command")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"
    adoCommand.ActiveConnection = adoConnection

    strBase = "<LDAP://" & strConfig & ">"
    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

     

    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

     

    For k = 0 To Ubound(arrstrDCs)
        strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
        strFilter = "(&(objectCategory=person)(objectClass=user))"
        strAttributes = "sAMAccountName,lastLogon,CN,UserAccountControl"
        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

            If strDN = adoRecordset.Fields("sAMAccountName").Value then

                       adoRecordset.MoveNext
            Else
                strDN = adoRecordset.Fields("sAMAccountName").Value
                On Error Resume Next
                Set objDate = adoRecordset.Fields("lastLogon").Value
                objNames = adoRecordset.Fields("CN").Value
                objStatus = adoRecordset.Fields("UserAccountControl").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 (objList.Exists(strDN) = True) Then
                    If (dtmDate > objList(strDN)) Then
                        objList.Item(strDN) = dtmDate
                    End If
                Else
                 arquivo.writeline strDN & ";" & objNames & ";" & dtmDate & ";" & objStatus
                End If
                adoRecordset.MoveNext
            End If
            Loop
            adoRecordset.Close
        End If
    Next


     

    adoConnection.Close
    Set objRootDSE = Nothing
    Set adoConnection = Nothing
    Set adoCommand = Nothing
    Set adoRecordset = Nothing
    Set objDC = Nothing
    Set objDate = Nothing
    Set objList = Nothing
    Set objShell = Nothing


     

    quarta-feira, 5 de março de 2008 10:32

Todas as Respostas

  • Diego, ainda não tive tempo de verificar o seu script, mas se estiver com pressa, pode usar esse aqui: Wink, vou ver se amanhã consigo olhar seu script

     

    Dim objRootDSE, strConfig, adoConnection, adoCommand, strQuery
    Dim adoRecordset, objDC
    Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
    Dim strDN, dtmDate, objDate, objList, strUser
    Dim strBase, strFilter, strAttributes, lngHigh, lngLow

    dim usuarios()
    i = 0

    Set objList = CreateObject("Scripting.Dictionary")
    objList.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

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strConfig = objRootDSE.Get("configurationNamingContext")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")

     

    Set adoCommand = CreateObject("ADODB.Command")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"
    adoCommand.ActiveConnection = adoConnection

    strBase = "<LDAP://" & strConfig & ">"
    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

     

     

    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

     

    For k = 0 To Ubound(arrstrDCs)
        strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
        strFilter = "(&(objectCategory=person)(objectClass=user))"
        strAttributes = "sAMAccountName,lastLogon"
        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
                strDN = adoRecordset.Fields("sAMAccountName").Value
                On Error Resume Next
                Set objDate = adoRecordset.Fields("lastLogon").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 (objList.Exists(strDN) = True) Then
                    If (dtmDate > objList(strDN)) Then
                        objList.Item(strDN) = dtmDate
                    End If
                Else
                     Redim Preserve usuarios(i)
                      usuarios(i) = strDN
                      i = i + 1
                End If
                adoRecordset.MoveNext
            Loop
            adoRecordset.Close
        End If
    Next
    Set ObjFSO = CreateObject("scripting.FileSystemObject")
    Set objfile = objFSO.Createtextfile("C:\Last_Logon.txt",2)
    objfile.close

    Set objfile = Objfso.OpentextFile("C:\LastLogon.txt",8)

    for j = 0 to i -1
       objfile.writeline usuarios(j) & " " & dtmDate
    next
    objfile.close

     

    ' Clean up.
    adoConnection.Close
    Set objRootDSE = Nothing
    Set adoConnection = Nothing
    Set adoCommand = Nothing
    Set adoRecordset = Nothing
    Set objDC = Nothing
    Set objDate = Nothing
    Set objList = Nothing
    Set objShell = Nothing

    segunda-feira, 25 de fevereiro de 2008 21:35
  • Obrigado Laerte!

     

    Meu script passou a funcionar no ambiente de testes, com 50 usuários, porém não funciona em produção, cerca de 50mil usuários, sabe o problema?

     

    Seu script está apresentando um erro na linha 18 char 35 , "LONG", esta VM do ambiente possui o AD 2000, será que é um problema com falta de comandos para este erro no seu script? pois ele reporta syntax error.

    Obrigado novamente rapaz.

     

    terça-feira, 26 de fevereiro de 2008 11:11
  • Diego, mil perdões te passei um script errado, esse aqui que funciona

     

    Dim objRootDSE, strConfig, adoConnection, adoCommand, strQuery
    Dim adoRecordset, objDC
    Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
    Dim strDN, dtmDate, objDate, objList, strUser
    Dim strBase, strFilter, strAttributes, lngHigh, lngLow

    set objFSO = CreateObject("scripting.FilesystemObject")
    set arq = OBjFSO.CreateTextFile("C:\LastLogon.txt",2)
    arq.close
    Set arquivo = objFSO.OpenTextFile("C:\LastLogon.txt", 8)

     

    Set objList = CreateObject("Scripting.Dictionary")
    objList.CompareMode = vbTextCompare

     

    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

     

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strConfig = objRootDSE.Get("configurationNamingContext")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")

     

    Set adoCommand = CreateObject("ADODB.Command")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"
    adoCommand.ActiveConnection = adoConnection

    strBase = "<LDAP://" & strConfig & ">"
    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

     

    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

     

    For k = 0 To Ubound(arrstrDCs)
        strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
        strFilter = "(&(objectCategory=person)(objectClass=user))"
        strAttributes = "sAMAccountName,lastLogon"
        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
                strDN = adoRecordset.Fields("sAMAccountName").Value
                On Error Resume Next
                Set objDate = adoRecordset.Fields("lastLogon").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 (objList.Exists(strDN) = True) Then
                    If (dtmDate > objList(strDN)) Then
                        objList.Item(strDN) = dtmDate
                    End If
                Else
                 arquivo.writeline strDN & " " & dtmDate
                End If
                adoRecordset.MoveNext
            Loop
            adoRecordset.Close
        End If
    Next


     

    adoConnection.Close
    Set objRootDSE = Nothing
    Set adoConnection = Nothing
    Set adoCommand = Nothing
    Set adoRecordset = Nothing
    Set objDC = Nothing
    Set objDate = Nothing
    Set objList = Nothing
    Set objShell = Nothing

    ele salva o arquivo  LastLogon.txt no C: Wink

     

    ps: quanto aos eu script, parece ser problema com cache, vou dar uma olhada melhor nele depois, testei ele com 1000 usuários e realmente deu problema, espero te retornar o problema logo Wink

    terça-feira, 26 de fevereiro de 2008 22:42
  • Caraca Laerte...

     

    Script muito bom.... Vc é f.....( no bom sentido)

     

    Perfeito, exatamente  o que eu precisava, porém quando tiver um tempinho se puder verificar o que acontecia no script que eu postei eu agradeço, assim quem sabe eu aprendo, hehe...

     

    Obrigado novamente!!!

     

    quarta-feira, 27 de fevereiro de 2008 10:53
  • Beleza, Diego sem problemas, que bom que te ajudou, qualquer coisa é só postar um tópico que tentaremos ajudar e quanto ao seu script vou tentar dar uma olhada assim que possivel e te retorno Wink

     

    quarta-feira, 27 de fevereiro de 2008 20:28
  •  

    Laerte....

     

    Estou zicado mesmo....

     

    Cara qndo analisei seu script havia colocado para rodar na VM, com os 50 usuários, funcionou perfeitamente.

     

    Quando coloco na Produção, 50k usuários ele aparece os logins 6 vezes e com 6 datas de ultimos logons diferentes....

    Num faço a menor ideia do que esta acontecendo....já viu isso?

    Sendo que uma das datas de último logon para todos usuários é a data de 01/01/1601.....

    Dados retirados do TXT no meu login.

     

    dgonzales 28/02/2008 06:05:26

    dgonzales 27/02/2008 11:37:49

    dgonzales 27/02/2008 15:58:28

    dgonzales 27/02/2008 11:37:49

    dgonzales 20/02/2008 10:26:12

    dgonzales 01/01/1601

     

     

    Obrigado novamente .......

    quinta-feira, 28 de fevereiro de 2008 09:56
  • Diego para todos os usuários aparece dessa forma, multiplicado por 6? muito estranho tenho que ver se o problema está em uma base com muitos usuários, pois testei aqui com uma base de 1000 e não repetiu nada.

     

    quinta-feira, 28 de fevereiro de 2008 16:31
  • Laerte,

     

    Sim, o pior é que todos tem 6 horários diferentes de last logon sendo que 1 deles é sempre a data 01/01/1601, se por acaso todos registrassem a data do logon correta um simples filtro me ajudaria, porém desta maneira não consigo acesso a informação correta....

    Engraçado é que na VM que temos para teste também funciona perfeitamente.....somente no ambiente de produção que ocorre o erro......já verifiquei as OUs para ver se havia mais que uma OU replicando o login...e nada feito...está tudo certinho.....

    inclusive os scripts que temos de reset e bloqueio funcionam normalmente e não apresentam erros referenet a usuários supostamente "duplicados" (que é impossivel)..

    sexta-feira, 29 de fevereiro de 2008 10:51
  • Diego,e ntão existem 300k de entradas na sua lista, mas me diz uma coisa, você loga em mais de um computador, e veja se com o seu login as datas de últimos logins estão batendo, acho bem estranho isso está acontecendo, será que ele tá pegando lixo? acho meio dificil

     

    sexta-feira, 29 de fevereiro de 2008 12:39
  •  

    Laerte..

    Estão aparecendo quase 300mil usuários, sendo que tenho quase 50mil...ou seja realmente está multiplicando todos por 6, o login que postei anteriormente com as 6 datas de ultimos logins diferentes é do meu login, por isso tenho certeza que está gerando errado, não teria como ele jogar meu login com data de 1/1/1601 e depois 5 datas recentes, ele ta pegando com certeza um lixo de algum lugar...e acredito que quando ele tenta fazer uma das buscas da um problema e ele fala que também nunca loguei...é bem loco esse "bug", hehe......

    logo apenas neste computador.....

    sexta-feira, 29 de fevereiro de 2008 14:49
  • Diego, muito estranho isso, ele realmente está pegando lixo, vou verificar o código aqui e vejo onde ele está fazendo esse loop 6 vezes.

    sexta-feira, 29 de fevereiro de 2008 19:16
  • Vlw mesmo cara....

     

    Eu não sou bom nisso, mais no pouco que conheço não encontrei esse bendito lugar...

     

    É muito estranho mesmo...

     

    No começo pensei que podia ser em relação ao acesso dos grupos que o usuário pertence, pois temos acesso a metaframe via grupos, porém consultei usuários que não tem e nunca se logaram no Metaframe e também tem este loop sendo repetido.

     

     

    sábado, 1 de março de 2008 12:02
  • Tentei efetuar algumas mudanças no código para tentar encontrar o lugar do BUG e nada.

     

    segunda-feira, 3 de março de 2008 09:06
  • Diego, fiz uma alteração no script não sei se vai funcionar pois não testei, veja se vai funcionar.

     

    Dim objRootDSE, strConfig, adoConnection, adoCommand, strQuery
    Dim adoRecordset, objDC
    Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
    Dim strDN, dtmDate, objDate, objList, strUser
    Dim strBase, strFilter, strAttributes, lngHigh, lngLow

    set objFSO = CreateObject("scripting.FilesystemObject")
    set arq = OBjFSO.CreateTextFile("C:\LastLogon.txt",2)
    arq.close
    Set arquivo = objFSO.OpenTextFile("C:\LastLogon.txt", 8)

     

    Set objList = CreateObject("Scripting.Dictionary")
    objList.CompareMode = vbTextCompare

    strDN = ""

    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

     

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strConfig = objRootDSE.Get("configurationNamingContext")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")

     

    Set adoCommand = CreateObject("ADODB.Command")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"
    adoCommand.ActiveConnection = adoConnection

    strBase = "<LDAP://" & strConfig & ">"
    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

     

    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

     

    For k = 0 To Ubound(arrstrDCs)
        strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
        strFilter = "(&(objectCategory=person)(objectClass=user))"
        strAttributes = "sAMAccountName,lastLogon"
        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

            if strDN = adoRecordset.Fields("sAMAccountName").Value then

                       adoRecordset.MoveNext
            else
                strDN = adoRecordset.Fields("sAMAccountName").Value
                On Error Resume Next
                Set objDate = adoRecordset.Fields("lastLogon").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 (objList.Exists(strDN) = True) Then
                    If (dtmDate > objList(strDN)) Then
                        objList.Item(strDN) = dtmDate
                    End If
                Else
                 arquivo.writeline strDN & " " & dtmDate
                End If
                adoRecordset.MoveNext
            Loop
            adoRecordset.Close
        End If
    Next


     

    adoConnection.Close
    Set objRootDSE = Nothing
    Set adoConnection = Nothing
    Set adoCommand = Nothing
    Set adoRecordset = Nothing
    Set objDC = Nothing
    Set objDate = Nothing
    Set objList = Nothing
    Set objShell = Nothing

    segunda-feira, 3 de março de 2008 14:58
  • É Laerte...

    Tem forças do mal agindo contra mim, heauheauaeh....

    No seu códio faltava apenas um End IF, coloquei e segue abaixo, como o anteiror, na VM funciona perfeitamente, inclusive neste abaixo ele busca já o nome do usuário e o campo UserAccountControl, que eu estava pensando em usar para tentar determinar se o usuário está ativo ou não, porém no ambiente de produção ele continua pegando lixo dos últimos 5 logons + data default (como se nunca tivesse logado), o pior é que ele não pega na ordem exata dos últimos logons, caso fosse eu podia pegar e validar se o usuário já existisse na lista para descartar, porém ele pega a sequencia aleatória dos últimos logons.

    Tá dificil imaginar onde está o problema, realmente é muito estranho.

    Não sei se você tem outra idéia de correção, porém de qualquer maneira até o momento muitissimo obrigado pela ajuda.

     

     

     

    Dim objRootDSE, strConfig, adoConnection, adoCommand, strQuery
    Dim adoRecordset, objDC
    Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
    Dim strDN, dtmDate, objDate, objList, strUser, objUser,objNames
    Dim strBase, strFilter, strAttributes, lngHigh, lngLow

    set objFSO = CreateObject("scripting.FilesystemObject")
    set arq = OBjFSO.CreateTextFile("C:\LastLogon.txt",2)
    arq.close
    Set arquivo = objFSO.OpenTextFile("C:\LastLogon.txt", 8)

     

    Set objList = CreateObject("Scripting.Dictionary")
    objList.CompareMode = vbTextCompare

    strDN = ""

    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

     

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strConfig = objRootDSE.Get("configurationNamingContext")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")

     

    Set adoCommand = CreateObject("ADODB.Command")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"
    adoCommand.ActiveConnection = adoConnection

    strBase = "<LDAP://" & strConfig & ">"
    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

     

    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

     

    For k = 0 To Ubound(arrstrDCs)
        strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
        strFilter = "(&(objectCategory=person)(objectClass=user))"
        strAttributes = "sAMAccountName,lastLogon,CN,UserAccountControl"
        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

            If strDN = adoRecordset.Fields("sAMAccountName").Value then

                       adoRecordset.MoveNext
            Else
                strDN = adoRecordset.Fields("sAMAccountName").Value
                On Error Resume Next
                Set objDate = adoRecordset.Fields("lastLogon").Value
                objNames = adoRecordset.Fields("CN").Value
                objStatus = adoRecordset.Fields("UserAccountControl").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 (objList.Exists(strDN) = True) Then
                    If (dtmDate > objList(strDN)) Then
                        objList.Item(strDN) = dtmDate
                    End If
                Else
                 arquivo.writeline strDN & ";" & objNames & ";" & dtmDate & ";" & objStatus
                End If
                adoRecordset.MoveNext
            End If
            Loop
            adoRecordset.Close
        End If
    Next


     

    adoConnection.Close
    Set objRootDSE = Nothing
    Set adoConnection = Nothing
    Set adoCommand = Nothing
    Set adoRecordset = Nothing
    Set objDC = Nothing
    Set objDate = Nothing
    Set objList = Nothing
    Set objShell = Nothing


     

    quarta-feira, 5 de março de 2008 10:32
  •  

    Laerte,

     

    Consegui que um amigo testasse este script na empresa dele em um ambiente com 10mil usuários, ele informou que no caso dele o Script também trouxe sujeira, porém, trouxe os usuários duplicados (2 vezes) ou seja, não igual o seu e nem igual ao meu ambiente, conseguiu verificar de onde está vindo esta sujeira???

     

    Alguém mais tem uma sugestão ou ajuda?

     

    Obrigado

    segunda-feira, 10 de março de 2008 13:13
  • Diego parece que o problema está quando se tem mais de 10k usuários pois testei com 1000 e naum deu problema, sinceramente não sei de onde pode estar vindo essa sujeira, teria que realmente testar em um ambiente maior e em produção pois em ambiente limpo fica complicado.

    segunda-feira, 10 de março de 2008 13:31
  • Boa Tarde Diego pelo que vi vc  conhece muito de script sera que poderia me ajudar?
    Gostaria de saber se teria algum script que eu descubra qual Grupo o usuario faz parte


    Grato pela sua ajuda
    ACH
    segunda-feira, 5 de maio de 2008 18:00
  • Trata-se do registro individual de cada DC, esse registro de lastlogon não é replicado e cada DC fica com o seu. Isso é até bom, pois se pode filtrar no excel para usar apenas a maior ou menor data para agir com bloqueio com base na data desejada.

    na rede maior deve ter muito mais DCs, por isso aparece umas 6 evidencias de cada login e cada um com data diferente, as de 1600 significa que nunca logaram.

    na rede menor, menos DCs (provavelmente 2 autenticadores) e por isso 2 evidencias.

    quarta-feira, 30 de setembro de 2015 14:13