Tag Archive for: Program

Folder Permission Analyzer Tool

<#
.SYNOPSIS
Folder Permission Analyzer Tool

.DESCRIPTION
This script analyzes and audits folder permissions on Windows systems, providing
insights into access rights, inheritance, and potential security issues.

.NOTES
File Name      : FolderPermissionAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, administrator rights
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\FolderPermissionAnalyzer.ps1
#>

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Folder_Permission_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
$global:targetPath = ""

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Folder Permission Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "Current Target Path: $global:targetPath"
    Write-Host "1. Set Target Folder Path"
    Write-Host "2. Analyze Folder Permissions"
    Write-Host "3. Check for Inherited Permissions"
    Write-Host "4. Identify Unique Permissions"
    Write-Host "5. Check for 'Everyone' Permissions"
    Write-Host "6. Analyze Nested Folder Permissions"
    Write-Host "7. Find Folders with Explicit Permissions"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Sets the target folder path for analysis.
#>
function Set-TargetFolderPath {
    $path = Read-Host "Enter the full path of the target folder"
    if (Test-Path -Path $path -PathType Container) {
        $global:targetPath = $path
        Write-Host "Target folder path set to: $global:targetPath" -ForegroundColor Green
    } else {
        Write-Host "Invalid path or folder does not exist." -ForegroundColor Red
    }
}

<#
.SYNOPSIS
Analyzes folder permissions.

