...hopefully some useful VMware related stuff

Script to identify Inactive Active Directory User Accounts for an AD 2003 domain

06/07/2010 21:00

Get all Active Directory users in the domain, pick out firstly User accounts which have never logged in and second get the last logged in time for each account which have logged in and report back any accounts which haven't logged in within the last 31 days.

Couldn't find PowerShell cmdlets for Active Directory 2003 and didn't want to install anything more than PowerShell on the servers, so I used a combination of standard tools 'dsget', 'dsquery' and also a VB script from https://www.rlmueller.net/Last%20Logon.htm

I created a couple of functions, first to strip the CN name from a Distinguished Name and second to get the domain name from the distinguished name so I could run this at multiple domains and yet the report could be distinguished by the domain name.

I also used a couple of functions to strip out a regex from the original CSV file from https://www.huddledmasses.org

 

The result is two email reports:

 

User accounts which have Never logged in:

User accounts which haven't logged in within the last 31 days:

 

Download the script HERE and is included below:

 

# Active Directory User Logon Statistics Email Report (AD 2003+)
# https://www.a2-alpha.co.uk
# Requires: dsget, dsquery, lastlogon.vbs (https://www.rlmueller.net/Last%20Logon.htm)
# lastlogon.vbs should be in the root of C:\ or update the script!
# Uses some import functions from: https://huddledmasses.org/powershell-convert-delimiters-import-tab-delimited-text/
# Version 1.0 - Original Script
# Version 1.1 - Added Time Status
# Version 1.2 - Added Error Checking
# 20100706
# Current Version 1.2
# Feedback to dan@a2-alpha.co.uk would be great!

##################################################

# PREREQUISITES

# Requires: dsget, dsquery, lastlogon.vbs (https://www.rlmueller.net/Last%20Logon.htm)
# lastlogon.vbs should be in the root of C:\ or update the script!
# Uses some import functions from: https://huddledmasses.org/powershell-convert-delimiters-import-tab-delimited-text/

##################################################

# DESCRIPTION

# Queries Active Directory for all users last logon time using the lastlogon.vbs script.
# This is then imported into a PowerShell variable
# Each user is queried using dsquery and dsget for their display name
# Two emails result, the first a list of users who have never logged in and
# a list of all users who have not logged in during the period specified (31 days at the moment)
# whos accounts are enabled.
# Use this script to check this information and disable any unused user accounts for security of the environment.

##################################################

# VARIABLES

$recipient = "user@domain.com"
$sender = "reporting@domain.com"
$smtpserver = "EXCHANGE01"
$daystocheck = 31

##################################################

