VB.net | Active Directory | Get last logon for computer/user account

Ever wondered how to fetch the last logon details for a domain member computer or user? Using .Net Microsoft has made it pretty easier for the developers to populate the active directory attributes to desired data repositories, however getting the last logon date time value still remains a complex stuff (for beginners like us), especially when your domain consist of multiple domain controllers and they are spread across different geographical areas and subnets :)

After dwelling for long a while, I came across a C# code snippet @ http://www.codeproject.com/Articles/19181/Find-LastLogon-Across-All-Windows-Domain-Controlle that was mostly built against http://www.rlmueller.net/Last%20Logon.htm

I had to copy the codes those were split into multiple blocks for proper explanations, re-arrange and then using the online C# to VB.Net converters, convert to readable VB.Net coding. Again, there were few mismatches and I was able to figure them out through stackoverflow & tech forums posts.

Without going on with what and how I did it, here comes the complete coding. Please note, this is a console application solution, and you should add the references as seen with the below image in order to successfully call the methods and types

Ref

[code language=”vb” gutter=”false” wraplines=”true”]
Imports System.DirectoryServices
Imports ActiveDs

Module Module1

”’ <summary>
”’ You should able to easily convert this console application to windows form application
”’ with least efforts
”’ Original code was posted with http://www.codeproject.com/Articles/19181/Find-LastLogon-Across-All-Windows-Domain-Controlle
”’ using C#, I converted most of the C# Codes using online converter(s)
”’ and ammended at few places, as the code block provided with the project were not fetching decent results
”’ Rajesh Thampi / 15-Jan-2015 | w7bugs at gmail dot com | windows7bugs.wordpress.com
”’ </summary>
”’ <remarks></remarks>
Sub Main()
‘Get the root of the directory data tree on a directory server.
Dim rootDse As New DirectoryEntry("LDAP://rootDSE")
‘Dictionary object to hold the records retrived by the search
Dim lastLogons As Dictionary(Of String, Int64) = New Dictionary(Of String, Int64)
‘Local variable for holding formatted last logon values in datetime format
Dim llogon As DateTime = Nothing

‘for User last logon
‘Dim TargetUsername As String = "george" ‘ -> Pass sAMAccountName
‘Dim objType As Integer = 805306368 ‘-> 805306368 User | 805306369 Computer

‘for Computer
Dim TargetUsername As String = "JOSE-KSP$" ‘ -> Pass sAMAccountName
Dim objType As Integer = 805306369 ‘-> 805306368 User | 805306369 Computer

‘Loop through all available domain controllers
For Each dsDC As DirectoryServices.ActiveDirectory.DomainController In _
DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain.DomainControllers
‘Print the individual domain controller name
‘Debug.Write(dsDC.Name & vbCrLf) ‘ Uncomment for print
‘Get the Entry details for domain controller
Dim dirEntry As DirectoryEntry = New DirectoryEntry("LDAP://" + dsDC.Name + "/" + DirectCast(rootDse.Properties("defaultNamingContext").Value, String))
‘Define searcher for the objects of interest
Dim dirObjects As DirectorySearcher = New DirectorySearcher(dirEntry)
‘Define a large integer to hold the COM object translated value
‘ActiveDS COM object is a MUST reference, yet to find another way to deal with highpart, lowpart values obtained from "lastlogon"
Dim lastLogonThisServer As Int64 = New Int64()
‘Set up the filter for object to be returned through findall method
dirObjects.Filter = "(&(sAMAccountType=" & objType & ")(sAMAccountName=" & TargetUsername & "))"
‘ Loop through the records found
For Each objRecords In dirObjects.FindAll()
‘Get the directory entry, this will return all the attributes associated with the object (Computer/User)
Dim dirObj As DirectoryEntry = objRecords.GetDirectoryEntry()
If Not dirObj Is Nothing Then
‘ Get the distinguishedName and lastLogon for each user

Dim distinguishedName As String = dirObj.Properties("distinguishedName").Value.ToString()

Try

If Not dirObj.Properties("lastLogon").Value Is Nothing Then
Dim lgIntas As ActiveDs.LargeInteger = dirObj.Properties("lastLogon").Value
Dim lngHigh As Long = lgIntas.HighPart
Dim lngLow As Long = lgIntas.LowPart
lastLogonThisServer = (lngHigh * (2 ^ 32) – lngLow)

End If

Catch ex As Exception
Debug.Write(ex.Message)
End Try
‘Different date time formats you can play around with
‘Dim format As String = "MMM ddd d HH:mm yyyy" -> Jan Thu 15 08:11 2015
‘Dim format As String = "dd/MMM/yyyy HH:mm tt" -> 15/Jan/2015 08:36 AM
‘Debug.Write(distinguishedName & ";" _
‘& DateTime.FromFileTime(lastLogonThisServer).ToString(format, Globalization.CultureInfo.InvariantCulture) & vbCrLf)

‘Save the most recent logon for each user in a Dictionary object
‘How it works
‘lastLogons dictionary object has two parts, key and corresponding value
‘Prior adding a new record, using ContainsKey call we can check the array for existing keys
‘With this example, the key is "distinguishedName"
‘If the distinguishedName as key found