.OUTPUTS
Array of PSObjects containing folder permission details.
#>
function Analyze-FolderPermissions {
    Write-Host "`nAnalyzing Folder Permissions..." -ForegroundColor Yellow
    if ([string]::IsNullOrWhiteSpace($global:targetPath)) {
        Write-Host "Target folder path is not set. Please set it first." -ForegroundColor Red
        return $null
    }

    $acl = Get-Acl -Path $global:targetPath
    $results = @()
    foreach ($ace in $acl.Access) {
        $results += [PSCustomObject]@{
            FolderName = Split-Path $global:targetPath -Leaf
            IdentityReference = $ace.IdentityReference
            AccessControlType = $ace.AccessControlType
            FileSystemRights = $ace.FileSystemRights
            IsInherited = $ace.IsInherited
            InheritanceFlags = $ace.InheritanceFlags
            PropagationFlags = $ace.PropagationFlags
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks for inherited permissions.

.OUTPUTS
Array of PSObjects containing inherited permission details.
#>
function Check-InheritedPermissions {
    Write-Host "`nChecking for Inherited Permissions..." -ForegroundColor Yellow
    if ([string]::IsNullOrWhiteSpace($global:targetPath)) {
        Write-Host "Target folder path is not set. Please set it first." -ForegroundColor Red
        return $null
    }

    $acl = Get-Acl -Path $global:targetPath
    $results = @()
    foreach ($ace in $acl.Access | Where-Object { $_.IsInherited -eq $true }) {
        $results += [PSCustomObject]@{
            FolderName = Split-Path $global:targetPath -Leaf
            IdentityReference = $ace.IdentityReference
            AccessControlType = $ace.AccessControlType
            FileSystemRights = $ace.FileSystemRights
            InheritanceFlags = $ace.InheritanceFlags
            PropagationFlags = $ace.PropagationFlags
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Identifies unique permissions.

.OUTPUTS
Array of PSObjects containing unique permission details.
#>
function Identify-UniquePermissions {
    Write-Host "`nIdentifying Unique Permissions..." -ForegroundColor Yellow
    if ([string]::IsNullOrWhiteSpace($global:targetPath)) {
        Write-Host "Target folder path is not set. Please set it first." -ForegroundColor Red
        return $null
    }

    $acl = Get-Acl -Path $global:targetPath
    $results = @()
    foreach ($ace in $acl.Access | Where-Object { $_.IsInherited -eq $false }) {
        $results += [PSCustomObject]@{
            FolderName = Split-Path $global:targetPath -Leaf
            IdentityReference = $ace.IdentityReference
            AccessControlType = $ace.AccessControlType
            FileSystemRights = $ace.FileSystemRights
            InheritanceFlags = $ace.InheritanceFlags
            PropagationFlags = $ace.PropagationFlags
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks for 'Everyone' permissions.

.OUTPUTS
Array of PSObjects containing 'Everyone' permission details.
#>
function Check-EveryonePermissions {
    Write-Host "`nChecking for 'Everyone' Permissions..." -ForegroundColor Yellow
    if ([string]::IsNullOrWhiteSpace($global:targetPath)) {
        Write-Host "Target folder path is not set. Please set it first." -ForegroundColor Red
        return $null
    }

    $acl = Get-Acl -Path $global:targetPath
    $results = @()
    foreach ($ace in $acl.Access | Where-Object { $_.IdentityReference -eq "Everyone" -or $_.IdentityReference -eq "NT AUTHORITY\Authenticated Users" }) {
        $results += [PSCustomObject]@{
            FolderName = Split-Path $global:targetPath -Leaf
            IdentityReference = $ace.IdentityReference
            AccessControlType = $ace.AccessControlType
            FileSystemRights = $ace.FileSystemRights
            IsInherited = $ace.IsInherited
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Analyzes nested folder permissions.

.OUTPUTS
Array of PSObjects containing nested folder permission details.
#>
function Analyze-NestedFolderPermissions {
    Write-Host "`nAnalyzing Nested Folder Permissions..." -ForegroundColor Yellow
    if ([string]::IsNullOrWhiteSpace($global:targetPath)) {
        Write-Host "Target folder path is not set. Please set it first." -ForegroundColor Red
        return $null
    }

    $results = @()
    $folders = Get-ChildItem -Path $global:targetPath -Directory -Recurse -Depth 2
    foreach ($folder in $folders) {
        $acl = Get-Acl -Path $folder.FullName
        foreach ($ace in $acl.Access) {
            $results += [PSCustomObject]@{
                FolderName = $folder.Name
                FullPath = $folder.FullName
                IdentityReference = $ace.IdentityReference
                AccessControlType = $ace.AccessControlType
                FileSystemRights = $ace.FileSystemRights
                IsInherited = $ace.IsInherited
            }
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Finds folders with explicit permissions.

.OUTPUTS
Array of PSObjects containing folders with explicit permissions.
#>
function Find-FoldersWithExplicitPermissions {
    Write-Host "`nFinding Folders with Explicit Permissions..." -ForegroundColor Yellow
    if ([string]::IsNullOrWhiteSpace($global:targetPath)) {
        Write-Host "Target folder path is not set. Please set it first." -ForegroundColor Red
        return $null
    }

    $results = @()
    $folders = Get-ChildItem -Path $global:targetPath -Directory -Recurse
    foreach ($folder in $folders) {
        $acl = Get-Acl -Path $folder.FullName
        if ($acl.Access | Where-Object { $_.IsInherited -eq $false }) {
            $results += [PSCustomObject]@{
                FolderName = $folder.Name
                FullPath = $folder.FullName
                ExplicitPermissionsCount = ($acl.Access | Where-Object { $_.IsInherited -eq $false }).Count
            }
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Folder Permission Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Folder Permission Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>
    <p>Target Folder: $global:targetPath</p>

    <h2>Folder Permissions</h2>
    $($AllResults.FolderPermissions | ConvertTo-Html -Fragment)

    <h2>Inherited Permissions</h2>
    $($AllResults.InheritedPermissions | ConvertTo-Html -Fragment)

    <h2>Unique Permissions</h2>
    $($AllResults.UniquePermissions | ConvertTo-Html -Fragment)

    <h2>'Everyone' Permissions</h2>
    $($AllResults.EveryonePermissions | ConvertTo-Html -Fragment)

    <h2>Nested Folder Permissions</h2>
    $($AllResults.NestedPermissions | ConvertTo-Html -Fragment)

    <h2>Folders with Explicit Permissions</h2>
    $($AllResults.ExplicitPermissions | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { Set-TargetFolderPath }
        "2" { $allResults.FolderPermissions = Analyze-FolderPermissions }
        "3" { $allResults.InheritedPermissions = Check-InheritedPermissions }
        "4" { $allResults.UniquePermissions = Identify-UniquePermissions }
        "5" { $allResults.EveryonePermissions = Check-EveryonePermissions }
        "6" { $allResults.NestedPermissions = Analyze-NestedFolderPermissions }
        "7" { $allResults.ExplicitPermissions = Find-FoldersWithExplicitPermissions }
        "8" { Generate-HTMLReport -AllResults $allResults }
        "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "9") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "9")

This Folder Permission Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of folder permissions:
    • Analysis of folder permissions
    • Check for inherited permissions
    • Identification of unique permissions
    • Check for ‘Everyone’ permissions
    • Analysis of nested folder permissions
    • Finding folders with explicit permissions
  3. Ability to set a target folder path for analysis.
  4. Comprehensive error handling for each analysis function.
  5. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of folder permissions, including access rights and inheritance
  • Identification of inherited vs. unique permissions
  • Detection of potentially risky ‘Everyone’ permissions
  • Analysis of permissions on nested folders
  • Identification of folders with explicit (non-inherited) permissions
  • Comprehensive HTML report generation

This tool is particularly useful for:

  • System administrators managing file system permissions
  • Security professionals auditing folder access rights
  • IT professionals troubleshooting permission-related issues
  • Compliance officers ensuring proper file system security

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to access and read folder permissions
  3. Be cautious when analyzing large directory structures, as it may take time for nested folder analysis

This script provides a comprehensive overview of folder permissions, making it easier to audit and maintain proper access controls, identify potential security issues, and ensure the correct configuration of folder permissions across Windows systems.

Workgroup Computer Audit Toolkit

<#
.SYNOPSIS
Workgroup Computer Audit Toolkit

.DESCRIPTION
This script performs a comprehensive audit of a Windows computer that is not part of a domain.
It checks various system settings, security configurations, and local information.

.NOTES
File Name      : WorkgroupComputerAuditToolkit.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, administrator rights on the local machine
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\WorkgroupComputerAuditToolkit.ps1
#>

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Workgroup_Computer_Audit_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

function Show-Menu {
    Clear-Host
    Write-Host "=== Workgroup Computer Audit Toolkit ===" -ForegroundColor Cyan
    Write-Host "1. System Information"
    Write-Host "2. Local User Accounts"
    Write-Host "3. Installed Software"
    Write-Host "4. Windows Update Status"
    Write-Host "5. Security Settings"
    Write-Host "6. Network Configuration"
    Write-Host "7. Shared Folders"
    Write-Host "8. Scheduled Tasks"
    Write-Host "9. Services Analysis"
    Write-Host "10. Generate Comprehensive HTML Report"
    Write-Host "11. Exit"
}

function Get-SystemInformation {
    Write-Host "`nGathering System Information..." -ForegroundColor Yellow
    $os = Get-WmiObject Win32_OperatingSystem
    $cs = Get-WmiObject Win32_ComputerSystem
    $bios = Get-WmiObject Win32_BIOS

    $result = [PSCustomObject]@{
        ComputerName = $env:COMPUTERNAME
        OSName = $os.Caption
        OSVersion = $os.Version
        OSArchitecture = $os.OSArchitecture
        Manufacturer = $cs.Manufacturer
        Model = $cs.Model
        BIOSVersion = $bios.SMBIOSBIOSVersion
        LastBootUpTime = $os.ConvertToDateTime($os.LastBootUpTime)
        InstallDate = $os.ConvertToDateTime($os.InstallDate)
        WorkgroupName = $cs.Workgroup
    }

    $result | Format-List
    return $result
}

function Get-LocalUserAccounts {
    Write-Host "`nGathering Local User Account Information..." -ForegroundColor Yellow
    $users = Get-WmiObject Win32_UserAccount -Filter "LocalAccount=True"
    $results = @()

    foreach ($user in $users) {
        $results += [PSCustomObject]@{
            Username = $user.Name
            FullName = $user.FullName
            Disabled = $user.Disabled
            PasswordRequired = $user.PasswordRequired
            PasswordChangeable = $user.PasswordChangeable
            PasswordExpires = $user.PasswordExpires
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-InstalledSoftware {
    Write-Host "`nGathering Installed Software Information..." -ForegroundColor Yellow
    $software = Get-WmiObject Win32_Product | Select-Object Name, Version, Vendor, InstallDate
    $software | Format-Table -AutoSize
    return $software
}

function Get-WindowsUpdateStatus {
    Write-Host "`nChecking Windows Update Status..." -ForegroundColor Yellow
    $updateSession = New-Object -ComObject Microsoft.Update.Session
    $updateSearcher = $updateSession.CreateUpdateSearcher()
    $pendingUpdates = $updateSearcher.Search("IsInstalled=0")

    $result = [PSCustomObject]@{
        PendingUpdatesCount = $pendingUpdates.Updates.Count
        LastUpdateDate = (Get-HotFix | Sort-Object -Property InstalledOn -Descending | Select-Object -First 1).InstalledOn
    }

    $result | Format-List
    return $result
}

function Get-SecuritySettings {
    Write-Host "`nGathering Security Settings..." -ForegroundColor Yellow
    $firewallStatus = Get-NetFirewallProfile | Select-Object Name, Enabled
    $avProduct = Get-WmiObject -Namespace root\SecurityCenter2 -Class AntiVirusProduct
    $uac = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "EnableLUA"

    $result = [PSCustomObject]@{
        FirewallStatus = $firewallStatus
        AntiVirusProduct = $avProduct.displayName
        UACEnabled = $uac.EnableLUA -eq 1
    }

    $result | Format-List
    return $result
}

function Get-NetworkConfiguration {
    Write-Host "`nGathering Network Configuration..." -ForegroundColor Yellow
    $adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true }
    $results = @()

    foreach ($adapter in $adapters) {
        $results += [PSCustomObject]@{
            AdapterName = $adapter.Description
            IPAddress = $adapter.IPAddress -join ", "
            SubnetMask = $adapter.IPSubnet -join ", "
            DefaultGateway = $adapter.DefaultIPGateway -join ", "
            DNSServers = $adapter.DNSServerSearchOrder -join ", "
            MACAddress = $adapter.MACAddress
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-SharedFolders {
    Write-Host "`nGathering Shared Folder Information..." -ForegroundColor Yellow
    $shares = Get-WmiObject Win32_Share
    $results = @()

    foreach ($share in $shares) {
        $results += [PSCustomObject]@{
            Name = $share.Name
            Path = $share.Path
            Description = $share.Description
            Type = switch ($share.Type) {
                0 {"Disk Drive"}
                1 {"Print Queue"}
                2 {"Device"}
                3 {"IPC"}
                2147483648 {"Disk Drive Admin"}
                2147483649 {"Print Queue Admin"}
                2147483650 {"Device Admin"}
                2147483651 {"IPC Admin"}
            }
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-ScheduledTasks {
    Write-Host "`nGathering Scheduled Task Information..." -ForegroundColor Yellow
    $tasks = Get-ScheduledTask | Where-Object {$_.State -ne "Disabled"}
    $results = @()

    foreach ($task in $tasks) {
        $results += [PSCustomObject]@{
            TaskName = $task.TaskName
            State = $task.State
            LastRunTime = $task.LastRunTime
            NextRunTime = $task.NextRunTime
            Author = $task.Author
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-ServicesAnalysis {
    Write-Host "`nAnalyzing Services..." -ForegroundColor Yellow
    $services = Get-WmiObject Win32_Service
    $results = @()

    foreach ($service in $services) {
        $results += [PSCustomObject]@{
            Name = $service.Name
            DisplayName = $service.DisplayName
            StartMode = $service.StartMode
            State = $service.State
            StartName = $service.StartName
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Workgroup Computer Audit Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .warning { color: orange; }
        .critical { color: red; }
    </style>
</head>
<body>
    <h1>Workgroup Computer Audit Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>System Information</h2>
    $($AllResults.SystemInfo | ConvertTo-Html -Fragment)

    <h2>Local User Accounts</h2>
    $($AllResults.LocalUsers | ConvertTo-Html -Fragment)

    <h2>Installed Software</h2>
    $($AllResults.InstalledSoftware | ConvertTo-Html -Fragment)

    <h2>Windows Update Status</h2>
    $($AllResults.WindowsUpdateStatus | ConvertTo-Html -Fragment)

    <h2>Security Settings</h2>
    $($AllResults.SecuritySettings | ConvertTo-Html -Fragment)

    <h2>Network Configuration</h2>
    $($AllResults.NetworkConfig | ConvertTo-Html -Fragment)

    <h2>Shared Folders</h2>
    $($AllResults.SharedFolders | ConvertTo-Html -Fragment)

    <h2>Scheduled Tasks</h2>
    $($AllResults.ScheduledTasks | ConvertTo-Html -Fragment)

    <h2>Services Analysis</h2>
    $($AllResults.ServicesAnalysis | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-11)"

    switch ($choice) {
        "1" { $allResults.SystemInfo = Get-SystemInformation }
        "2" { $allResults.LocalUsers = Get-LocalUserAccounts }
        "3" { $allResults.InstalledSoftware = Get-InstalledSoftware }
        "4" { $allResults.WindowsUpdateStatus = Get-WindowsUpdateStatus }
        "5" { $allResults.SecuritySettings = Get-SecuritySettings }
        "6" { $allResults.NetworkConfig = Get-NetworkConfiguration }
        "7" { $allResults.SharedFolders = Get-SharedFolders }
        "8" { $allResults.ScheduledTasks = Get-ScheduledTasks }
        "9" { $allResults.ServicesAnalysis = Get-ServicesAnalysis }
        "10" { Generate-HTMLReport -AllResults $allResults }
        "11" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "11") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "11")

This Workgroup Computer Audit Toolkit includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to gather various aspects of the local Windows computer:
    • System Information
    • Local User Accounts
    • Installed Software
    • Windows Update Status
    • Security Settings
    • Network Configuration
    • Shared Folders
    • Scheduled Tasks
    • Services Analysis
  3. HTML report generation for easy sharing and viewing of results.

Key features:

  • Comprehensive system information gathering
  • Local user account analysis
  • Software inventory
  • Windows Update status check
  • Basic security settings review (firewall, antivirus, UAC)
  • Network configuration details
  • Shared folder enumeration
  • Active scheduled tasks listing
  • Services analysis

This tool is particularly useful for:

  • IT administrators performing audits on standalone or workgroup computers
  • Security professionals assessing the configuration of non-domain Windows machines
  • Help desk personnel gathering system information for troubleshooting
  • Anyone needing to quickly collect comprehensive information about a Windows computer not joined to a domain

To use this script effectively:

  1. Run PowerShell as an administrator on the Windows computer you want to audit
  2. Ensure you have the necessary permissions to query system information
  3. Review the generated HTML report for a comprehensive overview of the computer’s configuration

This script provides a thorough audit of a workgroup Windows computer, helping to identify potential issues, misconfigurations, or security concerns. It’s designed to be run locally on the machine being audited, making it suitable for situations where centralized management tools are not available.

LDAP and LDAPS Check Toolkit

<#
.SYNOPSIS
LDAP and LDAPS Check Toolkit

.DESCRIPTION
This script provides comprehensive checks and tests for LDAP and LDAPS configurations,
including connectivity, security, and certificate validation.

.NOTES
File Name      : LDAPCheckToolkit.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, appropriate permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\LDAPCheckToolkit.ps1
#>

# Import required modules
Import-Module ActiveDirectory

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\LDAP_Check_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
$global:ldapServer = $env:COMPUTERNAME  # Default to local machine
$global:ldapPort = 389  # Default LDAP port
$global:ldapsPort = 636  # Default LDAPS port

function Show-Menu {
    Clear-Host
    Write-Host "=== LDAP and LDAPS Check Toolkit ===" -ForegroundColor Cyan
    Write-Host "Current LDAP Server: $global:ldapServer"
    Write-Host "1. Set LDAP Server"
    Write-Host "2. Test LDAP Connectivity"
    Write-Host "3. Test LDAPS Connectivity"
    Write-Host "4. Check LDAP Binding"
    Write-Host "5. Verify LDAP SSL Certificate"
    Write-Host "6. Check LDAP Server Capabilities"
    Write-Host "7. Test LDAP Query"
    Write-Host "8. Check LDAP Security Settings"
    Write-Host "9. Analyze LDAP Traffic"
    Write-Host "10. Generate Comprehensive HTML Report"
    Write-Host "11. Exit"
}

function Set-LDAPServer {
    $server = Read-Host "Enter the LDAP server name (or press Enter for localhost)"
    if ([string]::IsNullOrWhiteSpace($server)) {
        $global:ldapServer = $env:COMPUTERNAME
    } else {
        $global:ldapServer = $server
    }
    Write-Host "LDAP server set to: $global:ldapServer" -ForegroundColor Green
}

function Test-LDAPConnectivity {
    Write-Host "`nTesting LDAP Connectivity..." -ForegroundColor Yellow
    try {
        $result = Test-NetConnection -ComputerName $global:ldapServer -Port $global:ldapPort
        if ($result.TcpTestSucceeded) {
            Write-Host "LDAP connectivity test successful." -ForegroundColor Green
        } else {
            Write-Host "LDAP connectivity test failed." -ForegroundColor Red
        }
        return $result
    }
    catch {
        Write-Host "Error testing LDAP connectivity: $_" -ForegroundColor Red
        return $null
    }
}

function Test-LDAPSConnectivity {
    Write-Host "`nTesting LDAPS Connectivity..." -ForegroundColor Yellow
    try {
        $result = Test-NetConnection -ComputerName $global:ldapServer -Port $global:ldapsPort
        if ($result.TcpTestSucceeded) {
            Write-Host "LDAPS connectivity test successful." -ForegroundColor Green
        } else {
            Write-Host "LDAPS connectivity test failed." -ForegroundColor Red
        }
        return $result
    }
    catch {
        Write-Host "Error testing LDAPS connectivity: $_" -ForegroundColor Red
        return $null
    }
}

function Check-LDAPBinding {
    Write-Host "`nChecking LDAP Binding..." -ForegroundColor Yellow
    try {
        $domainDN = (Get-ADDomain).DistinguishedName
        $ldapPath = "LDAP://$global:ldapServer/$domainDN"
        $ldapConnection = New-Object System.DirectoryServices.DirectoryEntry($ldapPath)
        
        if ($ldapConnection.Name -ne $null) {
            Write-Host "LDAP binding successful." -ForegroundColor Green
            $result = @{
                Success = $true
                Path = $ldapPath
                Name = $ldapConnection.Name
            }
        } else {
            Write-Host "LDAP binding failed." -ForegroundColor Red
            $result = @{
                Success = $false
                Path = $ldapPath
                Error = "Unable to bind to LDAP server"
            }
        }
        return $result
    }
    catch {
        Write-Host "Error checking LDAP binding: $_" -ForegroundColor Red
        return @{
            Success = $false
            Path = $ldapPath
            Error = $_.Exception.Message
        }
    }
}

function Verify-LDAPSSLCertificate {
    Write-Host "`nVerifying LDAP SSL Certificate..." -ForegroundColor Yellow
    try {
        $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
        $cert.Import("LDAP://$global:ldapServer`:$global:ldapsPort")
        
        $result = @{
            Subject = $cert.Subject
            Issuer = $cert.Issuer
            ValidFrom = $cert.NotBefore
            ValidTo = $cert.NotAfter
            Thumbprint = $cert.Thumbprint
        }
        
        if ((Get-Date) -gt $cert.NotAfter) {
            Write-Host "SSL Certificate has expired." -ForegroundColor Red
        } else {
            Write-Host "SSL Certificate is valid." -ForegroundColor Green
        }
        
        return $result
    }
    catch {
        Write-Host "Error verifying LDAP SSL Certificate: $_" -ForegroundColor Red
        return $null
    }
}

function Check-LDAPServerCapabilities {
    Write-Host "`nChecking LDAP Server Capabilities..." -ForegroundColor Yellow
    try {
        $rootDSE = [ADSI]"LDAP://$global:ldapServer/RootDSE"
        $capabilities = $rootDSE.supportedCapabilities
        $ldapVersion = $rootDSE.supportedLDAPVersion
        $controls = $rootDSE.supportedControl
        
        $result = @{
            SupportedCapabilities = $capabilities
            SupportedLDAPVersion = $ldapVersion
            SupportedControls = $controls
        }
        
        Write-Host "LDAP Server Capabilities retrieved successfully." -ForegroundColor Green
        return $result
    }
    catch {
        Write-Host "Error checking LDAP Server Capabilities: $_" -ForegroundColor Red
        return $null
    }
}

function Test-LDAPQuery {
    Write-Host "`nTesting LDAP Query..." -ForegroundColor Yellow
    try {
        $domainDN = (Get-ADDomain).DistinguishedName
        $searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$global:ldapServer/$domainDN")
        $searcher.Filter = "(objectClass=user)"
        $searcher.SizeLimit = 5
        $results = $searcher.FindAll()
        
        $queryResults = @()
        foreach ($result in $results) {
            $queryResults += [PSCustomObject]@{
                Name = $result.Properties["name"][0]
                DistinguishedName = $result.Properties["distinguishedname"][0]
            }
        }
        
        Write-Host "LDAP Query test successful." -ForegroundColor Green
        return $queryResults
    }
    catch {
        Write-Host "Error testing LDAP Query: $_" -ForegroundColor Red
        return $null
    }
}

function Check-LDAPSecuritySettings {
    Write-Host "`nChecking LDAP Security Settings..." -ForegroundColor Yellow
    try {
        $ntdsSettings = Get-ADObject -Identity "CN=NTDS Settings,CN=$global:ldapServer,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,$((Get-ADDomain).DistinguishedName)" -Properties *
        
        $result = @{
            LDAPServerSigningRequired = $ntdsSettings.LDAPServerIntegrity -eq 2
            LDAPSEnabled = $ntdsSettings.SSLPort -ne $null
            NTLMAuthEnabled = $ntdsSettings.SupportedSASLMechanisms -contains "GSSAPI"
            KerberosAuthEnabled = $ntdsSettings.SupportedSASLMechanisms -contains "GSS-SPNEGO"
        }
        
        Write-Host "LDAP Security Settings retrieved successfully." -ForegroundColor Green
        return $result
    }
    catch {
        Write-Host "Error checking LDAP Security Settings: $_" -ForegroundColor Red
        return $null
    }
}

function Analyze-LDAPTraffic {
    Write-Host "`nAnalyzing LDAP Traffic..." -ForegroundColor Yellow
    Write-Host "This function would typically use network monitoring tools to analyze LDAP traffic."
    Write-Host "For security and complexity reasons, actual traffic analysis is not implemented in this script."
    Write-Host "Consider using tools like Wireshark or Microsoft Network Monitor for detailed LDAP traffic analysis."
    
    # Placeholder for traffic analysis results
    $result = @{
        TotalConnections = "N/A"
        AverageResponseTime = "N/A"
        ErrorRate = "N/A"
    }
    
    return $result
}

function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LDAP and LDAPS Check Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .success { color: green; }
        .warning { color: orange; }
        .error { color: red; }
    </style>
</head>
<body>
    <h1>LDAP and LDAPS Check Report</h1>
    <p>Generated on: $(Get-Date)</p>
    <p>LDAP Server: $global:ldapServer</p>

    <h2>LDAP Connectivity</h2>
    $($AllResults.LDAPConnectivity | ConvertTo-Html -Fragment)

    <h2>LDAPS Connectivity</h2>
    $($AllResults.LDAPSConnectivity | ConvertTo-Html -Fragment)

    <h2>LDAP Binding</h2>
    $($AllResults.LDAPBinding | ConvertTo-Html -Fragment)

    <h2>LDAP SSL Certificate</h2>
    $($AllResults.LDAPSSLCertificate | ConvertTo-Html -Fragment)

    <h2>LDAP Server Capabilities</h2>
    $($AllResults.ServerCapabilities | ConvertTo-Html -Fragment)

    <h2>LDAP Query Test</h2>
    $($AllResults.LDAPQuery | ConvertTo-Html -Fragment)

    <h2>LDAP Security Settings</h2>
    $($AllResults.SecuritySettings | ConvertTo-Html -Fragment)

    <h2>LDAP Traffic Analysis</h2>
    $($AllResults.TrafficAnalysis | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-11)"

    switch ($choice) {
        "1" { Set-LDAPServer }
        "2" { $allResults.LDAPConnectivity = Test-LDAPConnectivity }
        "3" { $allResults.LDAPSConnectivity = Test-LDAPSConnectivity }
        "4" { $allResults.LDAPBinding = Check-LDAPBinding }
        "5" { $allResults.LDAPSSLCertificate = Verify-LDAPSSLCertificate }
        "6" { $allResults.ServerCapabilities = Check-LDAPServerCapabilities }
        "7" { $allResults.LDAPQuery = Test-LDAPQuery }
        "8" { $allResults.SecuritySettings = Check-LDAPSecuritySettings }
        "9" { $allResults.TrafficAnalysis = Analyze-LDAPTraffic }
        "10" { Generate-HTMLReport -AllResults $allResults }
        "11" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "11") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "11")

This LDAP and LDAPS Check Toolkit includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze and test various aspects of LDAP and LDAPS:
    • LDAP and LDAPS Connectivity Tests
    • LDAP Binding Check
    • LDAP SSL Certificate Verification
    • LDAP Server Capabilities Check
    • LDAP Query Test
    • LDAP Security Settings Check
    • LDAP Traffic Analysis (placeholder)
  3. Option to set a target LDAP server (local or remote)
  4. HTML report generation for easy sharing and viewing of results

Key features:

  • Comprehensive LDAP and LDAPS connectivity testing
  • Detailed SSL certificate verification for LDAPS
  • Analysis of LDAP server capabilities and supported features
  • Basic LDAP query testing
  • Review of LDAP security settings
  • Placeholder for LDAP traffic analysis (which would typically require additional tools)

This tool is particularly useful for:

  • System administrators managing LDAP-enabled environments
  • Security professionals auditing LDAP configurations
  • IT professionals troubleshooting LDAP-related issues
  • Anyone needing to quickly gather comprehensive information about LDAP and LDAPS configurations

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the Active Directory PowerShell module installed
  3. Have the necessary permissions to query LDAP server information
  4. Review the generated HTML report for a comprehensive overview of the LDAP server’s configuration and status

Note: The LDAP traffic analysis function is a placeholder and would typically require additional network monitoring tools to implement fully. For actual traffic analysis, consider using specialized tools like Wireshark or Microsoft Network Monitor.

This script provides a thorough analysis of LDAP and LDAPS configurations, helping to identify potential issues, misconfigurations, or security concerns. It’s designed to give administrators a quick but comprehensive view of their LDAP server’s health and configuration.

DHCP Toolkit

<#
.SYNOPSIS
DHCP Toolkit

.DESCRIPTION
This script provides comprehensive analysis and management options for DHCP servers in a Windows environment.

.NOTES
File Name      : DHCPToolkit.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, DHCP Server module, and appropriate admin rights
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\DHCPToolkit.ps1
#>

# Import required module
Import-Module DHCPServer

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\DHCP_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
$global:dhcpServer = $env:COMPUTERNAME  # Default to local machine

function Show-Menu {
    Clear-Host
    Write-Host "=== DHCP Toolkit ===" -ForegroundColor Cyan
    Write-Host "Current DHCP Server: $global:dhcpServer"
    Write-Host "1. Set DHCP Server"
    Write-Host "2. Get DHCP Server Information"
    Write-Host "3. List DHCP Scopes"
    Write-Host "4. Analyze Scope Utilization"
    Write-Host "5. Check DHCP Options"
    Write-Host "6. List DHCP Reservations"
    Write-Host "7. Check DHCP Failover Configuration"
    Write-Host "8. Analyze DHCP Lease History"
    Write-Host "9. Check DHCP Server Statistics"
    Write-Host "10. Generate Comprehensive HTML Report"
    Write-Host "11. Exit"
}

function Set-DHCPServer {
    $server = Read-Host "Enter the DHCP server name (or press Enter for localhost)"
    if ([string]::IsNullOrWhiteSpace($server)) {
        $global:dhcpServer = $env:COMPUTERNAME
    } else {
        $global:dhcpServer = $server
    }
    Write-Host "DHCP server set to: $global:dhcpServer" -ForegroundColor Green
}

function Get-DHCPServerInformation {
    Write-Host "`nGathering DHCP Server Information..." -ForegroundColor Yellow
    try {
        $serverInfo = Get-DhcpServerSetting -ComputerName $global:dhcpServer
        $result = [PSCustomObject]@{
            ServerName = $global:dhcpServer
            ConflictDetectionAttempts = $serverInfo.ConflictDetectionAttempts
            DynamicBootp = $serverInfo.DynamicBootp
            IsAuthorized = $serverInfo.IsAuthorized
            NapEnabled = $serverInfo.NapEnabled
            RestoreStatus = $serverInfo.RestoreStatus
        }
        $result | Format-List
        return $result
    }
    catch {
        Write-Host "Error getting DHCP server information: $_" -ForegroundColor Red
        return $null
    }
}

function Get-DHCPScopes {
    Write-Host "`nListing DHCP Scopes..." -ForegroundColor Yellow
    try {
        $scopes = Get-DhcpServerv4Scope -ComputerName $global:dhcpServer
        $scopes | Format-Table -AutoSize
        return $scopes
    }
    catch {
        Write-Host "Error getting DHCP scopes: $_" -ForegroundColor Red
        return $null
    }
}

function Analyze-ScopeUtilization {
    Write-Host "`nAnalyzing Scope Utilization..." -ForegroundColor Yellow
    try {
        $scopes = Get-DhcpServerv4Scope -ComputerName $global:dhcpServer
        $results = @()
        foreach ($scope in $scopes) {
            $stats = Get-DhcpServerv4ScopeStatistics -ComputerName $global:dhcpServer -ScopeId $scope.ScopeId
            $results += [PSCustomObject]@{
                ScopeName = $scope.Name
                ScopeId = $scope.ScopeId
                TotalAddresses = $stats.TotalAddresses
                InUse = $stats.AddressesInUse
                Available = $stats.AddressesAvailable
                UtilizationPercentage = [math]::Round(($stats.AddressesInUse / $stats.TotalAddresses) * 100, 2)
            }
        }
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error analyzing scope utilization: $_" -ForegroundColor Red
        return $null
    }
}

function Check-DHCPOptions {
    Write-Host "`nChecking DHCP Options..." -ForegroundColor Yellow
    try {
        $serverOptions = Get-DhcpServerv4OptionValue -ComputerName $global:dhcpServer
        $scopeOptions = Get-DhcpServerv4Scope -ComputerName $global:dhcpServer | ForEach-Object {
            Get-DhcpServerv4OptionValue -ComputerName $global:dhcpServer -ScopeId $_.ScopeId
        }
        
        $results = @{
            ServerOptions = $serverOptions
            ScopeOptions = $scopeOptions
        }
        
        $serverOptions | Format-Table -AutoSize
        Write-Host "Scope-specific options are available in the returned object." -ForegroundColor Yellow
        return $results
    }
    catch {
        Write-Host "Error checking DHCP options: $_" -ForegroundColor Red
        return $null
    }
}

function List-DHCPReservations {
    Write-Host "`nListing DHCP Reservations..." -ForegroundColor Yellow
    try {
        $scopes = Get-DhcpServerv4Scope -ComputerName $global:dhcpServer
        $results = @()
        foreach ($scope in $scopes) {
            $reservations = Get-DhcpServerv4Reservation -ComputerName $global:dhcpServer -ScopeId $scope.ScopeId
            foreach ($reservation in $reservations) {
                $results += [PSCustomObject]@{
                    ScopeId = $scope.ScopeId
                    IPAddress = $reservation.IPAddress
                    ClientId = $reservation.ClientId
                    Name = $reservation.Name
                }
            }
        }
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error listing DHCP reservations: $_" -ForegroundColor Red
        return $null
    }
}

function Check-DHCPFailover {
    Write-Host "`nChecking DHCP Failover Configuration..." -ForegroundColor Yellow
    try {
        $failoverRelationships = Get-DhcpServerv4Failover -ComputerName $global:dhcpServer
        if ($failoverRelationships) {
            $failoverRelationships | Format-Table -AutoSize
        } else {
            Write-Host "No failover relationships configured." -ForegroundColor Yellow
        }
        return $failoverRelationships
    }
    catch {
        Write-Host "Error checking DHCP failover configuration: $_" -ForegroundColor Red
        return $null
    }
}

function Analyze-DHCPLeaseHistory {
    Write-Host "`nAnalyzing DHCP Lease History..." -ForegroundColor Yellow
    try {
        $startDate = (Get-Date).AddDays(-7)
        $leaseHistory = Get-DhcpServerv4ScopeStatistics -ComputerName $global:dhcpServer | ForEach-Object {
            Get-DhcpServerv4LeaseHistory -ComputerName $global:dhcpServer -ScopeId $_.ScopeId -StartDate $startDate
        }
        
        $results = $leaseHistory | Group-Object ScopeId | ForEach-Object {
            [PSCustomObject]@{
                ScopeId = $_.Name
                LeaseCount = $_.Count
                UniqueClients = ($_.Group | Select-Object -ExpandProperty ClientId -Unique).Count
            }
        }
        
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error analyzing DHCP lease history: $_" -ForegroundColor Red
        return $null
    }
}

function Check-DHCPServerStatistics {
    Write-Host "`nChecking DHCP Server Statistics..." -ForegroundColor Yellow
    try {
        $stats = Get-DhcpServerStatistics -ComputerName $global:dhcpServer
        $result = [PSCustomObject]@{
            TotalScopes = $stats.TotalScopes
            TotalAddresses = $stats.TotalAddresses
            AddressesInUse = $stats.AddressesInUse
            AddressesAvailable = $stats.AddressesAvailable
            PercentageInUse = [math]::Round(($stats.AddressesInUse / $stats.TotalAddresses) * 100, 2)
            Discovers = $stats.Discovers
            Offers = $stats.Offers
            Requests = $stats.Requests
            Acks = $stats.Acks
            Naks = $stats.Naks
            Declines = $stats.Declines
            Releases = $stats.Releases
        }
        $result | Format-List
        return $result
    }
    catch {
        Write-Host "Error checking DHCP server statistics: $_" -ForegroundColor Red
        return $null
    }
}

function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DHCP Server Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .warning { color: orange; }
        .critical { color: red; }
    </style>
</head>
<body>
    <h1>DHCP Server Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>
    <p>DHCP Server: $global:dhcpServer</p>

    <h2>DHCP Server Information</h2>
    $($AllResults.ServerInfo | ConvertTo-Html -Fragment)

    <h2>DHCP Scopes</h2>
    $($AllResults.Scopes | ConvertTo-Html -Fragment)

    <h2>Scope Utilization</h2>
    $($AllResults.ScopeUtilization | ConvertTo-Html -Fragment)

    <h2>DHCP Options</h2>
    <h3>Server Options</h3>
    $($AllResults.DHCPOptions.ServerOptions | ConvertTo-Html -Fragment)

    <h2>DHCP Reservations</h2>
    $($AllResults.Reservations | ConvertTo-Html -Fragment)

    <h2>DHCP Failover Configuration</h2>
    $($AllResults.FailoverConfig | ConvertTo-Html -Fragment)

    <h2>DHCP Lease History (Last 7 Days)</h2>
    $($AllResults.LeaseHistory | ConvertTo-Html -Fragment)

    <h2>DHCP Server Statistics</h2>
    $($AllResults.ServerStats | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-11)"

    switch ($choice) {
        "1" { Set-DHCPServer }
        "2" { $allResults.ServerInfo = Get-DHCPServerInformation }
        "3" { $allResults.Scopes = Get-DHCPScopes }
        "4" { $allResults.ScopeUtilization = Analyze-ScopeUtilization }
        "5" { $allResults.DHCPOptions = Check-DHCPOptions }
        "6" { $allResults.Reservations = List-DHCPReservations }
        "7" { $allResults.FailoverConfig = Check-DHCPFailover }
        "8" { $allResults.LeaseHistory = Analyze-DHCPLeaseHistory }
        "9" { $allResults.ServerStats = Check-DHCPServerStatistics }
        "10" { Generate-HTMLReport -AllResults $allResults }
        "11" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "11") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "11")

This DHCP Toolkit includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze and manage various aspects of DHCP servers:
    • DHCP Server Information
    • DHCP Scopes Listing
    • Scope Utilization Analysis
    • DHCP Options Check
    • DHCP Reservations Listing
    • DHCP Failover Configuration Check
    • DHCP Lease History Analysis
    • DHCP Server Statistics Check
  3. Option to set a target DHCP server (local or remote)
  4. HTML report generation for easy sharing and viewing of results

Key features:

  • Comprehensive DHCP server information gathering
  • Detailed analysis of scope utilization
  • Review of DHCP options at server and scope level
  • Listing of DHCP reservations across all scopes
  • Failover configuration check
  • Analysis of recent lease history
  • Overview of DHCP server statistics

This tool is particularly useful for:

  • Network administrators managing DHCP servers
  • IT professionals troubleshooting DHCP-related issues
  • System administrators performing regular DHCP health checks
  • Anyone needing to quickly gather comprehensive information about DHCP server configurations

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the DHCP Server PowerShell module installed (typically available on DHCP servers or management workstations)
  3. Have the necessary permissions to query DHCP server information (local admin rights on the DHCP server or appropriate delegated permissions)
  4. Review the generated HTML report for a comprehensive overview of the DHCP server’s configuration and status

This script provides a thorough analysis of a DHCP server, helping to identify potential issues, misconfigurations, or areas that need attention. It’s designed to give administrators a quick but comprehensive view of their DHCP server’s health and configuration.

Domain Check Toolkit

<#
.SYNOPSIS
Domain Check Toolkit

.DESCRIPTION
This script performs comprehensive checks and information gathering on an Active Directory domain,
providing insights into domain controllers, users, groups, GPOs, and other domain-related configurations.

.NOTES
File Name      : DomainCheckToolkit.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, Active Directory module, and appropriate domain admin rights
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\DomainCheckToolkit.ps1
#>

# Import required modules
Import-Module ActiveDirectory

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Domain_Check_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

function Show-Menu {
    Clear-Host
    Write-Host "=== Domain Check Toolkit ===" -ForegroundColor Cyan
    Write-Host "1. Domain Information"
    Write-Host "2. Domain Controller Health Check"
    Write-Host "3. User Account Analysis"
    Write-Host "4. Group Analysis"
    Write-Host "5. Group Policy Object (GPO) Check"
    Write-Host "6. DNS Health Check"
    Write-Host "7. FSMO Roles Check"
    Write-Host "8. Replication Status"
    Write-Host "9. Trust Relationships"
    Write-Host "10. Generate Comprehensive HTML Report"
    Write-Host "11. Exit"
}

function Get-DomainInformation {
    Write-Host "`nGathering Domain Information..." -ForegroundColor Yellow
    $domainInfo = Get-ADDomain
    $forestInfo = Get-ADForest

    $result = [PSCustomObject]@{
        DomainName = $domainInfo.DNSRoot
        NetBIOSName = $domainInfo.NetBIOSName
        DomainMode = $domainInfo.DomainMode
        ForestName = $forestInfo.Name
        ForestMode = $forestInfo.ForestMode
        DomainControllers = ($domainInfo.ReplicaDirectoryServers -join ", ")
        GlobalCatalogs = ($forestInfo.GlobalCatalogs -join ", ")
    }

    $result | Format-List
    return $result
}

function Get-DomainControllerHealth {
    Write-Host "`nPerforming Domain Controller Health Check..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $results = @()

    foreach ($dc in $dcs) {
        $dcdiag = dcdiag /s:$($dc.HostName) /test:services /test:advertising /test:fsmocheck /test:ridmanager
        $results += [PSCustomObject]@{
            Name = $dc.HostName
            Site = $dc.Site
            IPv4Address = $dc.IPv4Address
            OperatingSystem = $dc.OperatingSystem
            IsGlobalCatalog = $dc.IsGlobalCatalog
            ServicesTest = if ($dcdiag -match "passed test Services") { "Passed" } else { "Failed" }
            AdvertisingTest = if ($dcdiag -match "passed test Advertising") { "Passed" } else { "Failed" }
            FSMOCheckTest = if ($dcdiag -match "passed test FsmoCheck") { "Passed" } else { "Failed" }
            RidManagerTest = if ($dcdiag -match "passed test RidManager") { "Passed" } else { "Failed" }
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-UserAccountAnalysis {
    Write-Host "`nPerforming User Account Analysis..." -ForegroundColor Yellow
    $users = Get-ADUser -Filter * -Properties Enabled, PasswordLastSet, LastLogonDate, PasswordNeverExpires
    $results = @{
        TotalUsers = $users.Count
        EnabledUsers = ($users | Where-Object { $_.Enabled -eq $true }).Count
        DisabledUsers = ($users | Where-Object { $_.Enabled -eq $false }).Count
        PasswordNeverExpires = ($users | Where-Object { $_.PasswordNeverExpires -eq $true }).Count
        InactiveUsers = ($users | Where-Object { $_.LastLogonDate -lt (Get-Date).AddDays(-90) }).Count
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-GroupAnalysis {
    Write-Host "`nPerforming Group Analysis..." -ForegroundColor Yellow
    $groups = Get-ADGroup -Filter *
    $results = @{
        TotalGroups = $groups.Count
        SecurityGroups = ($groups | Where-Object { $_.GroupCategory -eq "Security" }).Count
        DistributionGroups = ($groups | Where-Object { $_.GroupCategory -eq "Distribution" }).Count
        GlobalGroups = ($groups | Where-Object { $_.GroupScope -eq "Global" }).Count
        UniversalGroups = ($groups | Where-Object { $_.GroupScope -eq "Universal" }).Count
        DomainLocalGroups = ($groups | Where-Object { $_.GroupScope -eq "DomainLocal" }).Count
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-GPOCheck {
    Write-Host "`nPerforming Group Policy Object Check..." -ForegroundColor Yellow
    $gpos = Get-GPO -All
    $results = @()

    foreach ($gpo in $gpos) {
        $results += [PSCustomObject]@{
            Name = $gpo.DisplayName
            ID = $gpo.Id
            CreationTime = $gpo.CreationTime
            ModificationTime = $gpo.ModificationTime
            UserVersionNumber = $gpo.UserVersion.DSVersion
            ComputerVersionNumber = $gpo.ComputerVersion.DSVersion
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-DNSHealthCheck {
    Write-Host "`nPerforming DNS Health Check..." -ForegroundColor Yellow
    $dnsServers = Get-ADDomainController -Filter * | Select-Object -ExpandProperty Name
    $results = @()

    foreach ($server in $dnsServers) {
        $dnsTest = Test-DnsServer -ComputerName $server -Context DnsServer
        $results += [PSCustomObject]@{
            Server = $server
            IsResponding = $dnsTest.IsResponding
            TCPPort53Open = ($dnsTest.TcpOpen -contains 53)
            UDPPort53Open = ($dnsTest.UdpOpen -contains 53)
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Get-FSMORolesCheck {
    Write-Host "`nChecking FSMO Roles..." -ForegroundColor Yellow
    $domain = Get-ADDomain
    $forest = Get-ADForest

    $result = [PSCustomObject]@{
        PDCEmulator = $domain.PDCEmulator
        RIDMaster = $domain.RIDMaster
        InfrastructureMaster = $domain.InfrastructureMaster
        SchemaMaster = $forest.SchemaMaster
        DomainNamingMaster = $forest.DomainNamingMaster
    }

    $result | Format-List
    return $result
}

function Get-ReplicationStatus {
    Write-Host "`nChecking Replication Status..." -ForegroundColor Yellow
    $results = @()
    $repl = repadmin /showrepl * /csv
    $replData = ConvertFrom-Csv $repl

    foreach ($item in $replData) {
        if ($item."Number of Failures" -ne "0") {
            $results += [PSCustomObject]@{
                SourceDC = $item."Source DC"
                DestinationDC = $item."Destination DC"
                FailureCount = $item."Number of Failures"
                LastFailureTime = $item."Last Failure Time"
                LastSuccessTime = $item."Last Success Time"
            }
        }
    }

    if ($results.Count -eq 0) {
        Write-Host "No replication failures detected." -ForegroundColor Green
    } else {
        $results | Format-Table -AutoSize
    }
    return $results
}

function Get-TrustRelationships {
    Write-Host "`nChecking Trust Relationships..." -ForegroundColor Yellow
    $trusts = Get-ADTrust -Filter *
    $results = @()

    foreach ($trust in $trusts) {
        $results += [PSCustomObject]@{
            Name = $trust.Name
            Direction = $trust.Direction
            TrustType = $trust.TrustType
            ForestTransitive = $trust.ForestTransitive
            IntraForest = $trust.IntraForest
        }
    }

    $results | Format-Table -AutoSize
    return $results
}

function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Domain Check Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .warning { color: orange; }
        .critical { color: red; }
    </style>
</head>
<body>
    <h1>Domain Check Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>Domain Information</h2>
    $($AllResults.DomainInfo | ConvertTo-Html -Fragment)

    <h2>Domain Controller Health</h2>
    $($AllResults.DCHealth | ConvertTo-Html -Fragment)

    <h2>User Account Analysis</h2>
    $($AllResults.UserAnalysis | ConvertTo-Html -Fragment)

    <h2>Group Analysis</h2>
    $($AllResults.GroupAnalysis | ConvertTo-Html -Fragment)

    <h2>Group Policy Objects</h2>
    $($AllResults.GPOCheck | ConvertTo-Html -Fragment)

    <h2>DNS Health Check</h2>
    $($AllResults.DNSHealth | ConvertTo-Html -Fragment)

    <h2>FSMO Roles</h2>
    $($AllResults.FSMORoles | ConvertTo-Html -Fragment)

    <h2>Replication Status</h2>
    $($AllResults.ReplicationStatus | ConvertTo-Html -Fragment)

    <h2>Trust Relationships</h2>
    $($AllResults.TrustRelationships | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-11)"

    switch ($choice) {
        "1" { $allResults.DomainInfo = Get-DomainInformation }
        "2" { $allResults.DCHealth = Get-DomainControllerHealth }
        "3" { $allResults.UserAnalysis = Get-UserAccountAnalysis }
        "4" { $allResults.GroupAnalysis = Get-GroupAnalysis }
        "5" { $allResults.GPOCheck = Get-GPOCheck }
        "6" { $allResults.DNSHealth = Get-DNSHealthCheck }
        "7" { $allResults.FSMORoles = Get-FSMORolesCheck }
        "8" { $allResults.ReplicationStatus = Get-ReplicationStatus }
        "9" { $allResults.TrustRelationships = Get-TrustRelationships }
        "10" { Generate-HTMLReport -AllResults $allResults }
        "11" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "11") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "11")

This Domain Check Toolkit includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of the Active Directory domain:
    • Domain Information
    • Domain Controller Health Check
    • User Account Analysis
    • Group Analysis
    • Group Policy Object (GPO) Check
    • DNS Health Check
    • FSMO Roles Check
    • Replication Status
    • Trust Relationships
  3. HTML report generation for easy sharing and viewing of results.

Key features:

  • Comprehensive domain information gathering
  • Health check of all domain controllers
  • Analysis of user accounts, including inactive and potentially insecure accounts
  • Overview of group distribution in the domain
  • GPO inventory and version checking
  • DNS server health verification
  • FSMO roles location check
  • Replication status and failure detection
  • Trust relationship enumeration

This tool is particularly useful for:

  • Domain administrators performing regular health checks
  • IT professionals troubleshooting domain-wide issues
  • Security auditors reviewing domain configurations
  • Anyone needing to quickly gather comprehensive information about an Active Directory domain

To use this script effectively:

  1. Run PowerShell as an administrator on a domain-joined machine (preferably a domain controller)
  2. Ensure you have the necessary permissions to query domain information (Domain Admin or equivalent rights)
  3. Have the Active Directory PowerShell module installed
  4. Review the generated HTML report for a comprehensive overview of the domain’s status and configuration

This script provides a thorough check of an Active Directory domain, helping to identify potential issues, misconfigurations, or security concerns. It’s designed to give administrators a quick but comprehensive view of their domain’s health and configuration.

Local Windows Client Audit Toolkit

<#
.SYNOPSIS
Local Windows Client Audit Toolkit

.DESCRIPTION
This script performs a comprehensive audit of a local Windows client machine,
gathering information about hardware, software, security settings, and more.

.NOTES
File Name      : LocalWindowsClientAuditToolkit.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, administrator rights
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\LocalWindowsClientAuditToolkit.ps1
#>

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Windows_Client_Audit_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

function Show-Menu {
    Clear-Host
    Write-Host "=== Local Windows Client Audit Toolkit ===" -ForegroundColor Cyan
    Write-Host "1. System Information"
    Write-Host "2. Hardware Inventory"
    Write-Host "3. Installed Software"
    Write-Host "4. Windows Update Status"
    Write-Host "5. Security Settings"
    Write-Host "6. Network Configuration"
    Write-Host "7. User Accounts and Groups"
    Write-Host "8. Startup Programs"
    Write-Host "9. Disk Space and File System"
    Write-Host "10. Event Log Analysis"
    Write-Host "11. Generate Comprehensive HTML Report"
    Write-Host "12. Exit"
}

function Get-SystemInformation {
    Write-Host "`nGathering System Information..." -ForegroundColor Yellow
    $os = Get-CimInstance Win32_OperatingSystem
    $cs = Get-CimInstance Win32_ComputerSystem
    $result = [PSCustomObject]@{
        ComputerName = $env:COMPUTERNAME
        OSName = $os.Caption
        OSVersion = $os.Version
        OSArchitecture = $os.OSArchitecture
        LastBootUpTime = $os.LastBootUpTime
        Manufacturer = $cs.Manufacturer
        Model = $cs.Model
        TotalPhysicalMemory = "{0:N2} GB" -f ($cs.TotalPhysicalMemory / 1GB)
    }
    $result | Format-List
    return $result
}

function Get-HardwareInventory {
    Write-Host "`nGathering Hardware Inventory..." -ForegroundColor Yellow
    $cpu = Get-CimInstance Win32_Processor
    $ram = Get-CimInstance Win32_PhysicalMemory
    $disk = Get-CimInstance Win32_DiskDrive
    $gpu = Get-CimInstance Win32_VideoController

    $result = [PSCustomObject]@{
        CPU = "$($cpu.Name) ($($cpu.NumberOfCores) cores, $($cpu.NumberOfLogicalProcessors) logical processors)"
        RAM = $ram | ForEach-Object { "$($_.Capacity / 1GB) GB $($_.Manufacturer)" }
        Disks = $disk | ForEach-Object { "$($_.Model) ($([math]::Round($_.Size / 1GB)) GB)" }
        GPU = $gpu.Name
    }
    $result | Format-List
    return $result
}

function Get-InstalledSoftware {
    Write-Host "`nGathering Installed Software..." -ForegroundColor Yellow
    $software = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*,
                                 HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
                Where-Object { $_.DisplayName -and $_.DisplayName -notmatch '^(Update for|Security Update for|Hotfix for)' } |
                Select-Object DisplayName, DisplayVersion, Publisher, InstallDate |
                Sort-Object DisplayName

    $software | Format-Table -AutoSize
    return $software
}

function Get-WindowsUpdateStatus {
    Write-Host "`nChecking Windows Update Status..." -ForegroundColor Yellow
    $updateSession = New-Object -ComObject Microsoft.Update.Session
    $updateSearcher = $updateSession.CreateUpdateSearcher()
    $pendingUpdates = $updateSearcher.Search("IsInstalled=0")

    $lastUpdate = Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 1

    $result = [PSCustomObject]@{
        PendingUpdatesCount = $pendingUpdates.Updates.Count
        LastUpdateDate = $lastUpdate.InstalledOn
        LastUpdateHotfixID = $lastUpdate.HotFixID
    }
    $result | Format-List
    return $result
}

function Get-SecuritySettings {
    Write-Host "`nGathering Security Settings..." -ForegroundColor Yellow
    $firewall = Get-NetFirewallProfile
    $av = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct
    $uac = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "EnableLUA"

    $result = [PSCustomObject]@{
        FirewallStatus = $firewall | ForEach-Object { "$($_.Name): $($_.Enabled)" }
        AntivirusProduct = $av.displayName
        UACEnabled = if ($uac.EnableLUA -eq 1) { "Enabled" } else { "Disabled" }
    }
    $result | Format-List
    return $result
}

function Get-NetworkConfiguration {
    Write-Host "`nGathering Network Configuration..." -ForegroundColor Yellow
    $adapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" }
    $result = @()
    foreach ($adapter in $adapters) {
        $ipConfig = Get-NetIPConfiguration -InterfaceIndex $adapter.ifIndex
        $result += [PSCustomObject]@{
            InterfaceName = $adapter.Name
            InterfaceDescription = $adapter.InterfaceDescription
            MACAddress = $adapter.MacAddress
            IPAddress = $ipConfig.IPv4Address.IPAddress
            SubnetMask = $ipConfig.IPv4Address.PrefixLength
            DefaultGateway = $ipConfig.IPv4DefaultGateway.NextHop
            DNSServers = $ipConfig.DNSServer.ServerAddresses -join ", "
        }
    }
    $result | Format-Table -AutoSize
    return $result
}

function Get-UserAccountsAndGroups {
    Write-Host "`nGathering User Accounts and Groups..." -ForegroundColor Yellow
    $users = Get-LocalUser | Select-Object Name, Enabled, LastLogon, PasswordLastSet
    $groups = Get-LocalGroup | Select-Object Name, Description

    $result = [PSCustomObject]@{
        Users = $users
        Groups = $groups
    }
    $result.Users | Format-Table -AutoSize
    $result.Groups | Format-Table -AutoSize
    return $result
}

function Get-StartupPrograms {
    Write-Host "`nGathering Startup Programs..." -ForegroundColor Yellow
    $startupPrograms = Get-CimInstance Win32_StartupCommand | Select-Object Name, Command, Location, User
    $startupPrograms | Format-Table -AutoSize
    return $startupPrograms
}

function Get-DiskSpaceAndFileSystem {
    Write-Host "`nAnalyzing Disk Space and File System..." -ForegroundColor Yellow
    $disks = Get-CimInstance Win32_LogicalDisk | Where-Object { $_.DriveType -eq 3 }
    $result = @()
    foreach ($disk in $disks) {
        $result += [PSCustomObject]@{
            DriveLetter = $disk.DeviceID
            VolumeName = $disk.VolumeName
            FileSystem = $disk.FileSystem
            TotalSpace = "{0:N2} GB" -f ($disk.Size / 1GB)
            FreeSpace = "{0:N2} GB" -f ($disk.FreeSpace / 1GB)
            PercentFree = "{0:N2}%" -f (($disk.FreeSpace / $disk.Size) * 100)
        }
    }
    $result | Format-Table -AutoSize
    return $result
}

function Get-EventLogAnalysis {
    Write-Host "`nAnalyzing Event Logs..." -ForegroundColor Yellow
    $logs = @("System", "Application", "Security")
    $result = @()
    foreach ($log in $logs) {
        $events = Get-EventLog -LogName $log -Newest 100
        $errorCount = ($events | Where-Object { $_.EntryType -eq "Error" }).Count
        $warningCount = ($events | Where-Object { $_.EntryType -eq "Warning" }).Count
        $result += [PSCustomObject]@{
            LogName = $log
            TotalEvents = $events.Count
            ErrorCount = $errorCount
            WarningCount = $warningCount
            MostCommonSource = ($events | Group-Object Source | Sort-Object Count -Descending | Select-Object -First 1).Name
        }
    }
    $result | Format-Table -AutoSize
    return $result
}

function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Windows Client Audit Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .warning { color: orange; }
        .critical { color: red; }
    </style>
</head>
<body>
    <h1>Windows Client Audit Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>System Information</h2>
    $($AllResults.SystemInfo | ConvertTo-Html -Fragment)

    <h2>Hardware Inventory</h2>
    $($AllResults.HardwareInventory | ConvertTo-Html -Fragment)

    <h2>Installed Software</h2>
    $($AllResults.InstalledSoftware | ConvertTo-Html -Fragment)

    <h2>Windows Update Status</h2>
    $($AllResults.WindowsUpdateStatus | ConvertTo-Html -Fragment)

    <h2>Security Settings</h2>
    $($AllResults.SecuritySettings | ConvertTo-Html -Fragment)

    <h2>Network Configuration</h2>
    $($AllResults.NetworkConfig | ConvertTo-Html -Fragment)

    <h2>User Accounts and Groups</h2>
    <h3>Users</h3>
    $($AllResults.UserAccountsAndGroups.Users | ConvertTo-Html -Fragment)
    <h3>Groups</h3>
    $($AllResults.UserAccountsAndGroups.Groups | ConvertTo-Html -Fragment)

    <h2>Startup Programs</h2>
    $($AllResults.StartupPrograms | ConvertTo-Html -Fragment)

    <h2>Disk Space and File System</h2>
    $($AllResults.DiskSpace | ConvertTo-Html -Fragment)

    <h2>Event Log Analysis</h2>
    $($AllResults.EventLogAnalysis | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-12)"

    switch ($choice) {
        "1" { $allResults.SystemInfo = Get-SystemInformation }
        "2" { $allResults.HardwareInventory = Get-HardwareInventory }
        "3" { $allResults.InstalledSoftware = Get-InstalledSoftware }
        "4" { $allResults.WindowsUpdateStatus = Get-WindowsUpdateStatus }
        "5" { $allResults.SecuritySettings = Get-SecuritySettings }
        "6" { $allResults.NetworkConfig = Get-NetworkConfiguration }
        "7" { $allResults.UserAccountsAndGroups = Get-UserAccountsAndGroups }
        "8" { $allResults.StartupPrograms = Get-StartupPrograms }
        "9" { $allResults.DiskSpace = Get-DiskSpaceAndFileSystem }
        "10" { $allResults.EventLogAnalysis = Get-EventLogAnalysis }
        "11" { Generate-HTMLReport -AllResults $allResults }
        "12" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "12") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "12")

This Local Windows Client Audit Toolkit includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to gather various aspects of system information:
    • System Information (OS details, manufacturer, model, etc.)
    • Hardware Inventory (CPU, RAM, disk, GPU)
    • Installed Software
    • Windows Update Status
    • Security Settings (firewall, antivirus, UAC)
    • Network Configuration
    • User Accounts and Groups
    • Startup Programs
    • Disk Space and File System information
    • Event Log Analysis
  3. HTML report generation for easy sharing and viewing of results

Key features:

  • Comprehensive system information gathering
  • Detailed hardware inventory
  • Software inventory including version information
  • Windows update status check
  • Security settings overview
  • Network configuration details
  • User account and group information
  • Startup program listing
  • Disk space analysis
  • Basic event log analysis

This tool is particularly useful for:

  • IT administrators performing system audits
  • Help desk personnel gathering system information
  • System analysts investigating performance or security issues
  • Anyone needing a comprehensive overview of a Windows client machine

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query system information
  3. Review the generated HTML report for a comprehensive overview of the system

This script provides a thorough audit of a Windows client machine, making it easier to inventory, troubleshoot, or document system configurations. Remember to use this tool responsibly and respect privacy and security policies when auditing systems.

Local Admin User and Group Toolkit

<#
.SYNOPSIS
Local Admin User and Group Toolkit

.DESCRIPTION
This script provides functionality to manage local administrators and groups on Windows systems.
It allows creating, deleting, and managing local admin users and groups, as well as viewing current configurations.

.NOTES
File Name      : LocalAdminToolkit.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, administrator rights
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\LocalAdminToolkit.ps1
#>

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Local_Admin_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

function Show-Menu {
    Clear-Host
    Write-Host "=== Local Admin User and Group Toolkit ===" -ForegroundColor Cyan
    Write-Host "1. View Local Administrators"
    Write-Host "2. Create New Local Admin User"
    Write-Host "3. Delete Local Admin User"
    Write-Host "4. Add User to Administrators Group"
    Write-Host "5. Remove User from Administrators Group"
    Write-Host "6. View All Local Groups"
    Write-Host "7. Create New Local Group"
    Write-Host "8. Delete Local Group"
    Write-Host "9. Add User to Group"
    Write-Host "10. Remove User from Group"
    Write-Host "11. Generate HTML Report"
    Write-Host "12. Exit"
}

function View-LocalAdministrators {
    Write-Host "`nViewing Local Administrators..." -ForegroundColor Yellow
    $admins = Get-LocalGroupMember -Group "Administrators"
    $admins | Format-Table Name, PrincipalSource
    return $admins
}

function Create-NewLocalAdminUser {
    $username = Read-Host "Enter the new admin username"
    $password = Read-Host "Enter the password" -AsSecureString
    $fullName = Read-Host "Enter the full name (optional)"
    $description = Read-Host "Enter a description (optional)"

    try {
        New-LocalUser -Name $username -Password $password -FullName $fullName -Description $description -ErrorAction Stop
        Add-LocalGroupMember -Group "Administrators" -Member $username
        Write-Host "User $username created and added to Administrators group." -ForegroundColor Green
    }
    catch {
        Write-Host "Error creating user: $_" -ForegroundColor Red
    }
}

function Delete-LocalAdminUser {
    $username = Read-Host "Enter the username to delete"
    
    try {
        Remove-LocalUser -Name $username -ErrorAction Stop
        Write-Host "User $username deleted." -ForegroundColor Green
    }
    catch {
        Write-Host "Error deleting user: $_" -ForegroundColor Red
    }
}

function Add-UserToAdministrators {
    $username = Read-Host "Enter the username to add to Administrators group"
    
    try {
        Add-LocalGroupMember -Group "Administrators" -Member $username -ErrorAction Stop
        Write-Host "User $username added to Administrators group." -ForegroundColor Green
    }
    catch {
        Write-Host "Error adding user to Administrators group: $_" -ForegroundColor Red
    }
}

function Remove-UserFromAdministrators {
    $username = Read-Host "Enter the username to remove from Administrators group"
    
    try {
        Remove-LocalGroupMember -Group "Administrators" -Member $username -ErrorAction Stop
        Write-Host "User $username removed from Administrators group." -ForegroundColor Green
    }
    catch {
        Write-Host "Error removing user from Administrators group: $_" -ForegroundColor Red
    }
}

function View-AllLocalGroups {
    Write-Host "`nViewing All Local Groups..." -ForegroundColor Yellow
    $groups = Get-LocalGroup
    $groups | Format-Table Name, Description
    return $groups
}

function Create-NewLocalGroup {
    $groupName = Read-Host "Enter the new group name"
    $description = Read-Host "Enter a description (optional)"

    try {
        New-LocalGroup -Name $groupName -Description $description -ErrorAction Stop
        Write-Host "Group $groupName created." -ForegroundColor Green
    }
    catch {
        Write-Host "Error creating group: $_" -ForegroundColor Red
    }
}

function Delete-LocalGroup {
    $groupName = Read-Host "Enter the group name to delete"
    
    try {
        Remove-LocalGroup -Name $groupName -ErrorAction Stop
        Write-Host "Group $groupName deleted." -ForegroundColor Green
    }
    catch {
        Write-Host "Error deleting group: $_" -ForegroundColor Red
    }
}

function Add-UserToGroup {
    $username = Read-Host "Enter the username to add"
    $groupName = Read-Host "Enter the group name"
    
    try {
        Add-LocalGroupMember -Group $groupName -Member $username -ErrorAction Stop
        Write-Host "User $username added to group $groupName." -ForegroundColor Green
    }
    catch {
        Write-Host "Error adding user to group: $_" -ForegroundColor Red
    }
}

function Remove-UserFromGroup {
    $username = Read-Host "Enter the username to remove"
    $groupName = Read-Host "Enter the group name"
    
    try {
        Remove-LocalGroupMember -Group $groupName -Member $username -ErrorAction Stop
        Write-Host "User $username removed from group $groupName." -ForegroundColor Green
    }
    catch {
        Write-Host "Error removing user from group: $_" -ForegroundColor Red
    }
}

function Generate-HTMLReport {
    Write-Host "`nGenerating HTML Report..." -ForegroundColor Yellow
    
    $admins = View-LocalAdministrators
    $groups = View-AllLocalGroups

    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Local Admin and Group Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Local Admin and Group Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>Local Administrators</h2>
    $($admins | ConvertTo-Html -Fragment)

    <h2>All Local Groups</h2>
    $($groups | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-12)"

    switch ($choice) {
        "1" { View-LocalAdministrators }
        "2" { Create-NewLocalAdminUser }
        "3" { Delete-LocalAdminUser }
        "4" { Add-UserToAdministrators }
        "5" { Remove-UserFromAdministrators }
        "6" { View-AllLocalGroups }
        "7" { Create-NewLocalGroup }
        "8" { Delete-LocalGroup }
        "9" { Add-UserToGroup }
        "10" { Remove-UserFromGroup }
        "11" { Generate-HTMLReport }
        "12" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "12") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "12")

This Local Admin User and Group Toolkit includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to manage local administrators and groups:
    • View local administrators
    • Create new local admin users
    • Delete local admin users
    • Add users to the Administrators group
    • Remove users from the Administrators group
    • View all local groups
    • Create new local groups
    • Delete local groups
    • Add users to groups
    • Remove users from groups
  3. HTML report generation for easy sharing and viewing of current configurations.

Key features:

  • Comprehensive management of local users and groups
  • Easy-to-use interface for common administrative tasks
  • Detailed error handling for each operation
  • HTML report generation for documentation purposes

Important notes:

  1. This script requires administrator rights to run effectively.
  2. Be cautious when deleting users or groups, as this action cannot be undone.
  3. Ensure you have proper authorization before modifying user accounts or group memberships.
  4. It’s recommended to test this script in a non-production environment first.

To use this script:

  1. Run PowerShell as an administrator
  2. Navigate to the directory containing the script
  3. Execute the script: .\LocalAdminToolkit.ps1
  4. Follow the on-screen menu to perform desired actions

This toolkit provides a convenient way to manage local administrators and groups on Windows systems, which can be particularly useful for system administrators managing multiple machines or performing routine user management tasks.

Windows Services Analyzer Tool

<#
.SYNOPSIS
Windows Services Analyzer Tool

.DESCRIPTION
This script analyzes and audits Windows services on local or remote systems,
providing insights into service configurations, startup types, and potential issues.

.NOTES
File Name      : ServicesAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, administrator rights
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\ServicesAnalyzer.ps1
#>

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Services_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
$global:targetComputer = $env:COMPUTERNAME

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Windows Services Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "Current Target: $global:targetComputer"
    Write-Host "1. Set Target Computer"
    Write-Host "2. Analyze All Services"
    Write-Host "3. Check Automatic Services Not Running"
    Write-Host "4. Identify Manual Services Running"
    Write-Host "5. Analyze Service Dependencies"
    Write-Host "6. Check Services with Non-Standard Accounts"
    Write-Host "7. Identify Services with No Description"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Sets the target computer for analysis.
#>
function Set-TargetComputer {
    $computer = Read-Host "Enter the name of the target computer (or press Enter for local machine)"
    if ([string]::IsNullOrWhiteSpace($computer)) {
        $global:targetComputer = $env:COMPUTERNAME
    } else {
        $global:targetComputer = $computer
    }
    Write-Host "Target computer set to: $global:targetComputer" -ForegroundColor Green
}

<#
.SYNOPSIS
Analyzes all services on the target computer.

.OUTPUTS
Array of PSObjects containing service details.
#>
function Analyze-AllServices {
    Write-Host "`nAnalyzing All Services..." -ForegroundColor Yellow
    try {
        $services = Get-WmiObject -Class Win32_Service -ComputerName $global:targetComputer
        $results = @()
        foreach ($service in $services) {
            $results += [PSCustomObject]@{
                Name = $service.Name
                DisplayName = $service.DisplayName
                State = $service.State
                StartMode = $service.StartMode
                StartName = $service.StartName
            }
        }
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error analyzing services: $_" -ForegroundColor Red
        return $null
    }
}

<#
.SYNOPSIS
Checks for automatic services that are not running.

.OUTPUTS
Array of PSObjects containing details of automatic services not running.
#>
function Check-AutomaticServicesNotRunning {
    Write-Host "`nChecking Automatic Services Not Running..." -ForegroundColor Yellow
    try {
        $services = Get-WmiObject -Class Win32_Service -ComputerName $global:targetComputer |
                    Where-Object { $_.StartMode -eq "Auto" -and $_.State -ne "Running" }
        $results = @()
        foreach ($service in $services) {
            $results += [PSCustomObject]@{
                Name = $service.Name
                DisplayName = $service.DisplayName
                State = $service.State
                StartMode = $service.StartMode
            }
        }
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error checking automatic services: $_" -ForegroundColor Red
        return $null
    }
}

<#
.SYNOPSIS
Identifies manual services that are running.

.OUTPUTS
Array of PSObjects containing details of manual services running.
#>
function Identify-ManualServicesRunning {
    Write-Host "`nIdentifying Manual Services Running..." -ForegroundColor Yellow
    try {
        $services = Get-WmiObject -Class Win32_Service -ComputerName $global:targetComputer |
                    Where-Object { $_.StartMode -eq "Manual" -and $_.State -eq "Running" }
        $results = @()
        foreach ($service in $services) {
            $results += [PSCustomObject]@{
                Name = $service.Name
                DisplayName = $service.DisplayName
                State = $service.State
                StartMode = $service.StartMode
            }
        }
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error identifying manual services: $_" -ForegroundColor Red
        return $null
    }
}

<#
.SYNOPSIS
Analyzes service dependencies.

.OUTPUTS
Array of PSObjects containing service dependency details.
#>
function Analyze-ServiceDependencies {
    Write-Host "`nAnalyzing Service Dependencies..." -ForegroundColor Yellow
    try {
        $services = Get-WmiObject -Class Win32_Service -ComputerName $global:targetComputer
        $results = @()
        foreach ($service in $services) {
            if ($service.DependentServices) {
                $results += [PSCustomObject]@{
                    Name = $service.Name
                    DisplayName = $service.DisplayName
                    DependentServices = $service.DependentServices -join ", "
                }
            }
        }
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error analyzing service dependencies: $_" -ForegroundColor Red
        return $null
    }
}

<#
.SYNOPSIS
Checks for services with non-standard accounts.

.OUTPUTS
Array of PSObjects containing details of services with non-standard accounts.
#>
function Check-ServicesWithNonStandardAccounts {
    Write-Host "`nChecking Services with Non-Standard Accounts..." -ForegroundColor Yellow
    try {
        $standardAccounts = @("LocalSystem", "NT AUTHORITY\LocalService", "NT AUTHORITY\NetworkService")
        $services = Get-WmiObject -Class Win32_Service -ComputerName $global:targetComputer |
                    Where-Object { $standardAccounts -notcontains $_.StartName }
        $results = @()
        foreach ($service in $services) {
            $results += [PSCustomObject]@{
                Name = $service.Name
                DisplayName = $service.DisplayName
                StartName = $service.StartName
                State = $service.State
            }
        }
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error checking services with non-standard accounts: $_" -ForegroundColor Red
        return $null
    }
}

<#
.SYNOPSIS
Identifies services with no description.

.OUTPUTS
Array of PSObjects containing details of services with no description.
#>
function Identify-ServicesWithNoDescription {
    Write-Host "`nIdentifying Services with No Description..." -ForegroundColor Yellow
    try {
        $services = Get-WmiObject -Class Win32_Service -ComputerName $global:targetComputer |
                    Where-Object { [string]::IsNullOrWhiteSpace($_.Description) }
        $results = @()
        foreach ($service in $services) {
            $results += [PSCustomObject]@{
                Name = $service.Name
                DisplayName = $service.DisplayName
                State = $service.State
                StartMode = $service.StartMode
            }
        }
        $results | Format-Table -AutoSize
        return $results
    }
    catch {
        Write-Host "Error identifying services with no description: $_" -ForegroundColor Red
        return $null
    }
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Windows Services Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Windows Services Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>
    <p>Target Computer: $global:targetComputer</p>

    <h2>All Services</h2>
    $($AllResults.AllServices | ConvertTo-Html -Fragment)

    <h2>Automatic Services Not Running</h2>
    $($AllResults.AutomaticNotRunning | ConvertTo-Html -Fragment)

    <h2>Manual Services Running</h2>
    $($AllResults.ManualRunning | ConvertTo-Html -Fragment)

    <h2>Service Dependencies</h2>
    $($AllResults.ServiceDependencies | ConvertTo-Html -Fragment)

    <h2>Services with Non-Standard Accounts</h2>
    $($AllResults.NonStandardAccounts | ConvertTo-Html -Fragment)

    <h2>Services with No Description</h2>
    $($AllResults.NoDescription | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { Set-TargetComputer }
        "2" { $allResults.AllServices = Analyze-AllServices }
        "3" { $allResults.AutomaticNotRunning = Check-AutomaticServicesNotRunning }
        "4" { $allResults.ManualRunning = Identify-ManualServicesRunning }
        "5" { $allResults.ServiceDependencies = Analyze-ServiceDependencies }
        "6" { $allResults.NonStandardAccounts = Check-ServicesWithNonStandardAccounts }
        "7" { $allResults.NoDescription = Identify-ServicesWithNoDescription }
        "8" { Generate-HTMLReport -AllResults $allResults }
        "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "9") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "9")

This Windows Services Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of Windows services:
    • Analysis of all services
    • Check for automatic services not running
    • Identification of manual services running
    • Analysis of service dependencies
    • Check for services with non-standard accounts
    • Identification of services with no description
  3. Ability to set a target computer for remote analysis.
  4. Comprehensive error handling for each analysis function.
  5. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of all services on the target system
  • Identification of potential issues like automatic services not running
  • Detection of manual services that are running (which might be unnecessary)
  • Analysis of service dependencies to understand the impact of service failures
  • Identification of services using non-standard accounts (potential security concern)
  • Detection of services lacking descriptions (which might indicate unauthorized or suspicious services)
  • Comprehensive HTML report generation

This tool is particularly useful for:

  • System administrators managing Windows services
  • Security professionals auditing service configurations
  • IT professionals troubleshooting service-related issues
  • Compliance officers ensuring proper service configurations

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query services on the target computer
  3. Be cautious when analyzing services on production systems

This script provides a comprehensive overview of Windows services, making it easier to audit and maintain proper service configurations, identify potential security issues, and ensure the correct setup of services across Windows systems.

RDS User Disconnected Monitor and Action Script

<#
.SYNOPSIS
RDS User Disconnected Monitor and Action Script

.DESCRIPTION
This script monitors Remote Desktop Services for disconnected user sessions
and performs specified actions when a user disconnects.

.PARAMETER Action
The action to perform when a user disconnects. Options are 'Log', 'Logoff', or 'Both'.

.PARAMETER LogFile
The path of the log file where disconnect events will be recorded.

.EXAMPLE
.\RDSDisconnectMonitor.ps1 -Action "Log" -LogFile "C:\Logs\RDSDisconnects.log"

.NOTES
File Name      : RDSDisconnectMonitor.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V3 or later, admin rights on the RDS server
Version        : 1.0
Date           : [Current Date]
#>

param (
    [Parameter(Mandatory=$true)]
    [ValidateSet("Log", "Logoff", "Both")]
    [string]$Action,

    [Parameter(Mandatory=$true)]
    [string]$LogFile
)

# Function to write log entries
function Write-Log {
    param (
        [string]$Message
    )
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "$timestamp - $Message"
    Add-Content -Path $LogFile -Value $logEntry
    Write-Host $logEntry
}

# Function to get disconnected sessions
function Get-DisconnectedSessions {
    $sessions = quser | Where-Object { $_ -match 'Disc' }
    $disconnectedUsers = @()
    foreach ($session in $sessions) {
        $sessionInfo = $session -split '\s+'
        $disconnectedUsers += [PSCustomObject]@{
            Username = $sessionInfo[1]
            SessionID = $sessionInfo[2]
        }
    }
    return $disconnectedUsers
}

# Function to perform action on disconnected session
function Perform-Action {
    param (
        [string]$Username,
        [string]$SessionID
    )

    switch ($Action) {
        "Log" {
            Write-Log "User disconnected: $Username (Session ID: $SessionID)"
        }
        "Logoff" {
            logoff $SessionID
            Write-Log "User logged off: $Username (Session ID: $SessionID)"
        }
        "Both" {
            Write-Log "User disconnected: $Username (Session ID: $SessionID)"
            logoff $SessionID
            Write-Log "User logged off: $Username (Session ID: $SessionID)"
        }
    }
}

# Create the log file if it doesn't exist
if (-not (Test-Path $LogFile)) {
    New-Item -Path $LogFile -ItemType File -Force
}

Write-Log "Starting RDS disconnect monitoring..."

# Main monitoring loop
try {
    $previousSessions = @()
    while ($true) {
        $currentSessions = Get-DisconnectedSessions
        
        # Check for new disconnections
        foreach ($session in $currentSessions) {
            if ($session.Username -notin $previousSessions.Username) {
                Perform-Action -Username $session.Username -SessionID $session.SessionID
            }
        }

        $previousSessions = $currentSessions
        Start-Sleep -Seconds 30  # Check every 30 seconds
    }
}
catch {
    Write-Log "An error occurred: $_"
}
finally {
    Write-Log "RDS disconnect monitoring stopped."
}

To use this script:

  1. Save it as RDSDisconnectMonitor.ps1.
  2. Open PowerShell as an administrator on the RDS server.
  3. Navigate to the directory containing the script.
  4. Run the script with the required parameters:

.\RDSDisconnectMonitor.ps1 -Action "Log" -LogFile "C:\Logs\RDSDisconnects.log"

You can replace “Log” with “Logoff” to automatically log off disconnected users, or “Both” to log and then log off.

Key features of this script:

  1. Monitoring: Continuously checks for disconnected RDS sessions.
  2. Flexible Actions: Can log disconnections, automatically log off disconnected users, or both.
  3. Logging: Records all actions and events to a specified log file.
  4. Customizable: Easy to modify for additional actions or different checking intervals.

Notes:

  • This script needs to be run with administrator privileges on the RDS server.
  • The script will continue running until manually stopped (e.g., by pressing Ctrl+C).
  • For production use, consider running this script as a Windows Service or scheduled task.
  • The script checks for disconnections every 30 seconds by default. You can adjust this interval by changing the Start-Sleep -Seconds 30 line.
  • Be cautious when using the “Logoff” action, as it will forcibly close user sessions, which might result in data loss if users have unsaved work.

This script provides a foundation for monitoring and managing disconnected RDS sessions. You can further customize it based on your specific requirements, such as sending notifications, integrating with other systems, or implementing more complex decision logic for when to log off users.

Creating Best Practices for PowerShell Functions

Functions are a fundamental building block in PowerShell, allowing you to encapsulate reusable code and make your scripts more modular and maintainable. However, to ensure your functions are well-designed and follow best practices, there are several guidelines you should consider. In this post, we’ll explore some of the best practices for creating PowerShell functions.

1. Use Meaningful Function Names

The name of your function should be descriptive and convey the purpose of the function. Avoid using generic names like “DoSomething” or “ProcessData”. Instead, use names that clearly indicate what the function does, such as “Get-UserInfo” or “Convert-StringToInt”.

2. Provide Detailed Function Documentation

Every function should have a well-written help comment block that includes a description of the function, its parameters, return values, and any relevant examples. This documentation will not only help other users understand how to use your function, but it will also serve as a reference for you when you need to revisit the function in the future.

3. Use Consistent Parameter Naming

When defining the parameters for your function, use consistent naming conventions. This will make your functions more intuitive and easier to use. For example, if you have a function that takes a file path as input, use a parameter name like “FilePath” rather than “Path” or “FileName”.

4. Validate Input Parameters

Always validate the input parameters to your function to ensure that they are of the expected type and within the expected range of values. This will help prevent errors and unexpected behavior in your functions.

5. Use Appropriate Data Types

Choose the appropriate data types for your function’s parameters and return values. This will help ensure that your function behaves as expected and interoperates well with other PowerShell cmdlets and functions.

6. Provide Meaningful Error Handling

When your function encounters an error, provide meaningful error messages that explain what went wrong and how the user can resolve the issue. Use the throw statement to raise exceptions and provide detailed error information.

7. Implement Robust Error Handling

Use try-catch blocks to handle exceptions that may occur within your function. This will help ensure that your function gracefully handles errors and doesn’t crash unexpectedly.

8. Use Appropriate Cmdlet Verbs

When naming your functions, use the appropriate cmdlet verbs as defined by the PowerShell team. This will help ensure that your functions follow the PowerShell naming conventions and are more easily recognized by other PowerShell users.

9. Provide Examples and Samples

Include examples and sample usage in your function’s help documentation to help users understand how to use your function effectively.

10. Test Your Functions Thoroughly

Before releasing your functions, test them thoroughly to ensure they work as expected and handle edge cases appropriately.

By following these best practices, you can create PowerShell functions that are well-designed, maintainable, and easy to use. This will not only benefit you as the function author, but also the users who will be consuming your functions.

Sample script:

<#
.SYNOPSIS
    Retrieves user information from Active Directory.
.DESCRIPTION
    This function retrieves user information from Active Directory, including the user's name, email address, and department.
.PARAMETER UserPrincipalName
    The user's principal name (e.g., "user@powershellblog.com").
.EXAMPLE
    Get-UserInfo -UserPrincipalName "user@powershellblog.com"
    Retrieves the user information for the user with the principal name "user@powershellblog.com".
.NOTES
    This function requires the ActiveDirectory module to be installed and the user running the script to have the necessary permissions to query Active Directory.
#>
function Get-UserInfo {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true, HelpMessage="Enter the user's principal name.")]
        [ValidateNotNullOrEmpty()]
        [string]$UserPrincipalName
    )

    try {
        # Retrieve the user object from Active Directory
        $user = Get-ADUser -Filter "UserPrincipalName -eq '$UserPrincipalName'" -Properties EmailAddress, Department

        # Create a custom object to hold the user information
        $userInfo = [PSCustomObject]@{
            Name = $user.Name
            EmailAddress = $user.EmailAddress
            Department = $user.Department
        }

        # Return the user information
        return $userInfo
    }
    catch {
        # Handle any errors that occur
        throw "Error retrieving user information: $($_.Exception.Message)"
    }
}

# Example usage
$userInfo = Get-UserInfo -UserPrincipalName "user@powershellblog.com"
Write-Host "Name: $($userInfo.Name)"
Write-Host "Email Address: $($userInfo.EmailAddress)"
Write-Host "Department: $($userInfo.Department)"

Here’s how this script follows the best practices we discussed:

  1. Meaningful Function Name: The function is named Get-UserInfo, which clearly indicates its purpose.
  2. Detailed Function Documentation: The function includes a comprehensive help comment block that provides a synopsis, description, parameter information, an example, and notes.
  3. Consistent Parameter Naming: The function takes a single parameter, UserPrincipalName, which is a clear and consistent name for the user’s principal name.
  4. Input Parameter Validation: The function uses the [Parameter(Mandatory=$true)] attribute to ensure that the UserPrincipalName parameter is provided, and the [ValidateNotNullOrEmpty()] attribute to ensure that the parameter is not null or empty.
  5. Appropriate Data Types: The function uses the [string] data type for the UserPrincipalName parameter, which is the expected data type for a user’s principal name.
  6. Meaningful Error Handling: The function uses a try-catch block to handle any errors that may occur during the execution of the function, and it throws a custom error message with detailed information about the error.
  7. Appropriate Cmdlet Verb: The function uses the Get- verb, which is the appropriate cmdlet verb for a function that retrieves information.
  8. Examples and Samples: The function includes an example usage in the help comment block, which demonstrates how to use the function.
  9. Thorough Testing: While not shown in the script, it’s important to thoroughly test the function to ensure it works as expected and handles edge cases appropriately.

By following these best practices, the Get-UserInfo function is well-designed, maintainable, and easy to use.