$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()
dsquery > c:\temp.txt
If($Error -like "*dsquery*")
{
    Clear
    ""
    "dsquery was not found on this machine, please check you are running this on a domain member server"
    ""
}
Else
{
    $Error.Clear()
    dsget > c:\temp.txt
    If($Error -like "*dsget*")
    {
        Clear
        ""
        "dsget was not found on this machine, please check you are running this on a domain member server"
        ""
    }
    Else
    {
        $Error.Clear()
        if(!(test-path -path "C:\LastLogon.vbs"))
        {
        Clear
        ""
        "The LastLogon.vbs Script was not in the default location, please check (C:\LastLogon.vbs)"
        ""
        }
        Else
        {
        Clear
        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Prerequisites optimal"

        ##################################################

        # FUNCTIONS

        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Loading Functions"

        Function Convert-Delimiter([regex]$from,[string]$to)
        {
          process
          {
            $_ = $_ -replace "(?:`"((?:(?:[^`"]|`"`"))+)(?:`"$from|`"`$))|(?:((?:.(?!$from))*.)(?:$from|`$))","Þ`$1`$2Þ$to"
            $_ = $_ -replace "Þ(?:$to|Þ)?`$","Þ"
            $_ = $_ -replace "`"`"","`"" -replace "`"","`"`""
            $_ = $_ -replace "Þ((?:[^Þ`"](?!$to))+)Þ($to|`$)","`$1`$2"
            $_ = $_ -replace "Þ","`"" -replace "Þ","`""
            $_
          }
        }

        Function Import-Delimited([regex]$delimiter=",", [string]$PsPath="")
        {
          begin{
            $script:tmp = [IO.Path]::GetTempFileName()
            write-debug "Using tempfile $($script:tmp)"
           
            Function Import-String([string]$inputString){
              if($inputString.Length -gt 0 ) {
              write-debug "Importing $inputString"
              if(($inputString -as [IO.FileInfo]).Exists) {
                Get-Content $inputString | Convert-Delimiter $delimiter "," | Add-Content $script:tmp
              } elseif( ((Join-Path $pwd $inputString) -as [IO.FileInfo]).Exists) {
                Get-Content (Join-Path $pwd $inputString) | Convert-Delimiter $delimiter "," | Add-Content $script:tmp
              } else {
                $inputString | Convert-Delimiter  $delimiter "," | Add-Content $script:tmp
              }
              } else {
                write-debug "Nothing to Import"
              }
            }
           
            Import-String $PsPath
          }
         
          process{
            Import-String $_
          }
          end
          {
            Import-Csv $script:tmp
          }
        }

        Function Get-CName([string]$DistName)
        # Convert Distinguished name to CN
        # https://www.a2-alpha.co.uk
        # 20100705
        {
          process
          {
            $_ = $DistName.Split(",")
            $_ = $_[0]
            $_.Substring(3)
          }
        }

        function Get-DC([string]$DistName)
        # Get Domain from Distinguished Name
        # https://www.a2-alpha.co.uk
        # 20100705
        {
            Process
            {
                $_ = $DistName.Split(",")
                $Count = 0
                ForEach($line in $_)
                {
                    If($line -like "*DC*")
                    {
                        $Count++
                    }
                }
                $LineTotal = $_.Count
                If($Count -gt 3)
                {
                    "Unable to Determine Domain"
                }
                ElseIf($Count -eq 3)
                {
                    $LastLine = ($_.Count)-1
                    $LastLine1 = ($_.Count)-2
                    $LastLine2 = ($_.Count)-3
                    $D1 = ($_[$LastLine]).Substring(3)
                    $D2 = ($_[$LastLine1]).Substring(3)
                    $D3 = ($_[$LastLine2]).Substring(3)
                    "$D3.$D2.$D1"
                }
                ElseIf($Count -eq 2)
                {
                    $LastLine = ($_.Count)-1
                    $LastLine1 = ($_.Count)-2
                    $D1 = ($_[$LastLine]).Substring(3)
                    $D2 = ($_[$LastLine1]).Substring(3)
                    "$D2.$D1"
                }
                Else
                {
                    "Unable to Determine Domain"
                }
            }
        }


        ##################################################

        # CREATING THE USER OBJECT AND INTERPRETING DATA

        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Importing AD User Data"

        $userdata = @()
        echo "Name;LastLogon" > c:\lastlogontemp.csv
        cscript //nologo c:\LastLogon.vbs >> c:\lastlogontemp.csv
        Get-content c:\lastlogontemp.csv | convert-delimiter ";" "," | set-content c:\lastlogon.csv
        $userdata += import-csv c:\lastlogon.csv
        $never = $userdata | select Name, LastLogon | where {$_.LastLogon -like "Never"}

        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Building First User Object"

        $NeverRep = @()
        ForEach($usrNev in $never)
        {
            $NeverObj = "" | Select Name, LastLogon, DisplayName
            $NeverObj.Name = $usrNev.Name
            $NeverObj.LastLogon = $usrNev.LastLogon
            $NeverObj.DisplayName = Get-CName $usrNev.Name
            $NeverRep += $NeverObj
        }
        $loggedinusers = @()
        $loggedin = $userdata | select Name, LastLogon | where {$_.LastLogon -notlike "Never"}

        $DomainbeingChecked = Get-DC (($loggedin[0]).Name)

        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Building Second User Object"

        ForEach($user in $loggedin)
        {
            $disabled = dsget user $user.Name -disabled
            $loggedinObj = "" | select Name, LastLogon, DisplayName, Disabled, "Last $daystocheck Days"
            $loggedinObj.Name = $user.Name
            [datetime]$lastlogon = (get-date -UFormat "%m/%d/%Y %T"($user.LastLogon))
            $loggedinObj.LastLogon = $lastlogon
            $loggedinObj.DisplayName = Get-CName $user.Name
            If($disabled -like "*no*")
            {
                $loggedinObj.Disabled = "No"
            }
            Else
            {
                $loggedinObj.Disabled = "Yes"
            }
            $loggedinUsers += $loggedinObj
           
            [datetime]$checkdate = (get-date((get-date).AddDays(-$daystocheck)))
           
            If($loggedinObj.LastLogon -gt ($checkdate))
            {
                $loggedinObj."Last $daystocheck Days" = "Yes"
            }
            Else
            {
                $loggedinObj."Last $daystocheck Days" = "No"
            }
        }

        ##################################################

        # REPORTING

        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Creating Report"

        $loggedinUsers = $loggedinUsers
        $report = $loggedinUsers | sort LastLogon | select DisplayName, "Last $daystocheck Days", LastLogon, Disabled | where {$_."Last $daystocheck Days" -like "No" -and $_.Disabled -like "No"}

        ##################################################

        # EMAILING

        $body = $report | ft -AutoSize

        if(!$body)
        {
            $body = "No Data to Report"
        }

        $body = $body | out-string

        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Emailing to $recipient"

        Send-MailMessage -to "$recipient" -From "$sender" -Subject "$DomainbeingChecked - Inactive Users" -SmtpServer "$smtpserver" -Body $body

        $Never = $NeverRep | Select DisplayName, LastLogon | Out-String

        Send-MailMessage -to "$recipient" -From "$sender" -Subject "$DomainbeingChecked - Users Never Logged In" -SmtpServer "$smtpserver" -Body $Never

        ##################################################

        # TIDY UP TEMP FILES

        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Deleting Temp Files"

        Remove-Item c:\lastlogontemp.csv
        Remove-Item c:\lastlogon.csv
        Remove-Item c:\temp.txt

        ##################################################

        # END OF SCRIPT

        $currenttime = get-date -UFormat "%T"
        "$currenttime ... Script Ends"

        ##################################################
        }
    }
}

 

Script to identify Inactive Active Directory User Accounts for an AD 2003 domain

Date: 31/12/2013

By: ncmoewmqd

Subject: uktzf


Date: 26/10/2010

By: Juk

Subject: Ive got it runing and working but with a few problems

First - if i change the days (from 31 to 7) i get incorrect dates
Second - if i run the script from powershell itselfe (not from the editor) iget the same failuer.

than again, if the "days to check" is not changed from 31 and the script is runing from PowerShell ISE (the editor) its working fine.

any ideas?

Search site