Public/Get-StaleLocalUser.ps1
#requires -Version 2 function Get-StaleLocalUser { <# .Synopsis Displays local user accounts whose passwords have not been changed in a given number of days. .DESCRIPTION The Get-StaleLocalUser function uses Powershell remoting to display local user accounts on remote computers whose passwords have not been changed in a given number of days. By default this function queries all domain-joined computers for any local user accounts that are enabled and whose password age has exceeded the maximum password age of the current domain. .EXAMPLE PS C:\> Get-StaleLocalUser This command queries all domain-joined computers for any local user accounts that are enabled and whose password age has exceeded the maximum password age of the current domain using the current user's credentials. .EXAMPLE PS C:\> Get-StaleLocalUser -Credential (Get-Credential) This command queries all domain-joined computers for any local user accounts that are enabled and whose password age has exceeded the maximum password age of the current domain using the specified credentials. .EXAMPLE PS C:\> Get-StaleLocalUser -IncludeDisabled This command queries all domain-joined computers for any local user accounts (both enabled and disabled) whose password age has exceeded the maximum password age of the current domain using the current user's credentials. .EXAMPLE PS C:\> Get-StaleLocalUser -IncludeDisabled | Export-csv -Path c:\LocalUsers.csv This command queries all domain-joined computers for any local user accounts (both enabled and disabled) whose password age has exceeded the maximum password age of the current domain using the current user's credentials. The results are then exported to a CSV file named LocalUsers.csv at the root of the C drive. .EXAMPLE PS C:\>Set-Item -Path wsman:\localhost\Client\TrustedHosts -Value 172.16.0.0 In this example a non-domain-joined computer is queried for any local user accounts (both enabled and disabled) whose password age has exceeded the maximum password age of the current domain. First, in order to use an IP adress in the value of the ComputerName parameter, the IP address of the remote computer must be included in the WinRM TrustedHosts list on the local computer. To do so, the first command is run. Please note, this command assumes the WinRM TrustedHosts list on the local computer has not been previously set or is empty. Next, the non-domain-joined computer can now be queried. The credentials of an administrator account on the remote computer must be provided as shown in the command below. PS C:\>Get-StaleLocalUser -IncludeDisabled -ComputerName 172.16.0.0 -Credential Administrator Finally, unless otherwise needed, the IP address of the remote computer can now be removed from the WinRM TrustedHosts list on the local computer. To do so, the below command is run. Please note, the above command assumes the WinRM TrustedHosts list on the local computer has not been previously set or is empty. PS C:\>Clear-Item -Path wsman:\localhost\Client\TrustedHosts .NOTES The Get-StaleLocalUser function requires administrator rights on the remote computer(s) to be queried. Powershell remoting must be enabled on the remote computer to properly query local user accounts. If Powershell remoting is not enabled on a remote computer it can be enabled by either - Running Enable-PSRemoting locally or - By running Enable-RemotePSRemoting and specifying the name of the remote computer. .PARAMETER ComputerName Specifies the computers on which the command runs. The default is all domain-joined computers. Type the NETBIOS name, IP address, or fully-qualified domain name of one or more computers in a comma-separated list. To specify the local computer, type the computer name, "localhost", or a dot (.). To use an IP address in the value of the ComputerName parameter, the command must include the Credential parameter. Also, the computer must be configured for HTTPS transport or the IP address of the remote computer must be included in the WinRM TrustedHosts list on the local computer. For instructions for adding a computer name to the TrustedHosts list, see "How to Add a Computer to the Trusted Host List" in about_Remote_Troubleshooting. .PARAMETER Credential Specifies a user account that has permission to perform this action. The default is the current user. Type a user name, such as "User01" or "Domain01\User01", or enter a variable that contains a PSCredential object, such as one generated by the Get-Credential cmdlet. When you type a user name, you will be prompted for a password. .PARAMETER DaysOld Specifies the maximum password age in number of days. The default is the maximum password age of the current domain. .PARAMETER IncludeDisabled Specifies the function include disabled local user accounts in the results. #> [cmdletbinding()] Param( [Parameter(Mandatory = $False,Position = 0,ValueFromPipelineByPropertyName = $True)] [Alias('Name')] [string[]]$ComputerName = (Get-ADComputer -Filter *).Name, [Parameter(Mandatory = $False)] [pscredential]$Credential = $null, [Parameter(Mandatory = $False)] [int]$DaysOld = (Get-ADDefaultDomainPasswordPolicy -Identity $env:USERDNSDOMAIN).MaxPasswordAge.Days, [Parameter(Mandatory = $False)] [switch]$IncludeDisabled ) Begin{} Process{ $ScriptBlock = { [int]$DaysOld = $Using:DaysOld [bool]$IncludeDisabled = $Using:IncludeDisabled $WarningPreference = $Using:WarningPreference Add-Type -AssemblyName System.DirectoryServices.AccountManagement $PrincipalContext = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList ([System.DirectoryServices.AccountManagement.ContextType]::Machine, $env:COMPUTERNAME) $UserPrincipal = New-Object -TypeName System.DirectoryServices.AccountManagement.UserPrincipal -ArgumentList ($PrincipalContext) $Searcher = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalSearcher $Searcher.QueryFilter = $UserPrincipal $Searcher.FindAll() | Where-Object -FilterScript { $_.LastPasswordSet -le (Get-Date).AddDays($(-$DaysOld)) } | Select-Object -Property Name, @{ n = 'Username' e = { $_.samaccountname } }, Enabled, Description, LastPasswordSet, PasswordNeverExpires, PasswordNotRequired | ForEach-Object -Process { $Object = $_ If($IncludeDisabled) { $Object } Else { $Object | Where-Object -FilterScript { $_.Enabled -eq $True } } } } $InvokeArgs = @{ ComputerName = $ComputerName } If($null -ne $Credential) { $InvokeArgs.Credential = $Credential } $InvokeArgs.ComputerName = Test-PSRemoting @InvokeArgs -WarningAction $WarningPreference If($null -eq $InvokeArgs.ComputerName) { Break } $InvokeArgs.ScriptBlock = $ScriptBlock Invoke-Command @InvokeArgs | Select-Object -Property * -ExcludeProperty RunspaceID } End{} } |