Monthly Archives: March 2015

Getting an accurate last logon date of Active Directory users

Sometimes the LastLogonTimeStamp attribute just doesn’t cut it and other times LastLogon just isn’t accurate on the Domain Controller you’re querying.

This attribute is not replicated and is maintained separately on each domain controller in the domain. To get an accurate value for the user’s last logon in the domain, the Last-Logon attribute for the user must be retrieved from every domain controller in the domain. The largest value that is retrieved is the true last logon time for that user.

Manually checking each DC and determinating the largest datetime value of LastLogon is clearly out the question so we’ll use Powershell instead!

To maintain as much flexibility as possible, ease of use and respect already established methods of working against AD with Powershell I’ve created a function that allows pipeline input from Get-ADUser and SamAccountName arrays (read: Import-CSV and Get-Content).

Per usual you’ll find the script at TechNet Gallery!

<#
.Synopsis
   Gets the newest LastLogon date based on data from all Domain Controllers in the Forest.
.DESCRIPTION
   Get the newest LastLogon attribute for the specified user by iterating through all Domain Controllers in the forest.
   Output is structured and enables sorting, CSV export and further processing.
.EXAMPLE
    # Get LastLogon date for one username:
    C:\PS> Get-ADUserLastLogon -SamAccountName username

    DomainController : dc01.contoso.com
    Enabled          : True
    Name             : User Name
    SamAccountName   : username
    LastLogon        : 2015-03-30 15:11:06

.EXAMPLE
    # Get LastLogon date for multiple usernames and output as table:
    C:\PS> "username","nameuser" | Get-ADUserLastLogon | Format-Table -AutoSize

    DomainController     Enabled Name        SamAccountName LastLogon
    ----------------     ------- ----        -------------- ---------
    dc01.contoso.com        True User Name   username       2015-03-30 15:11:06
    dc02.contoso.com        True Name User   nameuser       2015-03-30 13:58:38
.EXAMPLE
    # Get LastLogon date for all users under an Organizational Unit:
    C:\PS> $OU = "OU=ServiceAccounts,DC=contoso,DC=com"
    C:\PS> $ADUsers = Get-ADUsers -Filter * -SearchBase $OU
    C:\PS> $ADUsers | Get-ADUserLastLogon -Properties Title
.EXAMPLE
    # Get LastLogon date for the first 50 users of a remote forest and remote credentials:
    C:\PS> $Cred = Get-Credential
    C:\PS> Get-ADUserLastLogon -All -Count 50 -Forest contoso.org -Credential $Cred
.EXAMPLE
    # Get LastLogon date for the first 5 users and output the AD User object of the first users:
    C:\PS> $Result = Get-ADUserLastLogon -All -Count 5 -Passthru
    C:\PS> $Result[0].TargetObject
.INPUTS
   [System.String]
   [Microsoft.ActiveDirectory.Management.ADUser]
.OUTPUTS
   [System.Management.Automation.PSObject]
.PARAMETER SamAccountName
    Account name, as a string, to get LastLogon date.
.PARAMETER ADUser
    Account, from Get-ADUser cmdlet, to get LastLogon date.
.PARAMETER All
    Gets all AD users of the specified domain.
    Use together with -Count parameter to restrict amount of results.
.PARAMETER Count
    Max amount of results when using -All parameter.
.PARAMETER Forest
    Name of the remote forest. Needs to be resolvable.
.PARAMETER Properties
    Adds AD attributes to the output.
.PARAMETER Passthru
    Adds the Get-ADUser cmdlet output object into the TargetObject property.
.PARAMETER Credential
    Credentials to use with Get-ADUser and/or connecting to a remote forest.
.NOTES
    Version: 20150330.1
    Author: Daniel Grenemark
    Email: daniel@grenemark.se
    Twitter: @desek
    Blog: https://runbookautomation.wordpress.com/
.LINK
    https://runbookautomation.wordpress.com
    
#>

TechNet Gallery URL: https://gallery.technet.microsoft.com/Get-AD-User-Last-Logon-4c6b6fa6

Publishing SCSM Request Offerings like an engineer!

Ever had the great idea that you’d create an enumeration list that you’ll use on several RO’s to maximize data quality and ensure successful automation?

I’ve had it. Several times in fact.

However, for obvious reasons I don’t want to relate this enumeration to any class. I want it to be stand-alone and only be used with one or several RO(s). As all “centrally managed lists” I want a change in the list to reflect on all RO(s). And as most of you know you have to map every prompt to a property of a class that is defined in the template related to the RO to be able to publish it.
There’s actually a requirement for this on the data layer and not just in the GUI, which I tought at first.

So how do you map an enumeration that is not a property of any class?

Since all configuration of RO’s are saved in a Management Pack and in XML format we should start by reading the Management Pack XML Schema Reference.
After a few clicks we should notice that the <Extension> element (which contains the RO definition) isn’t documented on MSDN. Thank you very much! Continue reading