...hopefully some useful VMware related stuff
Script to identify Inactive Active Directory User Accounts for an AD 2003 domain
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" $userdata = @() $currenttime = get-date -UFormat "%T" $NeverRep = @() $DomainbeingChecked = Get-DC (($loggedin[0]).Name) $currenttime = get-date -UFormat "%T" ForEach($user in $loggedin) ################################################## # REPORTING $currenttime = get-date -UFormat "%T" $loggedinUsers = $loggedinUsers ################################################## # EMAILING $body = $report | ft -AutoSize if(!$body) $body = $body | out-string $currenttime = get-date -UFormat "%T" 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" Remove-Item c:\lastlogontemp.csv ################################################## # END OF SCRIPT $currenttime = get-date -UFormat "%T" ##################################################
##################################################
"$currenttime ... Importing AD User Data"
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 ... Building First User Object"
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"}
"$currenttime ... Building Second User Object"
{
$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"
}
}
"$currenttime ... Creating Report"
$report = $loggedinUsers | sort LastLogon | select DisplayName, "Last $daystocheck Days", LastLogon, Disabled | where {$_."Last $daystocheck Days" -like "No" -and $_.Disabled -like "No"}
{
$body = "No Data to Report"
}
"$currenttime ... Emailing to $recipient"
"$currenttime ... Deleting Temp Files"
Remove-Item c:\lastlogon.csv
Remove-Item c:\temp.txt
"$currenttime ... Script Ends"
}
}
}
Tags:
Script to identify Inactive Active Directory User Accounts for an AD 2003 domain
—————
—————
—————
—————
—————
—————
—————
—————
—————