If lastLogons.ContainsKey(distinguishedName) Then
‘We compare the latest fetched logon date integer value against the key value of the dictionary object
If lastLogons(distinguishedName) < lastLogonThisServer Then
‘If the existing value is smaller than the new value "lastLogonThisServer" holds
lastLogons(distinguishedName) = lastLogonThisServer
‘We will update the existing key value with recent lastLogonThisServer value
End If
Else
‘We will add a new entry to the dictionary object
lastLogons.Add(distinguishedName, lastLogonThisServer)
End If
End If
Next
Next
‘Now we will loop through the dictionary object and fetch the details
‘For a single user/computer the dictionary object will not have more than one entry
For Each kvp As KeyValuePair(Of String, Int64) In lastLogons
Dim v1 As String = kvp.Key
Dim v2 As DateTime = DateTime.FromFileTime(kvp.Value).ToString()
‘ llogon = v2
Dim format As String = "dd/MMM/yyyy HH:mm tt"
Debug.Write("Distinguished Name :" & v1 & "; Last logged :" & v2.ToString(format) & vbCrLf)

Next

End Sub

End Module
[/code]

You may download the solution from https://drive.google.com/file/d/0B-3iVeOMTCbWWFliTGN1NmNxMjQ/view?usp=sharing

regards,

rajesh

Windows 8.1 Update 1 available for download now

Are you already using Windows 8.1? Microsoft has added much of the missing Windows 7 features back to Windows 8.1 through the latest update, which is optional.

W8.1update

 

 

 

 

 

 

 

If you are already on Windows 8.1 (If you are on Windows 8, you must update to 8.1 using Windows store) please go ahead.

Please read this article to know what is included within the update http://www.cnet.com/news/the-windows-8-1-update-everything-you-need-to-know/

for Windows7bugs

rajesh

Oracle Applications R12 “Emergency” Rapid Clone

There could be occasions when as an apps DBA you would be asked to provide a fresh clone either over test or development environment to address a serious issue.

Rapid Clone hierarchy usually requires a DBA to pre-clone both application & database tiers, shutting down the source system and then souring the relevant folders to target system.

Today we are going to share a minor hack which could help you, when you cannot JUST shutdown a Production instance, however the cloned instance is a mandatory element to deal with a particular situation.

(Please note, this hack is ONLY applicable to situations where the backups were made without running PRE-CLONE or errors were raised stating

  1. Control file creation failed : ORA-01503: CREATE CONTROLFILE failed
  2. Certain database files were not recognized as part of the database : ORA-01565: error in identifying file)

Errors and example scenarios as mentioned with this thread

#cd /backup

#time tar –zcvf apps.tar.gz /u01/applprod/PROD/apps/*

(use “time” to check how much time the activity has taken)

Once the application tier has been tar balled

#time tar –zcvf db.tar.gz /u01/oraprod/PROD/db/*

Wait until the tar ball created

Now you can SCP the tar balls to your target system

scp –pr *.tar.gz root@targetsystem:/backup

The approximate time to transfer a database tar ball in 100GB size should be 33-35 minutes and the application tar ball in size 31GB around 9-10 minutes

Backup (if required after running the pre-clone) of your TEST/Development instance and delete the application and database folders (make sure you have shutdown the application and database instances)

#cd /u02/oratest/TEST/db

#rm –rf *

#cd /u02/appltest/TEST

#rm –rf *

Now extract the tar balls to respective base paths

#time tar –zxvf /backup/apps.tar.gz

We are already in the folder /u02/appltest/TEST so the application instance files will be extracted in the same location

Once the extraction is over, we can go ahead with extracting the database tier files

#cd /u02/oratest/TEST/db

#tar –zxvf db.tar.gz

Wait until the extraction part is over

The real hack starts from here

#cd /u02/oratest/TEST/db/tech_st/10.2.0/appsutil

#rm –rf *

Switch to source system (Aka Production instance)

#su – oraprod

If the .bash_profile has an exclusive call for the environment sourcing, your environment will be automatically sourced, else source it

Run pre-clone for the database tier now

$perl adpreclone.pl dbTier

Once the pre-clone activities completed successfully, switch to

$cd $ORACLE_HOME/appsutil

Create a tar file

$tar –zcvf appsutil.tar.gz *

Now move the new tar file to your TEST/Development instance

$scp –pr appsutil.tar.gz root@targetsystem:/backup

From the target system, move to

#cd /u02/oratest/TEST/db/tech_st/10.2.0/appsutil

Unzip the appsutil.tar.gz

#tar –zxvf /backup/appsutil.tar.gz

Once the files are extracted, change the ownership of the base path once again

#chown –R oratest:oinstall /u02/oratest

Change the access permissions

#chmod –R 777 /u02/oratest

Now as user “oratest” you can start the database tier cloning

#su – oratest

$cd /u02/oratest/TEST/db/tech_st/10.2.0/appsutil/clone/bin

$perl adcfgclone.pl dbTier

Once the database tier cloning completes successfully, you can proceed with application tier cloning, which doesn’t require any specific hacks

Side notes:

In my case I found that the “Gather schema statistics” program was missing from the scheduled jobs list. If you are experiencing slowness with your freshly cloned instance, it is highly recommended to run the said program prior going ahead with any other activities.

Make sure you would clear the cache under global configurations.

Hope you enjoyed another “hack” from us! Our sincere thanks and gratitude to Ravi Purbia (Sr. Apps DBA Consultant) who has provided us the details about this particular hack.

regards,

for Windows7bugs

admin