PowerShell Script Guide: Detecting Locked Accounts in Windows

Key takeaways

  • PowerShell for efficiency: Utilizes PowerShell to quickly identify locked accounts in Windows environments.
  • Excludes Azure AD: The script does not cover Azure AD accounts, focusing solely on local and domain controller accounts.
  • Environment-specific detection: Tailors its approach depending on whether it’s run on a Domain Controller or a workstation.
  • Customizable output: Offers flexibility in output format, allowing export in both CSV and TXT files.
  • User Filtering capability: Can target specific users if needed, enhancing its precision.
  • Automated over manual: Represents an efficient alternative to manual account checking methods.
  • Indicative of larger issues: Locked accounts can be a sign of broader security or operational issues.
  • Accessible to beginners: Friendly for those with basic PowerShell knowledge, while still customizable for advanced users.
  • Regular monitoring recommended: Best used as part of a regular account monitoring strategy.
  • Enhanced with NinjaOne: The script’s functionality complements NinjaOne’s comprehensive IT management tools.

In the ever-evolving landscape of IT security, managing user accounts remains a cornerstone of safeguarding systems and data. One critical aspect is monitoring and addressing locked accounts, a common issue in large and dynamic IT environments. With PowerShell, administrators can efficiently identify locked accounts, ensuring business continuity and security.

Background

The provided PowerShell script emerges as a vital tool for IT professionals and Managed Service Providers (MSPs). Its core function is to identify locked accounts in a Windows environment, excluding Azure AD accounts. This capability is crucial for maintaining operational efficiency and security, as locked accounts can be both a symptom of user error and a potential indicator of security breaches. 

The script:

<#
.SYNOPSIS
    This script will see if any accounts on a local machine or on a domain controller are locked out. 
    You can optionally export this information into a custom field.

    Does NOT check Azure AD Accounts.
.DESCRIPTION
    This script will see if any accounts on a local machine or on a domain controller are locked out. 
    You can optionally export this information into a custom field.

    Does NOT check Azure AD Accounts.
    
.EXAMPLE
    (No Parameters but ran on a DC)
    SamAccountName LastLogonDate        PasswordExpired Enabled
    -------------- -------------        --------------- -------
    user           4/20/2023 1:09:23 PM           False    True

.EXAMPLE
    (No Parameters but ran on a Workstation)
    Name  Domain LocalAccount Disabled
    ----  ------ ------------ --------
    user  TEST          False    False

PARAMETER: -ExportTXT "ReplaceMeWithAnyMultiLineCustomField"
    Name of a multi-line customfield you'd like to export the results to.
.EXAMPLE
    -ExportTXT "ReplaceMeWithAnyMultiLineCustomField"
    Name  Domain LocalAccount Disabled
    ----  ------ ------------ --------
    user  TEST          False    False

PARAMETER: -ExportCSV "ReplaceMeWithAnyMultiLineCustomField"
    Name of a multi-line customfield you'd like to export the results to.
.EXAMPLE
    -ExportCSV "ReplaceMeWithAnyMultiLineCustomField"
    Name  Domain LocalAccount Disabled
    ----  ------ ------------ --------
    user  TEST          False    False

.OUTPUTS
    None
.NOTES
    Minimum OS Architecture Supported: Windows 7, Windows Server 2008
    Release Notes: Renamed script, added Script Variable support, added support for showing results of only 1 or more specific users.
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param (
    [Parameter()]
    [String]$Users,
    [Parameter()]
    [String]$ExportCSV,
    [Parameter()]
    [String]$ExportTXT
)

