Skip to content
neztach edited this page Aug 31, 2023 · 1 revision

Support Functions

Check if we are running as admin

PowerShell 5.x only runs on Windows so use .NET types to determine isAdminProcess -OR If we are on v6 or higher, check the $IsWindows pre-defined variable.

If (($PSVersionTable.PSVersion.Major -le 5) -or $IsWindows) {
    $currentUser = [Security.Principal.WindowsPrincipal]([Security.Principal.WindowsIdentity]::GetCurrent())
    Return $currentUser.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
Write-Output (0 -eq (id -u)) # Must be Linux or OSX, so use the id util. Root has userid of 0.

Test if computer is trusted to domain

Test-ComputerSecureChannel -Verbose

Change size output to human readable format

$size = ''
Switch ($size) {
    {$_ -ge 1PB} {"{0:#.#' PB'}" -f ($size / 1PB); Break}
    {$_ -ge 1TB} {"{0:#.#' TB'}" -f ($size / 1TB); Break}
    {$_ -ge 1GB} {"{0:#.#' GB'}" -f ($size / 1GB); Break}
    {$_ -ge 1MB} {"{0:#.#' MB'}" -f ($size / 1MB); Break}
    {$_ -ge 1KB} {"{0:#' KB'}" -f ($size / 1KB); Break}
    default      {'{0:n0}' -f ($size) + ' Bytes'}
}

Unix equivalent of touch

$file = 'path\to\filename.ext'
If (Test-Path -Path $file){
    (Get-ChildItem -Path $file).LastWriteTime = Get-Date
} Else {
    Write-Output -InputObject $null > $file
}

Convert Phone numbers to a standardized format

Function Convert-StandardPhone ([String]$N) {
    If ($N -match '[0-9]'){
        $p = $N -replace '[^0-9]',''
        $p = $p -replace '^0' -replace '^1' -replace '\s' -as [LONG]
        $l = ($p | Measure-Object -Character).Characters

        If ($l -eq 7) {
            $PN  = '{0:###-####}' -f ([long]$p)
        } ElseIf ($l -eq 11) {
            $p = $p.Substring(1); $PN  = '{0:(###) ###-####}' -f ([long]$p)
        } ElseIf ($l -eq 10) {
            $PN  = '{0:(###) ###-####}' -f ([long]$p)
        } Else {
            $PN = $N
        }
    } Else {
        $PN = $null
    }
    Return $PN
}

Usage: Get-ADUser $env:USERNAME -prop mobile | Select @{n='mobile';e={Convert-StandardPhone $_.mobile}}

Find empty OUs

$ad_objects = Get-ADObject -Filter "ObjectClass -eq 'user' -or ObjectClass -eq 'computer' -or ObjectClass -eq 'group' -or ObjectClass -eq 'organizationalUnit'"
$aOuDns     = @()
ForEach ($o in $ad_objects) {
    If ($o.DistinguishedName -like '*OU=*' -and $o.DistinguishedName -notlike '*LostAndFound*') {
        $aOuDns += $o.DistinguishedName.Substring($o.DistinguishedName.IndexOf('OU='))
    }
}
$a0CountOus = $aOuDns | Group-Object | Where-Object {$_.Count -eq 1} | ForEach-Object {$_.Name}
$empty_ous  = 0
ForEach ($sOu in $a0CountOus) {
    If (-not 
        (
            Get-ADObject -Filter "ObjectClass -eq 'organizationalUnit'" | 
            Where-Object {$_.DistinguishedName -like "*$sOu*" -and $_.DistinguishedName -ne $sOu}
        )
    ) {
        $ou = Get-AdObject -Filter {DistinguishedName -eq $sOu}
        $ou
        $empty_ous++
    }
}
Write-Output -InputObject "-------------------`nTotal Empty OUs: $empty_ous"

Schema Level

Get Schema Version

$SchemaVersion = (Get-ADObject -Identity (Get-ADRootDSE).schemaNamingContext -Properties objectVersion).objectVersion
Switch ($SchemaVersion) {
    {'13'} {'Windows Server 2000'}
    {'30'} {'Windows Server 2003'}
    {'31'} {'Windows Server 2003 R2'}
    {'44'} {'Windows Server 2008'}
    {'47'} {'Windows Server 2008 R2'}
    {'56'} {'Windows Server 2012'}
    {'69'} {'Windows Server 2012 R2'}
    {'87'} {'Windows Server 2016'}
    {'88'} {'Windows Server 2019'}
}

Domain Controllers

Get the Primary Domain Controller Emulator

(Get-AdDomainController -Filter {OperationMasterRoles -like '*PDCEmulator*'}).HostName

Get List of all Domain Controllers including which have FSMO Roles

Get-AdDomainController -Filter * | 
Select-Object -Property Forest, Name, OperatingSystem, IPv4Address, Site, OperationMasterRoles | 
Format-Table -Autosize

DNS & IPs

Check if IP address given is a valid format

Function Get-IPValid ([String]$testip) {
    If ($testip -ne '0.0.0.0') {
        ### REGEX Pattern
        [regex]$pattern = '^(?:(?:1\d\d|2[0-5][0-4]|2[0-4]\d|0?[1-9]\d|0?0?\d)\.){3}(?:1\d\d|2[0-5][0-4]|2[0-4]\d|0?[1-9]\d|0?0?\d)$'

        ### Evaluate if the test IP matches the REGEX
        If ($testip -match $pattern) {
            return $true
        } Else {
            return $false
        }
    } Else {
        return $false
    }
}

Get a list of all DNS Servers

$DNSServers = @()
$Results    = (
    (
        & "$env:windir\system32\nltest.exe" /DnsGetDC:$env:USERDNSDOMAIN | 
        Select-Object -Skip 2 | 
        Select-Object -SkipLast 1
    ).Trim() -Replace '\s+',','
)
$Results | ForEach-Object {
    If ($_ -notmatch 'WARNING|successfully'){
        $DNSServers += [pscustomobject][ordered]@{
            Name = $_.Split(',')[0].Split('.')[0].toUpper()
            IP   = $_.Split(',')[1]
        }
    }
}
$results = @()
$DNSServers | Group-Object -Property Name,IP | ForEach-Object {
    $results += [pscustomobject][ordered]@{
        Name = $_.Name.split(',')[0].trim()
        IP   = $_.Name.split(',')[1].trim()
    }
}
$results | Format-Table -AutoSize

Get Bitlocker Password

$C = Get-ADComputer -Identity 'ComputerName'
Get-ADObject -Filter {objectclass -eq 'msFVE-RecoveryInformation'} -SearchBase $C.DistinguishedName -Properties 'msFVE-RecoveryPassword' | 
Select-Object -ExpandProperty 'msFVE-RecoveryPassword'

Getting AD user objects

Code Explanation
Get-ADUser -Identity 'samaccountname'
Standard basic get AD User
Get-ADUser -Filter {} `
Attribute
-(ceq/eq/ne $true/$false)
-(AND/OR) Attribute
-(clike/like/cnotlike/notlike)
'text with wildcards*'
etc.
-SearchBase OU=orgUnit,CN=domain,CN-local `
DistinguishedName of an OU
-Properties attribute `
Any attributes in AD that are in the current Schema
-Server ServerName ` | 
Domain Controller to send the query to
Where-Object <#?#> {$_.attribute -match 'blah'}
Where-Object {theobject.attribute -matches 'the text of blah'}
$_
The current object
.attribute
The attribute you're selecting to scrutinize (ex: $_.samaccountname)
<condition>
The condition is how we want to look at that attribute - in this case we're looking for text matches (not case sensitive)
'blah'
The text we're trying to find.
NOTE: Get-ADComputer works in almost the exact same way. It is always better/faster to apply as much in the filter as possible before resorting to the Where statement

Most useful/viewed attributes

Attribute Inline Expression
DistinguishedName
SamAccountname
Name
DisplayName
EmailAddress
Enabled
EmployeeID
GivenName
Surname
Company
Title
Description
Department
MemberOf
@{n='MemberOf';e={[string]$_.Memberof -join ', '}}
Manager
@{n='Manager';e={If ($_.Manager) {(Get-ADUser -Identity $_.Manager).Name}}
CanonicalName
@{n='Container';e={$_.CanonicalName -ireplace '\/[^\/]+$',''}}
UserPrincipalName
mobile
@{n='MobilePhone';e={Convert-StandardPhone -NumtoConv $_.mobile}} ## Convert-StandardPhone is above
OfficePhone
@{n='OfficePhone';e={Convert-StandardPhone -NumtoConv $_.OfficePhone}}
otherTelephone
@{n='otherTelephone';e={(@($_.otherTelephone | ForEach-Object {Convert-StandardPhone -NumtoConv $_}) -join ', ').TrimEnd(', ')}}
Fax
@{n='Fax';e={Convert-StandardPhone -NumtoConv $_.Fax}}
PasswordLastSet
whenCreated
whenChanged
LastLogonTimeStamp
@{n='LastLogonTimeStamp';e={[datetime]::FromFileTime($_.LastLogonTimeStamp)}}

Groups

Find Empty Groups

Try {
    $EmptyGroups = @(
        Get-ADGroup -Filter * -Properties isCriticalSystemObject, Members -ErrorAction Stop
    ).Where(
        {
            (-not $_.isCriticalSystemObject) -and 
            ($_.Members.Count -eq 0)
        }
    ) | 
    Sort-Object -Property Name
} Catch {
    $PSCmdlet.ThrowTerminatingError($_)
}

$EmptyGroupTotal = @()
$Act      = 'Working through Groups . . .'
$pi       = 0
$Progress = @{Activity = $Act; CurrentOperation = 'Loading'; PercentComplete  = 0}

Foreach ($EmptyGroup in $EmptyGroups) {
    $pi++
    [int]$percentage           = ($pi / $EmptyGroups.Count)*100
    $Progress.CurrentOperation = "$pi of $($EmptyGroups.Count) - $($EmptyGroup.Name)"
    $Progress.PercentComplete  = $percentage
    Write-Progress @Progress

    $cParam = @{
        Identity   = $EmptyGroup.Distinguishedname
        Properties = 'CanonicalName', 'Created', 'Description', 'GroupCategory', 'GroupScope', 'MemberOf', 'Membership', 'Modified', 'Name'
    }
    $cGroup = Get-ADGroup @cParam
    $EmptyGroupTotal += [PsCustomObject][Ordered]@{
        Name          = $cGroup.Name
        Description   = $cGroup.Description
        GroupScope    = $cGroup.GroupScope
        GroupCategory = $cGroup.GroupCategory
        Memberof      = $cGroup.MemberOf
        Membership    = ($cGroup.Membership).Count
        Created       = $cGroup.Created
        Modified      = $cGroup.Modified
        CanonicalName = $cGroup.CanonicalName
    }
}
Write-Progress -Activity $Act -Status 'Ready' -Completed
$EmptyGroupTotal | Out-GridView
Code Explanation
Search-ADAccount -LockedOut | Select-Object -Property Name, SamAccountName
Get users locked out
Get-ADUser -Identity 'samaccountname' | Unlock-ADAccount
Unlock user

Clone this wiki locally