begin {
    if ($env:usersToCheck -and $env:usersToCheck -notlike "null") { $Users = $env:usersToCheck }
    if ($env:exportCsvResultsToThisCustomField -and $env:exportCsvResultsToThisCustomField -notlike "null") { $ExportCSV = $env:exportCsvResultsToThisCustomField }
    if ($env:exportTextResultsToThisCustomField -and $env:exportTextResultsToThisCustomField -notlike "null") { $ExportTXT = $env:exportTextResultsToThisCustomField }

    if ($Users) {
        $UsersToCheck = $Users.split(',') | ForEach-Object { $_.Trim() }
        Write-Warning "Only the following users will be checked: $UsersToCheck"
    }
    function Test-IsDomainController {
        if ($PSVersionTable.PSVersion.Major -ge 5) {
            $OS = Get-CimInstance -ClassName Win32_OperatingSystem
        }
        else {
            $OS = Get-WmiObject -Class Win32_OperatingSystem
        }

        if ($OS.ProductType -eq "2") {
            return $True
        }
    }

    function Test-IsAzureJoined {
        $dsreg = dsregcmd.exe /status | Select-String "AzureAdJoined : YES"
        if ($dsreg) {
            return $True
        }
    }

    if ([System.Environment]::OSVersion.Version.Major -ge 10) {
        if (Test-IsAzureJoined) { Write-Warning "This device is Azure AD Joined, this script currently cannot detect if Azure AD Users are locked out!" }
    }
}
process {

    # For Domain Controllers find the locked out account using Search-ADAccount
    if (Test-IsDomainController) {
        Import-Module ActiveDirectory
        $LockedOutUsers = Search-ADAccount -LockedOut | Select-Object SamAccountName, LastLogonDate, PasswordExpired, Enabled
    }
    else {
        $LockedOutUsers = if ($PSVersionTable.PSVersion.Major -ge 5) {
            Get-CimInstance -ClassName Win32_Useraccount | Where-Object { $_.Lockout -eq $True } | Select-Object Name, Domain, LocalAccount, Disabled 
        }
        else {
            Get-WmiObject -Class Win32_Useraccount | Where-Object { $_.Lockout -eq $True } | Select-Object Name, Domain, LocalAccount, Disabled
        }
    }

    if ($Users) {
        $LockedOutUsers = $LockedOutUsers | Where-Object { $UsersToCheck -contains $_.Name -or $UsersToCheck -contains $_.SamAccountName } 
    }

    if ($LockedOutUsers) {
        # Output any locked out users into the activity log
        Write-Warning "Locked out users were found!"
        $LockedOutUsers | Format-Table | Out-String | Write-Host

        # Export the list in CSV format into a custom field
        if ($ExportCSV) {
            Ninja-Property-Set $ExportCSV ($LockedOutUsers | ConvertTo-Csv -NoTypeInformation)
        }

        # Export the usernames into a custom field
        if ($ExportTXT) {
            if ($LockedOutUsers.Name) {
                Ninja-Property-Set $ExportTXT ($LockedOutUsers.Name | Out-String)
            }

            if ($LockedOutUsers.SamAccountName) {
                Ninja-Property-Set $ExportTXT ($LockedOutUsers.SamAccountName | Out-String)
            }
        }
        Exit 1
    }

    Write-Host "No locked out users detected. Please note this does NOT check Azure AD Accounts."
    Exit 0
}
end {
    
    
    
}

 

Access over 300+ scripts in the NinjaOne Dojo

Get Access

Detailed breakdown

The script operates in a straightforward yet effective manner:

  • Parameter Initialization: It begins by setting parameters for user input, which include options for specifying particular users and exporting results in CSV or TXT formats.
  • Environment Checks: The script then assesses the operating environment, determining whether it’s running on a Domain Controller or a workstation, and whether the machine is Azure AD joined. This is crucial as it dictates the method used to find locked accounts.
  • Locked Account Detection:
    • On Domain Controllers, it employs Search-ADAccount to find locked accounts.
    • On workstations, it uses Win32_UserAccount class methods to achieve the same.
  • Selective User Checking: If specific users are provided, it filters the results accordingly.
  • Output and Exporting: The script displays locked accounts and offers the option to export this information in CSV or TXT formats.
  • Finalization: It concludes by indicating whether locked accounts were detected or not.

Potential use cases

Imagine an MSP managing a network with numerous user accounts. Suddenly, several users report inability to access their accounts. The MSP can quickly run this script to identify locked accounts, significantly speeding up the troubleshooting and resolution process.

Comparisons

Traditionally, locked account checks involve manual searches or using separate tools like AD administrative tools. The PowerShell approach streamlines this process, offering a more integrated and scriptable solution that’s efficient for large-scale environments.

FAQs

  • Can this script check Azure AD Accounts?
    No, it’s specifically designed for local and domain controller accounts.
  • Is this script suitable for beginners in PowerShell?
    Yes, it’s user-friendly, though basic understanding of PowerShell is recommended.
  • Can the script be customized?
    Absolutely, it’s flexible and can be modified to fit specific requirements.

Implications

While the script is highly effective, it’s important to remember that locked accounts can signal deeper issues, such as security breaches or system misuse. Timely identification and analysis are critical.

Recommendations

  • Regularly use the script for proactive checks.
  • Combine this with broader security protocols.
  • Customize the script for your specific environment needs.

Final thoughts

In an age where efficiency and security are paramount, NinjaOne offers the tools and capabilities necessary for modern IT management. This script exemplifies how PowerShell, a component of NinjaOne’s suite, can be leveraged to enhance IT operations and security. NinjaOne’s comprehensive approach to IT management makes it an indispensable ally in navigating the complex IT landscape.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).