IntegrisPowerShell.psm1

### ======================================================================================================================
### INTEGRIS POWERSHELL MODULE
### ======================================================================================================================

<#---
NAMING CONVENTION RULES:
 
    VERBS:
        GET/SET - Standard FUNCTIONs to Retrieve Information or Change Settings
        SEARCH - FUNCTIONs for Easier Use of Complex PowerShell Queries
        REPORT - Complex FUNCTIONs, Often With Numerous Parameter Options
        CHECK - FUNCTIONs for Quickly Gather Information Related to Potential Issues (In Development)
 
    Naming:
        GET-[Subject]Info - Get Info About a Single Item (GET-WindowsInfo, GET-InternetInfo)
        GET-[Subject][Item] - Collect Info About a Set of Items (GET-RAMModule, GET-DisplayDevice)
        GET-[Subject][Item]Event - Gets Info from Event Log
 
    ALIASES:
        Commands Have INT Alias for easier tabbing (i.e. GET-InternetInfo can also be called with INTGET-InternetInfo)
        Commands Have Aliases for common synonyms (i.e. GET-CPUInfo can also be called with GET-ProcessorInfo)
 
    OTHER:
        No Plurals in Command Names (GET-RAMModule not GET-RAMModules)
 
---#>


### ======================================================================================================================
### NOTES FOR CHANGES TO MAKE
### ======================================================================================================================
### Change Available RAM in Performance Report to a Percentage
### [Completed] Update Network Connection Commands to Check for Static IP\DNS
### [Failed] Add CPU Temp to Performance and CPU Info Script (Tried, Unable to Locate a Script that Can Read CPU Temp Info)
### Command for Getting Printers and Printer Statuses?
### Note Last Reboot in Performance Report
### Note Last Reboot in Check-All
### Note PageFile Size in Performance Report

### ### ==============================================================================================
### ### HELP FUNCTIONS
### ### ==============================================================================================

FUNCTION GET-IntegrisPowerShellVersion {
    RETURN "1.9.50"
}

New-Alias -Name INTGET-IntegrisPowerShellVersion -Value GET-IntegrisPowerShellVersion
Export-ModuleMember -FUNCTION GET-IntegrisPowerShellVersion -Alias INTGET-IntegrisPowerShellVersion

### ### ==============================================================================================
### ### ERROR FUNCTIONS
### ### ==============================================================================================

FUNCTION ErrorCheck-AdministratorElevation {
    IF (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(` [Security.Principal.WindowsBuiltInRole] “Administrator”)) {
        Write-Host
        Write-Warning “You must run this command in an elevated privilege context.`nNo changes were made. Please re-run this command as an administrator.”
        RETURN $True
    }
    RETURN $False
}
FUNCTION Warning-AdministratorElevation {
    IF (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(` [Security.Principal.WindowsBuiltInRole] “Administrator”)) {
        Write-Host
        Write-Warning “You are not running this command in an elevated privilege context.`nSome results will not be available. Please re-run this command as an Administrator for complete results.”
        Return $True
    }
    RETURN $False
}

Export-ModuleMember -FUNCTION ErrorCheck-AdministratorElevation -Alias ErrorCheck-AdministratorElevation
Export-ModuleMember -FUNCTION Warning-AdministratorElevation -Alias Warning-AdministratorElevation

### ### ==============================================================================================
### ### GET\SET FUNCTIONS
### ### ==============================================================================================

FUNCTION GET-ApplicationInstalled {

    $Results = @()

    $Applications = GET-CIMInstance Win32_Product -ErrorAction SilentlyContinue | Where-Object { $_.Name -ne $null -and $_.Name -notlike "*Visual C++*" -and $_.Name -notlike "*Update for Windows*" -and $_.Name -notlike "*Click-to-Run*" } 

    FOREACH ($Application in $Applications) {
        $InstallDateString = $Application.InstallDate.Substring(0,4)
        $InstallDateString += "-"
        $InstallDateString += $Application.InstallDate.Substring(4,2)
        $InstallDateString += "-"
        $InstallDateString += $Application.InstallDate.Substring(6,2)
        $InstallDateTime = [DateTime]$InstallDateString

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Name = $Application.Name
            Version = $Application.Version
            Vendor = $Application.Vendor
            InstallDate = $InstallDateTime
            UninstallerPath = $Application.LocalPackage
        }
    }

    RETURN $Results | Select Name, Version, InstallDate, Vendor, UninstallerPath
}
FUNCTION GET-ApplicationEvent {
    
    param (
        [ValidateSet("Install","Uninstall")]
        [string[]]$EventType = @("Install","Uninstall")
    )

    $Username = ""
    $Results = @()
    $Events = @()
    $ActionType = ""
    
    IF ($EventType -contains "Install") { $Events += Get-WinEvent -FilterHashtable @{ProviderName = "MSIInstaller"; ID = @(11707)} -ErrorAction SilentlyContinue }
    IF ($EventType -contains "Uninstall") { $Events += Get-WinEvent -FilterHashtable @{ProviderName = "MSIInstaller"; ID = @(1034)} -ErrorAction SilentlyContinue }

    FOREACH ($Event in $Events) {

        $SID = New-Object System.Security.Principal.SecurityIdentifier($Event.UserID)
        $Username = $SID.Translate([System.Security.Principal.NTAccount])

        IF ($Event.ID -eq "1034") { $ActionType = "Uninstall" } ELSE { $ActionType = "Install" } 

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Hostname = $Event.MachineName
            ID = $Event.ID
            Source = $Event.ProviderName
            LogName = $Event.LogName
            User = $Username
            TimeCreated = $Event.TimeCreated
            ActionType = $ActionType 
            Message = $Event.Message
        }
    }

    RETURN $Results | Select ActionType, User, TimeCreated, Message | Sort-Object -Property TimeCreated -Descending
}
FUNCTION GET-BIOSSetting {

    $Results = @()

    $Manufacturer = (GET-CIMInstance Win32_SystemEnclosure).Manufacturer
    IF ($Manufacturer -like "*Hewlett*") { $Results = GET-BIOSSettingsHP }
    ELSEIF ($Manufacturer -like "*Dell*") { $Results = GET-BIOSSettingsDell }
    ELSEIF ($Manufacturer -like "*Lenovo*") { $Results = GET-BIOSSettingsLenovo }
    ELSE { 
        Write-Host
        Write-Warning “This command is currently only supported for HP, Dell, and Lenovo computers.”
        RETURN
    }

    RETURN $Results
}
FUNCTION GET-ChassisInfo {

    $ChassisInfo = GET-CIMInstance Win32_SystemEnclosure -ErrorAction SilentlyContinue
    $ComputerInfo = GET-CIMInstance Win32_ComputerSystem
    Switch ($ChassisInfo.ChassisTypes) {
        "1" { $EnclosureType = "Other" }
        "2" { $EnclosureType = "Unknown" }
        "3" { $EnclosureType = "Desktop" }
        "4" { $EnclosureType = "Low Profile Desktop" }
        "5" { $EnclosureType = "Pizza Box" }
        "6" { $EnclosureType = "Mini Tower" }
        "7" { $EnclosureType = "Tower" }
        "8" { $EnclosureType = "Portable" }
        "9" { $EnclosureType = "Laptop" }
        "10" { $EnclosureType = "Notebook" }
        "11" { $EnclosureType = "Hand Held" }
        "12" { $EnclosureType = "Docking Station" }
        "13" { $EnclosureType = "All in One" }
        "14" { $EnclosureType = "Sub Notebook" }
        "15" { $EnclosureType = "Space-Saving" }
        "16" { $EnclosureType = "Lunch Box" }
        "17" { $EnclosureType = "Main System Chassis" }
        "18" { $EnclosureType = "Expansion Chassis" }
        "19" { $EnclosureType = "SubChassis" }
        "20" { $EnclosureType = "Bus Expansion Chassis" }
        "21" { $EnclosureType = "Peripheral Chassis" }
        "22" { $EnclosureType = "Storage Chassis" }
        "23" { $EnclosureType = "Rack Mount Chassis" }
        "24" { $EnclosureType = "Sealed-Case PC" }
        "30" { $EnclosureType = "Tablet" }
        "31" { $EnclosureType = "Convertible" }
        "32" { $EnclosureType = "Detachable" }
        default { $EnclosureType = "Unknown" }
    }

    $Age = (GET-CPUDevice).YearsOld
    
    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        Hostname = $ComputerInfo.Name
        Model = $ComputerInfo.Model
        Manufacturer = $ChassisInfo.Manufacturer
        SerialNumber = $ChassisInfo.SerialNumber
        ChassisType = $EnclosureType
        YearsOld = $Age
    }

    RETURN $Results | Select Hostname, Model, Manufacturer, ChassisType, SerialNumber, YearsOld
}
FUNCTION GET-CPUDevice {

    $Results = @()
    $CPUs = GET-CIMInstance win32_Processor
   
    
    FOREACH ($AllInfo in $CPUs) {
        $ProcessorName = New-Object 'string[]' 1000
        $ProcessorScore = New-Object 'string[]' 1000

    
        $WorkstationProcessorName = GET-CIMInstance win32_Processor | select name
        $WorkstationProcessorName = $WorkstationProcessorName.Name
        $WorkstationProcessorScore = "Unknown"

        $ProcessorName[0] = "i3-1000NG4 ";      $ProcessorScore[0] = "4326"
        $ProcessorName[1] = "i3-1005G1 ";      $ProcessorScore[1] = "5257"
        $ProcessorName[2] = "i3-10100 ";      $ProcessorScore[2] = "8865"
        $ProcessorName[3] = "i3-10100T ";      $ProcessorScore[3] = "7589"
        $ProcessorName[4] = "i3-10110U ";      $ProcessorScore[4] = "4076"
        $ProcessorName[5] = "i3-10110Y ";      $ProcessorScore[5] = "3639"
        $ProcessorName[6] = "i3-10300 ";      $ProcessorScore[6] = "9256"
        $ProcessorName[7] = "i3-10300T ";      $ProcessorScore[7] = "8355"
        $ProcessorName[8] = "i3-2100 ";      $ProcessorScore[8] = "1781"
        $ProcessorName[9] = "i3-2100T ";      $ProcessorScore[9] = "1694"
        $ProcessorName[10] = "i3-2102 ";      $ProcessorScore[10] = "2029"
        $ProcessorName[11] = "i3-2105 ";      $ProcessorScore[11] = "1814"
        $ProcessorName[12] = "i3-21050 ";      $ProcessorScore[12] = "2193"
        $ProcessorName[13] = "i3-2120 ";      $ProcessorScore[13] = "1901"
        $ProcessorName[14] = "i3-2120T ";      $ProcessorScore[14] = "1436"
        $ProcessorName[15] = "i3-2125 ";      $ProcessorScore[15] = "2167"
        $ProcessorName[16] = "i3-2130 ";      $ProcessorScore[16] = "1984"
        $ProcessorName[17] = "i3-2140 ";      $ProcessorScore[17] = "2456"
        $ProcessorName[18] = "i3-2310E ";      $ProcessorScore[18] = "1845"
        $ProcessorName[19] = "i3-2310M ";      $ProcessorScore[19] = "1169"
        $ProcessorName[20] = "i3-2312M ";      $ProcessorScore[20] = "1369"
        $ProcessorName[21] = "i3-2328M ";      $ProcessorScore[21] = "1217"
        $ProcessorName[22] = "i3-2330E ";      $ProcessorScore[22] = "1823"
        $ProcessorName[23] = "i3-2330M ";      $ProcessorScore[23] = "1226"
        $ProcessorName[24] = "i3-2332M ";      $ProcessorScore[24] = "1353"
        $ProcessorName[25] = "i3-2340UE ";      $ProcessorScore[25] = "976"
        $ProcessorName[26] = "i3-2348M ";      $ProcessorScore[26] = "1221"
        $ProcessorName[27] = "i3-2350M ";      $ProcessorScore[27] = "1204"
        $ProcessorName[28] = "i3-2357M ";      $ProcessorScore[28] = "866"
        $ProcessorName[29] = "i3-2365M ";      $ProcessorScore[29] = "864"
        $ProcessorName[30] = "i3-2367M ";      $ProcessorScore[30] = "933"
        $ProcessorName[31] = "i3-2370M ";      $ProcessorScore[31] = "1276"
        $ProcessorName[32] = "i3-2375M ";      $ProcessorScore[32] = "929"
        $ProcessorName[33] = "i3-2377M ";      $ProcessorScore[33] = "861"
        $ProcessorName[34] = "i3-3110M ";      $ProcessorScore[34] = "1568"
        $ProcessorName[35] = "i3-3120M ";      $ProcessorScore[35] = "1638"
        $ProcessorName[36] = "i3-3130M ";      $ProcessorScore[36] = "1824"
        $ProcessorName[37] = "i3-3210 ";      $ProcessorScore[37] = "2036"
        $ProcessorName[38] = "i3-3217U ";      $ProcessorScore[38] = "1177"
        $ProcessorName[39] = "i3-3217UE ";      $ProcessorScore[39] = "1362"
        $ProcessorName[40] = "i3-3220 ";      $ProcessorScore[40] = "2200"
        $ProcessorName[41] = "i3-3220T ";      $ProcessorScore[41] = "1991"
        $ProcessorName[42] = "i3-3225 ";      $ProcessorScore[42] = "2174"
        $ProcessorName[43] = "i3-3227U ";      $ProcessorScore[43] = "1285"
        $ProcessorName[44] = "i3-3229Y ";      $ProcessorScore[44] = "1236"
        $ProcessorName[45] = "i3-3240 ";      $ProcessorScore[45] = "2274"
        $ProcessorName[46] = "i3-3240T ";      $ProcessorScore[46] = "1981"
        $ProcessorName[47] = "i3-3245 ";      $ProcessorScore[47] = "2643"
        $ProcessorName[48] = "i3-3250 ";      $ProcessorScore[48] = "2331"
        $ProcessorName[49] = "i3-3250T ";      $ProcessorScore[49] = "2650"
        $ProcessorName[50] = "i3-330E ";      $ProcessorScore[50] = "1260"
        $ProcessorName[51] = "i3-330M ";      $ProcessorScore[51] = "971"
        $ProcessorName[52] = "i3-330UM ";      $ProcessorScore[52] = "666"
        $ProcessorName[53] = "i3-350M ";      $ProcessorScore[53] = "1056"
        $ProcessorName[54] = "i3-370M ";      $ProcessorScore[54] = "1128"
        $ProcessorName[55] = "i3-380M ";      $ProcessorScore[55] = "1124"
        $ProcessorName[56] = "i3-380UM ";      $ProcessorScore[56] = "708"
        $ProcessorName[57] = "i3-390M ";      $ProcessorScore[57] = "1231"
        $ProcessorName[58] = "i3-4000M ";      $ProcessorScore[58] = "1692"
        $ProcessorName[59] = "i3-4005U ";      $ProcessorScore[59] = "1666"
        $ProcessorName[60] = "i3-4010U ";      $ProcessorScore[60] = "1672"
        $ProcessorName[61] = "i3-4010Y ";      $ProcessorScore[61] = "1310"
        $ProcessorName[62] = "i3-4012Y ";      $ProcessorScore[62] = "1256"
        $ProcessorName[63] = "i3-4020Y ";      $ProcessorScore[63] = "1437"
        $ProcessorName[64] = "i3-4025U ";      $ProcessorScore[64] = "1918"
        $ProcessorName[65] = "i3-4030U ";      $ProcessorScore[65] = "1871"
        $ProcessorName[66] = "i3-4030Y ";      $ProcessorScore[66] = "1623"
        $ProcessorName[67] = "i3-4100M ";      $ProcessorScore[67] = "2362"
        $ProcessorName[68] = "i3-4110M ";      $ProcessorScore[68] = "2580"
        $ProcessorName[69] = "i3-4110U ";      $ProcessorScore[69] = "1853"
        $ProcessorName[70] = "i3-4120U ";      $ProcessorScore[70] = "1948"
        $ProcessorName[71] = "i3-4130 ";      $ProcessorScore[71] = "3266"
        $ProcessorName[72] = "i3-4130T ";      $ProcessorScore[72] = "2848"
        $ProcessorName[73] = "i3-4150 ";      $ProcessorScore[73] = "3375"
        $ProcessorName[74] = "i3-4150T ";      $ProcessorScore[74] = "2726"
        $ProcessorName[75] = "i3-4158U ";      $ProcessorScore[75] = "1718"
        $ProcessorName[76] = "i3-4160 ";      $ProcessorScore[76] = "3474"
        $ProcessorName[77] = "i3-4160T ";      $ProcessorScore[77] = "3086"
        $ProcessorName[78] = "i3-4170 ";      $ProcessorScore[78] = "3596"
        $ProcessorName[79] = "i3-4170T ";      $ProcessorScore[79] = "3177"
        $ProcessorName[80] = "i3-4330 ";      $ProcessorScore[80] = "3576"
        $ProcessorName[81] = "i3-4330T ";      $ProcessorScore[81] = "3098"
        $ProcessorName[82] = "i3-4330TE ";      $ProcessorScore[82] = "2500"
        $ProcessorName[83] = "i3-4340 ";      $ProcessorScore[83] = "3528"
        $ProcessorName[84] = "i3-4350 ";      $ProcessorScore[84] = "3163"
        $ProcessorName[85] = "i3-4350T ";      $ProcessorScore[85] = "2888"
        $ProcessorName[86] = "i3-4360 ";      $ProcessorScore[86] = "3577"
        $ProcessorName[87] = "i3-4360T ";      $ProcessorScore[87] = "3164"
        $ProcessorName[88] = "i3-4370 ";      $ProcessorScore[88] = "3851"
        $ProcessorName[89] = "i3-4370T ";      $ProcessorScore[89] = "3187"
        $ProcessorName[90] = "i3-4570T ";      $ProcessorScore[90] = "3244"
        $ProcessorName[91] = "i3-5005U ";      $ProcessorScore[91] = "2039"
        $ProcessorName[92] = "i3-5010U ";      $ProcessorScore[92] = "2161"
        $ProcessorName[93] = "i3-5015U ";      $ProcessorScore[93] = "2047"
        $ProcessorName[94] = "i3-5020U ";      $ProcessorScore[94] = "2222"
        $ProcessorName[95] = "i3-5157U ";      $ProcessorScore[95] = "2613"
        $ProcessorName[96] = "i3-530 ";      $ProcessorScore[96] = "1437"
        $ProcessorName[97] = "i3-540 ";      $ProcessorScore[97] = "1505"
        $ProcessorName[98] = "i3-550 ";      $ProcessorScore[98] = "1553"
        $ProcessorName[99] = "i3-560 ";      $ProcessorScore[99] = "1626"
        $ProcessorName[100] = "i3-6006U ";      $ProcessorScore[100] = "2288"
        $ProcessorName[101] = "i3-6098P ";      $ProcessorScore[101] = "4127"
        $ProcessorName[102] = "i3-6100 ";      $ProcessorScore[102] = "4153"
        $ProcessorName[103] = "i3-6100E ";      $ProcessorScore[103] = "3315"
        $ProcessorName[104] = "i3-6100H ";      $ProcessorScore[104] = "3191"
        $ProcessorName[105] = "i3-6100T ";      $ProcessorScore[105] = "3660"
        $ProcessorName[106] = "i3-6100TE ";      $ProcessorScore[106] = "3354"
        $ProcessorName[107] = "i3-6100U ";      $ProcessorScore[107] = "2623"
        $ProcessorName[108] = "i3-6102E ";      $ProcessorScore[108] = "2349"
        $ProcessorName[109] = "i3-6157U ";      $ProcessorScore[109] = "2758"
        $ProcessorName[110] = "i3-6300 ";      $ProcessorScore[110] = "4464"
        $ProcessorName[111] = "i3-6300T ";      $ProcessorScore[111] = "4040"
        $ProcessorName[112] = "i3-6320 ";      $ProcessorScore[112] = "4419"
        $ProcessorName[113] = "i3-7020U ";      $ProcessorScore[113] = "2557"
        $ProcessorName[114] = "i3-7100 ";      $ProcessorScore[114] = "4290"
        $ProcessorName[115] = "i3-7100H ";      $ProcessorScore[115] = "3460"
        $ProcessorName[116] = "i3-7100T ";      $ProcessorScore[116] = "3795"
        $ProcessorName[117] = "i3-7100U ";      $ProcessorScore[117] = "2724"
        $ProcessorName[118] = "i3-7101TE ";      $ProcessorScore[118] = "4003"
        $ProcessorName[119] = "i3-7102E ";      $ProcessorScore[119] = "2521"
        $ProcessorName[120] = "i3-7130U ";      $ProcessorScore[120] = "2995"
        $ProcessorName[121] = "i3-7167U ";      $ProcessorScore[121] = "3489"
        $ProcessorName[122] = "i3-7300 ";      $ProcessorScore[122] = "4778"
        $ProcessorName[123] = "i3-7300T ";      $ProcessorScore[123] = "4181"
        $ProcessorName[124] = "i3-7320 ";      $ProcessorScore[124] = "4862"
        $ProcessorName[125] = "i3-7350K ";      $ProcessorScore[125] = "4804"
        $ProcessorName[126] = "i3-8100 ";      $ProcessorScore[126] = "6153"
        $ProcessorName[127] = "i3-8100B ";      $ProcessorScore[127] = "6829"
        $ProcessorName[128] = "i3-8100T ";      $ProcessorScore[128] = "5293"
        $ProcessorName[129] = "i3-8109U ";      $ProcessorScore[129] = "4383"
        $ProcessorName[130] = "i3-8121U ";      $ProcessorScore[130] = "4340"
        $ProcessorName[131] = "i3-8130U ";      $ProcessorScore[131] = "3660"
        $ProcessorName[132] = "i3-8145U ";      $ProcessorScore[132] = "3727"
        $ProcessorName[133] = "i3-8145UE ";      $ProcessorScore[133] = "4140"
        $ProcessorName[134] = "i3-8300 ";      $ProcessorScore[134] = "6317"
        $ProcessorName[135] = "i3-8300T ";      $ProcessorScore[135] = "5827"
        $ProcessorName[136] = "i3-8350K ";      $ProcessorScore[136] = "7009"
        $ProcessorName[137] = "i3-9100 ";      $ProcessorScore[137] = "6667"
        $ProcessorName[138] = "i3-9100F ";      $ProcessorScore[138] = "6835"
        $ProcessorName[139] = "i3-9100T ";      $ProcessorScore[139] = "5623"
        $ProcessorName[140] = "i3-9300 ";      $ProcessorScore[140] = "7267"
        $ProcessorName[141] = "i3-9300T ";      $ProcessorScore[141] = "6367"
        $ProcessorName[142] = "i3-9320 ";      $ProcessorScore[142] = "7358"
        $ProcessorName[143] = "i3-9350K ";      $ProcessorScore[143] = "7759"
        $ProcessorName[144] = "i3-9350KF ";      $ProcessorScore[144] = "7913"
        $ProcessorName[145] = "i5-10210U ";      $ProcessorScore[145] = "6487"
        $ProcessorName[146] = "i5-10210Y ";      $ProcessorScore[146] = "4918"
        $ProcessorName[147] = "i5-10300H ";      $ProcessorScore[147] = "8913"
        $ProcessorName[148] = "i5-1030NG7 ";      $ProcessorScore[148] = "5331"
        $ProcessorName[149] = "i5-10310U ";      $ProcessorScore[149] = "6788"
        $ProcessorName[150] = "i5-1035G1 ";      $ProcessorScore[150] = "7977"
        $ProcessorName[151] = "i5-1035G4 ";      $ProcessorScore[151] = "8211"
        $ProcessorName[152] = "i5-1035G7 ";      $ProcessorScore[152] = "8495"
        $ProcessorName[153] = "i5-1038NG7 ";      $ProcessorScore[153] = "9907"
        $ProcessorName[154] = "i5-10400 ";      $ProcessorScore[154] = "12715"
        $ProcessorName[155] = "i5-10400F ";      $ProcessorScore[155] = "12704"
        $ProcessorName[156] = "i5-10400H ";      $ProcessorScore[156] = "8911"
        $ProcessorName[157] = "i5-10400T ";      $ProcessorScore[157] = "10429"
        $ProcessorName[158] = "i5-10500 ";      $ProcessorScore[158] = "13419"
        $ProcessorName[159] = "i5-10500T ";      $ProcessorScore[159] = "10802"
        $ProcessorName[160] = "i5-10600 ";      $ProcessorScore[160] = "14069"
        $ProcessorName[161] = "i5-10600K ";      $ProcessorScore[161] = "14577"
        $ProcessorName[162] = "i5-10600KF ";      $ProcessorScore[162] = "14900"
        $ProcessorName[163] = "i5-10600T ";      $ProcessorScore[163] = "11330"
        $ProcessorName[164] = "i5-1135G7 ";      $ProcessorScore[164] = "10537"
        $ProcessorName[165] = "i5-2300 ";      $ProcessorScore[165] = "3343"
        $ProcessorName[166] = "i5-2310 ";      $ProcessorScore[166] = "3435"
        $ProcessorName[167] = "i5-2320 ";      $ProcessorScore[167] = "3595"
        $ProcessorName[168] = "i5-2380P ";      $ProcessorScore[168] = "3709"
        $ProcessorName[169] = "i5-2390T ";      $ProcessorScore[169] = "2310"
        $ProcessorName[170] = "i5-2400 ";      $ProcessorScore[170] = "3795"
        $ProcessorName[171] = "i5-2400S ";      $ProcessorScore[171] = "3140"
        $ProcessorName[172] = "i5-24050S ";      $ProcessorScore[172] = "2799"
        $ProcessorName[173] = "i5-2405S ";      $ProcessorScore[173] = "2980"
        $ProcessorName[174] = "i5-2410M ";      $ProcessorScore[174] = "1920"
        $ProcessorName[175] = "i5-2415M ";      $ProcessorScore[175] = "2035"
        $ProcessorName[176] = "i5-2430M ";      $ProcessorScore[176] = "1963"
        $ProcessorName[177] = "i5-2435M ";      $ProcessorScore[177] = "1738"
        $ProcessorName[178] = "i5-2450M ";      $ProcessorScore[178] = "2053"
        $ProcessorName[179] = "i5-2450P ";      $ProcessorScore[179] = "3869"
        $ProcessorName[180] = "i5-2467M ";      $ProcessorScore[180] = "1611"
        $ProcessorName[181] = "i5-2500 ";      $ProcessorScore[181] = "4061"
        $ProcessorName[182] = "i5-2500K ";      $ProcessorScore[182] = "4087"
        $ProcessorName[183] = "i5-2500S ";      $ProcessorScore[183] = "3318"
        $ProcessorName[184] = "i5-2500T ";      $ProcessorScore[184] = "2741"
        $ProcessorName[185] = "i5-2510E ";      $ProcessorScore[185] = "1889"
        $ProcessorName[186] = "i5-2515E ";      $ProcessorScore[186] = "1882"
        $ProcessorName[187] = "i5-2520M ";      $ProcessorScore[187] = "2307"
        $ProcessorName[188] = "i5-2537M ";      $ProcessorScore[188] = "1094"
        $ProcessorName[189] = "i5-2540M ";      $ProcessorScore[189] = "2281"
        $ProcessorName[190] = "i5-2550K ";      $ProcessorScore[190] = "4105"
        $ProcessorName[191] = "i5-2557M ";      $ProcessorScore[191] = "1628"
        $ProcessorName[192] = "i5-2560M ";      $ProcessorScore[192] = "2131"
        $ProcessorName[193] = "i5-3170K ";      $ProcessorScore[193] = "8882"
        $ProcessorName[194] = "i5-3210M ";      $ProcessorScore[194] = "2438"
        $ProcessorName[195] = "i5-3230M ";      $ProcessorScore[195] = "2516"
        $ProcessorName[196] = "i5-3317U ";      $ProcessorScore[196] = "1954"
        $ProcessorName[197] = "i5-3320M ";      $ProcessorScore[197] = "2645"
        $ProcessorName[198] = "i5-3330 ";      $ProcessorScore[198] = "4089"
        $ProcessorName[199] = "i5-3330S ";      $ProcessorScore[199] = "3856"
        $ProcessorName[200] = "i5-3335S ";      $ProcessorScore[200] = "3754"
        $ProcessorName[201] = "i5-3337U ";      $ProcessorScore[201] = "2164"
        $ProcessorName[202] = "i5-3339Y ";      $ProcessorScore[202] = "1499"
        $ProcessorName[203] = "i5-3340 ";      $ProcessorScore[203] = "4281"
        $ProcessorName[204] = "i5-3340M ";      $ProcessorScore[204] = "2732"
        $ProcessorName[205] = "i5-3340S ";      $ProcessorScore[205] = "3876"
        $ProcessorName[206] = "i5-3350P ";      $ProcessorScore[206] = "4283"
        $ProcessorName[207] = "i5-3360M ";      $ProcessorScore[207] = "2955"
        $ProcessorName[208] = "i5-3380M ";      $ProcessorScore[208] = "3015"
        $ProcessorName[209] = "i5-3427U ";      $ProcessorScore[209] = "2275"
        $ProcessorName[210] = "i5-3437U ";      $ProcessorScore[210] = "2205"
        $ProcessorName[211] = "i5-3439Y ";      $ProcessorScore[211] = "1907"
        $ProcessorName[212] = "i5-3450 ";      $ProcessorScore[212] = "4396"
        $ProcessorName[213] = "i5-3450S ";      $ProcessorScore[213] = "4154"
        $ProcessorName[214] = "i5-3470 ";      $ProcessorScore[214] = "4645"
        $ProcessorName[215] = "i5-3470S ";      $ProcessorScore[215] = "4338"
        $ProcessorName[216] = "i5-3470T ";      $ProcessorScore[216] = "2978"
        $ProcessorName[217] = "i5-3475S ";      $ProcessorScore[217] = "4073"
        $ProcessorName[218] = "i5-3550 ";      $ProcessorScore[218] = "4801"
        $ProcessorName[219] = "i5-3550S ";      $ProcessorScore[219] = "4422"
        $ProcessorName[220] = "i5-3570 ";      $ProcessorScore[220] = "4894"
        $ProcessorName[221] = "i5-3570K ";      $ProcessorScore[221] = "4929"
        $ProcessorName[222] = "i5-3570S ";      $ProcessorScore[222] = "4615"
        $ProcessorName[223] = "i5-3570T ";      $ProcessorScore[223] = "4120"
        $ProcessorName[224] = "i5-3610ME ";      $ProcessorScore[224] = "2623"
        $ProcessorName[225] = "i5-4200H ";      $ProcessorScore[225] = "3079"
        $ProcessorName[226] = "i5-4200M ";      $ProcessorScore[226] = "2834"
        $ProcessorName[227] = "i5-4200U ";      $ProcessorScore[227] = "2172"
        $ProcessorName[228] = "i5-4200Y ";      $ProcessorScore[228] = "1558"
        $ProcessorName[229] = "i5-4202Y ";      $ProcessorScore[229] = "1606"
        $ProcessorName[230] = "i5-4210H ";      $ProcessorScore[230] = "2786"
        $ProcessorName[231] = "i5-4210M ";      $ProcessorScore[231] = "2876"
        $ProcessorName[232] = "i5-4210U ";      $ProcessorScore[232] = "2270"
        $ProcessorName[233] = "i5-4210Y ";      $ProcessorScore[233] = "1651"
        $ProcessorName[234] = "i5-4220Y ";      $ProcessorScore[234] = "1400"
        $ProcessorName[235] = "i5-4230U ";      $ProcessorScore[235] = "1853"
        $ProcessorName[236] = "i5-4250U ";      $ProcessorScore[236] = "2137"
        $ProcessorName[237] = "i5-4258U ";      $ProcessorScore[237] = "2713"
        $ProcessorName[238] = "i5-4260U ";      $ProcessorScore[238] = "2480"
        $ProcessorName[239] = "i5-4278U ";      $ProcessorScore[239] = "2948"
        $ProcessorName[240] = "i5-4288U ";      $ProcessorScore[240] = "2317"
        $ProcessorName[241] = "i5-4300M ";      $ProcessorScore[241] = "3042"
        $ProcessorName[242] = "i5-4300U ";      $ProcessorScore[242] = "2503"
        $ProcessorName[243] = "i5-4300Y ";      $ProcessorScore[243] = "1531"
        $ProcessorName[244] = "i5-4302Y ";      $ProcessorScore[244] = "1817"
        $ProcessorName[245] = "i5-4308U ";      $ProcessorScore[245] = "2854"
        $ProcessorName[246] = "i5-430M ";      $ProcessorScore[246] = "1216"
        $ProcessorName[247] = "i5-430UM ";      $ProcessorScore[247] = "836"
        $ProcessorName[248] = "i5-4310M ";      $ProcessorScore[248] = "3206"
        $ProcessorName[249] = "i5-4310U ";      $ProcessorScore[249] = "2505"
        $ProcessorName[250] = "i5-4330M ";      $ProcessorScore[250] = "3217"
        $ProcessorName[251] = "i5-4340M ";      $ProcessorScore[251] = "3398"
        $ProcessorName[252] = "i5-4350U ";      $ProcessorScore[252] = "2305"
        $ProcessorName[253] = "i5-4400E ";      $ProcessorScore[253] = "3251"
        $ProcessorName[254] = "i5-4402E ";      $ProcessorScore[254] = "2681"
        $ProcessorName[255] = "i5-4422E ";      $ProcessorScore[255] = "1907"
        $ProcessorName[256] = "i5-4430 ";      $ProcessorScore[256] = "4713"
        $ProcessorName[257] = "i5-4430S ";      $ProcessorScore[257] = "4332"
        $ProcessorName[258] = "i5-4440 ";      $ProcessorScore[258] = "4662"
        $ProcessorName[259] = "i5-4440S ";      $ProcessorScore[259] = "4010"
        $ProcessorName[260] = "i5-4460 ";      $ProcessorScore[260] = "4791"
        $ProcessorName[261] = "i5-4460S ";      $ProcessorScore[261] = "4445"
        $ProcessorName[262] = "i5-4460T ";      $ProcessorScore[262] = "3583"
        $ProcessorName[263] = "i5-4470S ";      $ProcessorScore[263] = "4742"
        $ProcessorName[264] = "i5-450M ";      $ProcessorScore[264] = "1226"
        $ProcessorName[265] = "i5-4570 ";      $ProcessorScore[265] = "5159"
        $ProcessorName[266] = "i5-4570R ";      $ProcessorScore[266] = "4820"
        $ProcessorName[267] = "i5-4570S ";      $ProcessorScore[267] = "5000"
        $ProcessorName[268] = "i5-4570T ";      $ProcessorScore[268] = "3256"
        $ProcessorName[269] = "i5-4570TE ";      $ProcessorScore[269] = "3043"
        $ProcessorName[270] = "i5-4590 ";      $ProcessorScore[270] = "5298"
        $ProcessorName[271] = "i5-4590S ";      $ProcessorScore[271] = "5083"
        $ProcessorName[272] = "i5-4590T ";      $ProcessorScore[272] = "3969"
        $ProcessorName[273] = "i5-460M ";      $ProcessorScore[273] = "1288"
        $ProcessorName[274] = "i5-4670 ";      $ProcessorScore[274] = "5452"
        $ProcessorName[275] = "i5-4670K ";      $ProcessorScore[275] = "5510"
        $ProcessorName[276] = "i5-4670K CPT ";      $ProcessorScore[276] = "5034"
        $ProcessorName[277] = "i5-4670R ";      $ProcessorScore[277] = "5335"
        $ProcessorName[278] = "i5-4670S ";      $ProcessorScore[278] = "4985"
        $ProcessorName[279] = "i5-4670T ";      $ProcessorScore[279] = "4404"
        $ProcessorName[280] = "i5-4690 ";      $ProcessorScore[280] = "5601"
        $ProcessorName[281] = "i5-4690K ";      $ProcessorScore[281] = "5545"
        $ProcessorName[282] = "i5-4690S ";      $ProcessorScore[282] = "5270"
        $ProcessorName[283] = "i5-4690T ";      $ProcessorScore[283] = "4267"
        $ProcessorName[284] = "i5-470UM ";      $ProcessorScore[284] = "752"
        $ProcessorName[285] = "i5-480M ";      $ProcessorScore[285] = "1305"
        $ProcessorName[286] = "i5-5200U ";      $ProcessorScore[286] = "2493"
        $ProcessorName[287] = "i5-520M ";      $ProcessorScore[287] = "1696"
        $ProcessorName[288] = "i5-520UM ";      $ProcessorScore[288] = "928"
        $ProcessorName[289] = "i5-5250U ";      $ProcessorScore[289] = "2458"
        $ProcessorName[290] = "i5-5257U ";      $ProcessorScore[290] = "2953"
        $ProcessorName[291] = "i5-5287U ";      $ProcessorScore[291] = "3356"
        $ProcessorName[292] = "i5-5300U ";      $ProcessorScore[292] = "2742"
        $ProcessorName[293] = "i5-5350U ";      $ProcessorScore[293] = "2667"
        $ProcessorName[294] = "i5-540M ";      $ProcessorScore[294] = "1753"
        $ProcessorName[295] = "i5-540UM ";      $ProcessorScore[295] = "1002"
        $ProcessorName[296] = "i5-5575R ";      $ProcessorScore[296] = "5550"
        $ProcessorName[297] = "i5-560M ";      $ProcessorScore[297] = "1830"
        $ProcessorName[298] = "i5-560UM ";      $ProcessorScore[298] = "1015"
        $ProcessorName[299] = "i5-5675C ";      $ProcessorScore[299] = "5932"
        $ProcessorName[300] = "i5-5675R ";      $ProcessorScore[300] = "5931"
        $ProcessorName[301] = "i5-580M ";      $ProcessorScore[301] = "1922"
        $ProcessorName[302] = "i5-6198DU ";      $ProcessorScore[302] = "3138"
        $ProcessorName[303] = "i5-6200U ";      $ProcessorScore[303] = "3021"
        $ProcessorName[304] = "i5-6260U ";      $ProcessorScore[304] = "3198"
        $ProcessorName[305] = "i5-6267U ";      $ProcessorScore[305] = "3124"
        $ProcessorName[306] = "i5-6287U ";      $ProcessorScore[306] = "3655"
        $ProcessorName[307] = "i5-6300HQ ";      $ProcessorScore[307] = "4625"
        $ProcessorName[308] = "i5-6300U ";      $ProcessorScore[308] = "3252"
        $ProcessorName[309] = "i5-6360U ";      $ProcessorScore[309] = "3259"
        $ProcessorName[310] = "i5-6400 ";      $ProcessorScore[310] = "5151"
        $ProcessorName[311] = "i5-6400T ";      $ProcessorScore[311] = "4396"
        $ProcessorName[312] = "i5-6402P ";      $ProcessorScore[312] = "5703"
        $ProcessorName[313] = "i5-6440EQ ";      $ProcessorScore[313] = "5368"
        $ProcessorName[314] = "i5-6440HQ ";      $ProcessorScore[314] = "5305"
        $ProcessorName[315] = "i5-6442EQ ";      $ProcessorScore[315] = "4519"
        $ProcessorName[316] = "i5-650 ";      $ProcessorScore[316] = "2200"
        $ProcessorName[317] = "i5-6500 ";      $ProcessorScore[317] = "5660"
        $ProcessorName[318] = "i5-6500T ";      $ProcessorScore[318] = "4977"
        $ProcessorName[319] = "i5-6500TE ";      $ProcessorScore[319] = "5295"
        $ProcessorName[320] = "i5-655K ";      $ProcessorScore[320] = "2017"
        $ProcessorName[321] = "i5-660 ";      $ProcessorScore[321] = "2331"
        $ProcessorName[322] = "i5-6600 ";      $ProcessorScore[322] = "6056"
        $ProcessorName[323] = "i5-6600K ";      $ProcessorScore[323] = "6287"
        $ProcessorName[324] = "i5-6600T ";      $ProcessorScore[324] = "5524"
        $ProcessorName[325] = "i5-661 ";      $ProcessorScore[325] = "2425"
        $ProcessorName[326] = "i5-670 ";      $ProcessorScore[326] = "2423"
        $ProcessorName[327] = "i5-680 ";      $ProcessorScore[327] = "2568"
        $ProcessorName[328] = "i5-7200U ";      $ProcessorScore[328] = "3391"
        $ProcessorName[329] = "i5-7260U ";      $ProcessorScore[329] = "3927"
        $ProcessorName[330] = "i5-7267U ";      $ProcessorScore[330] = "4093"
        $ProcessorName[331] = "i5-7287U ";      $ProcessorScore[331] = "4149"
        $ProcessorName[332] = "i5-7300HQ ";      $ProcessorScore[332] = "5107"
        $ProcessorName[333] = "i5-7300U ";      $ProcessorScore[333] = "3723"
        $ProcessorName[334] = "i5-7360U ";      $ProcessorScore[334] = "4334"
        $ProcessorName[335] = "i5-7400 ";      $ProcessorScore[335] = "5486"
        $ProcessorName[336] = "i5-7400T ";      $ProcessorScore[336] = "4556"
        $ProcessorName[337] = "i5-7440HQ ";      $ProcessorScore[337] = "5553"
        $ProcessorName[338] = "i5-7442EQ ";      $ProcessorScore[338] = "4834"
        $ProcessorName[339] = "i5-750 ";      $ProcessorScore[339] = "2431"
        $ProcessorName[340] = "i5-7500 ";      $ProcessorScore[340] = "6134"
        $ProcessorName[341] = "i5-7500T ";      $ProcessorScore[341] = "5356"
        $ProcessorName[342] = "i5-760 ";      $ProcessorScore[342] = "2559"
        $ProcessorName[343] = "i5-7600 ";      $ProcessorScore[343] = "6597"
        $ProcessorName[344] = "i5-7600K ";      $ProcessorScore[344] = "6855"
        $ProcessorName[345] = "i5-7600T ";      $ProcessorScore[345] = "5858"
        $ProcessorName[346] = "i5-760S ";      $ProcessorScore[346] = "5440"
        $ProcessorName[347] = "i5-7640X ";      $ProcessorScore[347] = "6467"
        $ProcessorName[348] = "i5-7Y54 ";      $ProcessorScore[348] = "2891"
        $ProcessorName[349] = "i5-7Y57 ";      $ProcessorScore[349] = "3070"
        $ProcessorName[350] = "i5-8200Y ";      $ProcessorScore[350] = "2308"
        $ProcessorName[351] = "i5-8210Y ";      $ProcessorScore[351] = "2905"
        $ProcessorName[352] = "i5-8250U ";      $ProcessorScore[352] = "6057"
        $ProcessorName[353] = "i5-8257U ";      $ProcessorScore[353] = "8182"
        $ProcessorName[354] = "i5-8259U ";      $ProcessorScore[354] = "8271"
        $ProcessorName[355] = "i5-8260U ";      $ProcessorScore[355] = "7776"
        $ProcessorName[356] = "i5-8265U ";      $ProcessorScore[356] = "6254"
        $ProcessorName[357] = "i5-8265UC ";      $ProcessorScore[357] = "5988"
        $ProcessorName[358] = "i5-8279U ";      $ProcessorScore[358] = "7917"
        $ProcessorName[359] = "i5-8300H ";      $ProcessorScore[359] = "7522"
        $ProcessorName[360] = "i5-8305G ";      $ProcessorScore[360] = "7073"
        $ProcessorName[361] = "i5-8350U ";      $ProcessorScore[361] = "6413"
        $ProcessorName[362] = "i5-8365U ";      $ProcessorScore[362] = "6422"
        $ProcessorName[363] = "i5-8365UE ";      $ProcessorScore[363] = "5243"
        $ProcessorName[364] = "i5-8400 ";      $ProcessorScore[364] = "9200"
        $ProcessorName[365] = "i5-8400H ";      $ProcessorScore[365] = "8146"
        $ProcessorName[366] = "i5-8400T ";      $ProcessorScore[366] = "7433"
        $ProcessorName[367] = "i5-8500 ";      $ProcessorScore[367] = "9486"
        $ProcessorName[368] = "i5-8500B ";      $ProcessorScore[368] = "9538"
        $ProcessorName[369] = "i5-8500T ";      $ProcessorScore[369] = "7881"
        $ProcessorName[370] = "i5-8600 ";      $ProcessorScore[370] = "9787"
        $ProcessorName[371] = "i5-8600K ";      $ProcessorScore[371] = "10266"
        $ProcessorName[372] = "i5-8600T ";      $ProcessorScore[372] = "8846"
        $ProcessorName[373] = "i5-9300H ";      $ProcessorScore[373] = "8008"
        $ProcessorName[374] = "i5-9300HF ";      $ProcessorScore[374] = "7742"
        $ProcessorName[375] = "i5-9400 ";      $ProcessorScore[375] = "9596"
        $ProcessorName[376] = "i5-9400F ";      $ProcessorScore[376] = "9597"
        $ProcessorName[377] = "i5-9400H ";      $ProcessorScore[377] = "8202"
        $ProcessorName[378] = "i5-9400T ";      $ProcessorScore[378] = "7819"
        $ProcessorName[379] = "i5-9500 ";      $ProcessorScore[379] = "9976"
        $ProcessorName[380] = "i5-9500F ";      $ProcessorScore[380] = "10342"
        $ProcessorName[381] = "i5-9500T ";      $ProcessorScore[381] = "8121"
        $ProcessorName[382] = "i5-9500TE ";      $ProcessorScore[382] = "9212"
        $ProcessorName[383] = "i5-9600 ";      $ProcessorScore[383] = "10741"
        $ProcessorName[384] = "i5-9600K ";      $ProcessorScore[384] = "10899"
        $ProcessorName[385] = "i5-9600KF ";      $ProcessorScore[385] = "10898"
        $ProcessorName[386] = "i5-9600T ";      $ProcessorScore[386] = "9406"
        $ProcessorName[387] = "i5-L16G7 ";      $ProcessorScore[387] = "3164"
        $ProcessorName[388] = "i7-10510U ";      $ProcessorScore[388] = "7072"
        $ProcessorName[389] = "i7-10510Y ";      $ProcessorScore[389] = "5523"
        $ProcessorName[390] = "i7-1060NG7 ";      $ProcessorScore[390] = "6234"
        $ProcessorName[391] = "i7-10610U ";      $ProcessorScore[391] = "7284"
        $ProcessorName[392] = "i7-1065G7 ";      $ProcessorScore[392] = "9005"
        $ProcessorName[393] = "i7-1068NG7 ";      $ProcessorScore[393] = "10689"
        $ProcessorName[394] = "i7-10700 ";      $ProcessorScore[394] = "17474"
        $ProcessorName[395] = "i7-10700F ";      $ProcessorScore[395] = "17251"
        $ProcessorName[396] = "i7-10700K ";      $ProcessorScore[396] = "19654"
        $ProcessorName[397] = "i7-10700KF ";      $ProcessorScore[397] = "19747"
        $ProcessorName[398] = "i7-10700T ";      $ProcessorScore[398] = "13344"
        $ProcessorName[399] = "i7-10710U ";      $ProcessorScore[399] = "10041"
        $ProcessorName[400] = "i9-10850K ";      $ProcessorScore[400] = "22535"
        $ProcessorName[401] = "i7-10750H ";      $ProcessorScore[401] = "12745"
        $ProcessorName[402] = "i7-10810U ";      $ProcessorScore[402] = "9100"
        $ProcessorName[403] = "i7-10850H ";      $ProcessorScore[403] = "13120"
        $ProcessorName[404] = "i7-10875H ";      $ProcessorScore[404] = "15996"
        $ProcessorName[405] = "i7-1165G7 ";      $ProcessorScore[405] = "12820"
        $ProcessorName[406] = "i7-1185G7 ";      $ProcessorScore[406] = "10354"
        $ProcessorName[407] = "i7-2600 ";      $ProcessorScore[407] = "5333"
        $ProcessorName[408] = "i7-2600K ";      $ProcessorScore[408] = "5428"
        $ProcessorName[409] = "i7-2600S ";      $ProcessorScore[409] = "4364"
        $ProcessorName[410] = "i7-2610UE ";      $ProcessorScore[410] = "1409"
        $ProcessorName[411] = "i7-2617M ";      $ProcessorScore[411] = "1687"
        $ProcessorName[412] = "i7-2620M ";      $ProcessorScore[412] = "2408"
        $ProcessorName[413] = "i7-2630QM ";      $ProcessorScore[413] = "3609"
        $ProcessorName[414] = "i7-2630UM ";      $ProcessorScore[414] = "400"
        $ProcessorName[415] = "i7-2635QM ";      $ProcessorScore[415] = "3232"
        $ProcessorName[416] = "i7-2637M ";      $ProcessorScore[416] = "1946"
        $ProcessorName[417] = "i7-2640M ";      $ProcessorScore[417] = "2442"
        $ProcessorName[418] = "i7-2655LE ";      $ProcessorScore[418] = "1928"
        $ProcessorName[419] = "i7-2670QM ";      $ProcessorScore[419] = "3739"
        $ProcessorName[420] = "i7-2675QM ";      $ProcessorScore[420] = "3168"
        $ProcessorName[421] = "i7-2677M ";      $ProcessorScore[421] = "1799"
        $ProcessorName[422] = "i7-2700K ";      $ProcessorScore[422] = "5471"
        $ProcessorName[423] = "i7-2710QE ";      $ProcessorScore[423] = "3704"
        $ProcessorName[424] = "i7-2715QE ";      $ProcessorScore[424] = "3221"
        $ProcessorName[425] = "i7-2720QM ";      $ProcessorScore[425] = "4072"
        $ProcessorName[426] = "i7-2760QM ";      $ProcessorScore[426] = "4304"
        $ProcessorName[427] = "i7-2820QM ";      $ProcessorScore[427] = "4195"
        $ProcessorName[428] = "i7-2840QM ";      $ProcessorScore[428] = "3842"
        $ProcessorName[429] = "i7-2860QM ";      $ProcessorScore[429] = "4526"
        $ProcessorName[430] = "i7-2920XM ";      $ProcessorScore[430] = "4512"
        $ProcessorName[431] = "i7-2960XM ";      $ProcessorScore[431] = "3985"
        $ProcessorName[432] = "i7-3517U ";      $ProcessorScore[432] = "2170"
        $ProcessorName[433] = "i7-3517UE ";      $ProcessorScore[433] = "2141"
        $ProcessorName[434] = "i7-3520M ";      $ProcessorScore[434] = "2860"
        $ProcessorName[435] = "i7-3537U ";      $ProcessorScore[435] = "2402"
        $ProcessorName[436] = "i7-3540M ";      $ProcessorScore[436] = "2921"
        $ProcessorName[437] = "i7-3555LE ";      $ProcessorScore[437] = "1880"
        $ProcessorName[438] = "i7-3610QE ";      $ProcessorScore[438] = "4730"
        $ProcessorName[439] = "i7-3610QM ";      $ProcessorScore[439] = "5139"
        $ProcessorName[440] = "i7-3612QE ";      $ProcessorScore[440] = "4783"
        $ProcessorName[441] = "i7-3612QM ";      $ProcessorScore[441] = "4403"
        $ProcessorName[442] = "i7-3615QE ";      $ProcessorScore[442] = "5174"
        $ProcessorName[443] = "i7-3615QM ";      $ProcessorScore[443] = "4913"
        $ProcessorName[444] = "i7-3630QM ";      $ProcessorScore[444] = "5069"
        $ProcessorName[445] = "i7-3632QM ";      $ProcessorScore[445] = "4449"
        $ProcessorName[446] = "i7-3635QM ";      $ProcessorScore[446] = "4527"
        $ProcessorName[447] = "i7-3667U ";      $ProcessorScore[447] = "2515"
        $ProcessorName[448] = "i7-3687U ";      $ProcessorScore[448] = "2592"
        $ProcessorName[449] = "i7-3689Y ";      $ProcessorScore[449] = "1642"
        $ProcessorName[450] = "i7-3720QM ";      $ProcessorScore[450] = "5633"
        $ProcessorName[451] = "i7-3740QM ";      $ProcessorScore[451] = "5648"
        $ProcessorName[452] = "i7-3770 ";      $ProcessorScore[452] = "6370"
        $ProcessorName[453] = "i7-3770K ";      $ProcessorScore[453] = "6459"
        $ProcessorName[454] = "i7-3770S ";      $ProcessorScore[454] = "6241"
        $ProcessorName[455] = "i7-3770T ";      $ProcessorScore[455] = "5511"
        $ProcessorName[456] = "i7-3820 ";      $ProcessorScore[456] = "5863"
        $ProcessorName[457] = "i7-3820QM ";      $ProcessorScore[457] = "5608"
        $ProcessorName[458] = "i7-3840QM ";      $ProcessorScore[458] = "5983"
        $ProcessorName[459] = "i7-3920XM ";      $ProcessorScore[459] = "6001"
        $ProcessorName[460] = "i7-3930K ";      $ProcessorScore[460] = "8147"
        $ProcessorName[461] = "i7-3940XM ";      $ProcessorScore[461] = "5320"
        $ProcessorName[462] = "i7-3960X ";      $ProcessorScore[462] = "8672"
        $ProcessorName[463] = "i7-3970X ";      $ProcessorScore[463] = "8490"
        $ProcessorName[464] = "i7-4500U ";      $ProcessorScore[464] = "2532"
        $ProcessorName[465] = "i7-4510U ";      $ProcessorScore[465] = "2607"
        $ProcessorName[466] = "i7-4550U ";      $ProcessorScore[466] = "2131"
        $ProcessorName[467] = "i7-4558U ";      $ProcessorScore[467] = "2999"
        $ProcessorName[468] = "i7-4560U ";      $ProcessorScore[468] = "2950"
        $ProcessorName[469] = "i7-4578U ";      $ProcessorScore[469] = "3258"
        $ProcessorName[470] = "i7-4600M ";      $ProcessorScore[470] = "3181"
        $ProcessorName[471] = "i7-4600U ";      $ProcessorScore[471] = "2683"
        $ProcessorName[472] = "i7-4610M ";      $ProcessorScore[472] = "3249"
        $ProcessorName[473] = "i7-4610Y ";      $ProcessorScore[473] = "2446"
        $ProcessorName[474] = "i7-4650U ";      $ProcessorScore[474] = "2247"
        $ProcessorName[475] = "i7-4700EQ ";      $ProcessorScore[475] = "4941"
        $ProcessorName[476] = "i7-4700HQ ";      $ProcessorScore[476] = "5458"
        $ProcessorName[477] = "i7-4700MQ ";      $ProcessorScore[477] = "5286"
        $ProcessorName[478] = "i7-4702HQ ";      $ProcessorScore[478] = "5382"
        $ProcessorName[479] = "i7-4702MQ ";      $ProcessorScore[479] = "5222"
        $ProcessorName[480] = "i7-4710HQ ";      $ProcessorScore[480] = "5470"
        $ProcessorName[481] = "i7-4710MQ ";      $ProcessorScore[481] = "5851"
        $ProcessorName[482] = "i7-4712HQ ";      $ProcessorScore[482] = "4618"
        $ProcessorName[483] = "i7-4712MQ ";      $ProcessorScore[483] = "5209"
        $ProcessorName[484] = "i7-4720HQ ";      $ProcessorScore[484] = "5634"
        $ProcessorName[485] = "i7-4722HQ ";      $ProcessorScore[485] = "5620"
        $ProcessorName[486] = "i7-4750HQ ";      $ProcessorScore[486] = "5348"
        $ProcessorName[487] = "i7-4760HQ ";      $ProcessorScore[487] = "6300"
        $ProcessorName[488] = "i7-4765T ";      $ProcessorScore[488] = "4867"
        $ProcessorName[489] = "i7-4770 ";      $ProcessorScore[489] = "7023"
        $ProcessorName[490] = "i7-4770HQ ";      $ProcessorScore[490] = "6158"
        $ProcessorName[491] = "i7-4770K ";      $ProcessorScore[491] = "7031"
        $ProcessorName[492] = "i7-4770R ";      $ProcessorScore[492] = "6666"
        $ProcessorName[493] = "i7-4770S ";      $ProcessorScore[493] = "6768"
        $ProcessorName[494] = "i7-4770T ";      $ProcessorScore[494] = "5957"
        $ProcessorName[495] = "i7-4770TE ";      $ProcessorScore[495] = "4257"
        $ProcessorName[496] = "i7-4771 ";      $ProcessorScore[496] = "6985"
        $ProcessorName[497] = "i7-4785T ";      $ProcessorScore[497] = "5291"
        $ProcessorName[498] = "i7-4790 ";      $ProcessorScore[498] = "7211"
        $ProcessorName[499] = "i7-4790K ";      $ProcessorScore[499] = "8052"
        $ProcessorName[500] = "i9-10880H ";      $ProcessorScore[500] = "15137"
        $ProcessorName[501] = "i7-4790S ";      $ProcessorScore[501] = "6971"
        $ProcessorName[502] = "i7-4790T ";      $ProcessorScore[502] = "6508"
        $ProcessorName[503] = "i7-4800MQ ";      $ProcessorScore[503] = "5937"
        $ProcessorName[504] = "i7-4810MQ ";      $ProcessorScore[504] = "6152"
        $ProcessorName[505] = "i7-4820K ";      $ProcessorScore[505] = "6531"
        $ProcessorName[506] = "i7-4850HQ ";      $ProcessorScore[506] = "6198"
        $ProcessorName[507] = "i7-4860EQ ";      $ProcessorScore[507] = "5280"
        $ProcessorName[508] = "i7-4860HQ ";      $ProcessorScore[508] = "6485"
        $ProcessorName[509] = "i7-4870HQ ";      $ProcessorScore[509] = "6359"
        $ProcessorName[510] = "i7-4900MQ ";      $ProcessorScore[510] = "6080"
        $ProcessorName[511] = "i7-4910MQ ";      $ProcessorScore[511] = "6185"
        $ProcessorName[512] = "i7-4930K ";      $ProcessorScore[512] = "9151"
        $ProcessorName[513] = "i7-4930MX ";      $ProcessorScore[513] = "6765"
        $ProcessorName[514] = "i7-4940MX ";      $ProcessorScore[514] = "6943"
        $ProcessorName[515] = "i7-4960HQ ";      $ProcessorScore[515] = "6638"
        $ProcessorName[516] = "i7-4960X ";      $ProcessorScore[516] = "9740"
        $ProcessorName[517] = "i7-4980HQ ";      $ProcessorScore[517] = "6735"
        $ProcessorName[518] = "i7-5500U ";      $ProcessorScore[518] = "2731"
        $ProcessorName[519] = "i7-5550U ";      $ProcessorScore[519] = "2908"
        $ProcessorName[520] = "i7-5557U ";      $ProcessorScore[520] = "3558"
        $ProcessorName[521] = "i7-5600U ";      $ProcessorScore[521] = "3065"
        $ProcessorName[522] = "i7-5650U ";      $ProcessorScore[522] = "3110"
        $ProcessorName[523] = "i7-5675C ";      $ProcessorScore[523] = "6089"
        $ProcessorName[524] = "i7-5700EQ ";      $ProcessorScore[524] = "5905"
        $ProcessorName[525] = "i7-5700HQ ";      $ProcessorScore[525] = "5951"
        $ProcessorName[526] = "i7-5775C ";      $ProcessorScore[526] = "7813"
        $ProcessorName[527] = "i7-5775R ";      $ProcessorScore[527] = "7819"
        $ProcessorName[528] = "i7-5820K ";      $ProcessorScore[528] = "9759"
        $ProcessorName[529] = "i7-5850EQ ";      $ProcessorScore[529] = "7036"
        $ProcessorName[530] = "i7-5850HQ ";      $ProcessorScore[530] = "6866"
        $ProcessorName[531] = "i7-5930K ";      $ProcessorScore[531] = "10230"
        $ProcessorName[532] = "i7-5950HQ ";      $ProcessorScore[532] = "7728"
        $ProcessorName[533] = "i7-5960X ";      $ProcessorScore[533] = "12692"
        $ProcessorName[534] = "i7-610E ";      $ProcessorScore[534] = "1818"
        $ProcessorName[535] = "i7-620LM ";      $ProcessorScore[535] = "1367"
        $ProcessorName[536] = "i7-620M ";      $ProcessorScore[536] = "1950"
        $ProcessorName[537] = "i7-620UM ";      $ProcessorScore[537] = "964"
        $ProcessorName[538] = "i7-640LM ";      $ProcessorScore[539] = "1623"
        $ProcessorName[539] = "i7-640M ";      $ProcessorScore[539] = "2050"
        $ProcessorName[540] = "i7-640UM ";      $ProcessorScore[540] = "1026"
        $ProcessorName[541] = "i7-6498DU ";      $ProcessorScore[541] = "3293"
        $ProcessorName[542] = "i7-6500U ";      $ProcessorScore[542] = "3279"
        $ProcessorName[543] = "i7-6560U ";      $ProcessorScore[543] = "3322"
        $ProcessorName[544] = "i7-6567U ";      $ProcessorScore[544] = "3825"
        $ProcessorName[545] = "i7-6600U ";      $ProcessorScore[545] = "3563"
        $ProcessorName[546] = "i7-660UM ";      $ProcessorScore[546] = "1284"
        $ProcessorName[547] = "i7-6650U ";      $ProcessorScore[547] = "3544"
        $ProcessorName[548] = "i7-6700 ";      $ProcessorScore[548] = "8036"
        $ProcessorName[549] = "i7-6700HQ ";      $ProcessorScore[549] = "6482"
        $ProcessorName[550] = "i7-6700K ";      $ProcessorScore[550] = "8954"
        $ProcessorName[551] = "i7-6700T ";      $ProcessorScore[551] = "7247"
        $ProcessorName[552] = "i7-6700TE ";      $ProcessorScore[552] = "6600"
        $ProcessorName[553] = "i7-6770HQ ";      $ProcessorScore[553] = "7338"
        $ProcessorName[554] = "i7-6800K ";      $ProcessorScore[554] = "10543"
        $ProcessorName[555] = "i7-680UM ";      $ProcessorScore[555] = "1196"
        $ProcessorName[556] = "i7-6820EQ ";      $ProcessorScore[556] = "6746"
        $ProcessorName[557] = "i7-6820HK ";      $ProcessorScore[557] = "7067"
        $ProcessorName[558] = "i7-6820HQ ";      $ProcessorScore[558] = "6892"
        $ProcessorName[559] = "i7-6822EQ ";      $ProcessorScore[559] = "5241"
        $ProcessorName[560] = "i7-6850K ";      $ProcessorScore[560] = "11266"
        $ProcessorName[561] = "i7-6900K ";      $ProcessorScore[561] = "13402"
        $ProcessorName[562] = "i7-6920HQ ";      $ProcessorScore[562] = "7307"
        $ProcessorName[563] = "i7-6950X ";      $ProcessorScore[563] = "17363"
        $ProcessorName[564] = "i7-720QM ";      $ProcessorScore[564] = "1686"
        $ProcessorName[565] = "i7-740QM ";      $ProcessorScore[565] = "1715"
        $ProcessorName[566] = "i7-7500U ";      $ProcessorScore[566] = "3673"
        $ProcessorName[567] = "i7-7560U ";      $ProcessorScore[567] = "3920"
        $ProcessorName[568] = "i7-7567U ";      $ProcessorScore[568] = "4188"
        $ProcessorName[569] = "i7-7600U ";      $ProcessorScore[569] = "3630"
        $ProcessorName[570] = "i7-7660U ";      $ProcessorScore[570] = "4163"
        $ProcessorName[571] = "i7-7700 ";      $ProcessorScore[571] = "8661"
        $ProcessorName[572] = "i7-7700HQ ";      $ProcessorScore[572] = "6960"
        $ProcessorName[573] = "i7-7700K ";      $ProcessorScore[573] = "9729"
        $ProcessorName[574] = "i7-7700T ";      $ProcessorScore[574] = "7814"
        $ProcessorName[575] = "i7-7740X ";      $ProcessorScore[575] = "9940"
        $ProcessorName[576] = "i7-7800X ";      $ProcessorScore[576] = "12702"
        $ProcessorName[577] = "i7-7820EQ ";      $ProcessorScore[577] = "7059"
        $ProcessorName[578] = "i7-7820HK ";      $ProcessorScore[578] = "7884"
        $ProcessorName[579] = "i7-7820HQ ";      $ProcessorScore[579] = "7179"
        $ProcessorName[580] = "i7-7820X ";      $ProcessorScore[580] = "17489"
        $ProcessorName[581] = "i7-7900X ";      $ProcessorScore[581] = "19358"
        $ProcessorName[582] = "i7-7920HQ ";      $ProcessorScore[582] = "7694"
        $ProcessorName[583] = "i7-7Y75 ";      $ProcessorScore[583] = "2715"
        $ProcessorName[584] = "i7-8086K ";      $ProcessorScore[584] = "14717"
        $ProcessorName[585] = "i7-820QM ";      $ProcessorScore[585] = "1921"
        $ProcessorName[586] = "i7-840QM ";      $ProcessorScore[586] = "1894"
        $ProcessorName[587] = "i7-8500Y ";      $ProcessorScore[587] = "3189"
        $ProcessorName[588] = "i7-8550U ";      $ProcessorScore[588] = "6002"
        $ProcessorName[589] = "i7-8557U ";      $ProcessorScore[589] = "7820"
        $ProcessorName[590] = "i7-8559U ";      $ProcessorScore[590] = "8892"
        $ProcessorName[591] = "i7-8565U ";      $ProcessorScore[591] = "6489"
        $ProcessorName[592] = "i7-8565UC ";      $ProcessorScore[592] = "6187"
        $ProcessorName[593] = "i7-8569U ";      $ProcessorScore[593] = "9251"
        $ProcessorName[594] = "i7-860 ";      $ProcessorScore[594] = "2887"
        $ProcessorName[595] = "i7-860S ";      $ProcessorScore[595] = "2725"
        $ProcessorName[596] = "i7-8650U ";      $ProcessorScore[596] = "6584"
        $ProcessorName[597] = "i7-8665U ";      $ProcessorScore[597] = "6602"
        $ProcessorName[598] = "i7-8665UE ";      $ProcessorScore[598] = "6587"
        $ProcessorName[599] = "i7-870 ";      $ProcessorScore[599] = "3036"
        $ProcessorName[600] = "i7-8700 ";      $ProcessorScore[600] = "13115"
        $ProcessorName[601] = "i7-8700B ";      $ProcessorScore[601] = "12286"
        $ProcessorName[602] = "i7-8700K ";      $ProcessorScore[602] = "13887"
        $ProcessorName[603] = "i7-8700T ";      $ProcessorScore[603] = "10779"
        $ProcessorName[604] = "i7-8705G ";      $ProcessorScore[604] = "7974"
        $ProcessorName[605] = "i7-8706G ";      $ProcessorScore[605] = "8136"
        $ProcessorName[606] = "i7-8709G ";      $ProcessorScore[606] = "7921"
        $ProcessorName[607] = "i7-870S ";      $ProcessorScore[607] = "2786"
        $ProcessorName[608] = "i7-8750H ";      $ProcessorScore[608] = "10203"
        $ProcessorName[609] = "i7-875K ";      $ProcessorScore[609] = "3028"
        $ProcessorName[610] = "i7-880 ";      $ProcessorScore[610] = "3205"
        $ProcessorName[611] = "i7-8809G ";      $ProcessorScore[611] = "8774"
        $ProcessorName[612] = "i7-8850H ";      $ProcessorScore[612] = "10439"
        $ProcessorName[613] = "i7-920 ";      $ProcessorScore[613] = "2734"
        $ProcessorName[614] = "i7-920XM ";      $ProcessorScore[614] = "2178"
        $ProcessorName[615] = "i7-930 ";      $ProcessorScore[615] = "2921"
        $ProcessorName[616] = "i7-940 ";      $ProcessorScore[616] = "3081"
        $ProcessorName[617] = "i7-940XM ";      $ProcessorScore[617] = "2308"
        $ProcessorName[618] = "i7-950 ";      $ProcessorScore[618] = "3074"
        $ProcessorName[619] = "i7-960 ";      $ProcessorScore[619] = "3219"
        $ProcessorName[620] = "i7-965 ";      $ProcessorScore[620] = "3269"
        $ProcessorName[621] = "i7-970 ";      $ProcessorScore[621] = "6719"
        $ProcessorName[622] = "i7-9700 ";      $ProcessorScore[622] = "13613"
        $ProcessorName[623] = "i7-9700F ";      $ProcessorScore[623] = "13757"
        $ProcessorName[624] = "i7-9700K ";      $ProcessorScore[624] = "14603"
        $ProcessorName[625] = "i7-9700KF ";      $ProcessorScore[625] = "14711"
        $ProcessorName[626] = "i7-9700T ";      $ProcessorScore[626] = "10885"
        $ProcessorName[627] = "i7-9700TE ";      $ProcessorScore[627] = "10680"
        $ProcessorName[628] = "i7-975 ";      $ProcessorScore[628] = "3331"
        $ProcessorName[629] = "i7-9750H ";      $ProcessorScore[629] = "11385"
        $ProcessorName[630] = "i7-9750HF ";      $ProcessorScore[630] = "11803"
        $ProcessorName[631] = "i7-980 ";      $ProcessorScore[631] = "6922"
        $ProcessorName[632] = "i7-9800X ";      $ProcessorScore[632] = "18337"
        $ProcessorName[633] = "i7-980X ";      $ProcessorScore[633] = "6757"
        $ProcessorName[634] = "i7-985 ";      $ProcessorScore[634] = "3928"
        $ProcessorName[635] = "i7-9850H ";      $ProcessorScore[635] = "11643"
        $ProcessorName[636] = "i7-9850HL ";      $ProcessorScore[636] = "9112"
        $ProcessorName[637] = "i7-990X ";      $ProcessorScore[637] = "7298"
        $ProcessorName[638] = "i7-995X ";      $ProcessorScore[638] = "7079"
        $ProcessorName[639] = "i9-9990XE ";      $ProcessorScore[639] = "31941"
        $ProcessorName[640] = "i9-9980XE ";      $ProcessorScore[640] = "31556"
        $ProcessorName[641] = "i9-9980HK ";      $ProcessorScore[641] = "15298"
        $ProcessorName[642] = "i9-9960X ";      $ProcessorScore[642] = "30663"
        $ProcessorName[643] = "i9-9940X ";      $ProcessorScore[643] = "28242"
        $ProcessorName[644] = "i9-9920X ";      $ProcessorScore[644] = "25389"
        $ProcessorName[645] = "i9-9900X ";      $ProcessorScore[645] = "21679"
        $ProcessorName[646] = "i9-9900T ";      $ProcessorScore[646] = "13609"
        $ProcessorName[647] = "i9-9900KS ";      $ProcessorScore[647] = "19470"
        $ProcessorName[648] = "i9-9900KF ";      $ProcessorScore[648] = "18801"
        $ProcessorName[649] = "i9-9900K ";      $ProcessorScore[649] = "18876"
        $ProcessorName[650] = "i9-9900 ";      $ProcessorScore[650] = "17181"
        $ProcessorName[651] = "i9-9880H ";      $ProcessorScore[651] = "14081"
        $ProcessorName[652] = "i9-9820X ";      $ProcessorScore[652] = "20626"
        $ProcessorName[653] = "i9-8950HK ";      $ProcessorScore[653] = "10755"
        $ProcessorName[654] = "i9-7980XE ";      $ProcessorScore[654] = "29541"
        $ProcessorName[655] = "i9-7960X ";      $ProcessorScore[655] = "27264"
        $ProcessorName[656] = "i9-7940X ";      $ProcessorScore[656] = "26864"
        $ProcessorName[657] = "i9-7920X ";      $ProcessorScore[657] = "23338"
        $ProcessorName[658] = "i9-7900X ";      $ProcessorScore[658] = "21428"
        $ProcessorName[659] = "i9-10980XE ";      $ProcessorScore[659] = "34264"
        $ProcessorName[660] = "i9-10980HK ";      $ProcessorScore[660] = "17308"
        $ProcessorName[661] = "i9-10940X ";      $ProcessorScore[661] = "29673"
        $ProcessorName[662] = "i9-10920X ";      $ProcessorScore[662] = "26257"
        $ProcessorName[663] = "i9-10910 ";      $ProcessorScore[663] = "22090"
        $ProcessorName[664] = "i9-10900X ";      $ProcessorScore[664] = "22960"
        $ProcessorName[665] = "i9-10900T ";      $ProcessorScore[665] = "16991"
        $ProcessorName[666] = "i9-10900KF ";      $ProcessorScore[666] = "23539"
        $ProcessorName[667] = "i9-10900K ";      $ProcessorScore[667] = "24181"
        $ProcessorName[668] = "i9-10900F ";      $ProcessorScore[668] = "21228"
        $ProcessorName[669] = "i9-10900 ";      $ProcessorScore[669] = "21289"
        $ProcessorName[670] = "i9-10885H ";      $ProcessorScore[670] = "16381"
        $ProcessorName[671] = "i9-10880H ";      $ProcessorScore[671] = "15137"
        $ProcessorName[672] = "E3400 ";      $ProcessorScore[672] = "841"
        $ProcessorName[673] = "E5504 ";      $ProcessorScore[673] = "1529"
        $ProcessorName[674] = "E7500 ";      $ProcessorScore[674] = "1099"
        $ProcessorName[675] = "E8400 ";      $ProcessorScore[675] = "1161"
        $ProcessorName[676] = "E5-2609 v2 ";      $ProcessorScore[676] = "3851"
        $ProcessorName[677] = "E5-2620 v3 ";      $ProcessorScore[677] = "7981"
        $ProcessorName[678] = "E5-2620 v4 ";      $ProcessorScore[678] = "8699"
        $ProcessorName[679] = "E5400 ";      $ProcessorScore[679] = "880"
        $ProcessorName[680] = "E2180 ";      $ProcessorScore[680] = "662"
        $ProcessorName[681] = "J3710 ";      $ProcessorScore[681] = "1409"
        $ProcessorName[682] = "G3260 ";      $ProcessorScore[682] = "2053"
        $ProcessorName[683] = "G3260T ";      $ProcessorScore[683] = "1993"
        $ProcessorName[684] = "A8-6500 ";      $ProcessorScore[684] = "2738"
        $ProcessorName[685] = "E7200 ";      $ProcessorScore[685] = "963"
        $ProcessorName[686] = "7300B ";      $ProcessorScore[686] = "1448"
        $ProcessorName[687] = "CPU 6300 ";      $ProcessorScore[687] = "521"
        $ProcessorName[688] = "CPU 6400 ";      $ProcessorScore[688] = "786"
        $ProcessorName[689] = "E6550 ";      $ProcessorScore[689] = "883"
        $ProcessorName[690] = "E7600 ";      $ProcessorScore[690] = "1138"
        $ProcessorName[691] = "E8500 ";      $ProcessorScore[691] = "1243"
        $ProcessorName[692] = "1220 v3 ";      $ProcessorScore[692] = "5198"
        $ProcessorName[693] = "1226 v3 ";      $ProcessorScore[693] = "5354"
        $ProcessorName[694] = "1245 v3 ";      $ProcessorScore[694] = "7024"
        $ProcessorName[695] = "E5-1620 v3 ";      $ProcessorScore[695] = "7020"
        $ProcessorName[696] = "E5-1620 v4 ";      $ProcessorScore[696] = "7322"
        $ProcessorName[697] = "E5-2609 v4 ";      $ProcessorScore[697] = "5974"
        $ProcessorName[698] = "E5300 ";      $ProcessorScore[698] = "976"
        $ProcessorName[699] = "E5700 ";      $ProcessorScore[699] = "1057"
        $ProcessorName[700] = "Silver 4110 ";      $ProcessorScore[700] = "10453"
        $ProcessorName[701] = "E5-2630 v3 ";      $ProcessorScore[701] = "9694"
        $ProcessorName[702] = "N270 ";      $ProcessorScore[702] = "175"
        $ProcessorName[703] = "x5-Z8350 ";      $ProcessorScore[703] = "922"
        $ProcessorName[704] = "Z3735F ";      $ProcessorScore[704] = "529"
        $ProcessorName[705] = "7 2700X ";      $ProcessorScore[705] = "17576"
        $ProcessorName[706] = "X4 635 ";      $ProcessorScore[706] = "2196"
        $ProcessorName[707] = "E5-1650 v2 ";      $ProcessorScore[707] = "8977"
        $ProcessorName[708] = "CPU 960 ";      $ProcessorScore[708] = "3219"
        $ProcessorName[709] = "CPU 650 ";      $ProcessorScore[709] = "2200"
        $ProcessorName[710] = "D CPU 3.40GHz";      $ProcessorScore[710] = "634"
        $ProcessorName[711] = "E5-1620 v4 ";      $ProcessorScore[711] = "7322"
        $ProcessorName[712] = "E5-2620 0 ";      $ProcessorScore[712] = "5179"
        $ProcessorName[713] = "E5-1650 0 ";      $ProcessorScore[713] = "8176"
        $ProcessorName[714] = "E3-1245 v6 ";      $ProcessorScore[714] = "8455"
        $ProcessorName[715] = "J2900 ";      $ProcessorScore[715] = "1216"
        $ProcessorName[716] = "Ryzen 5 Microsoft Surface ";      $ProcessorScore[716] = "8065"
        $ProcessorName[717] = "A8-6410 ";      $ProcessorScore[717] = "1766"
        $ProcessorName[718] = "A8-5500 ";      $ProcessorScore[718] = "2557"
        $ProcessorName[719] = "A6-7310 ";      $ProcessorScore[719] = "1699"
        $ProcessorName[720] = "A6-5200 ";      $ProcessorScore[720] = "1632"
        $ProcessorName[721] = "A10-7800 ";      $ProcessorScore[721] = "3118"
        $ProcessorName[722] = "E5-2407 0 ";      $ProcessorScore[722] = "2661"
        $ProcessorName[723] = "A10-6700 APU";      $ProcessorScore[723] = "3130"
        $ProcessorName[724] = "E5620 @";      $ProcessorScore[724] = "3709"
        $ProcessorName[725] = "E5-2420 0 @";      $ProcessorScore[725] = "5165"
        $ProcessorName[726] = "Silver 4216 CPU @";      $ProcessorScore[726] = "18561"
        $ProcessorName[727] = "E5-2430 0 @";      $ProcessorScore[727] = "5867"
        $ProcessorName[728] = "X5667 @";      $ProcessorScore[728] = "4534"
        $ProcessorName[729] = "X5650 @";      $ProcessorScore[729] = "5796"
        $ProcessorName[730] = "A4-3400 APU";      $ProcessorScore[730] = "1049"
        $ProcessorName[731] = "E3-1230 v5 @";      $ProcessorScore[731] = "7746"
        $ProcessorName[732] = "EPYC 7251 ";      $ProcessorScore[732] = "15542"
        $ProcessorName[733] = "E5-2420 v2 @";      $ProcessorScore[733] = "6490"
        $ProcessorName[734] = "i3 CPU 540 @";      $ProcessorScore[734] = "1503"
        $ProcessorName[735] = "1214 HE ";      $ProcessorScore[735] = "806"
        $ProcessorName[736] = "Ryzen 5 2600X ";      $ProcessorScore[736] = "14080"
        $ProcessorName[737] = "i5 CPU M 560 @";      $ProcessorScore[737] = "1848"
        $ProcessorName[738] = "CPU E3-1220 v5 @";      $ProcessorScore[738] = "5687"
        $ProcessorName[739] = "A9-9400 ";      $ProcessorScore[739] = "1407"
        $ProcessorName[740] = "E5-2640 0 @";      $ProcessorScore[740] = "6314"
        $ProcessorName[741] = "E5-2690 v2 @";      $ProcessorScore[741] = "13116"
        $ProcessorName[742] = "A9-9425 ";      $ProcessorScore[742] = "1554"
        $ProcessorName[743] = "E-2234 CPU @";      $ProcessorScore[743] = "9555"
        $ProcessorName[744] = "CPU E5620 @";      $ProcessorScore[744] = "3709"
        $ProcessorName[745] = "E5-2690 v2 @";      $ProcessorScore[745] = "13116"
        $ProcessorName[746] = "E3-1271 v3 @";      $ProcessorScore[746] = "7308"
        $ProcessorName[747] = "E-2234 CPU @";      $ProcessorScore[747] = "9555"
        $ProcessorName[748] = "Silver 4215 CPU @";      $ProcessorScore[748] = "14439"
        $ProcessorName[749] = "E5-2673 v4 @";      $ProcessorScore[749] = "17533"
        $ProcessorName[750] = "Gold 5215 CPU @";      $ProcessorScore[750] = "16058"
        $ProcessorName[751] = "AMD FX(tm)-6100 ";      $ProcessorScore[751] = "3642"
        $ProcessorName[752] = "E-2278G CPU @";      $ProcessorScore[752] = "17609"
        $ProcessorName[753] = "CPU 4205U @";      $ProcessorScore[753] = "1300"
        $ProcessorName[754] = "AMD A4-9125 ";      $ProcessorScore[754] = "1216"
        $ProcessorName[755] = "W-2104 CPU @";      $ProcessorScore[755] = "6362"
        $ProcessorName[756] = "9150e ";      $ProcessorScore[756] = "1267"
        $ProcessorName[757] = "CPU E5-2667 v4 @";      $ProcessorScore[757] = "14148"
        $ProcessorName[758] = "i7 CPU 930 @";      $ProcessorScore[758] = "2871"
        $ProcessorName[759] = "CPU E5-2403 v2 @";      $ProcessorScore[759] = "2873"
        $ProcessorName[760] = "W-2104 CPU @";      $ProcessorScore[760] = "6362"
        $ProcessorName[761] = "CPU X5650 @";      $ProcessorScore[761] = "5796"
        $ProcessorName[762] = "E5-1620 0 @";      $ProcessorScore[762] = "5862"
        $ProcessorName[763] = "E5620 @";      $ProcessorScore[763] = "3709"
        $ProcessorName[764] = "E5-2673 v3 @";      $ProcessorScore[764] = "13738"
        $ProcessorName[765] = "N3150 @";      $ProcessorScore[765] = "1189"
        $ProcessorName[766] = "P8700 @";      $ProcessorScore[766] = "945"
        $ProcessorName[767] = "E5-2630L 0 @";      $ProcessorScore[767] = "5285"
        $ProcessorName[768] = "E5-2690 v2 @";      $ProcessorScore[768] = "13116"
        $ProcessorName[769] = "i5 CPU M 560 @";      $ProcessorScore[769] = "1626"
        $ProcessorName[770] = "E3-1230 V2 @";      $ProcessorScore[770] = "6193"
        $ProcessorName[771] = "E-2134 CPU @";      $ProcessorScore[771] = "8253"
        $ProcessorName[772] = "E3-1270 v5 @";      $ProcessorScore[772] = "8456"
        $ProcessorName[773] = "E3-1220L V2 @";      $ProcessorScore[773] = "2687"
        $ProcessorName[774] = "Platinum 8171M CPU @";      $ProcessorScore[774] = "27000"
        $ProcessorName[775] = "2 Duo CPU E8600 @";      $ProcessorScore[775] = "1338"
        $ProcessorName[776] = "2 Duo CPU E8200 @";      $ProcessorScore[776] = "983"
        $ProcessorName[777] = "Ryzen 3 2200U";      $ProcessorScore[777] = "3692"
        $ProcessorName[778] = "i7-9750H CPU @ ";      $ProcessorScore[778] = "11337"
        $ProcessorName[779] = "E5-2650 v2 @";      $ProcessorScore[779] = "9986"
        $ProcessorName[780] = "E-2136 CPU @";      $ProcessorScore[780] = "13506"
        $ProcessorName[781] = "FX-9800P ";      $ProcessorScore[781] = "2125"
        $ProcessorName[782] = "Ryzen 5 4500U ";      $ProcessorScore[782] = "11273"
        $ProcessorName[783] = "i5-11300H @";      $ProcessorScore[783] = "11056"
        $ProcessorName[784] = "i5-11400 @";      $ProcessorScore[784] = "17066"
        $ProcessorName[785] = "i5-11400H @";      $ProcessorScore[785] = "15986"
        $ProcessorName[786] = "i5-11500 @";      $ProcessorScore[786] = "17629"
        $ProcessorName[787] = "i5-11500H @";      $ProcessorScore[787] = "16133"
        $ProcessorName[788] = "i5-11600 @";      $ProcessorScore[788] = "18236"
        $ProcessorName[789] = "i7-11370H @";      $ProcessorScore[789] = "11937"
        $ProcessorName[790] = "i7-11390H @";      $ProcessorScore[790] = "10545"
        $ProcessorName[791] = "i7-11700 @";      $ProcessorScore[791] = "20114"
        $ProcessorName[792] = "i7-11800H @";      $ProcessorScore[792] = "21154"
        $ProcessorName[793] = "i7-11850H @";      $ProcessorScore[793] = "21117"
        $ProcessorName[794] = "i9-11950H @";      $ProcessorScore[794] = "22414"
        $ProcessorName[795] = "i7-12800HX";      $ProcessorScore[795] = "35483"
        $ProcessorName[796] = "i7-12800H";      $ProcessorScore[796] = "24247"
        $ProcessorName[797] = "A10-9620P";      $ProcessorScore[797] = "2541"
        $ProcessorName[798] = "E1-2500 APU";      $ProcessorScore[798] = "595"
        $ProcessorName[799] = "A10-8770E";      $ProcessorScore[799] = "3075"
        $ProcessorName[800] = "A10-8770";      $ProcessorScore[800] = "3465"
        $ProcessorName[801] = "3 3200U";      $ProcessorScore[801] = "3868"
        $ProcessorName[802] = "5 2500U";      $ProcessorScore[802] = "6533"
        $ProcessorName[803] = "5 3500U";      $ProcessorScore[803] = "7069"
        $ProcessorName[804] = "5 5600X";      $ProcessorScore[804] = "21975"
        $ProcessorName[805] = "O 3400GE";      $ProcessorScore[805] = "8270"
        $ProcessorName[806] = "V1605B";      $ProcessorScore[806] = "6866"
        $ProcessorName[807] = "x7-Z8700";      $ProcessorScore[807] = "1323"
        $ProcessorName[808] = "i5-10505 CPU @";      $ProcessorScore[808] = "12336"
        $ProcessorName[809] = "E8200 @";      $ProcessorScore[809] = "1075"
        $ProcessorName[810] = "Q6600 @";      $ProcessorScore[810] = "1780"
        $ProcessorName[811] = "N3700 @";      $ProcessorScore[811] = "1247"
        $ProcessorName[812] = "G3250 @";      $ProcessorScore[812] = "1945"
        $ProcessorName[813] = "J5005 CPU @";      $ProcessorScore[813] = "3043"
        $ProcessorName[814] = "5110 @";      $ProcessorScore[814] = "600"
        $ProcessorName[815] = "E5502 @";      $ProcessorScore[815] = "837"
        $ProcessorName[816] = "L5520 @";      $ProcessorScore[816] = "2238"
        $ProcessorName[817] = "X5570 @";      $ProcessorScore[817] = "3270"
        $ProcessorName[818] = "X5667 @";      $ProcessorScore[818] = "4551"
        $ProcessorName[819] = "E3-1245 v5 @";      $ProcessorScore[819] = "7933"
        $ProcessorName[820] = "E5-2630 v4 @";      $ProcessorScore[820] = "11622"
        $ProcessorName[821] = "E5-2640 v3 @";      $ProcessorScore[821] = "11327"
        $ProcessorName[822] = "E5-2650 v3 @";      $ProcessorScore[822] = "11781"
        $ProcessorName[823] = "E5-2650 v4 @";      $ProcessorScore[823] = "13839"
        $ProcessorName[824] = "E5-2667 v3 @";      $ProcessorScore[824] = "12378"
        $ProcessorName[825] = "E5-2680 v2 @";      $ProcessorScore[825] = "12671"
        $ProcessorName[826] = "E5-2690 v2 @";      $ProcessorScore[826] = "13535"
        $ProcessorName[827] = "E-2144G";      $ProcessorScore[827] = "9322"
        $ProcessorName[828] = "E-2246G";      $ProcessorScore[828] = "14050"
        $ProcessorName[829] = "Silver 4208";      $ProcessorScore[829] = "11157"
        $ProcessorName[830] = "W-10855M";      $ProcessorScore[830] = "12902"
        $ProcessorName[831] = "W-2223";      $ProcessorScore[831] = "8706"
        $ProcessorName[832] = "W-2225";      $ProcessorScore[832] = "10794"
        $ProcessorName[833] = "i5-9500T CPU @";      $ProcessorScore[833] = "8161"
        $ProcessorName[834] = "E5-2690 v2 @";      $ProcessorScore[834] = "13454"
        $ProcessorName[835] = "Ryzen 7 Microsoft Surface (R)";      $ProcessorScore[835] = "17459"
        $ProcessorName[836] = "Core(TM) i7-12800H ";      $ProcessorScore[836] = "24919"
        $ProcessorName[837] = "i3-10105T CPU @";      $ProcessorScore[837] = "8012"
        $ProcessorName[838] = "i5-1240P";      $ProcessorScore[838] = "17351"
        $ProcessorName[839] = "i7-12700H ";      $ProcessorScore[839] = "26462"
        $ProcessorName[840] = "i7-1260P";      $ProcessorScore[840] = "17215"
        $ProcessorName[841] = "Ryzen 7 5825U";      $ProcessorScore[841] = "18426"
        $ProcessorName[842] = "i5-1145G7 @";      $ProcessorScore[842] = "9959"
        $ProcessorName[843] = "i5-1135G7 @";      $ProcessorScore[843] = "9902"
        $ProcessorName[844] = "i5-12500 ";      $ProcessorScore[844] = "19977"
        $ProcessorName[845] = "i5-1245U ";      $ProcessorScore[845] = "13508"
        $ProcessorName[846] = "i9-12900K ";      $ProcessorScore[846] = "41418"
        $ProcessorName[847] = "W-2102 CPU @";      $ProcessorScore[847] = "5081"
        $ProcessorName[848] = "i7-11700K @";      $ProcessorScore[848] = "24663"
        $ProcessorName[849] = "W-2125 CPU @";      $ProcessorScore[849] = "10030"
        $ProcessorName[850] = "Ryzen 5 5600G";      $ProcessorScore[850] = "19912"
        $ProcessorName[851] = "i5-12500T ";      $ProcessorScore[851] = "16738"
        $ProcessorName[852] = "Ryzen 9 7950X";      $ProcessorScore[852] = "63223"
        $ProcessorName[854] = "i7-12700 ";      $ProcessorScore[853] = "30911"
        $ProcessorName[854] = "i7-1255U ";      $ProcessorScore[854] = "13790"
        $ProcessorName[855] = "i7-7820HQ CPU ";      $ProcessorScore[855] = "7184"
        $ProcessorName[856] = "i7-1260P ";      $ProcessorScore[856] = "17212"
        $ProcessorName[857] = "i7-1255U ";      $ProcessorScore[857] = "13794"
        $ProcessorName[858] = "Ryzen 5 PRO 5675U ";      $ProcessorScore[858] = "14448"
        $ProcessorName[859] = "i5-1235U ";      $ProcessorScore[859] = "13594"
        $ProcessorName[860] = "i3-10105T CPU ";      $ProcessorScore[860] = "8012"



        $ProcessorName[861] = "Done";      $ProcessorScore[861] = "Done"
        $TotalNumber = 861



        $Count = 0


    

    

        $CPUScore = "Unknown"
        WHILE ( $ProcessorName[$Count] -ne "Done" )    {
            IF ( $WorkstationProcessorName -cmatch $ProcessorName[$Count] ) { 
                [int]$CPUScore = $ProcessorScore[$Count]
            break
            }
            ELSE { $Count++ }
        } 

        IF ($CPUScore -gt 40000) { $CPURating = 9; $CPURatingString = "Crazy Fast" }
        ELSEIF ($CPUScore -gt 25000) { $CPURating = 8; $CPURatingString = "Extrmemly Fast" }
        ELSEIF ($CPUScore -gt 17500) { $CPURating = 7; $CPURatingString = "Very Fast" }
        ELSEIF ($CPUScore -gt 12000) { $CPURating = 6; $CPURatingString = "Fast" }
        ELSEIF ($CPUScore -gt 8000) { $CPURating = 5; $CPURatingString = "Good" }
        ELSEIF ($CPUScore -gt 5500) { $CPURating = 4; $CPURatingString = "Acceptable" }
        ELSEIF ($CPUScore -gt 4000) { $CPURating = 3; $CPURatingString = "Slow" }
        ELSEIF ($CPUScore -gt 3000) { $CPURating = 2; $CPURatingString = "Very Slow" }
        ELSE { $CPURating = 1; $CPURatingString = "Extremely Slow" }

        $CPUName = $WorkstationProcessorName
        $Now = GET-Date
        [string]$CPUDate = "Unknown"
        $CPUAge = "Unknown"
        IF($CPUName -like "*i3-14*" -or $CPUName -like "*i5-14*" -or $CPUName -like "*i7-14*" -or $CPUName -like "*i9-14*") { [DateTime]$CPUDate = "NOV 2023" }
        IF($CPUName -like "*i3-13*" -or $CPUName -like "*i5-13*" -or $CPUName -like "*i7-13*" -or $CPUName -like "*i9-12*") { [DateTime]$CPUDate = "NOV 2022" }
        IF($CPUName -like "*i3-12*" -or $CPUName -like "*i5-12*" -or $CPUName -like "*i7-12*" -or $CPUName -like "*i9-13*") { [DateTime]$CPUDate = "NOV 2021" }
        IF($CPUName -like "*i3-11*" -or $CPUName -like "*i5-11*" -or $CPUName -like "*i7-11*" -or $CPUName -like "*i9-11*") { [DateTime]$CPUDate = "AUG 2020" }
        IF($CPUName -like "*i3-10*" -or $CPUName -like "*i5-10*" -or $CPUName -like "*i7-10*" -or $CPUName -like "*i9-10*") { [DateTime]$CPUDate = "NOV 2019" }
        IF($CPUName -like "*i3-9*" -or $CPUName -like "*i5-9*" -or $CPUName -like "*i7-9*" -or $CPUName -like "*i9-9*") { [DateTime]$CPUDate = "FEB 2019" }
        IF($CPUName -like "*i3-8*" -or $CPUName -like "*i5-8*" -or $CPUName -like "*i7-8*" -or $CPUName -like "*i9-8*") { [DateTime]$CPUDate = "DEC 2017" }
        IF($CPUName -like "*i3-7*" -or $CPUName -like "*i5-7*" -or $CPUName -like "*i7-7*" -or $CPUName -like "*i9-7*") { [DateTime]$CPUDate = "NOV 2016" }
        IF($CPUName -like "*i3-6*" -or $CPUName -like "*i5-6*" -or $CPUName -like "*i7-6*" -or $CPUName -like "*i9-6*") { [DateTime]$CPUDate = "NOV 2015" }
        IF($CPUName -like "*i3-5*" -or $CPUName -like "*i5-5*" -or $CPUName -like "*i7-5*" -or $CPUName -like "*i9-5*") { [DateTime]$CPUDate = "FEB 2015" }
        IF($CPUName -like "*i3-4*" -or $CPUName -like "*i5-4*" -or $CPUName -like "*i7-4*" -or $CPUName -like "*i9-4*") { [DateTime]$CPUDate = "MAY 2014" }
        IF($CPUName -like "*i3-3*" -or $CPUName -like "*i5-3*" -or $CPUName -like "*i7-3*" -or $CPUName -like "*i9-3*") { [DateTime]$CPUDate = "MAY 2013" }
        IF($CPUName -like "*i3-2*" -or $CPUName -like "*i5-2*" -or $CPUName -like "*i7-2*" -or $CPUName -like "*i9-2*") { [DateTime]$CPUDate = "NOV 2012" }

        IF ($CPUDate -ne "Unknown") { $AgeDifference = $Now - $CPUDate; $CPUAge = [math]::Round($AgeDifference.TotalDays / 365, 2) }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Socket = $AllInfo.SocketDesignation
            CPUModel = $WorkstationProcessorName
            CPUScore = $CPUScore
            YearsOld = $CPUAge
            NumberOfCores = $AllInfo.NumberOfCores
            NumberOfThreads = $AllInfo.ThreadCount
            CPURating = $CPURating
            CPURatingString = $CPURatingString
        }
    }
    RETURN $Results | Select CPUModel, CPUScore, YearsOld, NumberOfCores, NumberOfThreads, CPURating, CPURatingString
}
FUNCTION GET-DiskDrive {

    $Results = @()

    $Disks = GET-PhysicalDisk

    $DriveLetter = $env:windir
    $DriveLetter = $DriveLetter.Substring(0,1)
    $Partition = GET-Partition -DriveLetter $DriveLetter
    $OSDriveDiskNumber = $Partition.DiskNumber
    
    FOREACH ($Disk in $Disks) {
        $IsOSDrive = "$False"
        IF ($Disk.DeviceID -eq $OSDriveDiskNumber) { $IsOSDrive = "$True" }
    
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            DeviceID = $Disk.DeviceID
            ContainsSystemOS = $IsOSDrive
            Model = $Disk.Model
            MediaType = $Disk.MediaType
            BusType = $Disk.BusType
            SerialNumber = $Disk.SerialNumber
            HealthStatus = $Disk.HealthStatus
            SizeGBs = [int]($Disk.Size / 1GB)
        }
    }

    RETURN $Results | Select DeviceID, ContainsSystemOS, BusType, MediaType, Model, SizeGBs, SerialNumber, HealthStatus | Sort-Object -Descending -Property ContainsSystemOS
}
FUNCTION GET-DiskPerformance {

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    $Results = @()

    IF ((GET-Item -Path "C:\Program Files\IntegrisPowerShell Utilities\DiskSpd\diskspd.exe" -ErrorAction SilentlyContinue) -eq $null) {
        Write-Host ""
        Write-Warning "DiskSpd.exe not found, disk speed benchmark results will not be available. For disk speed benchmarking, download the Microsoft diskspd.exe application from 'https://github.com/microsoft/diskspd' and place it in the 'C:\Program Files\IntegrisPowerShell Utilities\DiskSpd\' folder"
        RETURN
    }

    $ExeFolder = "C:\Program Files\IntegrisPowerShell Utilities\DiskSpd"
    $IOType = ""
    $AccessType = ""
    $ResultRating = 0
    $ResultRatingString = ""

    Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "0% - Random Read - About 15 Seconds" -PercentComplete 0

    $RandomTest = & "$ExeFolder\diskspd.exe" -b4k -d10 -t1 -O32 -r -W2 -C2 -w0 -Z -c1G -Su "$ExeFolder\test.dat"
    $RandomTestResults = $RandomTest[-15] | convertfrom-csv -Delimiter "|" -Header Bytes,IO,Mib,IOPS,File | Select-Object IO,MIB,IOPs
    [int]$RandomMBs = $RandomTestResults.Mib
  
    IF ($RandomMBs -gt 200) { $ResultRating = 9; $ResultRatingString = "Crazy Fast" }
    ELSEIF ($RandomMBs -gt 100) { $ResultRating = 8; $ResultRatingString = "Extremely Fast" }
    ELSEIF ($RandomMBs -gt 60) { $ResultRating = 7; $ResultRatingString = "Very Fast" }
    ELSEIF ($RandomMBs -gt 30) { $ResultRating = 6; $ResultRatingString = "Fast" }
    ELSEIF ($RandomMBs -gt 15) { $ResultRating = 5; $ResultRatingString = "Good" }
    ELSEIF ($RandomMBs -gt 8) { $ResultRating = 4; $ResultRatingString = "Acceptable" }
    ELSEIF ($RandomMBs -gt 3) { $ResultRating = 3; $ResultRatingString = "Slow" }
    ELSEIF ($RandomMBs -gt 1) { $ResultRating = 2; $ResultRatingString = "VerySlow" }
    ELSE { $ResultRating = 1; $ResultRatingString = "Extremely Slow" }
    
    $IOType = "Random"
    $AccessType = "Read"
    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        IOType = $IOType
        AccessType = $AccessType
        ResultMBs = [int]$RandomTestResults.Mib
        ResultIOPS = [int]$RandomTestResults.IOPS
        ResultRating = $ResultRating
        ResultRatingString = $ResultRatingString
    }    

    Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "25% - Random Write - About 15 Seconds" -PercentComplete 25

    $Random4kWrite = & "$ExeFolder\diskspd.exe" -b4k -d10 -t1 -O32 -r -W2 -C2 -w100 -Z -c1G -Su "$ExeFolder\test.dat" 
    $Random4kWriteResults = $Random4kWrite[-15] | convertfrom-csv -Delimiter "|" -Header Bytes,IO,Mib,IOPS,File | Select-Object IO,MIB,IOPs

    [int]$RandomWriteMBs = $Random4kWriteResults.Mib
        
    IF ($RandomWriteMBs -gt 200) { $ResultRating = 9; $ResultRatingString = "Crazy Fast" }
    ELSEIF ($RandomWriteMBs -gt 100) { $ResultRating = 8; $ResultRatingString = "Extremely Fast" }
    ELSEIF ($RandomWriteMBs -gt 60) { $ResultRating = 7; $ResultRatingString = "Very Fast" }
    ELSEIF ($RandomWriteMBs -gt 30) { $ResultRating = 6; $ResultRatingString = "Fast" }
    ELSEIF ($RandomWriteMBs -gt 15) { $ResultRating = 5; $ResultRatingString = "Good" }
    ELSEIF ($RandomWriteMBs -gt 8) { $ResultRating = 4; $ResultRatingString = "Acceptable" }
    ELSEIF ($RandomWriteMBs -gt 3) { $ResultRating = 3; $ResultRatingString = "Slow" }
    ELSEIF ($RandomWriteMBs -gt 1) { $ResultRating = 2; $ResultRatingString = "VerySlow" }
    ELSE { $ResultRating = 1; $ResultRatingString = "Extremely Slow" }
    
    $IOType = "Random"
    $AccessType = "Write"
    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        IOType = $IOType
        AccessType = $AccessType
        ResultMBs = [int]$Random4kWriteResults.Mib
        ResultIOPS = [int]$Random4kWriteResults.IOPS
        ResultRating = $ResultRating
        ResultRatingString = $ResultRatingString
    }
    
    Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "50% - Sequential Read - About 15 Seconds" -PercentComplete 50

    $Sequential1MBRead = & "$ExeFolder\diskspd.exe" -b1M -d10 -t1 -O8 -s -W2 -C2 -w0 -Z -c1G -Su "$ExeFolder\test.dat"
    $Sequential1MBReadResults = $Sequential1MBRead[-8] | convertfrom-csv -Delimiter "|" -Header Bytes,IO,Mib,IOPS,File | Select-Object IO,MIB,IOPs
    
    [int]$SequentialReadMBs = $Sequential1MBReadResults.Mib

    IF ($SequentialReadMBs -gt 1500) { $ResultRating = 9; $ResultRatingString = "Crazy Fast" }
    ELSEIF ($SequentialReadMBs -gt 900) { $ResultRating = 8; $ResultRatingString = "Extremely Fast" }
    ELSEIF ($SequentialReadMBs -gt 450) { $ResultRating = 7; $ResultRatingString = "Very Fast" }
    ELSEIF ($SequentialReadMBs -gt 225) { $ResultRating = 6; $ResultRatingString = "Fast" }
    ELSEIF ($SequentialReadMBs -gt 150) { $ResultRating = 5; $ResultRatingString = "Good" }
    ELSEIF ($SequentialReadMBs -gt 90) { $ResultRating = 4; $ResultRatingString = "Acceptable" }
    ELSEIF ($SequentialReadMBs -gt 50) { $ResultRating = 3; $ResultRatingString = "Slow" }
    ELSEIF ($SequentialReadMBs -gt 25) { $ResultRating = 2; $ResultRatingString = "VerySlow" }
    ELSE { $ResultRating = 1; $ResultRatingString = "Extremely Slow" }
    
    $IOType = "Sequential"
    $AccessType = "Read"
    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        IOType = $IOType
        AccessType = $AccessType
        ResultMBs = [int]$Sequential1MBReadResults.Mib
        ResultIOPS = [int]$Sequential1MBReadResults.IOPS
        ResultRating = $ResultRating
        ResultRatingString = $ResultRatingString
    }

    Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "75% - Sequential Write - About 15 Seconds" -PercentComplete 75
    ## Sequential Write
    $Sequential1MBWrite = & "$ExeFolder\diskspd.exe" -b1M -d10 -t1 -O8 -s -W2 -C2 -w100 -Z -c1G -Su "$ExeFolder\test.dat"
    $Sequential1MBWriteResults = $Sequential1MBWrite[-15] | convertfrom-csv -Delimiter "|" -Header Bytes,IO,Mib,IOPS,File | Select-Object IO,MIB,IOPs
    
    [int]$SequentialWriteMBs = $Sequential1MBWriteResults.Mib

    IF ($SequentialWriteMBs -gt 1500) { $ResultRating = 9; $ResultRatingString = "Crazy Fast" }
    ELSEIF ($SequentialWriteMBs -gt 900) { $ResultRating = 8; $ResultRatingString = "Extremely Fast" }
    ELSEIF ($SequentialWriteMBs -gt 450) { $ResultRating = 7; $ResultRatingString = "Very Fast" }
    ELSEIF ($SequentialWriteMBs -gt 225) { $ResultRating = 6; $ResultRatingString = "Fast" }
    ELSEIF ($SequentialWriteMBs -gt 150) { $ResultRating = 5; $ResultRatingString = "Good" }
    ELSEIF ($SequentialWriteMBs -gt 90) { $ResultRating = 4; $ResultRatingString = "Acceptable" }
    ELSEIF ($SequentialWriteMBs -gt 50) { $ResultRating = 3; $ResultRatingString = "Slow" }
    ELSEIF ($SequentialWriteMBs -gt 25) { $ResultRating = 2; $ResultRatingString = "VerySlow" }
    ELSE { $ResultRating = 1; $ResultRatingString = "Extremely Slow" }
    Write-Progress -ID 3 -Activity "Running Disk Benchmark Tests" -Status "100% - Finalizing Results" -PercentComplete 100 -Completed
    $IOType = "Sequential"
    $AccessType = "Write"
    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        IOType = $IOType
        AccessType = $AccessType
        ResultMBs = [int]$Sequential1MBWriteResults.Mib
        ResultIOPS = [int]$Sequential1MBWriteResults.IOPS
        ResultRating = $ResultRating
        ResultRatingString = $ResultRatingString
    }
    RETURN $Results | select IOType, AccessType, ResultMBs, ResultRating, ResultRatingString
}
FUNCTION GET-DisplayDevice {

    $Results = @()
    
    $MonitorInstances = GET-CIMInstance -Class WMIMonitorID -Namespace root\wmi -ErrorAction SilentlyContinue | Select InstanceName 
    IF ($MonitorInstances.Count -ge 1) { }
    ELSE {
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            ModelID = "Not Connected"
            ModelName = "Not Connected"
            Manufacturer = "Not Connected"
            VideoInput = "Not Connected"
            SerialNumber = "Not Connected"
            ManufacturerYear = "Not Connected"
        }    

        RETURN $Results | Select ModelID, ModelName, Manufacturer, VideoInput, SerialNumber, ManufacturerYear 
    }
    
    $MonitorCount = 0
    
    FOREACH ($MonitorInstance in $MonitorInstances) {
        $MonitorCount++

        ### Hardware ID
        $HardwareID = ($MonitorInstance.InstanceName.Split('\'))[1]

        ### Manufacture Year
        $MonitorInfo = GET-CIMInstance WMIMonitorID -Namespace root\wmi | Where-Object { $_.InstanceName -eq $MonitorInstance.InstanceName }
        $ManufactureYear = "Unknown"
        $ManufactureYear = $MonitorInfo.YearOfManufacture

        ### Serial Number
        $SerialNumber = "Unknown"
        $SerialNumber = [System.Text.Encoding]::ASCII.GetString($MonitorInfo.SerialNumberID).Trim(0x00)

        $MonitorInfo = GET-CIMInstance WmiMonitorConnectionParams -Namespace root\wmi | Where-Object { $_.InstanceName -eq $MonitorInstance.InstanceName }
        
        ### Video Connector
        $VideoOutput = "Unknown"
        $VideoOutput = $MonitorInfo.VideoOutputTechnology
        Switch ($VideoOutput) {
            "0" { $VideoOutput = "VGA" }
            "1" { $VideoOutput = "S-Video" }
            "2" { $VideoOutput = "Composite_Video" }
            "3" { $VideoOutput = "Component_Video" }
            "4" { $VideoOutput = "DVI" }
            "5" { $VideoOutput = "HDMI" }
            "6" { $VideoOutput = "LVDS" }
            "7" { $VideoOutput = "Unknown" }
            "8" { $VideoOutput = "D_JPN" }
            "9" { $VideoOutput = "SDI" }
            "10" { $VideoOutput = "DisplayPort" }
            "11" { $VideoOutput = "DisplayPort" }
            "12" { $VideoOutput = "UDI" }
            "13" { $VideoOutput = "UDI" }
            "14" { $VideoOutput = "SDTV_Dongle" }
            "15" { $VideoOutput = "Miracast" }
            "16" { $VideoOutput = "Indirect_Wired" }
            default { $VideoOutput = "Unknown" }
        }


        $MonitorInfo = GET-PnpDevice | Where-Object { $_.PNPDeviceID -eq $MonitorInfo.InstanceName.Replace("_0","") }

        ### Model
        $MonitorModel = "Unknown"
        $MonitorModel = $MonitorInfo.Name
        
        ### Vendor
        $MonitorManufacturer = "Unknown"
        $MonitorManufacturer = $MonitorInfo.Manufacturer

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Number = $MonitorCount
            ModelID = $HardwareID
            ModelName = $MonitorInfo.Name
            Manufacturer = $MonitorManufacturer
            VideoInput = $VideoOutput
            SerialNumber = $SerialNumber
            ManufacturerYear = $ManufactureYear
        }    
    }

    RETURN $Results | Select Number, ModelID, ModelName, Manufacturer, VideoInput, SerialNumber, ManufacturerYear 
}
FUNCTION GET-DisplayAdapter {

    $Results = @()

    $VideoAdapters = GET-CIMInstance win32_videocontroller -ErrorAction SilentlyContinue 

    FOREACH ($VideoAdapter in $VideoAdapters) {
        $DriverDate = $VideoAdapter.DriverDate
        $InstallDate = $VideoAdapter.InstallDate

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            ModelName = $VideoAdapter.Name
            GBsOfVRAM = $VideoAdapter.AdapterRAM / 1GB
            Vendor = $VideoAdapter.AdapterCompatibility
            DriverVersion = $VideoAdapter.DriverVersion
            DriverReleaseDate = $DriverDate
        }
    }

    RETURN $Results | Select ModelName, Vendor, GBsOfVRAM, DriverVersion, DriverReleaseDate
}
FUNCTION GET-InternetInfo {

    param (

        [switch]$SpeedTest = $false

    )

     ### IP and Geo Location Data
        TRY {
            $GeoData = Invoke-RestMethod -Method Get -Uri "http://ip-api.com/json/$PublicIPv4"
        }
        Catch {
            Write-Warning "WebRequest blocked. Check firewall settings or other web security applications, such as ThreatLocker or OpenDNS. IP-API.com must be whitelisted on port 80."
            RETURN
        }

    IF ($SpeedTest -eq $true) {
        IF ((GET-Item -Path "C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\speedtest.exe" -ErrorAction SilentlyContinue) -eq $null) {
            Write-Host ""
            Write-Warning "SpeedTest.exe not found. Internet connection benchmark results will not be available. For internet connection benchmarking, download the Ookla speedtest.exe application from 'https://www.speedtest.net/apps/cli' and place it in the 'C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\' folder"
        
            $DownloadSpeed = "Unavailable"
            $DownloadLatency = "Unavailable"
            $UploadSpeed = "Unavailable"
            $UploadLatency = "Unavailable"
            $PacketLoss = "Unavailable"
        }
        ELSE {
            TRY {
                $SpeedTestResults = & "C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\speedtest.exe" --accept-license

                ### Download Speed
                $DownloadSpeed = $SpeedTestResults | select-string -Pattern "Download:"
                $DownloadSpeed = $DownloadSpeed.ToString().Replace('Download:','')
                [string[]]$DownloadSpeed = $DownloadSpeed.Split('.')
                [int]$DownloadSpeed = $DownloadSpeed[0].Replace(' ','')

                ### Download Latency
                [string]$DownloadLatency = $SpeedTestResults | select-string -Pattern "jitter:"
                [string[]]$DownloadLatency = $DownloadLatency.Split('j')
                [string]$DownloadLatency = $DownloadLatency[1]
                [string[]]$DownloadLatency = $DownloadLatency.split(')')
                [string]$DownloadLatency = $DownloadLatency[1]
                $DownloadLatency = $DownloadLatency.Replace("ms","")
                $DownloadLatency = $DownloadLatency.Replace("(","")
                [int]$DownloadLatency = $DownloadLatency.Replace(" ","")

                ### Download Latency High
                [string[]]$DownloadLatencyHigh = $SpeedTestResults | select-string -Pattern "high:"
                [string]$DownloadLatencyHigh = $DownloadLatencyHigh[1]
                [string[]]$DownloadLatencyHigh = $DownloadLatencyHigh.Split(':')
                [string]$DownloadLatencyHigh = $DownloadLatencyHigh[3]
                $DownloadLatencyHigh = $DownloadLatencyHigh.Replace("ms","")
                $DownloadLatencyHigh = $DownloadLatencyHigh.Replace(")","")
                [int]$DownloadLatencyHigh = $DownloadLatencyHigh.Replace(" ","")
        
                ### Upload Speed
                $UploadSpeed = $SpeedTestResults | select-string -Pattern "Upload:"
                $UploadSpeed = $UploadSpeed.ToString().Replace('Upload:','')
                [string[]]$UploadSpeed = $UploadSpeed.Split('.')
                [int]$UploadSpeed = $UploadSpeed[0].Replace(' ','')

                ### Upload Latency
                [string]$UploadLatency = $SpeedTestResults | select-string -Pattern "jitter:"
                [string[]]$UploadLatency = $UploadLatency.Split('j')
                [string]$UploadLatency = $UploadLatency[2]
                [string[]]$UploadLatency = $UploadLatency.split(')')
                [string]$UploadLatency = $UploadLatency[1]
                $UploadLatency = $UploadLatency.Replace("ms","")
                $UploadLatency = $UploadLatency.Replace("(","")
                [int]$UploadLatency = $UploadLatency.Replace(" ","")

                ### Upload Latency High
                [string[]]$UploadLatencyHigh = $SpeedTestResults | select-string -Pattern "high:"
                [string]$UploadLatencyHigh = $UploadLatencyHigh[2]
                [string[]]$UploadLatencyHigh = $UploadLatencyHigh.Split(':')
                [string]$UploadLatencyHigh = $UploadLatencyHigh[3]
                $UploadLatencyHigh = $UploadLatencyHigh.Replace("ms","")
                $UploadLatencyHigh = $UploadLatencyHigh.Replace(")","")
                [int]$UploadLatencyHigh = $UploadLatencyHigh.Replace(" ","")

                ### Packet Loss
                $PacketLoss = $SpeedTestResults | select-string -Pattern "Packet Loss:"
                $PacketLoss = $PacketLoss.ToString().Replace('%','')
                $PacketLoss = $PacketLoss.ToString().Replace('Packet Loss:','')
                [int]$PacketLoss = $PacketLoss.ToString().Replace(' ','')

                ### Internet Service Provider
                [string]$ISP = $SpeedTestResults | select-string -Pattern "ISP:"
                $ISP = $ISP.Replace("ISP:","")
                $ISP = $ISP.Replace(" ","")
                
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PublicIP = $GeoData.query
                    Country = $GeoData.Country
                    State = $GeoData.RegionName
                    City = $GeoData.City
                    ZipCode = $GeoData.zip
                    ISP = $GeoData.Org
                    Org = $GeoData.ISP
                    DownloadSpeed = $DownloadSpeed.ToString() + " Mbps"
                    DownloadLatencyAvg = $DownloadLatency.ToString() + " ms"
                    DownloadLatencyHigh = $DownloadLatencyHigh.ToString() + " ms"
                    UploadSpeed = $UploadSpeed.ToString() + " Mbps"
                    UploadLatencyAvg = $UploadLatency.ToString() + " ms"
                    UploadLatencyHigh = $UploadLatencyHigh.ToString() + " ms"
                    PacketLoss = $PacketLoss.ToString() + "%"
                }

                RETURN $Results | Select PublicIP, Country, State, City, ZipCode, ISP, Org, DownloadSpeed, DownloadLatencyAvg, DownloadLatencyHigh, UploadSpeed, UploadLatencyAvg, UploadLatencyHigh, PacketLoss
            }
            Catch {
                Write-Warning "SpeedTest.exe was blocked from running. Check security applications such as SentinelOne or ThreatLocker."

                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PublicIP = $GeoData.query
                    Country = $GeoData.Country
                    State = $GeoData.RegionName
                    City = $GeoData.City
                    ZipCode = $GeoData.zip
                    ISP = $GeoData.Org
                    Org = $GeoData.ISP
                }
            }
        }
     
        RETURN $Results | Select PublicIP, Country, State, City, ZipCode, ISP, Org
    }
    ELSE {
         ### IP and Geo Location Data
        $GeoData = Invoke-RestMethod -Method Get -Uri "http://ip-api.com/json/$PublicIPv4"

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            PublicIP = $GeoData.query
            Country = $GeoData.Country
            State = $GeoData.RegionName
            City = $GeoData.City
            ZipCode = $GeoData.zip
            ISP = $GeoData.Org
            Org = $GeoData.ISP
        }

        RETURN $Results | Select PublicIP, Country, State, City, ZipCode, ISP, Org
    }
}
FUNCTION GET-InternetSpeedTest {

    param (
        [switch]$GUI = $false
    )
    
    IF ($GUI -eq $True) {
        IF ((GET-Item -Path "C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\speedtest.exe" -ErrorAction SilentlyContinue) -eq $null) {
            Write-Host ""
            Write-Warning "SpeedTest.exe not found. Internet connection benchmark results will not be available. For internet connection benchmarking, download the Ookla speedtest.exe application from 'https://www.speedtest.net/apps/cli' and place it in the 'C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\' folder"
            RETURN
        }
        ELSE {
            TRY {
                & "C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\speedtest.exe" --accept-license
            }
            CATCH {
                Write-Warning "SpeedTest.exe was blocked from running. Check security applications such as SentinelOne or ThreatLocker."
                RETURN    
            }
        }
    }
    ELSE {
        $Results = REPORT-InternetSpeedTestMonitor -NumberOfTests 1

        IF ($Results.DownloadSpeed -Contains "Test Failed") {
            Write-Warning "SpeedTest.exe was blocked from running. Check security applications such as SentinelOne or ThreatLocker."
            RETURN    
        }
    
        RETURN $Results | Select DownloadSpeed, DownloadLatencyAvg, DownloadLatencyHigh, UploadSpeed, UploadSpeedAvg, UploadSpeedHigh, PacketLoss
    }
}
FUNCTION GET-NetworkAdapter {

    param(
        [switch]$Real = $False
    )

    IF ($Real -eq $true) {
        $Results = GET-CIMInstance Win32_NetworkAdapter -ErrorAction SilentlyContinue | Where-Object { $_.MACAddress -ne $null -and $_.Name -notlike "*Miniport*" -and $_.Name -notlike "*Virtual*" -and $_.Name -notlike "*NetExtender*" -and $_.Name -notlike "*AppGate*" } | Select InterfaceIndex, Name, NetConnectionID, MACAddress, Manufacturer
    }
    ELSE {
        $Results = GET-CIMInstance Win32_NetworkAdapter -ErrorAction SilentlyContinue | Select InterfaceIndex, Name, NetConnectionID, MACAddress, Manufacturer
    }

    RETURN $Results
}
FUNCTION GET-NetworkAdapterReal {
    GET-NetworkAdapter -Real
}
FUNCTION GET-NetworkConnection { 

    param (
        [ValidateSet("IPv4","IPv6")]
        [string[]]$IPType = @("IPv4"),

        [switch]$PhysicalOnly = $false
    )
    
    $Results = @()
    $NotApplicable  = "N/A"
    $Count = 0
    $AdapterBindings = @()
    
    $AdapterBindings += GET-NetAdapterBinding | Where-Object { $_.ComponentID -Like "*ms_tcpip*" -and $_.Enabled -eq "True" -and $_.Name -notlike "*bluetooth*" -and $_.ifDesc -notlike "*Hyper*" } -ErrorAction SilentlyContinue | Sort-Object -Property Name,ComponentID -Descending
    $AdapterBindings += GET-NetAdapterBinding | Where-Object { $_.ComponentID -Like "*ms_tcpip*" -and $_.Enabled -eq "True" -and $_.Name -notlike "*bluetooth*" -and $_.ifDesc -like "*Hyper*" } -ErrorAction SilentlyContinue | Sort-Object -Property Name,ComponentID
    
    FOREACH ($AdapterBinding in $AdapterBindings) {
        $IPVersion = ""
        $ConnectedSSID = ""
        $AdapterType = ""
        $ConnectionStatus = ""
        $NetAdapter = ""
        $IPInterface = ""
        $Status = ""
        $Blank = ""
        $SignalStrength = ""
        $Protocol = ""
        $DNSSuffix = ""
        $LinkSpeed = ""
        $vAdapterName = ""
        $VMSwitch = ""
        $DNSAssignment = ""    
        $NetConnectionProfile = ""
        
        $Count++
        $PercentComplete = (($Count-1) / $AdapterBindings.Count) * 100
        Write-Progress -ID 7 -Activity "Collecting Adapter Data" -Status "$([int]$PercentComplete)% - Collecting Data" -PercentComplete $PercentComplete

        ### Get IP Version
        IF ($AdapterBinding.ComponentID -eq "ms_tcpip") { $IPVersion = "IPv4" }
        ELSEIF ($AdapterBinding.ComponentID -eq "ms_tcpip6") { $IPVersion = "IPv6" }
        ELSE { $IPVersion = "Unknown" }

        IF ($IPType -contains $IPVersion) { } ELSE { continue }
        
        ### Get Status
        IF ($AdapterBinding.Enabled -eq "True") { $Status = "Enabled" }
        ELSEIF ($AdapterBinding.Enabled -eq "False") { $Status = "Disabled" }
        ELSE { $Status = "Unknown" }

        $NetAdapter = $null
        IF($PhysicalOnly -eq $true) {
            $NetAdapter = Get-NetAdapter -InterfaceDescription $AdapterBinding.InterfaceDescription -Physical -ErrorAction SilentlyContinue
        }
        Else {
            $NetAdapter = Get-NetAdapter -InterfaceDescription $AdapterBinding.InterfaceDescription -ErrorAction SilentlyContinue
        }
        IF ($NetAdapter -eq $null) { continue }
        
        $IPInterface = Get-NetIPInterface -InterfaceIndex $NetAdapter.ifIndex -AddressFamily $IPVersion -ErrorAction SilentlyContinue

        IF ($NetAdapter.AdminStatus -eq "Down") { continue }

        ### Get Connection Status
        $ConnectionStatus = $NetAdapter.MediaConnectionState

        ### Get DHCP Status
        $DHCPStatus = (Get-NetIPInterface -InterfaceIndex $NetAdapter.ifIndex -ErrorAction SilentlyContinue | Where-Object { $_.AddressFamily -eq $IPVersion}).DHCP
        IF ($DHCPStatus -eq "Enabled") { $IPAsssignment = "DHCP" } ELSE { $IPAsssignment = "Static" } 

        ### DNS Assignment
        $KeyName = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\" + $NetAdapter.DeviceName.Replace("\Device\","")
        $Value = Get-ItemPropertyValue -Path $KeyName -Name NameServer -ErrorAction SilentlyContinue
        IF ($Value -eq "" -or $Value -eq $null) { $DNSAssignment = "DHCP" }
        ELSEIF ( $Value -like "*.*" ) { $DNSAssignment = "Static" }
        ELSE { Continue }

        ### Get DNS Suffix
        $DNSSuffix = (GET-DNSClient -InterfaceIndex $NetAdapter.ifIndex -ErrorAction SilentlyContinue).ConnectionSpecificSuffix
        $NetConnectionProfile = (Get-NetConnectionProfile -InterfaceIndex $NetAdapter.ifIndex -ErrorAction SilentlyContinue).NetworkCategory
        IF ($NetConnectionProfile -eq "" -or $NetConnectionProfile -eq $null) { $NetConnectionProfile = "None" }

        ### Get Adapter Type
        IF ($NetAdapter.Name -eq "Wi-Fi" -or $NetAdapter.MediaType -like "*802.11*" -or $NetAdapter.PhysicalMediaType -like "*802.11*" -or $NetAdapter.ifName -like "*802.11*" -or $NetAdapter.InterfaceName -like "*wireless*") { 
            $AdapterType = "WiFi" 
            $ParentAdapter = $NotApplicable

            IF ($ConnectionStatus -eq "Connected") {
                $ConnectedSSID = netsh wlan show interfaces | select-string -Pattern "[\s]SSID"
                $ConnectedSSID = $ConnectedSSID.tostring().replace(" SSID : ","")

                $Protocol = netsh wlan show interfaces | select-string -Pattern "[\s]Radio Type"
                $Protocol = $Protocol.tostring().replace(" Radio type : ","")

                $SignalStrength = netsh wlan show interfaces | select-string -Pattern "[\s]Signal"
                $SignalStrength = $SignalStrength.tostring().replace(" Signal : ","")

                $LinkSpeed = ([int]($NetAdapter.ReceiveLinkSpeed / 1000000)).ToString()+"\"+([int]($NetAdapter.TransmitLinkSpeed / 1000000)).ToString()
            }
            ELSE {
                $ConnectedSSID = $Blank
                $Protocol = $Blank
                $SignalStrength = $Blank
                $LinkSpeed = $Blank
            }
        } 
        ELSEIF ($NetAdapter.Name -eq "Ethernet" -or $NetAdapter.PhysicalMediaType -like "*802.3*") { 
            $AdapterType = "Wired"
            $ParentAdapter = $NotApplicable
            
            IF ($ConnectionStatus -eq "Connected") {
                $ConnectedSSID = $NotApplicable
                $Protocol = "802.3"
                $SignalStrength = $NotApplicable

                $LinkSpeed = ([int]($NetAdapter.ReceiveLinkSpeed / 1000000)).ToString()+"\"+([int]($NetAdapter.TransmitLinkSpeed / 1000000)).ToString()
            }
            ELSE { 
                $ConnectedSSID = $NotApplicable
                $Protocol = $Blank
                $SignalStrength = $NotApplicable
                $LinkSpeed = $Blank
            }
        }
        ELSEIF ($NetAdapter.Name -like "*vEthernet*" -or $NetAdapter.MediaType -like "*802.3*" -or $NetAdapter.ifDesc -like "*Hyper-V*") 
        { 
            $AdapterType = "Hyper-V"

            $vAdapterName = $NetAdapter.Name.Replace("vEthernet (","")
            $vAdapterName = $vAdapterName.Replace(")","")

            $VMSwitch = Get-VMSwitch -Name $vAdapterName -ErrorAction SilentlyContinue
            IF ($VMSwitch.NetAdapterInterfaceDescription -ne "" -and $VMSwitch.NetAdapterInterfaceDescription -ne $null) {
                $ParentAdapter = $VMSwitch.NetAdapterInterfaceDescription
                $ParentAdapter = Get-NetAdapter -InterfaceDescription $ParentAdapter -ErrorAction SilentlyContinue
                $ParentAdapter = $ParentAdapter.Name + " ("+$ParentAdapter.InterfaceDescription+")"
            }
            ELSE { $ParentAdapter = "Internal" }
            
            IF ($ConnectionStatus -eq "Connected") {
                $ConnectedSSID = $NotApplicable
                $Protocol = "802.3"
                $SignalStrength = $NotApplicable

                $LinkSpeed = ([int]($NetAdapter.ReceiveLinkSpeed / 1000000)).ToString()+"\"+([int]($NetAdapter.TransmitLinkSpeed / 1000000)).ToString()
            }
            ELSE { 
                $ConnectedSSID = $NotApplicable
                $Protocol = $Blank
                $SignalStrength = $NotApplicable
                $LinkSpeed = $Blank
            }
        }
        ELSE { continue }
       
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Name = $NetAdapter.Name + " (" + $NetAdapter.DriverDescription + ")"
            Type = $AdapterType+" ($IPVersion)"
            ParentAdapter = $ParentAdapter
            Protocol = $Protocol
            IPAssignment = $IPAsssignment
            DNSAssignment = $DNSAssignment
            Status = $ConnectionStatus
            SSID = $ConnectedSSID
            SignalStrength = $SignalStrength
            LinkSpeed = $LinkSpeed
            DNSSuffix = $DNSSuffix
            MACAddress = $NetAdapter.MACAddress
            ConnectionProfile = $NetConnectionProfile
        }
    }
    Write-Progress -ID 7 -Activity "Collecting Adapter Data" -Status "$PercentComplete% - Collecting Data" -PercentComplete 100 -Completed

    RETURN $Results | Select Name, Type, Status, IPAssignment, DNSAssignment, LinkSpeed, Protocol, SignalStrength, SSID, DNSSuffix, ParentAdapter, MACAddress, ConnectionProfile | Sort-Object -Property Status
}
FUNCTION GET-PeripheralDevice {

    $Results = @()

    $Items = @()
    $Items += GET-CIMInstance Win32_PnPEntity -ErrorAction SilentlyContinue | ? { $_.Service -eq "WSDScan" } 
    $Items += GET-CIMInstance Win32_PnPEntity -ErrorAction SilentlyContinue | ? { $_.Service -eq "usbaudio" } 
    $Items += GET-CIMInstance Win32_PnPEntity -ErrorAction SilentlyContinue | ? { $_.Service -eq "usbvideo" } 

    FOREACH ($Item in $Items) {

        IF ($Item.Service -eq "usbvideo") {
            $Description = "USB Video Device"
        }
        ELSE { $Description = $Item.Description }
    
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Hostname = $Item.SystemName
            DeviceType = $Description
            DeviceName = $Item.Caption
            Service = $Item.Service
            Manufacturer = $Item.Manufacturer
            PNPClass = $Item.PNPClass
            DriverName = ""
            Capabilities = $Item.PowerManagementCapabilities
        }
    }

    $Items = GET-CIMInstance Win32_Printer -ErrorAction SilentlyContinue | Where-Object { $_.PortName -like "*USB*" } 

    FOREACH ($Item in $Items) {
    
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Hostname = $Item.SystemName
            DeviceType = "USB Printer Device"
            DeviceName = $Item.Caption
            Service = $Item.PortName
            Manufacturer = ""
            PNPClass = $Item.CreationClassName
            DriverName = $Item.DriverName
            Capabilities = $Item.CapabilityDescriptions
        }
    }

    RETURN $Results | Select HostName, DeviceType, DeviceName, Service, Manufacturer, PNPClass, DriverName, Capabilities
}
FUNCTION GET-RAMModule {

    $Results = @()

    $MemoryArray = GET-CIMInstance -Class "Win32_PhysicalMemoryArray"
    $MemoryModuleTotal = $MemoryArray.MemoryDevices
    $MemoryModuleCount = 
    
    IF ($MemoryArray.MemoryErrorCorrection -eq 3) { $MemType = "Non-ECC" }
    ELSEIF ($MemoryArray.MemoryErrorCorrection -eq 5) { $MemType = "ECC" }
    ELSEIF ($MemoryArray.MemoryErrorCorrection -eq 6) { $MemType = "ECC" }
    ELSE { $MemType = "Unknown" }
     
    $Modules = GET-CIMInstance -Class "Win32_PhysicalMemory"
    $TotalMem = 0

    FOREACH ($Module in $Modules) {
       $MemoryModuleCount++
       $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            BankLabel = $Module.DeviceLocator
            CapacityInGBs = $Module.Capacity / 1GB
            ClockSpeed = $Module.ConfiguredClockSpeed
            MemoryType = $MemType
            Manufacturer = $Module.Manufacturer
            PartNumber = $Module.PartNumber
            SerialNumber = $Module.SerialNumber
        }
        $TotalMem += $Module.Capacity / 1GB
    }

    While ($MemoryModuleCount -lt $MemoryModuleTotal) {
        
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            BankLabel = "Empty Slot"
            CapacityInGBs = ""
            ClockSpeed = ""
            MemoryType = ""
            Manufacturer = ""
            PartNumber = ""
            SerialNumber = ""
        }

        $MemoryModuleCount++
    }


    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        BankLabel = "Total"
        CapacityInGBs = $TotalMem
        ClockSpeed = ""
        MemoryType = ""
        Manufacturer = ""
        PartNumber = ""
        SerialNumber = ""
    }

    $Results | Select BankLabel, CapacityInGBs, ClockSpeed, MemoryType, Manufacturer, PartNumber, SerialNumber
}
FUNCTION GET-WindowsCrashEvent {

    param (
        [ValidateSet("BSOD","PowerLoss")]
        [string[]]$EventType = @("BSOD","PowerLoss")
    )

    $Results = @()
    $Events = @()

    IF ($EventType -contains "BSOD") { $Events += Get-WinEvent -FilterHashtable @{ProviderName = "Microsoft-Windows-WER-SystemErrorReporting"; ID = @(1001)} -ErrorAction SilentlyContinue }
    IF ($EventType -contains "PowerLoss") { $Events += Get-WinEvent -FilterHashtable @{ProviderName = "Microsoft-Windows-Kernel-Power"; ID = @(41)} -ErrorAction SilentlyContinue }

    FOREACH ($Event in $Events) {

        IF ($Event.ID -eq 1001) { $CrashType = "BSOD"; $Message = "The computer has rebooted from a bugcheck." }
        IF ($Event.ID -eq 41) { $CrashType = "Power Loss"; $Message = "The system has rebooted without cleanly shutting down first." }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            CrashType = $CrashType
            TimeCreated = $Event.TimeCreated 
            Message = $Message
        }
    }

    RETURN $Results | Select TimeCreated, CrashType, Message | Sort-Object -Property TimeCreated -Descending
}

### ### ==============================================================================================
### ### GET\SET FUNCTIONS
### ### ==============================================================================================

FUNCTION GET-VolumeSystem {
    
    $Results = @()

    $OSVolume = GET-Volume -DriveLetter $env:SystemDrive.Substring(0,1)
    $OSPartition = GET-Partition -DriveLetter $env:SystemDrive.Substring(0,1)
    $OSDisk = GET-PhysicalDisk -DeviceNumber $OSPartition.DiskNumber

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        DriveLetter = $OSVolume.DriveLetter
        VolumeFreeSizeInGBs = [int]($OSVolume.SizeRemaining / 1GB)
        VolumeMaxSizeInGBs = [int]($OSVolume.Size / 1GB)
        VolumeHealthStatus = $OSVolume.HealthStatus
        VolumeFileSystem = $OSVolume.FileSystem
        IsBootPartition = $OSPartition.IsBoot
        PartitionNumber = $OSPartition.PartitionNumber
        PartitionSizeInGBs = [int]($OSPartition.Size / 1GB) 
        DiskNumber = $OSDisk.DeviceID
        DiskMediaType = $OSDisk.MediaType
        DiskBusType = $OSDisk.BusType
        DiskUnallocatedSizeInGBs = ([int]($OSDisk.Size / 1GB)) - ([int]($OSDisk.AllocatedSize / 1GB))
        DiskMaxSizeInGBs = [int]($OSDisk.Size / 1GB)
        DiskFirmwareVersion = $OSDisk.FirmwareVersion
        DiskLocation = $OSDisk.PhysicalLocation
        DiskModel = $OSDisk.Model
        DiskHealthStatus = $OSDisk.HealthStatus
    }

    RETURN $Results | Select DriveLetter, VolumeFreeSizeInGBs, VolumeMaxSizeInGBs, VolumeHealthStatus, VolumeFileSystem, IsBootPartition, PartitionNumber, PartitionSizeInGBs, DiskNumber, DiskMediaType, DiskBusType, DiskUnallocatedSizeInGBs, DiskMaxSizeInGBs, DiskFirmwareVersion, DiskLocation, DiskModel, DiskHealthStatus
}
FUNCTION GET-WindowsInfo {

    $Results = @()

    $ContextNotElevated = Warning-AdministratorElevation

    $OS = GET-CIMInstance Win32_OperatingSystem
    $TimeZone = GET-TimeZone
    $DomainType = ""

    ### Check DomainJoin Type
    IF ($True) {
        $DomainServicesRegistration = dsregcmd /status

        IF ($DomainServicesRegistration -like "*DomainJoined : YES*") { $DomainType = "Local AD Domain" }
        ELSEIF ($DomainServicesRegistration -like "*AzureAdJoined : YES*" -and $DomainServicesRegistration -like "*DomainJoined : NO*") { $DomainType = "AzureAD" }
        ELSEIF ($DomainServicesRegistration -like "*AzureAdJoined : NO*" -and $DomainServicesRegistration -like "*DomainJoined : NO*") { $DomainType = "None (Workgroup)" }
        ELSE { $DomainType = "Error" }
    }

    IF ($ContextNotElevated -eq $False) {
        $BitLockerEncryptedDrives = Get-BitLockerVolume -ErrorAction SilentlyContinue | Where-Object { $_.VolumeStatus -like "*encrypted*" } 
        $BitLockerEncryptedDrives = $BitLockerEncryptedDrives.MountPoint
        $UnencryptedDrives = Get-BitLockerVolume -ErrorAction SilentlyContinue | Where-Object { $_.VolumeStatus -like "*decrypted*" }
        $UnencryptedDrives = $UnencryptedDrives.MountPoint
    }
    ELSE {
        $BitLockerEncryptedDrives = "[Elevation Required]"
        $UnencryptedDrives = "[Elevation Required]"
    }

    $ProductType = "Unknown"
    IF ($OS.ProductType -eq 1) { $ProductType = "Workstation" }
    IF ($OS.ProductType -eq 2) { $ProductType = "Domain Controller" }
    IF ($OS.ProductType -eq 3) { $ProductType = "Server" }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        Name = $OS.Caption
        Type = $ProductType
        DomainType = $DomainType
        Architecture = $OS.OSArchitecture 
        BuildNumber = $OS.BuildNumber
        TimeZone = $TimeZone.DisplayName
        InstallDate = $OS.InstallDate
        LastBootTime = $OS.LastBootUpTime
        LastWindowsUpdate = (GET-HotFix | Sort-Object -Property InstalledOn -Descending | Select-Object -First 1).InstalledOn
        BitLockerEncryptedDrives = $BitLockerEncryptedDrives
        UnencryptedDrives = $UnencryptedDrives
    }

    RETURN $Results | Select Name, Type, BuildNumber, DomainType, Architecture, TimeZone, InstallDate, LastBootTime, LastWindowsUpdate, BitLockerEncryptedDrives, UnencryptedDrives
}
FUNCTION GET-WindowsLogonEvent {

    [CmdletBinding(DefaultParameterSetName='Null')]
    param(
        [string[]]$LogonType = @("Logon","Logoff")
    )  
    
    $Results = @()
    $Events = @()
    
    IF ($LogonType -contains "Logon") { $Events += Get-WinEvent -FilterHashtable @{ProviderName = "Microsoft-Windows-Winlogon"; ID = @(7001)} }
    IF ($LogonType -contains "Logoff") { $Events += Get-WinEvent -FilterHashtable @{ProviderName = "Microsoft-Windows-Winlogon"; ID = @(7002)} }
    
    FOREACH ($Event in $Events) {
        TRY {
            $SID = New-Object System.Security.Principal.SecurityIdentifier($Event.Properties[1].Value.Value)
            $Username = $SID.Translate([System.Security.Principal.NTAccount])
        }
        CATCH {
            $Username = "Unknown or Deleted Account"
        }

        IF ($Event.ID -eq "7001") { $Type = "Logon" }
        IF ($Event.ID -eq "7002") { $Type = "Logoff" }
        IF ($Username -eq $null -or $Username -eq "") { $Username = "Account Deleted" }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Hostname = $Event.MachineName
            ID = $Event.ID
            Type = $Type
            Username = $Username
            Time = $Event.TimeCreated
        }
    }

    RETURN $Results | Select Hostname, ID, Username, Type, Time
}
FUNCTION GET-WindowsUpdate {

    GET-HotFix | Sort-Object -Property InstalledOn -Descending
}
FUNCTION GET-WindowsUserProfile {

    $Results = @()
    $Profiles = GET-ChildItem -Path C:\Users -Directory

    FOREACH ($Profile in $Profiles) { 
        IF($Profile.Name -ne "Public" -and $Profile.Name  -ne "public" -and $Profile.Name  -ne "admin" -and $Profile.Name  -ne "Admin" -and $Profile.Name  -ne "Administrator" -and $Profile.Name  -ne "administrator" -and $Profile.Name  -ne "Labtech" -and $Profile.Name  -ne "labtech" -and $Profile.Name  -ne "bjnadmin" -and $Profile.Name  -ne "cyberhawk" -and $Profile.Name  -ne "DefaultAppPool" -and $Profile.Name  -ne "labtechservice") {
            Write-Host $Profile.Name 
        } 

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            ProfileName = $Profile.Name
            ProfilePath = $Profile.FullName
            CreationTime = $Profile.CreationTime
            LastWriteTime = $Profile.LastWriteTime
        }
    }

    RETURN $Results | Select ProfileName, ProfilePath, CreationTime, LastWriteTime
}

### ### ==============================================================================================
### ### GET\SET EXPORTS
### ### ==============================================================================================

New-Alias -Name INTGET-ApplicationInstalled -Value GET-ApplicationInstalled
Export-ModuleMember -FUNCTION GET-ApplicationInstalled -Alias INTGET-ApplicationInstalled

New-Alias -Name INTGET-ApplicationEvent -Value GET-ApplicationEvent
Export-ModuleMember -FUNCTION GET-ApplicationEvent -Alias INTGET-ApplicationEvent

New-Alias -Name INTGET-BIOSSetting -Value GET-BIOSSetting
Export-ModuleMember -FUNCTION GET-BIOSSetting -Alias INTGET-BIOSSetting

New-Alias -Name INTGET-ChassisInfo -Value GET-ChassisInfo
Export-ModuleMember -FUNCTION GET-ChassisInfo -Alias INTGET-ChassisInfo

New-Alias -Name INTGET-CPUDevice -Value GET-CPUDevice
New-Alias -Name GET-ProcessorDevice -Value GET-CPUDevice
New-Alias -Name INTGET-ProcessorDevice -Value GET-CPUDevice
Export-ModuleMember -FUNCTION GET-CPUDevice -Alias INTGET-CPUDevice,GET-ProcessorDevice,INTGET-ProcessorDevice

New-Alias -Name INTGET-DiskDrive -Value GET-DiskDrive
Export-ModuleMember -FUNCTION GET-DiskDrive -Alias INTGET-DiskDrive

New-Alias -Name INTGET-DiskPerformance -Value GET-DiskPerformance
Export-ModuleMember -FUNCTION GET-DiskPerformance -Alias INTGET-DiskPerformance

New-Alias -Name INTGET-DisplayDevice -Value GET-DisplayDevice
New-Alias -Name GET-MonitorDevice -Value GET-DisplayDevice
New-Alias -Name INTGET-MonitorDevice -Value GET-DisplayDevice
Export-ModuleMember -FUNCTION GET-DisplayDevice -Alias INTGET-DisplayDevice,GET-MonitorDevice,INTGET-MonitorDevice

New-Alias -Name INTGET-DisplayAdapter -Value GET-DisplayAdapter
New-Alias -Name GET-GPUDevice -Value GET-DisplayAdapter
New-Alias -Name INTGET-GPUDevice -Value GET-DisplayAdapter
New-Alias -Name GET-VideoAdapter -Value GET-DisplayAdapter
New-Alias -Name INTGET-VideoAdapter -Value GET-DisplayAdapter
Export-ModuleMember -FUNCTION GET-DisplayAdapter -Alias INTGET-DisplayAdapter,GET-GPUDevice,INTGET-GPUDevice,GET-VideoAdapter,INTGET-VideoAdapter

New-Alias -Name INTGET-InternetInfo -Value GET-InternetInfo
Export-ModuleMember -FUNCTION GET-InternetInfo -Alias INTGET-InternetInfo

New-Alias -Name INTGET-InternetSpeedTest -Value GET-InternetSpeedTest
Export-ModuleMember -FUNCTION GET-InternetSpeedTest -Alias INTGET-InternetSpeedTest

New-Alias -Name INTGET-InternetSpeedTestGUI -Value GET-InternetSpeedTestGUI
Export-ModuleMember -FUNCTION GET-InternetSpeedTestGUI -Alias INTGET-InternetSpeedTestGUI

New-Alias -Name INTGET-NetworkAdapter -Value GET-NetworkAdapter
Export-ModuleMember -FUNCTION GET-NetworkAdapter -Alias INTGET-NetworkAdapter

New-Alias -Name INTGET-NetworkAdapterReal -Value GET-NetworkAdapterReal
Export-ModuleMember -FUNCTION GET-NetworkAdapterReal -Alias INTGET-NetworkAdapterReal

New-Alias -Name INTGET-NetworkConnection -Value GET-NetworkConnection
Export-ModuleMember -FUNCTION GET-NetworkConnection -Alias INTGET-NetworkConnection

New-Alias -Name INTGET-NetworkAdapterIPv6 -Value GET-NetworkAdapterIPv6
Export-ModuleMember -FUNCTION GET-NetworkAdapterIPv6 -Alias INTGET-NetworkAdapterIPv6

New-Alias -Name INTSET-NetworkAdapterIPv6 -Value SET-NetworkAdapterIPv6
Export-ModuleMember -FUNCTION SET-NetworkAdapterIPv6 -Alias INTSET-NetworkAdapterIPv6

New-Alias -Name INTGET-OneDriveBackupSetting -Value GET-OneDriveBackupSetting
Export-ModuleMember -FUNCTION GET-OneDriveBackupSetting -Alias INTGET-OneDriveBackupSetting

New-Alias -Name INTSET-OneDriveBackupSetting -Value SET-OneDriveBackupSetting
Export-ModuleMember -FUNCTION SET-OneDriveBackupSetting -Alias INTSET-OneDriveBackupSetting

New-Alias -Name INTGET-PeripheralDevice -Value GET-PeripheralDevice
Export-ModuleMember -FUNCTION GET-PeripheralDevice -Alias INTGET-PeripheralDevice

New-Alias -Name INTGET-RAMModule -Value GET-RAMModule
New-Alias -Name GET-RAMInfo -Value GET-RAMModule
New-Alias -Name INTGET-RAMInfo -Value GET-RAMModule
Export-ModuleMember -FUNCTION GET-RAMModule -Alias INTGET-RAMModule, GET-RAMInfo, INTGET-RAMInfo

New-Alias -Name INTGET-VolumeSystem -Value GET-VolumeSystem
Export-ModuleMember -FUNCTION GET-VolumeSystem -Alias INTGET-VolumeSystem

New-Alias -Name INTGET-WindowsCrashEvent -Value GET-WindowsCrashEvent
Export-ModuleMember -FUNCTION GET-WindowsCrashEvent -Alias INTGET-WindowsCrashEvent

New-Alias -Name INTGET-WindowsFirewallInfo -Value GET-WindowsFirewallInfo
Export-ModuleMember -FUNCTION GET-WindowsFirewallInfo -Alias INTGET-WindowsFirewallInfo

New-Alias -Name INTGET-WindowsHideFastUserSwitchingSetting -Value GET-WindowsHideFastUserSwitchingSetting
Export-ModuleMember -FUNCTION GET-WindowsHideFastUserSwitchingSetting -Alias INTGET-WindowsHideFastUserSwitchingSetting

New-Alias -Name INTSET-WindowsHideFastUserSwitchingSetting -Value SET-WindowsHideFastUserSwitchingSetting
Export-ModuleMember -FUNCTION SET-WindowsHideFastUserSwitchingSetting -Alias INTSET-WindowsHideFastUserSwitchingSetting

New-Alias -Name INTGET-WindowsInfo -Value GET-WindowsInfo
Export-ModuleMember -FUNCTION GET-WindowsInfo -Alias INTGET-WindowsInfo

New-Alias -Name INTGET-WindowsLocalAccountEnumerationSetting -Value GET-WindowsLocalAccountEnumerationSetting
Export-ModuleMember -FUNCTION GET-WindowsLocalAccountEnumerationSetting -Alias INTGET-WindowsLocalAccountEnumerationSetting

New-Alias -Name INTGET-WindowsLogonEvent -Value GET-WindowsLogonEvent
Export-ModuleMember -FUNCTION GET-WindowsLogonEvent -Alias INTGET-WindowsLogonEvent

New-Alias -Name INTGET-WindowsUpdate -Value GET-WindowsUpdate
Export-ModuleMember -FUNCTION GET-WindowsUpdate -Alias INTGET-WindowsUpdate

New-Alias -Name INTGET-WindowsUserProfile -Value GET-WindowsUserProfile
Export-ModuleMember -FUNCTION GET-WindowsUserProfile -Alias INTGET-WindowsUserProfile

### ### ==============================================================================================
### ### SEARCH\REPORT FUNCTIONS
### ### ==============================================================================================

FUNCTION SEARCH-EventLog {

    [CmdletBinding(DefaultParameterSetName='Minutes')]
    param(

        [Parameter(ParameterSetName = 'Full')]
        [Parameter(ParameterSetName = 'Minutes')]
        [int]$Minutes = 480,
        
        [Parameter(ParameterSetName = 'Full')]
        [Parameter(ParameterSetName = 'Hours')]
        [int]$Hours = $null,
        
        [Parameter(ParameterSetName = 'Full')]
        [Parameter(ParameterSetName = 'Days')]
        [int]$Days = $null,
                
        [Parameter(ParameterSetName = 'Minutes')]
        [Parameter(ParameterSetName = 'Hours')]
        [Parameter(ParameterSetName = 'Days')]
        [ValidateSet("Critical","Error","Warning","Information","All")]
        [String[]]$SeverityLevel = @("Critical","Error"),

        [Parameter(ParameterSetName = 'Full')]
        [Parameter(ParameterSetName = 'Minutes')]
        [Parameter(ParameterSetName = 'Hours')]
        [Parameter(ParameterSetName = 'Days')]
        [String[]]$Keywords = $null,

        [Parameter(ParameterSetName = 'Full')]
        [Parameter(ParameterSetName = 'Minutes')]
        [Parameter(ParameterSetName = 'Hours')]
        [Parameter(ParameterSetName = 'Days')]
        [int[]]$EventID = $null,

        [Parameter(ParameterSetName = 'Full')]
        [Parameter(ParameterSetName = 'Minutes')]
        [Parameter(ParameterSetName = 'Hours')]
        [Parameter(ParameterSetName = 'Days')]
        [String[]]$ProviderName = $null,
        
        [Parameter(ParameterSetName = 'Minutes')]
        [Parameter(ParameterSetName = 'Hours')]
        [Parameter(ParameterSetName = 'Days')]
        [switch]$IncludeSecurityLog = $False,

        [Parameter(Mandatory, ParameterSetName = 'Full')]
        [switch]$Full = $False
    )

    [int[]]$SearchIDs = @()
    $Now = GET-Date
    
    [int[]]$Level = @()
    IF ($SeverityLevel.Contains("Critical")) { $Level += 1 }
    IF ($SeverityLevel.Contains("Error")) { $Level += 2 }
    IF ($SeverityLevel.Contains("Warning")) { $Level += 3 }
    IF ($SeverityLevel.Contains("Information")) { $Level += 4 }
    IF ($SeverityLevel.Contains("All")) { $Level = @(0,1,2,3,4,5) }
    IF ($Full -eq $True) { $Level = @(0,1,2,3,4,5) }

    IF ($EventID -ne $null) {
        FOREACH ($Item in $EventID) {
            $SearchIDs += $Item
        }
    }
       
    IF ($Days -gt 0) { $Minutes = $Days * 1440 }
    IF ($Hours -gt 0) { $Minutes = $Hours * 60 }
    $Results = @()
    $Logs = GET-WinEvent -ListLog * -EA SilentlyContinue | Where { $_.RecordCount -ne 0 -and $_.LastWriteTime -gt $Now.AddMinutes(-$Minutes) }

    $CurrentLogCount = 0
    $TotalRecordCount = 0
    $ProgressPercent = 0
    FOREACH ($Log in $Logs) { $TotalRecordCount += $Log.RecordCount }  
    
    FOREach ($Log in $Logs) {
        
        $CurrentLogCount++
        Write-Progress -ID 12 -Activity "Searching Through Log Data" -Status "$ProgressPercent% - Processing Log $CurrentLogCount of $($Logs.Count)" -PercentComplete $ProgressPercent

        $CurrentRecordCount += $Log.RecordCount
        $ProgressPercent = [math]::round($CurrentRecordCount / $TotalRecordCount * 100,0)
        

        IF ($Log.LogName -eq "Windows PowerShell" -and $Full -eq $False) { continue }
        IF ($Log.LogName -eq "Security" -and $IncludeSecurityLog -eq $False) { IF ($Full -eq $False) { continue } }
        IF ($Log.LogName -like "Microsoft-Windows-Ntfs/Operational" -and $Full -eq $False) { continue }
        IF ($Log.LogName -like "Microsoft-Windows-Store/Operational" -and $Full -eq $False) { continue }
        IF ($Log.LogName -like "Microsoft-Windows-StateRepository/Operational" -and $Full -eq $False) { continue }
        IF ($Log.LogName -like "Microsoft-Windows-SmbClient/Connectivity" -and $Full -eq $False) { continue }
        IF ($Log.LogName -like "Microsoft-Windows-PowerShell" -and $Full -eq $False) { continue }
        IF ($Log.LogName -like "Microsoft-Windows-Storage-Storport/Operational" -and $Full -eq $False) { continue }
        IF ($Log.LogName -like "Microsoft-Windows-Storage-Storport/Health" -and $Full -eq $False) { continue }
        IF ($Log.LogName -like "Microsoft-Windows-PowerShell/Operational" -and $Full -eq $False) { continue }
        IF ($Log.LogName -like "Microsoft-Windows-LiveId/Operational" -and $Full -eq $False) { continue } 

        IF ($EventID -eq $null) { $EventInfo = GET-WinEvent -FilterHashtable @{logname = $Log.LogName; Level = @($Level); StartTime = $Now.AddMinutes(-$minutes)} -ErrorAction SilentlyContinue }
        ELSE { $EventInfo = GET-WinEvent -FilterHashtable @{logname = $Log.LogName; Level = @($Level); ID = @($SearchIDs); StartTime = $Now.AddMinutes(-$minutes)} -ErrorAction SilentlyContinue }
          
                
        FOREACH ($Event in $EventInfo) {
            
            IF ($Keywords -ne $null) {
                $KeywordFound = $False
                FOREACH ($Keyword in $Keywords) {
                    IF ($Event.Message -like "*$Keyword*") { $KeywordFound = $True }
                    ELSEIF ($Event.ProviderName -like "*$Keyword*") { $KeywordFound = $True }
                }
                IF ($KeywordFound -eq $False) { continue }
            }

            IF ($ProviderName -ne $null) {
                $ProviderNameFound = $False
                FOREACH ($Name in $ProviderName) {
                    IF ($Event.ProviderName -like "*$Name*") { $ProviderNameFound = $True }
                }
                IF ($ProviderNameFound -eq $False) { continue }
            }


            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Message = $Event.Message
                Id = $Event.ID 
                Version = $Event.Version
                Qualifiers = $Event.Qualifiers
                Level = $Event.Level
                Task = $Event.Task
                Opcode = $Event.Opcode
                Keywords = $Event.Keywords
                RecordId = $Event.RecordId
                ProviderName = $Event.ProviderName
                ProviderId = $Event.ProviderId
                LogName = $Event.LogName 
                ProcessId = $Event.ProcessId
                ThreadId = $Event.ThreadId
                MachineName = $Event.MachineName
                UserId = $Event.UserId
                TimeCreated = $Event.TimeCreated
                ActivityId = $Event.ActivityId
                RelatedActivityId = $Event.RelatedActivityId
                ContainerLog = $Event.ContainerLog
                MatchedQueryIds = $Event.MatchedQueryIds
                Bookmark = $Event.Bookmark
                LevelDisplayName = $Event.LevelDisplayName
                OpcodeDisplayName = $Event.OpcodeDisplayName
                KeywordsDisplayNames = $Event.KeywordsDisplayNames
                Properties = $Event.Properties
            }
        }
    }

    Write-Progress -ID 12 -Activity "Searching Through Log Data" -Status "$ProgressPercent% - Processing Log $CurrentLogCount of $($Logs.Count)" -PercentComplete 100 -Completed

    RETURN $Results | Select ID,ProviderName,LevelDisplayName,TimeCreated,Message 
}
FUNCTION SEARCH-AppData {

    [CmdletBinding(DefaultParameterSetName='None')]
    param(
        
        [Parameter(Mandatory)]
        [Parameter(ParameterSetName = 'None')]
        [Parameter(ParameterSetName = 'Rename')]
        [Parameter(ParameterSetName = 'Delete')]
        [string[]]$Keyword = "",
        
        [Parameter(ParameterSetName = 'None')]
        [Parameter(ParameterSetName = 'Rename')]
        [Parameter(ParameterSetName = 'Delete')]
        [switch]$ExactMatch = $False,

        [Parameter(ParameterSetName = 'Rename')]
        [switch]$Rename = $False,

        [Parameter(ParameterSetName = 'Delete')]
        [switch]$Delete = $False
    )    

    $ActionTaken = "None"
    IF ($Rename -eq $True) { $ActionTaken = "Rename" }
    IF ($Delete -eq $True) { $ActionTaken = "Delete" }
    
    $Folders = GET-ChildItem -Path $env:APPDATA,$env:LOCALAPPDATA -Directory
    $Results = @()
    FOREACH ($Folder in $Folders) {
        IF ($Folder.Name -like "*_bak_*") { continue }
        FOREACH ($Item in $Keyword) {
            IF ($ExactMatch -eq $False) {
                IF ($Folder -Like "*$Item*") {
                    IF ($Delete -eq $True) {
                        TRY {
                            Remove-Item -Path $Folder.FullName -Force -ErrorAction SilentlyContinue
                            $ActionResult = "Successful"
                            IF ((GET-Item -Path $Folder.FullName -ErrorAction SilentlyContinue) -ne $null) {
                                $ActionResult = "Failed"
                            }
                        }
                        CATCH {
                            IF ((GET-Item -Path $Folder.FullName) -ne $null) {
                                $ActionResult = "Failed"
                            }
                            ELSE { $ActionResult = "Successful" }
                        }
                    }
                    ELSEIF ($Rename -eq $True) {
                        $Now = GET-Date
                        $NewName = $Folder.FullName
                        $NewName += "_bak_$($Now.ToString('yyy_MM_dd_HH_mm_ss'))"
                        
                        TRY {
                            Rename-Item -Path $Folder.FullName -NewName $NewName -Force -ErrorAction SilentlyContinue
                            $ActionResult = "Successful"
                            IF ((GET-Item -Path $Folder.FullName -ErrorAction SilentlyContinue) -ne $null) {
                                $ActionResult = "Failed"
                            }
                        }
                        CATCH {
                            IF ((GET-Item -Path $Folder.FullName -ErrorAction SilentlyContinue) -ne $null) {
                                $ActionResult = "Failed"
                            }
                            ELSE { $ActionResult = "Successful" }
                        }
                    }
                    ELSE { $ActionResult = "N/A" }
                    
                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        FolderName = $Folder.Name
                        FolderPath = $Folder.FullName 
                        RequestedAction = $ActionTaken
                        ActionResult = $ActionResult
                    }
                    break
                }
            }
            ELSEIF ($ExactMatch -eq $True) {
                IF ($Folder -Like "$Item") {
                    IF ($Delete -eq $True) {
                        TRY {
                            Remove-Item -Path $Folder.FullName -Force -ErrorAction SilentlyContinue
                            $ActionResult = "Successful"
                            IF ((GET-Item -Path $Folder.FullName -ErrorAction SilentlyContinue) -ne $null) {
                                $ActionResult = "Failed"
                            }
                        }
                        CATCH {
                            IF ((GET-Item -Path $Folder.FullName -ErrorAction SilentlyContinue) -ne $null) {
                                $ActionResult = "Failed"
                            }
                            ELSE { $ActionResult = "Successful" }
                        }
                    }
                    ELSEIF ($Rename -eq $True) {
                        $Now = GET-Date
                        $NewName = $Folder.FullName
                        $NewName += "_bak_$($Now.ToString('yyy_MM_dd_HH_mm_ss'))"
                        
                        TRY {
                            Rename-Item -Path $Folder.FullName -NewName $NewName -Force -ErrorAction SilentlyContinue
                            $ActionResult = "Successful"
                            IF ((GET-Item -Path $Folder.FullName -ErrorAction SilentlyContinue) -ne $null) {
                                $ActionResult = "Failed"
                            }
                        }
                        CATCH {
                            IF ((GET-Item -Path $Folder.FullName -ErrorAction SilentlyContinue) -ne $null) {
                                $ActionResult = "Failed"
                            }
                            ELSE { $ActionResult = "Successful" }
                        }
                    }
                    ELSE { $ActionResult = "N/A" }
                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        FolderName = $Folder.Name
                        FolderPath = $Folder.FullName
                        RequestedAction = $ActionTaken
                        ActionResult = $ActionResult
                    }
                    break
                }  
            } 
        }
    }
    FOREACH ($Result in $Results) {
        IF ($Result.ActionResult -eq "Failed") {
            Write-Host ""
            Write-Warning "$ActionTaken Failed: Verifiy the Associated Application is Not Running"
        }
    }

    RETURN $Results | Select FolderName, FolderPath, RequestedAction, ActionResult
}
FUNCTION REPORT-ComputerPerformance {

    param(
        [ValidateSet("CPU","RAM","Disk","Network","Internet")]
        [String[]]$Category = @("CPU","RAM","Disk","Network","Internet"),

        [switch]$SortByRating = $false,

        [switch]$FormatOutput = $false
    )

    $Results = @()
    $Blank = ""

    Write-Progress -ID 2 -Activity "Running Performance Tests" -Status "Gathering CPU Data" -PercentComplete 0
    IF ($Category -contains "CPU") { 
        ### CPU Information
        IF ($True) {
            $CPUResults = GET-CPUDevice

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "CPU"
                PerformanceItem = "CPU Score"
                PerformanceResult = $CPUResults.CPUScore
                PerformanceRating = $CPUResults.CPURating
                PerformanceRatingString = $CPUResults.CPURatingString
            }

            IF ($CPUResults.YearsOld -eq "Unknown") { $AgeRating = $Blank; $AgeRatingString = $Blank }
            ELSEIF ($CPUResults.YearsOld -le 2) { $AgeRating = 9; $AgeRatingString = "Brand New" }
            ELSEIF ($CPUResults.YearsOld -le 3) { $AgeRating = 7; $AgeRatingString = "Very New" }
            ELSEIF ($CPUResults.YearsOld -le 4) { $AgeRating = 5; $AgeRatingString = "Good" }
            ELSEIF ($CPUResults.YearsOld -le 5) { $AgeRating = 4; $AgeRatingString = "Acceptable" }
            ELSEIF ($CPUResults.YearsOld -le 6) { $AgeRating = 3; $AgeRatingString = "Old" }
            ELSEIF ($CPUResults.YearsOld -le 7) { $AgeRating = 2; $AgeRatingString = "Very Old" }
            ELSE { $AgeRating = 1; $AgeRatingString = "Extremely Old" }
    
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "CPU"
                PerformanceItem = "CPU Age"
                PerformanceResult = $CPUResults.YearsOld
                PerformanceRating = $AgeRating
                PerformanceRatingString = $AgeRatingString
            }

            $CPUUsage = GET-CPUUsagePercent

            IF ($CPUUsage -le 20) { $CPUUsageRating = 9; $CPUUsageRatingString = "Crazy Low" }
            ELSEIF ($CPUUsage -le 30) { $CPUUsageRating = 8; $CPUUsageRatingString = "Extremely Low" }
            ELSEIF ($CPUUsage -le 40) { $CPUUsageRating = 7; $CPUUsageRatingString = "Very Low" }
            ELSEIF ($CPUUsage -le 50) { $CPUUsageRating = 6; $CPUUsageRatingString = "Low" }
            ELSEIF ($CPUUsage -le 60) { $CPUUsageRating = 5; $CPUUsageRatingString = "Good" }
            ELSEIF ($CPUUsage -le 70) { $CPUUsageRating = 4; $CPUUsageRatingString = "Acceptable" }
            ELSEIF ($CPUUsage -le 80) { $CPUUsageRating = 3; $CPUUsageRatingString = "High" }
            ELSEIF ($CPUUsage -le 90) { $CPUUsageRating = 2; $CPUUsageRatingString = "Very High" }
            ELSE { $CPUUsageRating = 1; $CPUUsageRatingString = "Extremely High" }

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "CPU"
                PerformanceItem = "CPU Usage"
                PerformanceResult = [string]$CPUUsage + "%"
                PerformanceRating = $CPUUsageRating
                PerformanceRatingString = $CPUUsageRatingString
            }
        }
    }

    Write-Progress -ID 2 -Activity "Running Performance Tests" -Status "Gathering RAM Data" -PercentComplete 10
    IF ($Category -contains "RAM") { 
        ### RAM Information
        IF ($True) {
            [int]$TotalRAM = GET-RAMInstalledTotalGB
            $RAMRating = $null
            IF ($TotalRAM -gt 39) { $RAMRating = 9; $RAMRatingString = "Crazy High" }
            ELSEIF ($TotalRAM -gt 31) { $RAMRating = 8; $RAMRatingString = "Extremely High" }
            ELSEIF ($TotalRAM -gt 23) { $RAMRating = 7; $RAMRatingString = "Very High" }
            ELSEIF ($TotalRAM -gt 19) { $RAMRating = 6; $RAMRatingString = "High" }
            ELSEIF ($TotalRAM -gt 15) { $RAMRating = 5; $RAMRatingString = "Good" }
            ELSEIF ($TotalRAM -gt 11) { $RAMRating = 4; $RAMRatingString = "Acceptable" }
            ELSEIF ($TotalRAM -gt 7) { $RAMRating = 3; $RAMRatingString = "Low" }
            ELSEIF ($TotalRAM -gt 5) { $RAMRating = 2; $RAMRatingString = "Very Low" }
            ELSE { $RAMRating = 1; $RAMRatingString = "Extremely Low" }

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "RAM"
                PerformanceItem = "RAM Amount"
                PerformanceResult = [string]$TotalRAM + " GB"
                PerformanceRating = $RAMRating
                PerformanceRatingString = $RAMRatingString
            }
             
            $AvailableMemoryGBs = [math]::round((Get-CIMInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB,2)

            IF ($AvailableMemoryGBs -gt 12) { $AvailMemPerformanceRating =9; $AvailMemPerformanceRatingString = "Crazy High" }
            ELSEIF ($AvailableMemoryGBs -gt 6) { $AvailMemPerformanceRating = 8; $AvailMemPerformanceRatingString = "Extremely High" }
            ELSEIF ($AvailableMemoryGBs -gt 4) { $AvailMemPerformanceRating = 7; $AvailMemPerformanceRatingString = "Very High" }
            ELSEIF ($AvailableMemoryGBs -gt 3) { $AvailMemPerformanceRating = 6; $AvailMemPerformanceRatingString = "High" }
            ELSEIF ($AvailableMemoryGBs -gt 2) { $AvailMemPerformanceRating = 5; $AvailMemPerformanceRatingString = "Good" }
            ELSEIF ($AvailableMemoryGBs -gt 1.5) { $AvailMemPerformanceRating = 4; $AvailMemPerformanceRatingString = "Acceptable" }
            ELSEIF ($AvailableMemoryGBs -gt 1) { $AvailMemPerformanceRating = 3; $AvailMemPerformanceRatingString = "Low"}
            ELSEIF ($AvailableMemoryGBs -gt .5) { $AvailMemPerformanceRating = 2; $AvailMemPerformanceRatingString = "Very Low" }
            ELSE { $AvailMemPerformanceRating = 1; $AvailMemPerformanceRatingString = "Extremely Low" }
    
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "RAM"
                PerformanceItem = "Available Memory"
                PerformanceResult = [string]$AvailableMemoryGBs+ " GB"
                PerformanceRating = $AvailMemPerformanceRating
                PerformanceRatingString = $AvailMemPerformanceRatingString
            }
        }
    }
        
    Write-Progress -ID 2 -Activity "Running Performance Tests" -Status "Running Disk Benchmarks - About 60 Seconds" -PercentComplete 15
    IF ($Category -contains "Disk") { 

        $DiskSpd = $True
        IF ((GET-Item -Path "C:\Program Files\IntegrisPowerShell Utilities\DiskSpd\diskspd.exe" -ErrorAction SilentlyContinue) -eq $null) {
            Write-Host ""
            Write-Warning "DiskSpd.exe not found, disk speed benchmark results will not be available. For disk speed benchmarking, download the Microsoft diskspd.exe application from 'https://github.com/microsoft/diskspd' and place it in the 'C:\Program Files\IntegrisPowerShell Utilities\DiskSpd\' folder"
            $DiskSpd = $False
        }

        ### Disk Information
        IF ($DiskSpd -eq $True) {
        #$DriveType = GET-DiskDrive | Where-Object { $_.ContainsSystemOS -eq $True }

        #$Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        # PerformanceCategory = "Disk"
        # PerformanceItem = "Media Type"
        # PerformanceResult = $DriveType.MediaType
        # PerformanceRating = $Blank
        # PerformanceRatingString = $Blank
        #}
        
        $DiskPerf = GET-DiskPerformance
        FOREACH ($Perf in $DiskPerf) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Disk"
                PerformanceItem = $Perf.IOType.ToString() + " " + $Perf.AccessType.ToString() 
                PerformanceResult = $Perf.ResultMBs.ToString() + " MB/s"
                PerformanceRating = $Perf.ResultRating
                PerformanceRatingString = $Perf.ResultRatingString
            }
        }

        #$Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        # PerformanceCategory = "Disk"
        # PerformanceItem = "Disk Size"
        # PerformanceResult = $DriveType.SizeGBs.ToString() + " GB"
        # PerformanceRating = $Blank
        # PerformanceRatingString = $Blank
        #}
    }
        ELSE {
            
            $DriveType = GET-DiskDrive | Where-Object { $_.ContainsSystemOS -eq $True }

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Disk"
                PerformanceItem = "Media Type"
                PerformanceResult = $DriveType.MediaType
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Disk"
                PerformanceItem = "Random Read"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Disk"
                PerformanceItem = "Random Write"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Disk"
                PerformanceItem = "Sequential Read"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }   
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Disk"
                PerformanceItem = "Sequential Write"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
        }
    }

    Write-Progress -ID 2 -Activity "Running Performance Tests" -Status "Gathering Network Data" -PercentComplete 65
    IF ($Category -contains "Network") { 
        ### Network Information
        IF ($True) {
        $NetworkConnections = GET-NetworkConnection

        FOREACH ($NetworkConnection in $NetworkConnections) {
            IF ($NetworkConnection.Type -like "*WiFi*" -and $NetworkConnection.Status -eq "Connected") {
                IF([int]$NetworkConnection.SignalStrength.Replace('%','') -ge 95) { $NetPeformanceRating = 9; $NetPerformanceRatingString = "Crazy Stable" }
                ELSEIF([int]$NetworkConnection.SignalStrength.Replace('%','') -ge 85) { $NetPeformanceRating = 8; $NetPerformanceRatingString = "Extremely Stable" }
                ELSEIF([int]$NetworkConnection.SignalStrength.Replace('%','') -ge 75) { $NetPeformanceRating = 7; $NetPerformanceRatingString = "Very Stable" }
                ELSEIF([int]$NetworkConnection.SignalStrength.Replace('%','') -ge 65) { $NetPeformanceRating = 6; $NetPerformanceRatingString = "Stable" }
                ELSEIF([int]$NetworkConnection.SignalStrength.Replace('%','') -ge 55) { $NetPeformanceRating = 5; $NetPerformanceRatingString = "Good" }
                ELSEIF([int]$NetworkConnection.SignalStrength.Replace('%','') -ge 45) { $NetPeformanceRating = 4; $NetPerformanceRatingString = "Acceptable" }
                ELSEIF([int]$NetworkConnection.SignalStrength.Replace('%','') -ge 35) { $NetPeformanceRating = 3; $NetPerformanceRatingString = "Unstable" }
                ELSEIF([int]$NetworkConnection.SignalStrength.Replace('%','') -ge 25) { $NetPeformanceRating = 2; $NetPerformanceRatingString = "Very Unstable" }
                ELSE { $NetPeformanceRating = 1; $NetPerformanceRatingString = "Extremely Unstable" }
           
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PerformanceCategory = "Network"
                    PerformanceItem = "Wireless Signal Strength"
                    PerformanceResult = $NetworkConnection.SignalStrength
                    PerformanceRating = $NetPeformanceRating
                    PerformanceRatingString = $NetPerformanceRatingString
                }
            }

            IF ($NetworkConnection.Status -eq "Connected") {
                $LinkSpeedCalc = 0
                IF ((($NetworkConnection.LinkSpeed.Split('\'))[0] / 4) -lt ($NetworkConnection.LinkSpeed.Split('\'))[1]) { $LinkSpeedCalc = ($NetworkConnection.LinkSpeed.Split('\'))[0] / 4 }
                ELSE { $LinkSpeedCalc = ($NetworkConnection.LinkSpeed.Split('\'))[1] } 

                IF ($LinkSpeedCalc -gt 250) { $LinkSpeedPerformanceRating = 9; $LinkSpeedPerformanceRatingString = "Crazy Fast" }
                ELSEIF ($LinkSpeedCalc -gt 175) { $LinkSpeedPerformanceRating = 8; $LinkSpeedPerformanceRatingString = "Extremely Fast" }
                ELSEIF ($LinkSpeedCalc -gt 115) { $LinkSpeedPerformanceRating = 7; $LinkSpeedPerformanceRatingString = "Very Fast" }
                ELSEIF ($LinkSpeedCalc -gt 70) { $LinkSpeedPerformanceRating = 6; $LinkSpeedPerformanceRatingString = "Fast" }
                ELSEIF ($LinkSpeedCalc -gt 45) { $LinkSpeedPerformanceRating = 5; $LinkSpeedPerformanceRatingString = "Good" }
                ELSEIF ($LinkSpeedCalc -gt 25) { $LinkSpeedPerformanceRating = 4; $LinkSpeedPerformanceRatingString = "Acceptable" }
                ELSEIF ($LinkSpeedCalc -gt 12) { $LinkSpeedPerformanceRating = 3; $LinkSpeedPerformanceRatingString = "Slow" }
                ELSEIF ($LinkSpeedCalc -gt 5) { $LinkSpeedPerformanceRating = 2; $LinkSpeedPerformanceRatingString = "Very Slow" }
                ELSE { $LinkSpeedPerformanceRating = 1; $LinkSpeedPerformanceRatingString = "Extremely Slow" }

                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PerformanceCategory = "Network"
                    PerformanceItem = $NetworkConnection.Type + " Link Speed"
                    PerformanceResult = ($NetworkConnection.LinkSpeed.Split('\'))[0].ToString() + "/" + ($NetworkConnection.LinkSpeed.Split('\'))[1].ToString() + " Mbps"
                    PerformanceRating = $LinkSpeedPerformanceRating
                    PerformanceRatingString = $LinkSpeedPerformanceRatingString
                }
            }

            IF ($NetworkConnection.Status -eq "Disconnected") {
                #$Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                # PerformanceCategory = "Network"
                # PerformanceItem = $NetworkConnection.AdapterType + " Status"
                # PerformanceResult = "Disconnected"
                # PerformanceRating = $Blank
                # PerformanceRatingString = $Blank
                #}
            }
        }
    }
    }
        
    Write-Progress -ID 2 -Activity "Running Performance Tests" -Status "Running Internet SpeedTest - About 30 Seconds" -PercentComplete 70
    IF ($Category -contains "Internet") { 

        $SpeedTestCLI = $True
        IF ((GET-Item -Path "C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\speedtest.exe" -ErrorAction SilentlyContinue) -eq $null) {
            Write-Host ""
            Write-Warning "SpeedTest.exe not found. Internet connection benchmark results will not be available. For internet connection benchmarking, download the Ookla speedtest.exe application from 'https://www.speedtest.net/apps/cli' and place it in the 'C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\' folder"
            $SpeedTestCLI = $False
        }

        ### Internet Information
        IF ($SpeedTestCLI -eq $True) {
            
            $SpeedTestResults = $null
            $SpeedTestFail = $false
            TRY { $SpeedTestResults = & "C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\speedtest.exe" --accept-license }
            CATCH { TRY { Start-Sleep -Seconds 1; $SpeedTestResults = & "C:\Program Files\IntegrisPowerShell Utilities\SpeedTest CLI\speedtest.exe" } CATCH { $SpeedTestFail = $true } }
            
            IF ($SpeedTestFail -eq $true -or $SpeedTestResults -eq $null) { 

                Write-Warning "SpeedTest.exe was blocked from running. Check security applications such as SentinelOne or ThreatLocker."

                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PerformanceCategory = "Internet"
                    PerformanceItem = "Download Speed"
                    PerformanceResult = "Test Failed"
                    PerformanceRating = $Blank
                    PerformanceRatingString = $Blank
                }
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PerformanceCategory = "Internet"
                    PerformanceItem = "Download Latency"
                    PerformanceResult = "Test Failed"
                    PerformanceRating = $Blank
                    PerformanceRatingString = $Blank
                }
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PerformanceCategory = "Internet"
                    PerformanceItem = "Upload Speed"
                    PerformanceResult = "Test Failed"
                    PerformanceRating = $Blank
                    PerformanceRatingString = $Blank
                }
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PerformanceCategory = "Internet"
                    PerformanceItem = "Upload Latency"
                    PerformanceResult = "Test Failed"
                    PerformanceRating = $Blank
                    PerformanceRatingString = $Blank
                }
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PerformanceCategory = "Internet"
                    PerformanceItem = "Packet Loss"
                    PerformanceResult = "Test Failed"
                    PerformanceRating = $Blank
                    PerformanceRatingString = $Blank
                }
            }
            ELSE { 
                ### Download Speed
                IF ($True) {
                $DownloadSpeed = $SpeedTestResults | select-string -Pattern "Download:"
                $DownloadSpeed = $DownloadSpeed.ToString().Replace('Download:','')
                [string[]]$DownloadSpeed = $DownloadSpeed.Split('.')
                [int]$DownloadSpeed = $DownloadSpeed[0].Replace(' ','')

                IF ($DownloadSpeed -ge 800) { $DownloadSpeedPerformanceRating = 9; $DownloadSpeedPerformanceRatingString = "Crazy Fast" }
                ELSEIF ($DownloadSpeed -ge 400) { $DownloadSpeedPerformanceRating = 8; $DownloadSpeedPerformanceRatingString = "Extremely Fast" }
                ELSEIF ($DownloadSpeed -ge 200) { $DownloadSpeedPerformanceRating = 7; $DownloadSpeedPerformanceRatingString = "Very Fast" }
                ELSEIF ($DownloadSpeed -ge 100) { $DownloadSpeedPerformanceRating = 6; $DownloadSpeedPerformanceRatingString = "Fast" }
                ELSEIF ($DownloadSpeed -ge 65) { $DownloadSpeedPerformanceRating = 5; $DownloadSpeedPerformanceRatingString = "Good" }
                ELSEIF ($DownloadSpeed -ge 40) { $DownloadSpeedPerformanceRating = 4; $DownloadSpeedPerformanceRatingString = "Acceptable" }
                ELSEIF ($DownloadSpeed -ge 20) { $DownloadSpeedPerformanceRating = 3; $DownloadSpeedPerformanceRatingString = "Slow" }
                ELSEIF ($DownloadSpeed -ge 10) { $DownloadSpeedPerformanceRating = 2; $DownloadSpeedPerformanceRatingString = "Very Slow" }
                ELSE { $DownloadSpeedPerformanceRating = 1; $DownloadSpeedPerformanceRatingString = "Extremely Slow" }

                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    PerformanceCategory = "Internet"
                    PerformanceItem = "Download Speed"
                    PerformanceResult = $DownloadSpeed.ToString() + " Mbps"
                    PerformanceRating = $DownloadSpeedPerformanceRating
                    PerformanceRatingString = $DownloadSpeedPerformanceRatingString
                }
            }

                ### Download Latency Avg
                IF ($True) {
                    [string]$DownloadLatency = $SpeedTestResults | select-string -Pattern "jitter:"
                    [string[]]$DownloadLatency = $DownloadLatency.Split('j')
                    [string]$DownloadLatency = $DownloadLatency[1]
                    [string[]]$DownloadLatency = $DownloadLatency.split(')')
                    [string]$DownloadLatency = $DownloadLatency[1]
                    $DownloadLatency = $DownloadLatency.Replace("ms","")
                    $DownloadLatency = $DownloadLatency.Replace("(","")
                    [int]$DownloadLatency = $DownloadLatency.Replace(" ","")

                    IF ($DownloadLatency -le 20) { $DownloadLatencyPerformanceRating = 9; $DownloadLatencyPerformanceRatingString = "Crazy Fast" }
                    ELSEIF ($DownloadLatency -le 40) { $DownloadLatencyPerformanceRating = 8; $DownloadLatencyPerformanceRatingString = "Extremely Fast" }
                    ELSEIF ($DownloadLatency -le 80) { $DownloadLatencyPerformanceRating = 7; $DownloadLatencyPerformanceRatingString = "Very Fast" }
                    ELSEIF ($DownloadLatency -le 125) { $DownloadLatencyPerformanceRating = 6; $DownloadLatencyPerformanceRatingString = "Fast" }
                    ELSEIF ($DownloadLatency -le 200) { $DownloadLatencyPerformanceRating = 5; $DownloadLatencyPerformanceRatingString = "Good" }
                    ELSEIF ($DownloadLatency -le 350) { $DownloadLatencyPerformanceRating = 4; $DownloadLatencyPerformanceRatingString = "Acceptable" }
                    ELSEIF ($DownloadLatency -le 750) { $DownloadLatencyPerformanceRating = 3; $DownloadLatencyPerformanceRatingString = "Slow" }
                    ELSEIF ($DownloadLatency -le 1250) { $DownloadLatencyPerformanceRating = 2; $DownloadLatencyPerformanceRatingString = "Very Slow" }
                    ELSE { $DownloadLatencyPerformanceRating = 1; $DownloadLatencyPerformanceRatingString = "Extremely Slow" }

                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        PerformanceCategory = "Internet"
                        PerformanceItem = "Download Latency (Avg)"
                        PerformanceResult = $DownloadLatency.ToString() + " ms"
                        PerformanceRating = $DownloadLatencyPerformanceRating
                        PerformanceRatingString = $DownloadLatencyPerformanceRatingString
                    }
                }

                ### Download Latency High
                IF ($true) {
                    [string[]]$DownloadLatencyHigh = $SpeedTestResults | select-string -Pattern "high:"
                    [string]$DownloadLatencyHigh = $DownloadLatencyHigh[1]
                    [string[]]$DownloadLatencyHigh = $DownloadLatencyHigh.Split(':')
                    [string]$DownloadLatencyHigh = $DownloadLatencyHigh[3]
                    $DownloadLatencyHigh = $DownloadLatencyHigh.Replace("ms","")
                    $DownloadLatencyHigh = $DownloadLatencyHigh.Replace(")","")
                    [int]$DownloadLatencyHigh = $DownloadLatencyHigh.Replace(" ","")

                    IF ($DownloadLatencyHigh -le 40) { $DownloadLatencyHighRating = 9; $DownloadLatencyHighRatingString = "Crazy Fast" }
                    ELSEIF ($DownloadLatencyHigh -le 80) { $DownloadLatencyHighRating = 8; $DownloadLatencyHighRatingString = "Extremely Fast" }
                    ELSEIF ($DownloadLatencyHigh -le 160) { $DownloadLatencyHighRating = 7; $DownloadLatencyHighRatingString = "Very Fast" }
                    ELSEIF ($DownloadLatencyHigh -le 250) { $DownloadLatencyHighRating = 6; $DownloadLatencyHighRatingString = "Fast" }
                    ELSEIF ($DownloadLatencyHigh -le 400) { $DownloadLatencyHighRating = 5; $DownloadLatencyHighRatingString = "Good" }
                    ELSEIF ($DownloadLatencyHigh -le 700) { $DownloadLatencyHighRating = 4; $DownloadLatencyHighRatingString = "Acceptable" }
                    ELSEIF ($DownloadLatencyHigh -le 1500) { $DownloadLatencyHighRating = 3; $DownloadLatencyHighRatingString = "Slow" }
                    ELSEIF ($DownloadLatencyHigh -le 2500) { $DownloadLatencyHighRating = 2; $DownloadLatencyHighRatingString = "Very Slow" }
                    ELSE { $DownloadLatencyHighRating = 1; $DownloadLatencyHighRatingString = "Extremely Slow" }

                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        PerformanceCategory = "Internet"
                        PerformanceItem = "Download Latency (High)"
                        PerformanceResult = $DownloadLatencyHigh.ToString() + " ms"
                        PerformanceRating = $DownloadLatencyHighRating
                        PerformanceRatingString = $DownloadLatencyHighRatingString
                    }
                }
       
                ### Upload Speed
                IF ($True) {
                    $UploadSpeed = $SpeedTestResults | select-string -Pattern "Upload:"
                    $UploadSpeed = $UploadSpeed.ToString().Replace('Upload:','')
                    [string[]]$UploadSpeed = $UploadSpeed.Split('.')
                    [int]$UploadSpeed = $UploadSpeed[0].Replace(' ','')

                    IF ($UploadSpeed -ge 200) { $UploadSpeedPerformanceRating = 9; $UploadSpeedPerformanceRatingString = "Crazy Fast" }
                    ELSEIF ($UploadSpeed -ge 100) { $UploadSpeedPerformanceRating = 8; $UploadSpeedPerformanceRatingString = "Extremely Fast" }
                    ELSEIF ($UploadSpeed -ge 50) { $UploadSpeedPerformanceRating = 7; $UploadSpeedPerformanceRatingString = "Very Fast" }
                    ELSEIF ($UploadSpeed -ge 25) { $UploadSpeedPerformanceRating = 6; $UploadSpeedPerformanceRatingString = "Fast" }
                    ELSEIF ($UploadSpeed -ge 18) { $UploadSpeedPerformanceRating = 5; $UploadSpeedPerformanceRatingString = "Good" }
                    ELSEIF ($UploadSpeed -ge 12) { $UploadSpeedPerformanceRating = 4; $UploadSpeedPerformanceRatingString = "Acceptable" }
                    ELSEIF ($UploadSpeed -ge 8) { $UploadSpeedPerformanceRating = 3; $UploadSpeedPerformanceRatingString = "Slow" }
                    ELSEIF ($UploadSpeed -ge 4) { $UploadSpeedPerformanceRating = 2; $UploadSpeedPerformanceRatingString = "Very Slow" }
                    ELSE { $UploadSpeedPerformanceRating = 1; $UploadSpeedPerformanceRatingString = "Extremely Slow" }

                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        PerformanceCategory = "Internet"
                        PerformanceItem = "Upload Speed"
                        PerformanceResult = $UploadSpeed.ToString() + " Mbps"
                        PerformanceRating = $UploadSpeedPerformanceRating
                        PerformanceRatingString = $UploadSpeedPerformanceRatingString
                    }
                }

                ### Upload Latency Avg
                IF ($True) {
                    [string]$UploadLatency = $SpeedTestResults | select-string -Pattern "jitter:"
                    [string[]]$UploadLatency = $UploadLatency.Split('j')
                    [string]$UploadLatency = $UploadLatency[2]
                    [string[]]$UploadLatency = $UploadLatency.split(')')
                    [string]$UploadLatency = $UploadLatency[1]
                    $UploadLatency = $UploadLatency.Replace("ms","")
                    $UploadLatency = $UploadLatency.Replace("(","")
                    [int]$UploadLatency = $UploadLatency.Replace(" ","")

                    IF ($UploadLatency -le 20) { $UploadLatencyPerformanceRating = 9; $UploadLatencyPerformanceRatingString = "Crazy Fast" }
                    ELSEIF ($UploadLatency -le 40) { $UploadLatencyPerformanceRating = 8; $UploadLatencyPerformanceRatingString = "Extremely Fast" }
                    ELSEIF ($UploadLatency -le 80) { $UploadLatencyPerformanceRating = 7; $UploadLatencyPerformanceRatingString = "Very Fast" }
                    ELSEIF ($UploadLatency -le 125) { $UploadLatencyPerformanceRating = 6; $UploadLatencyPerformanceRatingString = "Fast" }
                    ELSEIF ($UploadLatency -le 200) { $UploadLatencyPerformanceRating = 5; $UploadLatencyPerformanceRatingString = "Good" }
                    ELSEIF ($UploadLatency -le 350) { $UploadLatencyPerformanceRating = 4; $UploadLatencyPerformanceRatingString = "Acceptable" }
                    ELSEIF ($UploadLatency -le 750) { $UploadLatencyPerformanceRating = 3; $UploadLatencyPerformanceRatingString = "Slow" }
                    ELSEIF ($UploadLatency -le 1250) { $UploadLatencyPerformanceRating = 2; $UploadLatencyPerformanceRatingString = "Very Slow" }
                    ELSE { $UploadLatencyPerformanceRating = 1; $UploadLatencyPerformanceRatingString = "Extremely Slow" }

                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        PerformanceCategory = "Internet"
                        PerformanceItem = "Upload Latency (Avg)"
                        PerformanceResult = $UploadLatency.ToString() + " ms"
                        PerformanceRating = $UploadLatencyPerformanceRating
                        PerformanceRatingString = $UploadLatencyPerformanceRatingString
                    }
                }

                ### Upload Latency High
                IF ($true) {
                    [string[]]$UploadLatencyHigh = $SpeedTestResults | select-string -Pattern "high:"
                    [string]$UploadLatencyHigh = $UploadLatencyHigh[2]
                    [string[]]$UploadLatencyHigh = $UploadLatencyHigh.Split(':')
                    [string]$UploadLatencyHigh = $UploadLatencyHigh[3]
                    $UploadLatencyHigh = $UploadLatencyHigh.Replace("ms","")
                    $UploadLatencyHigh = $UploadLatencyHigh.Replace(")","")
                    [int]$UploadLatencyHigh = $UploadLatencyHigh.Replace(" ","")

                    IF ($UploadLatencyHigh -le 40) { $UploadLatencyHighPerformanceRating = 9; $UploadLatencyHighPerformanceRatingString = "Crazy Fast" }
                    ELSEIF ($UploadLatencyHigh -le 80) { $UploadLatencyHighPerformanceRating = 8; $UploadLatencyHighPerformanceRatingString = "Extremely Fast" }
                    ELSEIF ($UploadLatencyHigh -le 1600) { $UploadLatencyHighPerformanceRating = 7; $UploadLatencyHighPerformanceRatingString = "Very Fast" }
                    ELSEIF ($UploadLatencyHigh -le 250) { $UploadLatencyHighPerformanceRating = 6; $UploadLatencyHighPerformanceRatingString = "Fast" }
                    ELSEIF ($UploadLatencyHigh -le 400) { $UploadLatencyHighPerformanceRating = 5; $UploadLatencyHighPerformanceRatingString = "Good" }
                    ELSEIF ($UploadLatencyHigh -le 700) { $UploadLatencyHighPerformanceRating = 4; $UploadLatencyHighPerformanceRatingString = "Acceptable" }
                    ELSEIF ($UploadLatencyHigh -le 1500) { $UploadLatencyHighPerformanceRating = 3; $UploadLatencyHighPerformanceRatingString = "Slow" }
                    ELSEIF ($UploadLatencyHigh -le 2500) { $UploadLatencyHighPerformanceRating = 2; $UploadLatencyHighPerformanceRatingString = "Very Slow" }
                    ELSE { $UploadLatencyHighPerformanceRating = 1; $UploadLatencyHighPerformanceRatingString = "Extremely Slow" }

                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        PerformanceCategory = "Internet"
                        PerformanceItem = "Upload Latency (High)"
                        PerformanceResult = $UploadLatencyHigh.ToString() + " ms"
                        PerformanceRating = $UploadLatencyHighPerformanceRating
                        PerformanceRatingString = $UploadLatencyHighPerformanceRatingString
                    }
                }

                ### Packet Loss
                IF ($True) {
                    try {
                    $PacketLoss = $SpeedTestResults | select-string -Pattern "Packet Loss:"
                    $PacketLoss = $PacketLoss.ToString().Replace('%','')
                    $PacketLoss = $PacketLoss.ToString().Replace('Packet Loss:','')
                    [int]$PacketLoss = $PacketLoss.ToString().Replace(' ','')
                }
                    Catch { }

                    IF ($PacketLoss -eq 0) { $PacketLossPerformanceRating = 9; $PacketLossPerformanceRatingString = "Perfect" }
                    ELSEIF ($PacketLoss -le 1) { $PacketLossPerformanceRating = 8; $PacketLossPerformanceRatingString = "Extremely Low" }
                    ELSEIF ($PacketLoss -le 2) { $PacketLossPerformanceRating = 7; $PacketLossPerformanceRatingString = "Very Low" }
                    ELSEIF ($PacketLoss -le 3) { $PacketLossPerformanceRating = 6; $PacketLossPerformanceRatingString = "Low" }
                    ELSEIF ($PacketLoss -le 4) { $PacketLossPerformanceRating = 5; $PacketLossPerformanceRatingString = "Good" }
                    ELSEIF ($PacketLoss -le 5) { $PacketLossPerformanceRating = 4; $PacketLossPerformanceRatingString = "Acceptable" }
                    ELSEIF ($PacketLoss -le 7) { $PacketLossPerformanceRating = 3; $PacketLossPerformanceRatingString = "Bad" }
                    ELSEIF ($PacketLoss -le 10) { $PacketLossPerformanceRating = 2; $PacketLossPerformanceRatingString = "Very Bad" }
                    ELSE { $PacketLossPerformanceRating = 1; $PacketLossPerformanceRatingString = "Extremely Bad" }

                    IF ($PacketLoss -ge 0) { [string]$PacketLoss = $PacketLoss.ToString() + "%" }
                    ELSE { [string]$PacketLoss = "Unavailable"; $PacketLossPerformanceRating = ""; $PacketLossPerformanceRatingString = "" }

                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        PerformanceCategory = "Internet"
                        PerformanceItem = "Packet Loss"
                        PerformanceResult = $PacketLoss
                        PerformanceRating = $PacketLossPerformanceRating
                        PerformanceRatingString = $PacketLossPerformanceRatingString
                    }
                }
            }
        }
        ELSE {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Internet"
                PerformanceItem = "Download Speed"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Internet"
                PerformanceItem = "Download Latency"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Internet"
                PerformanceItem = "Upload Speed"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Internet"
                PerformanceItem = "Upload Latency"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                PerformanceCategory = "Internet"
                PerformanceItem = "Packet Loss"
                PerformanceResult = "Unavailable"
                PerformanceRating = $Blank
                PerformanceRatingString = $Blank
            }
        }
    }

    Write-Progress -ID 2 -Activity "Running Performance Tests" -Completed
    IF ($SortByRating -eq $True) { 
    RETURN $Results | Select PerformanceCategory, PerformanceItem, PerformanceResult, PerformanceRating, PerformanceRatingString | Sort-Object -Property PerformanceRating -Descending }
    ELSEIF ($FormatOutput -eq $False) { 
    RETURN $Results | Select PerformanceCategory, PerformanceItem, PerformanceResult, PerformanceRating, PerformanceRatingString }
    ELSE { 
    RETURN $Results | Select PerformanceCategory, PerformanceItem, PerformanceResult, PerformanceRating, PerformanceRatingString | FT -GroupBy PerformanceCategory }
}
FUNCTION REPORT-ComputerSummary {

    $Results = @() 

    ### Get Info
    $ChassisInfo = GET-ChassisInfo
    $CPUInfo = GET-CPUDevice
    $OSName = (GET-CIMInstance Win32_OperatingSystem).Caption
    
    ### Computer Name
    IF ($True) {
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Category = "Computer"
            Item = "General"
            ItemDetails = "Hostname"
            ItemValue = $env:COMPUTERNAME
        }
    }

    ### Case Type
    IF ($True) {
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Category = "Computer"
            Item = "General"
            ItemDetails = "Form Factor"
            ItemValue = $ChassisInfo.ChassisType
        }
    }

    ### Model Type
    IF ($True) {
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Category = "Computer"
            Item = "General"
            ItemDetails = "Model Name"
            ItemValue = $ChassisInfo.Model
        }
    }

    ### Manufacturer
    IF ($True) {
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Category = "Computer"
            Item = "General"
            ItemDetails = "Manufacturer"
            ItemValue = $ChassisInfo.Manufacturer
        }
    }

    ### OS Name
    IF ($True) {
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Category = "Computer"
            Item = "General"
            ItemDetails = "Operating System"
            ItemValue = $OSName
        }
    }

    ### CPU Model
    IF ($True) {
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Category = "Hardware"
            Item = "CPU"
            ItemDetails = "Model"
            ItemValue = $CPUInfo.CPUModel
        }
    }

    ### RAM
    IF ($True) {
        $RAMModules = GET-RAMModule

        FOREACH ($RAMModule in $RAMModules) {
            IF ($RAMModule.BankLabel -eq "Empty") { continue }

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Category = "Hardware"
                Item = "RAM"
                ItemDetails = $RAMModule.BankLabel
                ItemValue = $RAMModule.CapacityInGBs.ToString() + " GB"
            }
        }
    }

    ### Display Adapters
    IF ($True) {
        $DisplayAdapters = GET-DisplayAdapter

        FOREACH ($DisplayAdapter in $DisplayAdapters) {

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Category = "Hardware"
                Item = "Video"
                ItemDetails = "Model"
                ItemValue = $DisplayAdapter.ModelName
            }
        }
    }

    ### Network Adapters
    IF ($True) {
        $NetworkAdapters = Get-NetworkAdapterReal

        FOREACH ($NetworkAdapter in $NetworkAdapters) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Category = "Network"
                Item = "Adapter"
                ItemDetails = $NetworkAdapter.NetConnectionID
                ItemValue = $NetworkAdapter.NAme
            }
        }
    }

    ### Monitors
    IF ($True) {
        $Monitors = GET-DisplayDevice

        FOREACH ($Monitor in $Monitors) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Category = "Peripheral"
                Item = "Hardware"
                ItemDetails = "Monitor"
                ItemValue = $Monitor.ModelName
            }
        }
    }

    ### Peripheral Devices
    IF ($True) {
        $Peripherals = Get-PeripheralDevice

        FOREACH ($Peripheral in $Peripherals) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Category = "Peripheral"
                Item = "Hardware"
                ItemDetails = $Peripheral.DeviceType
                ItemValue = $Peripheral.DeviceName
            }
        }
    }

    ### Applications
    IF ($True) {
        $Applications = INTGET-ApplicationInstalled

        FOREACH ($Application in $Applications) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Category = "Software"
                Item = "Application"
                ItemDetails = "Name"
                ItemValue = $Application.Name
            }
        }
    }

    RETURN $Results | Select Category, Item, ItemDetails, ItemValue | FT -GroupBy Category
}
FUNCTION REPORT-NTFSPermission {

    [CmdletBinding(DefaultParameterSetName='StandardAudit')]
    param(
        [Parameter(Mandatory)]
        [string[]]$Path = "C:\",

        [string[]]$Identity = @("Everyone","Guest","\Users","Domain Users"),

        [ValidateSet("Allow","Deny")]
        [String[]]$AccessType = @("Allow"),

        [ValidateSet("ReadOnly","ReadWrite","FullControl","All")]
        [String[]]$PermissionType = @("ReadOnly","ReadWrite","FullControl"),
 
        [Switch]$IncludeInherited = $False,

        [Switch]$ExactMatch = $False
    )
        
    IF (ErrorCheck-AdministratorElevation) { RETURN }
    IF ((GET-InstalledModule -Name NTFSSecurity -ErrorAction SilentlyContinue) -eq $null) {
        TRY { Install-Module -Name NTFSSecurity -AllowClobber -Force }
        Catch{ Write-Warning "The NTFSSecurity module is not installed. Some results will not be available." }
        IF ((GET-InstalledModule -Name NTFSSecurity) -eq $null) { Write-Warning "The NTFSSecurity module is not installed. Some results will not be available." }
    }
    
    $Results = @()
    $CurrentFolderCount = 0
    $CurrentFolderPercent = 0
    $Count = 0
    FOREACH ($Permission in $PermissionType) { 
        IF ($PermissionType[$Count] -eq "ReadOnly") { $PermissionType[$Count] = "ReadAndExecute" }  
        IF ($PermissionType[$Count] -eq "ReadWrite") { $PermissionType[$Count] = "Modify" }
        $Count++    
    }
    IF ($PermissionType -contains "All") { $PermissionType = @("All") }
    
    Write-Progress -ID 8 -Activity "Collecting Folder Data" -Status "Collecting Folder Data - This May Take A While for Large Folder Structures" -PercentComplete 0
    
    ### Collecting All Folders From All Paths
    $Folders = @()
    FOREACH ($Item in $Path) {
        $Folders += GET-Item -Path $Item -ErrorAction SilentlyContinue
        FOREACH ($FolderItem in (GET-ChildItem -Path $Item -Recurse -Directory -ErrorAction SilentlyContinue)) {
            $Folders += $FolderItem
        }
    }

    $ProcessingStartTime = GET-Date

    ### Proccessing Folders
    FOREACH ($Folder in $Folders) {

        $CurrentFolderCount++
        $CurrentFolderPercent = [math]::round((($CurrentFolderCount-1) / $Folders.Count * 100),0)
        
        $TimeElapsed = (GET-Date) - $ProcessingStartTime
        IF (($CurrentFolderCount-1) -eq 0) { }
        ELSE {
            $TimeElapsedCalc = New-TimeSpan -Seconds (($TimeElapsed.TotalSeconds / ($CurrentFolderCount-1)) * ($Folders.Count - ($CurrentFolderCount - 1))) 
        }
        $TimeLeftString = [math]::round(($TimeElapsedCalc.Days),0).ToString().PadLeft(2,"0") + ":"
        $TimeLeftString += [math]::round(($TimeElapsedCalc.Hours),0).ToString().PadLeft(2,"0") + ":"
        $TimeLeftString += [math]::round(($TimeElapsedCalc.Minutes),0).ToString().PadLeft(2,"0") + ":"
        $TimeLeftString += [math]::round(($TimeElapsedCalc.Seconds),0).ToString().PadLeft(2,"0")

        Write-Progress -ID 8 -Activity "Processing..." -Status "$CurrentFolderPercent% - ETR: $TimeLeftString - Folder $CurrentFolderCount of $($Folders.Count) ($($Folder.FullName))" -PercentComplete $CurrentFolderPercent


        $ACL = GET-ACL -Path $Folder.FullName -ErrorAction SilentlyContinue

        ### Check Each Access Entry in ACL
        FOREACH ($AccessIdentity in $ACL.Access) {
            
            IF ((($Identity | %{$AccessIdentity.IdentityReference.Value.contains($_)}) -contains $True -and $ExactMatch -eq $False) -or 
                (($Identity | %{$AccessIdentity.IdentityReference.Value -contains $_}) -contains $True -and $ExactMatch -eq $True)) { 
                IF ($AccessType -contains $AccessIdentity.AccessControlType) {
                    FOREACH ($FileSystemRight in $AccessIdentity.FileSystemRights.ToString().Replace(" ","").Split(',')) {
                        IF ($PermissionType -contains $FileSystemRight -or $PermissionType -contains "All") {
                            IF($IncludeInherited -eq $True -or $AccessIdentity.IsInherited -eq $False) {
                            
                                $NTFSSecurity = GET-NTFSAccess -Path $Folder.FullName | Where-Object { $_.Account -like $AccessIdentity.IdentityReference.Value }

                                IF($AccessIdentity.InheritanceFlags -eq "ContainerInherit, ObjectInherit" -and $AccessIdentity.PropagationFlags -eq "InheritOnly") { $AppliesTo = "Subfolders and Files Only" }
                                ELSEIF($AccessIdentity.InheritanceFlags -eq "ContainerInherit, ObjectInherit" -and $AccessIdentity.PropagationFlags -eq "None") { $AppliesTo = "This Folder, Subfolders, and Files" }
                                ELSEIF($AccessIdentity.InheritanceFlags -eq "ContainerInherit, ObjectInherit" -and $AccessIdentity.PropagationFlags -eq "NoPropagateInherit") { $AppliesTo = "This Folder, Subfolders, and Files" }
                                ELSEIF($AccessIdentity.InheritanceFlags -eq "ContainerInherit" -and $AccessIdentity.PropagationFlags -eq "None") { $AppliesTo = "This Folder and Subfolders" }
                                ELSEIF($AccessIdentity.InheritanceFlags -eq "ContainerInherit" -and $AccessIdentity.PropagationFlags -eq "InheritOnly") { $AppliesTo = "Subfolders Only" }
                                ELSEIF($AccessIdentity.InheritanceFlags -eq "ObjectInherit" -and $AccessIdentity.PropagationFlags -eq "None") { $AppliesTo = "This Folder and Files" }
                                ELSEIF($AccessIdentity.InheritanceFlags -eq "ObjectInherit" -and $AccessIdentity.PropagationFlags -eq "NoPropagateInherit") { $AppliesTo = "This Folder and Files" }
                                ELSEIF($AccessIdentity.InheritanceFlags -eq "None" -and $AccessIdentity.PropagationFlags -eq "None") { $AppliesTo = "This Folder Only" }
                                ELSE { $ApplesTo = "Unknown" }

                                IF ($AccessIdentity.IsInherited -eq $False) { $InheritanceType = "Explicit" }
                                ELSE { $InheritanceType = "Inherited" }

                                IF ($AccessIdentity.IsInherited -eq $False) { $InheritedFrom = "N/A" }
                                ELSE { $InheritedFrom = $NTFSSecurity.InheritedFrom }

                                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                                    Identity = $AccessIdentity.IdentityReference.Value
                                    AccessType = $AccessIdentity.AccessControlType
                                    PermissionType = $AccessIdentity.FileSystemRights.ToString().Replace(", Synchronize","")
                                    Path = $Folder.FullName
                                    AppliesTo = $AppliesTo
                                    InheritanceType = $InheritanceType
                                    InheritedFrom = $InheritedFrom
                                } 

                                Break
                            }
                        }
                    }
                }
            }
        }
    }
    RETURN $Results | Select Identity, AccessType, PermissionType, Path, InheritanceType, InheritedFrom, AppliesTo
}
FUNCTION REPORT-ADGroupMembership {
    
    [CmdletBinding(DefaultParameterSetName='Audit')]
    param(
        [Parameter(Mandatory,ParameterSetName = 'Audit')]
        [Parameter(Mandatory,ParameterSetName = 'Compare')]
        [string[]]$Group = $null,

        [Parameter(ParameterSetName = 'Audit')]
        [Parameter(ParameterSetName = 'Compare')]
        [Switch]$ExactMatch = $False,

        [Parameter(ParameterSetName = 'Audit')]
        [Parameter(Mandatory,ParameterSetName = 'Compare')]
        [string]$SaveFileName = $null,

        [Parameter(ParameterSetName = 'Compare')]
        [Switch]$Compare = $False
    )
    
    ### Check for Administrator Access
    IF (ErrorCheck-AdministratorElevation) { RETURN }

    ### Check Save File Exists
    IF ($Compare -ne $False) {
        [string]$CSVCheck = "C:\IntegrisPowerShellTemp\Audit-ADGroupMembership\Saves\"
        $CSVCheck += $SaveFileName
        IF($CSVCheck.Substring($CSVCheck.Length-4,4) -ne ".csv") { $CSVCheck += ".csv" }
        IF((GET-Item $CSVCheck) -eq $null) {
            Write-Warning “The save file you entered was not found.`nPlease re-run this command with a valid save file in C:\IntegrisPowerShellTemp\Audit-ADGroupMembership\Saves.”
            RETURN
        }
    }
    
    #Write-Host ""
    $EmptyString = ""
    $DividerLength = 50
    $NamePadding = 30
    $UsernamePadding = 25
    $Results = @()
    $CompareResultsOut = @()

    IF ($ExactMatch -eq $True) {
        FOREACH ($Entry in $Group){
            $Membership = $null
            try { $Membership = GET-ADGroupMember -Identity $Entry -ErrorAction SilentlyContinue } catch { }
            IF ($Membership -eq $null) { continue }
            #Write-Host $Entry.PadLeft(($DividerLength - $Entry.Length)/2+$Entry.Length," ")
            #Write-Host $EmptyString.tostring().Padleft($DividerLength,'=')
            FOREACH ($Member in $Membership) {
                #Write-Host $Member.Name.PadRight($NamePadding,' ') -NoNewline
                #Write-Host $Member.SAMAccountName
                ### Output Results
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    GroupName = $Membership
                    UserName = $Member.SAMAccountName
                    FullName = $Member.Name
                 }
            }
            #Write-Host ""
            #Write-Host ""
        }
    }

    IF ($ExactMatch -eq $False) {
        FOREACH ($Entry in $Group){

            try { $GroupSearch = GET-ADGroup -Filter * -ErrorAction SilentlyContinue | Where-Object { $_.Name -like "*$Entry*" } } catch { }

            FOREACH ($GroupEntry in $GroupSearch){
                $Membership = $null
                $Membership = GET-ADGroupMember -Identity $GroupEntry.Name -ErrorAction SilentlyContinue
                IF ($Membership -eq $null) { continue }
                #Write-Host $GroupEntry.Name.PadLeft(($DividerLength - $GroupEntry.Name.Length)/2+$GroupEntry.Name.Length," ")
                #Write-Host $EmptyString.tostring().Padleft($DividerLength,'=')
                FOREACH ($Member in $Membership) {
                    #Write-Host $Member.Name.PadRight($NamePadding,' ') -NoNewline
                    #Write-Host $Member.SAMAccountName
                    ### Output Results
                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        GroupName = $GroupEntry.Name
                        UserName = $Member.SAMAccountName
                        FullName = $Member.Name
                    }
                }
                #Write-Host ""
                #Write-Host ""
            }
        }
    }

    IF ($Compare -eq $True) {
        [string]$ImportPath = "C:\IntegrisPowerShellTemp\Audit-ADGroupMembership\Saves\"
        $ImportPath += $SaveFileName
        IF($ImportPath.Substring($ImportPath.Length-4,4) -ne ".csv") { $ImportPath += ".csv" }
        $ImportResults = Import-CSV $ImportPath
        $CompareResults = Compare-Object -ReferenceObject $Results -DifferenceObject $ImportResults -Property GroupName,UserName,FullName
        FOREACH ($Item in $CompareResults) {
            $CompareResultsOut += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                GroupName = $Item.GroupName
                UserName = $Item.UserName
                FullName = $Item.FullName
                ChangeType = $Item.SideIndicator
            }
            FOREACH ($Item in $CompareResultsOut) {
                IF ($Item.ChangeType -eq "=>") { $Item.ChangeType = "Removed" }
                IF ($Item.ChangeType -eq "<=") { $Item.ChangeType = "Added" }
            }
        } 
        MKDir "C:\IntegrisPowerShellTemp\Audit-ADGroupMembership\Comparisons\" -ErrorAction SilentlyContinue | Out-Null
        [string]$ComparePath = "C:\IntegrisPowerShellTemp\Audit-ADGroupMembership\Comparisons\"
        $ComparePath += $SaveFileName
        IF($ComparePath.Substring($ComparePath.Length-4,4) -ne ".csv") { $ComparePath += ".csv" }
        ### Check If File Already Exists, If So Rename It
        IF((GET-Item $ComparePath -ErrorAction SilentlyContinue) -ne $null) { 
            $CreatedDate = GET-Item -Path $ComparePath
            $NewName = $ComparePath.Replace(".csv","")
            $NewName += $CreatedDate.LastWriteTime.ToString(" yyy_MM_dd h_mm_s")
            $NewName += ".csv"
            Rename-Item -Path $ComparePath -NewName $NewName -Force   
        }
         $Results | Export-CSV $ComparePath -Force
    }

    
    IF ($SaveFileName -ne $null) {
        MKDir "C:\IntegrisPowerShell\Audit-ADGroupMembership\Saves\" -ErrorAction SilentlyContinue | Out-Null
        [string]$ExportPath = "C:\IntegrisPowerShell\Audit-ADGroupMembership\Saves\"
        $ExportPath += $SaveFileName
        IF($ExportPath.Substring($ExportPath.Length-4,4) -ne ".csv") { $ExportPath += ".csv" }
        ### Check If File Already Exists, If So Rename It
        IF((GET-Item $ExportPath -ErrorAction SilentlyContinue) -ne $null) { 
            $CreatedDate = GET-Item -Path $ExportPath
            $NewName = $ExportPath.Replace(".csv","")
            $NewName += $CreatedDate.LastWriteTime.ToString(" yyy_MM_dd h_mm_s")
            $NewName += ".csv"
            Rename-Item -Path $ExportPath -NewName $NewName -Force  
        }
        $Results | Export-CSV $ExportPath -Force
    }
   
    IF ($Compare -eq $True) { RETURN $CompareResultsOut | Select UserName,FullName,GroupName,ChangeType }
    ELSE { RETURN $Results | Select UserName,FullName,GroupName }
}
FUNCTION REPORT-ADUser {
    
    param(   
                
        [Parameter()]
        [string[]]$OrganizationalUnit = @("*"),
        
        [Parameter()]
        [switch]$ExactMatch = $False,

        [Parameter()]
        [string[]]$ExcludeUser = @(),

        [Parameter()]
        [ValidateSet("Enabled","Disabled")]
        [String[]]$AccountStatus = @("Enabled")
    )

    $Accounts = @()

    IF ($OrganizationalUnit -eq $null) { $OrganizationalUnit = @("*")}

    FOREACH ($Status in $AccountStatus) {
        IF ($Status -eq "Enabled") { $Check = $True }
        IF ($Status -eq "Disabled") { $Check = $False }
        FOREACH ($OU in $OrganizationalUnit) {
            IF ($ExactMatch -eq $True -and $OU.SubString(0,3) -ne "OU=") { $OU = "OU=" + $OU }
            IF ($ExactMatch -eq $True -and $OU.SubString($OU.Length-1,1) -ne ",") { $OU += "," }
            IF (($DCCheck = $OU.Split(','))[$DCCheck.Count-2] -like "*DC=*") { $OU = $OU.Substring(0,$OU.Length-1) }           
            $OUString = "*" + $OU + "*"
            $Accounts += GET-ADUser -Filter * | Where { $_.Enabled -eq $Check } | Where { $_.DistinguishedName -like "$OUString" }
        }
    }
    $ExcludeSkip = $False
    $Results = @()
    FOREACH ($Entry in $Accounts) {
        FOREACH ($User in $ExcludeUser) { IF($Entry.SamAccountName -eq $User -or $Entry.Name -eq $User) { $ExcludeSkip = $True } }
        IF ($ExcludeSkip -eq $True) { $ExcludeSkip = $False; continue }
        $OUResult = ""
        $Properties = GET-ADUser -Identity $Entry.DistinguishedName -Properties *
        $OUPath = $Entry.DistinguishedName.Split(",")
        $Count = 1
        FOREACH ($Item in $OUPath) {
            IF ($Count -ne 1) { $OUResult += $Item + "," }
            $Count++
        }
        $OUResult = $OUResult.Substring(0,$OUResult.Length-1)
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            OrganizationalUnit = $OUResult
            Enabled = $Entry.Enabled 
            #GivenName = $Entry.GivenName
            #Surname = $Entry.Surname
            Name = $Entry.Name
            #ObjectClass = $Entry.ObjectClass
            #ObjectGUID = $Entry.ObjectGUID
            SAMAccountName = $Entry.SamAccountName
            #SID = $Entry.SID
            #UserPrincipalName = $Entry.UserPrincipalName
            #BadLogonCount = $Properties.BadLogonCount
            Created = $Properties.Created
            #EmailAddress = $Properties.EmailAddress
            LastLogonDate = $Properties.LastLogonDate
            #Manager = $Properties.Manager
            PasswordLastSet = $Properties.PasswordLastSet
            #PasswordExpired = $Properties.PasswordExpired
            #PasswordNeverExpires = $Properties.PasswordNeverExpires
            #ScriptPath = $Properties.ScriptPath
          
        }
    }

    RETURN $Results
}
FUNCTION REPORT-SMBShareData {
    
    $Results = @()
    
    ### GET SMB SHARES
    $SMBShares = GET-CIMInstance -Class Win32_Share
    $ServerMeasureSum = 0
    $ServerMeasureCount = 0
    $ShareCount = 0
    $CurrentShareCount = 0
    $RootShareFolderCount = 0
    $CurrentRootShareFolderCount = 0

    FOREACH ($SMBShare in $SMBShares) {
        
        ### SKIP THESE SHARES
        IF ($SMBShare.Name -eq "ADMIN$") { continue }
        IF ($SMBShare.Name -eq "IPC$") { continue }
        IF ($SMBShare.Name -eq "print$") { continue }
        IF ($SMBShare.Name -eq "SYSVOL") { continue }
        IF ($SMBShare.Name -eq "NETLOGON") { continue }
        IF ($SMBShare.Name -eq "Cache$") { continue }
        IF ($SMBShare.Name.Length -le 2) { continue }
        IF ($SMBShare.Name -eq "CertEnroll") { continue }
        IF ($SMBShare.Name -eq "print$") { continue }
        IF ($SMBShare.Name -eq "") { continue }
        IF ($SMBShare.Path -like "*Localspl*") { continue }
        IF ($SMBShare.Path -like "*DFSR*") { continue }

        $ShareCount++
    }


    FOREACH ($SMBShare in $SMBShares) {
        
        ### SKIP THESE SHARES
        IF ($SMBShare.Name -eq "ADMIN$") { continue }
        IF ($SMBShare.Name -eq "IPC$") { continue }
        IF ($SMBShare.Name -eq "print$") { continue }
        IF ($SMBShare.Name -eq "SYSVOL") { continue }
        IF ($SMBShare.Name -eq "NETLOGON") { continue }
        IF ($SMBShare.Name -eq "Cache$") { continue }
        IF ($SMBShare.Name.Length -le 2) { continue }
        IF ($SMBShare.Name -eq "CertEnroll") { continue }
        IF ($SMBShare.Name -eq "print$") { continue }
        IF ($SMBShare.Name -eq "") { continue }
        IF ($SMBShare.Path -like "*Localspl*") { continue }
        IF ($SMBShare.Path -like "*DFSR*") { continue }

        $CurrentShareCount++
        $CurrentProgress = [math]::round((($CurrentShareCount-1) / $ShareCount * 100),0)

        ### GET ROOT SHARE FOLDERS
        $RootShareFolders = GET-ChildItem -Path $SMBShare.Path -Directory -ErrorAction SilentlyContinue
        $TotalMeasureSum = 0
        $TotalMeasureCount = 0

        $Measure = GET-ChildItem -Path $SMBShare.Path -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            ComputerName = $env:COMPUTERNAME 
            ShareName = $SMBShare.Name
            SharePath = $SMBShare.Path
            FolderName = ""
            FolderPath = $SMBShare.Path
            FileCount = $Measure.Count
            TotalSizeMB = [math]::round($Measure.Sum / 1MB,2)
            TotalSizeGB = [math]::round($Measure.Sum / 1GB,2)
        }
        $TotalMeasureSum += $Measure.Sum
        $TotalMeasureCount += $Measure.Count
        $ServerMeasureSum += $Measure.Sum
        $ServerMeasureCount += $Measure.Count

        $CurrentRootShareFolderCount = 0
        FOREACH ($RootShareFolder in $RootShareFolders) { $RootShareFolderCount++ }

        FOREACH ($RootShareFolder in $RootShareFolders) {
            $CurrentRootShareFolderCount++
            $ShareProgress = [math]::round((($CurrentRootShareFolderCount-1) / $RootShareFolderCount * 100),0)

            Write-Progress -ID 8 -Activity "Collecting All SMB Share Data" -Status "Total Progress: $($CurrentProgress.ToString())%" -PercentComplete $CurrentProgress
            Write-Progress -ID 9 -Activity "Collecting $($SMBShare.Name) Share Data" -Status "Share Progress: $($ShareProgress.ToString())%" -PercentComplete $ShareProgress



            $Measure = GET-ChildItem -Path $RootShareFolder.FullName -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                ComputerName = $env:COMPUTERNAME 
                ShareName = $SMBShare.Name
                SharePath = $SMBShare.Path
                FolderName = $RootShareFolder.Name
                FolderPath = $RootShareFolder.FullName
                FileCount = $Measure.Count
                TotalSizeMB = [math]::round($Measure.Sum / 1MB,2)
                TotalSizeGB = [math]::round($Measure.Sum / 1GB,2)
            }
            $TotalMeasureSum += $Measure.Sum
            $TotalMeasureCount += $Measure.Count
            $ServerMeasureSum += $Measure.Sum
            $ServerMeasureCount += $Measure.Count
        }
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            ComputerName = $env:COMPUTERNAME 
            ShareName = $SMBShare.Name
            SharePath = $SMBShare.Path
            FolderName = "Share Total"
            FolderPath = "N/A"
            FileCount = $TotalMeasureCount
            TotalSizeMB = [math]::round($TotalMeasureSum / 1MB,2)
            TotalSizeGB = [math]::round($TotalMeasureSum / 1GB,2)
        }
    }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        ComputerName = $env:COMPUTERNAME 
        ShareName = "Server Total"
        SharePath = "N/A"
        FolderName = "N/A"
        FolderPath = "N/A"
        FileCount = $ServerMeasureCount
        TotalSizeMB = [math]::round($ServerMeasureSum / 1MB,2)
        TotalSizeGB = [math]::round($ServerMeasureSum / 1GB,2)
    }

    ### OUTPUT RESULTS
    $Now = GET-Date
    MKDir "C:\IntegrisPowerShell\REPORT-SMBShareData\Results\" -ErrorAction SilentlyContinue | Out-Null
    [string]$ExportPath = "C:\IntegrisPowerShell\REPORT-SMBShareData\Results\"
    $FileName = "SMB Share Data Report - "
    $FileName += $Now.ToString("yyy_MM_dd h_mm_s")
    $FileName += ".csv"
    $ExportPath += $FileName
    $Results | Select-Object ComputerName, ShareName, SharePath, FolderName, FolderPath, FileCount, TotalSizeMB, TotalSizeGB | Export-CSV -Path $ExportPath

    Write-Progress -ID 9 -Activity "Collecting SMB Share Data" -Status "Total Progress: $TotalProgress - Share Name: $($RootShareFolder.Name) - Share Progress: $ShareProgress" -PercentComplete 100 -Completed
    Write-Progress -ID 8 -Activity "Collecting SMB Share Data" -Status "Total Progress: $TotalProgress - Share Name: $($RootShareFolder.Name) - Share Progress: $ShareProgress" -PercentComplete 100 -Completed

    ### RETURN RESULTS
    RETURN $Results | Select-Object ComputerName, ShareName, SharePath, FolderName, FolderPath, FileCount, TotalSizeMB, TotalSizeGB
}
FUNCTION REPORT-SharePointPreMigationCheckOld {
    
    param(
        [Parameter(Mandatory,ParameterSetName = 'Path')]
        [string[]]$Path = @(),

        [Parameter(Mandatory,ParameterSetName = 'AllShares')]
        [switch]$AllShares = $False
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }
    
    ### START
    $Now = GET-Date
    MKDir "C:\IntegrisPowerShell\REPORT-SharePointPreMigationCheck\Temp\" -ErrorAction SilentlyContinue | Out-Null
    [string]$TempPath = "C:\IntegrisPowerShell\REPORT-SharePointPreMigationCheck\Temp\"
    $TempPath += $Now.ToString("yyy_MM_dd h_mm_s")
    $TempPath += "\"
    MKDir $TempPath -ErrorAction SilentlyContinue | Out-Null

    IF ($AllShares -eq $True) {  
        $SMBShares = GET-CIMInstance -Class Win32_Share

        FOREACH ($SMBShare in $SMBShares) {

            ### SKIP THESE SHARES
            IF ($SMBShare.Name -eq "ADMIN$") { continue }
            IF ($SMBShare.Name -eq "IPC$") { continue }
            IF ($SMBShare.Name -eq "print$") { continue }
            IF ($SMBShare.Name -eq "SYSVOL") { continue }
            IF ($SMBShare.Name -eq "NETLOGON") { continue }
            IF ($SMBShare.Name -eq "Cache$") { continue }
            IF ($SMBShare.Name.Length -le 2) { continue }
            IF ($SMBShare.Name -eq "CertEnroll") { continue }
            IF ($SMBShare.Name -eq "print$") { continue }
            IF ($SMBShare.Path -like "*LocalsplOnly*") { continue }
            IF ($SMBShare.Path -like "*DFSR*") { continue }
            IF ($SMBShare.Name -eq "") { continue }
            
            $Path += $SMBShare.Path
        }
    }
    
    $Results = @()
    
    $Files = @()
    
    $Count = 0
    ### COLLECT FILE DATA
    FOREACH ($Item in $Path) {
        $Folders = GET-ChildItem -Path $Item -Directory -Force | Select FullName     
        FOREACH ($Folder in $Folders) {
            $SavePath = $TempPath + "SharePoint Pre-Migration Temp "
            $SavePath += $Count.ToString().PadLeft(4,'0')
            $SavePath += ".csv"
            GET-ChildItem -Path $Folder.FullName -Recurse -Force | Select Name, FullName | Export-CSV -Path $SavePath -Delimiter ","
            $Count++
        }
    }
    TRY { $EncryptedFiles = cipher /u /n /h } CATCH { }

    $ExportFiles = GET-ChildItem -Path $TempPath 

    $SearchFiles = New-Object PSObject
    ### PROCESS DATA
    FOREACH ($CSV in $ExportFiles) {
        $SearchFiles = Import-CSV -Path $CSV.FullName | ForEach-Object {
            [PSCustomObject]@{
                'Name' = $_.Name
                'FullName' = $_.FullName
            }
        }
        FOREACH ($File in $SearchFiles) {
            TRY {
                IF ($File.FullName.Length -gt 200) {                
                    $IssueDetails = $File.FullName.Length.ToString()
                    $IssueDetails += " Characters" 
                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        ComputerName = $env:COMPUTERNAME
                        FilePath = $File.FullName
                        IssueFound = "File Path Too Long"
                        IssueDetails = $IssueDetails
                    }
                }
            }
            CATCH { }
             
                TRY {    
                IF ($File.Name.Substring(0,1) -eq " ") { 
                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        ComputerName = $env:COMPUTERNAME
                        FilePath = $File.FullName
                        IssueFound = "Invalid File Name"
                        IssueDetails = "File Name Begins With a Space"
                    }     
                }
            }
            CATCH { }

            TRY {
                IF ($File.Name.Substring(($File.Name.Length-5),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-6),1) -eq " ") { 
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
            CATCH { }
        
            TRY {
                IF ($File.Name.Substring(($File.Name.Length-4),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-5),1) -eq " ") { 
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
            CATCH { }

            TRY {
                IF ($File.Name.Substring(($File.Name.Length-3),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-4),1) -eq " ") { 
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
            CATCH { }

                TRY {
                IF ($EncryptedFiles -contains $File.FullName) {
                    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        ComputerName = $env:COMPUTERNAME
                        FilePath = $File.FullName
                        IssueFound = "Encrypted File"
                        IssueDetails = "File is Encrypted with EFS Encryption"
                    }
                }
            }
            CATCH { }                     
        }
    }

    ### OUTPUT RESULTS
    $Now = GET-Date
    MKDir "C:\IntegrisPowerShell\REPORT-SharePointPreMigationCheck\Results\" -ErrorAction SilentlyContinue | Out-Null
    [string]$ExportPath = "C:\IntegrisPowerShell\REPORT-SharePointPreMigationCheck\Results\"
    $FileName = "SharePoint Pre-Migration Report - "
    $FileName += $Now.ToString("yyy_MM_dd h_mm_s")
    $FileName += ".csv"
    $ExportPath += $FileName
    $Results | Select-Object IssueFound, IssueDetails, ComputerName, FilePath | Export-CSV -Path $ExportPath

    ### RETURN RESULTS
    RETURN $Results | Select-Object IssueFound, IssueDetails, ComputerName, FilePath
}
FUNCTION REPORT-SharePointPreMigationCheck {
    
    param(
        [Parameter(Mandatory,ParameterSetName = 'Path')]
        [string[]]$Path = @(),

        [Parameter(Mandatory,ParameterSetName = 'AllShares')]
        [switch]$AllShares = $False,

        [int]$PathLengthThreshold = 200
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    ## Check Function
    FUNCTION SharePointCheckFile {

        param (
       
            [Parameter(Mandatory)]
            [PSCustomObject]$File = ""
        )

        TRY {
                IF ($File.FullName.Length -gt $PathLengthThreshold) {                
                    $IssueDetails = $File.FullName.Length.ToString()
                    $IssueDetails += " Characters" 
                    $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        ComputerName = $env:COMPUTERNAME
                        FilePath = $File.FullName
                        IssueFound = "File Path Too Long"
                        IssueDetails = $IssueDetails
                    }
                }
            }
        CATCH { }
             
        TRY {    
                IF ($File.Name.Substring(0,1) -eq " ") { 
                    $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        ComputerName = $env:COMPUTERNAME
                        FilePath = $File.FullName
                        IssueFound = "Invalid File Name"
                        IssueDetails = "File Name Begins With a Space"
                    }     
                }
            }
        CATCH { }

        TRY {
                IF ($File.Name.Substring(($File.Name.Length-5),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-6),1) -eq " ") { 
                        $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
        CATCH { }
        
        TRY {
                IF ($File.Name.Substring(($File.Name.Length-4),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-5),1) -eq " ") { 
                        $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
        CATCH { }

        TRY {
                IF ($File.Name.Substring(($File.Name.Length-3),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-4),1) -eq " ") { 
                        $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
        CATCH { }

        TRY {
                IF ($EncryptedFiles -contains $File.FullName) {
                    $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        ComputerName = $env:COMPUTERNAME
                        FilePath = $File.FullName
                        IssueFound = "Encrypted File"
                        IssueDetails = "File is Encrypted with EFS Encryption"
                    }
                }
            }
        CATCH { }                     
        
        RETURN $TempResults
    }
    FUNCTION UpdateProgressBar {
        $PercentComplete = $CurrentFolderCount / $FolderCount * 100
         
        Write-Progress -ID 5 -Activity "Performing SharePoint Migration Pre-Check" -Status "Analyzing Folders $CurrentFolderCount of $FolderCount - $($Subfolder.FullName)" -PercentComplete $PercentComplete
    }

    Write-Progress -ID 5 -Activity "Performing SharePoint Migration Pre-Check" -Status "Initializing Analysis Process" -PercentComplete 0

    ### START
    $StartDate = GET-Date
    $Results = @()
    $Folders = @()
    $FolderCount = 0
    $CurrentFolderCount = 0


    Write-Progress -ID 5 -Activity "Performing SharePoint Migration Pre-Check" -Status "Gathering Folder Data - This May Take a Couple Minutes" -PercentComplete 0
    TRY { $EncryptedFiles = cipher /u /n /h } CATCH { }

    ### Gather Share Paths if AllShares
    IF ($AllShares -eq $True) {  
        $SMBShares = GET-CIMInstance -Class Win32_Share

        FOREACH ($SMBShare in $SMBShares) {

            ### SKIP THESE SHARES
            IF ($SMBShare.Name -eq "ADMIN$") { continue }
            IF ($SMBShare.Name -eq "IPC$") { continue }
            IF ($SMBShare.Name -eq "print$") { continue }
            IF ($SMBShare.Name -eq "SYSVOL") { continue }
            IF ($SMBShare.Name -eq "NETLOGON") { continue }
            IF ($SMBShare.Name -eq "Cache$") { continue }
            IF ($SMBShare.Name.Length -le 2) { continue }
            IF ($SMBShare.Name -eq "CertEnroll") { continue }
            IF ($SMBShare.Name -eq "print$") { continue }
            IF ($SMBShare.Path -like "*LocalsplOnly*") { continue }
            IF ($SMBShare.Name -eq "") { continue }
           
            $Path += $SMBShare.Path
        }
    }
        
    ### Get All Folders in Path
    FOREACH ($Item in $Path) {
        $Folders += Get-Item -Path $Item 
    }

    ### Count Folders
    FOREACH ($Folder in $Folders) {
        $FolderCount++
        FOREACH ($SubFolder in (Get-ChildItem -Path $Folder.FullName -Directory -Force -ErrorAction SilentlyContinue)) {
            $FolderCount++
        }
    }

    ### Process Files
    $FolderStartTime = Get-Date
    $CurrentFolderCount = 0
    FOREACH ($Folder in $Folders) {
        UpdateProgressBar
        FOREACH ($File in (Get-ChildItem -Path $Folder.FullName -File -Force -ErrorAction SilentlyContinue)) {
            IF ($File.Name.Substring(0,2) -eq "~$") { continue }
            $Results += SharePointCheckFile -File $File
        }
        $CurrentFolderCount++
        FOREACH ($SubFolder in (Get-ChildItem -Path $Folder.FullName -Directory -Force -ErrorAction SilentlyContinue)) {
            UpdateProgressBar
            FOREACH ($File in (Get-ChildItem -Path $SubFolder.FullName -File -Recurse -Force -ErrorAction SilentlyContinue)) {
                IF ($File.Name.Substring(0,2) -eq "~$") { continue }
                $Results += SharePointCheckFile -File $File
            }
            $CurrentFolderCount++
            
        }
    }

    Write-Progress -ID 5 -Activity "Performing SharePoint Migration Pre-Check" -Status "Analyzing Folders $CurrentFolderCount of $FolderCount - $($Subfolder.FullName)" -PercentComplete $PercentComplete -Completedcls

    
    ### OUTPUT RESULTS
    MKDir "C:\IntegrisPowerShell\REPORT-SharePointPreMigationCheck\Results\" -ErrorAction SilentlyContinue | Out-Null
    [string]$ExportPath = "C:\IntegrisPowerShell\REPORT-SharePointPreMigationCheck\Results\"
    $FileName = "SharePoint Pre-Migration Report - "
    $FileName += $StartDate.ToString("yyy_MM_dd h_mm_s")
    $FileName += ".csv"
    $ExportPath += $FileName
    $Results | Select-Object IssueFound, IssueDetails, ComputerName, FilePath | Export-CSV -Path $ExportPath

    RETURN $Results | Select-Object IssueFound, IssueDetails, ComputerName, FilePath
}
FUNCTION REPORT-SharePointRenameInvalidSpaceCharacter {
    
    param(
        [Parameter(Mandatory,ParameterSetName = 'Path')]
        [string[]]$Path = @(),

        [Parameter(Mandatory,ParameterSetName = 'AllShares')]
        [switch]$AllShares = $False,

        [switch]$Rename = $False
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    ### START
    $StartDate = GET-Date
    $Results = @()
    $Folders = @()
    $FolderCount = 0
    $CurrentFolderCount = 0
    $PercentComplete = 0
    $RenameResults = @()

    ## Check Function
    FUNCTION SharePointCheckFile {

        param (
       
            [Parameter(Mandatory)]
            [PSCustomObject]$File = ""
        )
        $TempResults = @()
             
        TRY {    
                IF ($File.Name.Substring(0,1) -eq " ") { 
                    $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                        ComputerName = $env:COMPUTERNAME
                        FilePath = $File.FullName
                        IssueFound = "Invalid File Name"
                        IssueDetails = "File Name Begins With a Space"
                    }     
                }
            }
        CATCH { }

        TRY {
                IF ($File.Name.Substring(($File.Name.Length-5),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-6),1) -eq " ") { 
                        $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
        CATCH { }
        
        TRY {
                IF ($File.Name.Substring(($File.Name.Length-4),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-5),1) -eq " ") { 
                        $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
        CATCH { }

        TRY {
                IF ($File.Name.Substring(($File.Name.Length-3),1) -eq ".") {
                    IF ($File.Name.Substring(($File.Name.Length-4),1) -eq " ") { 
                        $TempResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            ComputerName = $env:COMPUTERNAME
                            FilePath = $File.FullName
                            IssueFound = "Invalid File Name"
                            IssueDetails = "File Name Ends With a Space"
                        }
                    }  
                }
            }
        CATCH { }
   
        RETURN $TempResults
    }
    FUNCTION UpdateProgressBar {
        TRY { $PercentComplete = $CurrentFolderCount / $FolderCount * 100 } CATCH { }
         
        Write-Progress -ID 5 -Activity "Searching for Files Starting or Ending with a Space" -Status "Analyzing Folders $CurrentFolderCount of $FolderCount - $($Subfolder.FullName)" -PercentComplete $PercentComplete
    }

    Write-Progress -ID 5 -Activity "Performing SharePoint Migration Pre-Check" -Status "Initializing Analysis Process" -PercentComplete 0

    
    
    Write-Progress -ID 5 -Activity "Performing SharePoint Migration Pre-Check" -Status "Gathering Folder Data - This May Take a Couple Minutes" -PercentComplete 0
    #TRY { $EncryptedFiles = cipher /u /n /h } CATCH { }

    ### Gather Share Paths if AllShares
    IF ($AllShares -eq $True) {  
        $SMBShares = GET-CIMInstance -Class Win32_Share

        FOREACH ($SMBShare in $SMBShares) {

            ### SKIP THESE SHARES
            IF ($SMBShare.Name -eq "ADMIN$") { continue }
            IF ($SMBShare.Name -eq "IPC$") { continue }
            IF ($SMBShare.Name -eq "print$") { continue }
            IF ($SMBShare.Name -eq "SYSVOL") { continue }
            IF ($SMBShare.Name -eq "NETLOGON") { continue }
            IF ($SMBShare.Name -eq "Cache$") { continue }
            IF ($SMBShare.Name.Length -le 2) { continue }
            IF ($SMBShare.Name -eq "CertEnroll") { continue }
            IF ($SMBShare.Name -eq "print$") { continue }
            IF ($SMBShare.Path -like "*LocalsplOnly*") { continue }
            IF ($SMBShare.Name -eq "") { continue }
           
            $Path += $SMBShare.Path
        }
    }
        
    ### Get All Folders in Path
    FOREACH ($Item in $Path) {
        $Folders += Get-Item -Path $Item 
    }

    ### Count Folders
    FOREACH ($Folder in $Folders) {
        $FolderCount++
        FOREACH ($SubFolder in (Get-ChildItem -Path $Folder.FullName -Directory -Force -ErrorAction SilentlyContinue)) {
            $FolderCount++
        }
    }

    ### Process Files
    $FolderStartTime = Get-Date
    $CurrentFolderCount = 0
    FOREACH ($Folder in $Folders) {
        UpdateProgressBar
        FOREACH ($File in (Get-ChildItem -Path $Folder.FullName -File -Force -ErrorAction SilentlyContinue)) {
            TRY { IF ($File.Name.Substring(0,2) -eq "~$") { continue } } CATCH { }
            $Results += SharePointCheckFile -File $File
        }
        $CurrentFolderCount++
        FOREACH ($SubFolder in (Get-ChildItem -Path $Folder.FullName -Directory -Force -ErrorAction SilentlyContinue)) {
            UpdateProgressBar
            FOREACH ($File in (Get-ChildItem -Path $SubFolder.FullName -File -Recurse -Force -ErrorAction SilentlyContinue)) {
                TRY { IF ($File.Name.Substring(0,2) -eq "~$") { continue } } CATCH { }
                $Results += SharePointCheckFile -File $File
            }
            $CurrentFolderCount++
        }
    }

    Write-Progress -ID 5 -Activity "Performing SharePoint Migration Pre-Check" -Status "Analyzing Folders $CurrentFolderCount of $FolderCount - $($Subfolder.FullName)" -PercentComplete 100 -Completed
   
    FOREACH ($Result in $Results) {
        $FileNameArray = $Result.FilePath.Split('\')
        $FileName = $FileNameArray[$FileNameArray.Count-1]
        $OriginalFileName = $FileNameArray[$FileNameArray.Count-1]
        $OriginalFilePath = $Result.FilePath
        $NewFilePath = $OriginalFilePath.Replace($OriginalFileName,"") 

        ### Skip Stuff
        TRY { IF ($FileName.Substring(0,2) -eq "~$") { continue } } CATCH { }

        ### Space Only Name
        IF ($FileName.Split('.').Length -eq 2 -and ($FileName.Split('.'))[0] -eq " ") {
            $NewFileName = "BlankName."
            $NewFileName += ($FileName.Split('.'))[1]

            WHILE (GET-Item -Path ($NewFilePath+$NewFileName) -ErrorAction SilentlyContinue) { 
                $TempName = $NewFileName.Split('.')
                $NewFileName = $TempName[0]
                $NewFileName += "_Copy."
                $NewFileName += $TempName[1]
            }

            IF ($Rename -eq $true) {
                $ActionRequested = "Rename"
                Rename-Item -Path $Result.FilePath -NewName $NewFileName -ErrorAction SilentlyContinue
                                
                IF ((Get-Item -Path $Result.FilePath -ErrorAction SilentlyContinue) -ne $null) { $ActionStatus = "Failed" }
                ELSEIF ((Get-Item -Path $NewFilePath) -eq $null) { $ActionStatus = "Failed" }
                ELSE { $ActionStatus = "Success" }
            }
            ELSE {
                $ActionRequested = "Preview"
                $ActionStatus = "N/A"
            }

            $RenameResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                FilePath = $OriginalFilePath
                OriginalName = $OriginalFileName
                NewName = $NewFileName
                ActionRequested = $ActionRequested
                ActionStatus = $ActionStatus
            }
        }
        ### 2 Character File Extension (ex FileName .ai)
        ELSEIF (($FileName.Substring($FileName.Length-3,1)) -eq "." -and ($FileName.Substring($FileName.Length-4,1)) -eq " ") { 
            $TempFileName = $OriginalFileName
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $NewFileName = $TempFileName.Substring(0,$TempFileName.Length-4)
            $NewFileName += $TempFileName.Substring($TempFileName.Length-3)

            WHILE (GET-Item -Path ($NewFilePath+$NewFileName) -ErrorAction SilentlyContinue) { 
                $TempName = $NewFileName.Split('.')
                $NewFileName = $TempName[0]
                $NewFileName += "_Copy."
                $NewFileName += $TempName[1]
            }

            IF ($Rename -eq $true) {
                $ActionRequested = "Rename"
                Rename-Item -Path $Result.FilePath -NewName $NewFileName -ErrorAction SilentlyContinue
                                
                IF ((Get-Item -Path $Result.FilePath -ErrorAction SilentlyContinue) -ne $null) { $ActionStatus = "Failed" }
                ELSEIF ((Get-Item -Path ($NewFilePath+$NewFileName)) -eq $null) { $ActionStatus = "Failed" }
                ELSE { $ActionStatus = "Success" }
            }
            ELSE {
                $ActionRequested = "Preview"
                $ActionStatus = "N/A"
            }

            $RenameResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                FilePath = $OriginalFilePath
                OriginalName = $OriginalFileName
                NewName = $NewFileName
                ActionRequested = $ActionRequested
                ActionStatus = $ActionStatus
            }
        }
        ### 3 Character File Extension (ex FileName .txt)
        ELSEIF (($FileName.Substring($FileName.Length-4,1)) -eq "." -and ($FileName.Substring($FileName.Length-5,1)) -eq " ") { 
            $TempFileName = $OriginalFileName
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $NewFileName = $TempFileName.Substring(0,$TempFileName.Length-5)
            $NewFileName += $TempFileName.Substring($TempFileName.Length-4)

            WHILE (GET-Item -Path ($NewFilePath+$NewFileName) -ErrorAction SilentlyContinue) { 
                $TempName = $NewFileName.Split('.')
                $NewFileName = $TempName[0]
                $NewFileName += "_Copy."
                $NewFileName += $TempName[1]
            }

            IF ($Rename -eq $true) {
                $ActionRequested = "Rename"
                Rename-Item -Path $Result.FilePath -NewName $NewFileName -ErrorAction SilentlyContinue
                                
                IF ((Get-Item -Path $Result.FilePath -ErrorAction SilentlyContinue) -ne $null) { $ActionStatus = "Failed" }
                ELSEIF ((Get-Item -Path ($NewFilePath+$NewFileName)) -eq $null) { $ActionStatus = "Failed" }
                ELSE { $ActionStatus = "Success" }
            }
            ELSE {
                $ActionRequested = "Preview"
                $ActionStatus = "N/A"
            }
            
            $RenameResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                FilePath = $OriginalFilePath
                OriginalName = $OriginalFileName
                NewName = $NewFileName
                ActionRequested = $ActionRequested
                ActionStatus = $ActionStatus
            }
        }
        ### 4 Character File Extension (ex FileName .xlsx)
        ELSEIF (($FileName.Substring($FileName.Length-5,1)) -eq "." -and ($FileName.Substring($FileName.Length-6,1)) -eq " ") { 
            $TempFileName = $OriginalFileName
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $NewFileName = $TempFileName.Substring(0,$TempFileName.Length-6)
            $NewFileName += $TempFileName.Substring($TempFileName.Length-5)

            WHILE (GET-Item -Path ($NewFilePath+$NewFileName) -ErrorAction SilentlyContinue) { 
                $TempName = $NewFileName.Split('.')
                $NewFileName = $TempName[0]
                $NewFileName += "_Copy."
                $NewFileName += $TempName[1]
            }

            IF ($Rename -eq $true) {
                $ActionRequested = "Rename"
                Rename-Item -Path $Result.FilePath -NewName $NewFileName -ErrorAction SilentlyContinue
                                
                IF ((Get-Item -Path $Result.FilePath -ErrorAction SilentlyContinue) -ne $null) { $ActionStatus = "Failed" }
                ELSEIF ((Get-Item -Path ($NewFilePath+$NewFileName)) -eq $null) { $ActionStatus = "Failed" }
                ELSE { $ActionStatus = "Success" }
            }
            ELSE {
                $ActionRequested = "Preview"
                $ActionStatus = "N/A"
            }
            
            $RenameResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                FilePath = $OriginalFilePath
                OriginalName = $OriginalFileName
                NewName = $NewFileName
                ActionRequested = $ActionRequested
                ActionStatus = $ActionStatus
            }
        }
        ### 5 Character File Extension (ex FileName .3DXML)
        ELSEIF (($FileName.Substring($FileName.Length-6,1)) -eq "." -and ($FileName.Substring($FileName.Length-7,1)) -eq " ") { 
            $TempFileName = $OriginalFileName
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $NewFileName = $TempFileName.Substring(0,$TempFileName.Length-7)
            $NewFileName += $TempFileName.Substring($TempFileName.Length-6)

            WHILE (GET-Item -Path ($NewFilePath+$NewFileName) -ErrorAction SilentlyContinue) { 
                $TempName = $NewFileName.Split('.')
                $NewFileName = $TempName[0]
                $NewFileName += "_Copy."
                $NewFileName += $TempName[1]
            }

            IF ($Rename -eq $true) {
                $ActionRequested = "Rename"
                Rename-Item -Path $Result.FilePath -NewName $NewFileName -ErrorAction SilentlyContinue
                                
                IF ((Get-Item -Path $Result.FilePath -ErrorAction SilentlyContinue) -ne $null) { $ActionStatus = "Failed" }
                ELSEIF ((Get-Item -Path ($NewFilePath+$NewFileName)) -eq $null) { $ActionStatus = "Failed" }
                ELSE { $ActionStatus = "Success" }
            }
            ELSE {
                $ActionRequested = "Preview"
                $ActionStatus = "N/A"
            }
            
            $RenameResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                FilePath = $OriginalFilePath
                OriginalName = $OriginalFileName
                NewName = $NewFileName
                ActionRequested = $ActionRequested
                ActionStatus = $ActionStatus
            }
        }
        ### 6 Character File Extension (ex FileName .sldprt)
        ELSEIF (($FileName.Substring($FileName.Length-7,1)) -eq "." -and ($FileName.Substring($FileName.Length-8,1)) -eq " ") { 
            $TempFileName = $OriginalFileName
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $NewFileName = $TempFileName.Substring(0,$TempFileName.Length-8)
            $NewFileName += $TempFileName.Substring($TempFileName.Length-7)

            WHILE (GET-Item -Path ($NewFilePath+$NewFileName) -ErrorAction SilentlyContinue) { 
                $TempName = $NewFileName.Split('.')
                $NewFileName = $TempName[0]
                $NewFileName += "_Copy."
                $NewFileName += $TempName[1]
            }

            IF ($Rename -eq $true) {
                $ActionRequested = "Rename"
                Rename-Item -Path $Result.FilePath -NewName $NewFileName -ErrorAction SilentlyContinue
                                
                IF ((Get-Item -Path $Result.FilePath -ErrorAction SilentlyContinue) -ne $null) { $ActionStatus = "Failed" }
                ELSEIF ((Get-Item -Path ($NewFilePath+$NewFileName)) -eq $null) { $ActionStatus = "Failed" }
                ELSE { $ActionStatus = "Success" }
            }
            ELSE {
                $ActionRequested = "Preview"
                $ActionStatus = "N/A"
            }
            
            $RenameResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                FilePath = $OriginalFilePath
                OriginalName = $OriginalFileName
                NewName = $NewFileName
                ActionRequested = $ActionRequested
                ActionStatus = $ActionStatus
            }
        }
        ### 1st Character is Space
        ELSEIF ($FileName.Substring(0,1) -eq " ") { 
            $TempFileName = $OriginalFileName
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $TempFileName = $TempFileName.Replace(" "," ")
            $NewFileName = $TempFileName.Substring(1,$TempFileName.Length-1)

            WHILE (GET-Item -Path ($NewFilePath+$NewFileName) -ErrorAction SilentlyContinue) { 
                $TempName = $NewFileName.Split('.')
                $NewFileName = $TempName[0]
                $NewFileName += "_Copy."
                $NewFileName += $TempName[1]
            }

            IF ($Rename -eq $true) {
                $ActionRequested = "Rename"
                Rename-Item -Path $Result.FilePath -NewName $NewFileName -ErrorAction SilentlyContinue
                                
                IF ((Get-Item -Path $Result.FilePath -ErrorAction SilentlyContinue) -ne $null) { $ActionStatus = "Failed" }
                ELSEIF ((Get-Item -Path ($NewFilePath+$NewFileName)) -eq $null) { $ActionStatus = "Failed" }
                ELSE { $ActionStatus = "Success" }
            }
            ELSE {
                $ActionRequested = "Preview"
                $ActionStatus = "N/A"
            }

            $RenameResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                FilePath = $OriginalFilePath
                OriginalName = $OriginalFileName
                NewName = $NewFileName
                ActionRequested = $ActionRequested
                ActionStatus = $ActionStatus
            }
        }
        ELSE {
            $RenameResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                FilePath = $OriginalFilePath
                OriginalName = $OriginalFileName
                NewName = $NewFileName
                ActionRequested = "Preview"
                ActionStatus = "Failed"
            }
        }
    }
            
    ### OUTPUT RESULTS
    MKDir "C:\IntegrisPowerShell\REPORT-SharePointRenameInvalidSpaceCharacters\Results\" -ErrorAction SilentlyContinue | Out-Null
    [string]$ExportPath = "C:\IntegrisPowerShell\REPORT-SharePointRenameInvalidSpaceCharacters\Results\"
    $FileName = "SharePoint Invalid Space Character Report - "
    $FileName += $StartDate.ToString("yyy_MM_dd h_mm_s")
    $FileName += ".csv"
    $ExportPath += $FileName
    $RenameResults | Select-Object FilePath, OriginalName, NewName, ActionRequested, ActionStatus | Export-CSV -Path $ExportPath

    RETURN $RenameResults | Select-Object FilePath, OriginalName, NewName, ActionRequested, ActionStatus
}
FUNCTION REPORT-InternetPingMonitor {

    param(
        [int]$MonitorDurationInMinutes = 60
    )

    $ExportCSVIntervalMinutes = 5
    
    $Check = $null
    TRY { $Check = pwsh -c "Test-Connection -TargetName 127.0.0.1 -Count 1 -Timeout 1" }
    CATCH { Write-Warning "This module requires PowerShell 7 to be installed (You can run it in PowerShell 5, but PowerShell 7 must be installed)."
            Write-Warning "If you just installed PowerShell 7 you may need to reboot."; RETURN $Null }
    IF ($Check -clike "*Success*") { }
    ELSE { Write-Warning "This module requires PowerShell 7 to be installed (You can run it in PowerShell 5, but PowerShell 7 must be installed)."
           Write-Warning "If you just installed PowerShell 7 you may need to reboot." ; RETURN $Null }

    $Results = @()
    $MonitorStartTime = Get-Date
    $MonitorEndTime = $MonitorStartTime.AddMinutes($MonitorDurationInMinutes)
    $MonitorEndTime = $MonitorEndTime.AddSeconds(1)
    $Now = Get-Date
    $End = $Now.AddMinutes($MonitorDurationInMinutes) 

    $CloudFlare = ""
    $Quad9 = ""
    $Google =""
    $Microsoft = ""
    $CloudFlareLatency = ""
    $Quad9Latency = ""
    $GoogleLatency = ""
    $MicrosoftLatency = ""

    $NextExportTime = Get-Date
    $NextExportTime = $NextExportTime.AddMinutes($ExportCSVIntervalMinutes)
    $Count = 0
    $TotalCount = $MonitorDurationInMinutes * 60 / 5

    $LoopStartTime = Get-Date
    $NextLoopTime = $LoopStartTime
    WHILE ((Get-Date) -le $End -and $Count+1 -le $TotalCount) {
        $NextLoopTime = $NextLoopTime.AddSeconds(5)
        $Count++
        $PercentCompleted = $Count / $TotalCount * 100
        $PercentCompletedString = [math]::Round($PercentCompleted,2).ToString() + "%"

        $TimeRemaining = $MonitorEndTime - (Get-Date) 
        [int]$DaysLeft = [math]::floor($TimeRemaining.Days)
        [int]$HoursLeft = [math]::floor($TimeRemaining.Hours)
        [int]$MinutesLeft = [math]::floor($TimeRemaining.Minutes)
        [int]$SecondsLeft = [math]::floor($TimeRemaining.Seconds)
        $TimeRemainingString = $DaysLeft.ToString().Padleft(2,'0') + ":" + $HoursLeft.ToString().Padleft(2,'0') + ":" + $MinutesLeft.ToString().Padleft(2,'0') + ":" + $SecondsLeft.ToString().Padleft(2,'0')

        Write-Progress -ID 1 -Activity "Pinging" -Status "$PercentCompletedString - $Count of $TotalCount - Time Remaining: $TimeRemainingString" -PercentComplete $PercentCompleted

        $StartTime = Get-Date
        $EndTime = $StartTime.AddSeconds($InvervalInSeconds)  
        $PingTests = @()
        $ResultTime = Get-Date

        IF ($PSVersionTable.PSVersion.Major -eq 5) {
            $Job1 = Start-Job -ScriptBlock { pwsh -c Test-Connection -TargetName 1.1.1.1 -Count 1 -Timeout 3 -ErrorAction SilentlyContinue } 
            $Job2 = Start-Job -ScriptBlock { pwsh -c Test-Connection -TargetName 9.9.9.9 -Count 1 -Timeout 3 -ErrorAction SilentlyContinue }
            $Job3 = Start-Job -ScriptBlock { pwsh -c Test-Connection -TargetName Google.com -Count 1 -Timeout 3 -ErrorAction SilentlyContinue }
            $Job4 = Start-Job -ScriptBlock { pwsh -c Test-Connection -TargetName Microsoft.com -Count 1 -Timeout 3 -ErrorAction SilentlyContinue } 

            Start-Sleep -Seconds 3
            Start-Sleep -Milliseconds 500

            $CloudFlare = Receive-Job -Job $Job1
            $Quad9 = Receive-Job -Job $Job2
            $Google = Receive-Job -Job $Job3
            $Microsoft = Receive-Job -Job $Job4
    
            IF ($CloudFlare -clike "*Success*") { 
                $CloudFlareResult = "Success"

                [string]$CloudFlareLatency = $CloudFlare[6]
                $CloudFlareLatency = $CloudFlareLatency.Replace("$env:COMPUTERNAME","")
                $CloudFlareLatency = $CloudFlareLatency.Replace("$($env:COMPUTERNAME.ToLower())","")
                $CloudFlareLatency = $CloudFlareLatency.Replace("Success","")
                $CloudFlareLatency = $CloudFlareLatency.Substring(36,$CloudFlareLatency.Length-47)
                [int]$CloudFlareLatency = $CloudFlareLatency.Replace(" ","")
            }
            ELSE { $CloudFlareResult = "Timeout"; [string]$CloudFlareLatency = "Timeout" }
        
            IF ($Quad9 -clike "*Success*") { 
                $Quad9Result = "Success"

                [string]$Quad9Latency = $Quad9[6]
                $Quad9Latency = $Quad9Latency.Replace("$env:COMPUTERNAME","")
                $Quad9Latency = $Quad9Latency.Replace("$($env:COMPUTERNAME.ToLower())","")
                $Quad9Latency = $Quad9Latency.Replace("Success","")
                $Quad9Latency = $Quad9Latency.Substring(36,$Quad9Latency.Length-47)
                [int]$Quad9Latency = $Quad9Latency.Replace(" ","")
            } 
            ELSE { $Quad9Result = "Timeout"; [string]$Quad9Latency = "Timeout" }
       
            IF ($Google -clike "*Success*") { 
                $GoogleResult = "Success"

                [string]$GoogleLatency = $Google[6]
                $GoogleLatency = $GoogleLatency.Replace("$env:COMPUTERNAME","")
                $GoogleLatency = $GoogleLatency.Replace("$($env:COMPUTERNAME.ToLower())","")
                $GoogleLatency = $GoogleLatency.Replace("Success","")
                $GoogleLatency = $GoogleLatency.Substring(36,$GoogleLatency.Length-47)
                [int]$GoogleLatency = $GoogleLatency.Replace(" ","")
            }
            ELSEIF ($Google -eq $null) { $GoogleResult = "DNS Failure"; [string]$GoogleLatency = "N/A" } 
            ELSE { $GoogleResult = "Timeout"; [string]$GoogleLatency = "Timeout" }
        
            IF ($Microsoft -clike "*Success*") { 
                $MicrosoftResult = "Success"

                [string]$MicrosoftLatency = $Microsoft[6]
                $MicrosoftLatency = $MicrosoftLatency.Replace("$env:COMPUTERNAME","")
                $MicrosoftLatency = $MicrosoftLatency.Replace("$($env:COMPUTERNAME.ToLower())","")
                $MicrosoftLatency = $MicrosoftLatency.Replace("Success","")
                $MicrosoftLatency = $MicrosoftLatency.Substring(36,$MicrosoftLatency.Length-42)
                [int]$MicrosoftLatency = $MicrosoftLatency.Replace(" ","")
            } 
            ELSEIF ($Microsoft -eq $null) { $MicrosoftResult = "DNS Failure"; [string]$MicrosoftLatency = "N/A" } 
            ELSE { $MicrosoftResult = "Timeout"; [string]$MicrosoftLatency = "Timeout" }
        }

        IF ($PSVersionTable.PSVersion.Major -ge 6) {
            $Job1 = Start-Job -ScriptBlock { Test-Connection -TargetName 1.1.1.1 -Count 1 -Timeout 3 -ErrorAction SilentlyContinue } 
            $Job2 = Start-Job -ScriptBlock { Test-Connection -TargetName 9.9.9.9 -Count 1 -Timeout 3 -ErrorAction SilentlyContinue }
            $Job3 = Start-Job -ScriptBlock { Test-Connection -TargetName Google.com -Count 1 -Timeout 3 -ErrorAction SilentlyContinue }
            $Job4 = Start-Job -ScriptBlock { Test-Connection -TargetName Microsoft.com -Count 1 -Timeout 3 -ErrorAction SilentlyContinue } 

            Start-Sleep -Seconds 3
            Start-Sleep -Milliseconds 500

            $CloudFlare = Receive-Job -Job $Job1
            $Quad9 = Receive-Job -Job $Job2
            $Google = Receive-Job -Job $Job3
            $Microsoft = Receive-Job -Job $Job4

            IF ($CloudFlare.Status -eq "Success") { 
                $CloudFlareResult = "Success"
                [int]$CloudFlareLatency = $CloudFlare.Latency
            }
            ELSE { [string]$CloudFlareResult = "Timeout"; [string]$CloudFlareLatency = "Timeout" }
        
            IF ($Quad9.Status -eq "Success") { 
                $Quad9Result = "Success"
                [int]$Quad9Latency = $Quad9.Latency
            } 
            ELSE { [string]$Quad9Result = "Timeout"; [string]$Quad9Latency = "Timeout" }
       
            IF ($Google.Status -eq "Success") { 
                $GoogleResult = "Success"
                [int]$GoogleLatency = $Google.Latency
            }
            ELSEIF ($Google -eq $null) { $GoogleResult = "DNS Failure"; $GoogleLatency = "Timeout" } 
            ELSE { [string]$GoogleResult = "Timeout"; [string]$GoogleLatency = "Timeout" }
        
            IF ($Microsoft.Status -eq "Success") { 
                $MicrosoftResult = "Success"
                [int]$MicrosoftLatency = $Microsoft.Latency
            } 
            ELSEIF ($Microsoft -eq $null) { $MicrosoftResult = "DNS Failure"; $MicrosoftLatency = "Timeout" } 
            ELSE { [string]$MicrosoftResult = "Timeout"; [string]$MicrosoftLatency = "Timeout" }
        }
                
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            ResultTime = $ResultTime
            CloudFlareResult = $CloudFlareResult
            CloudFlareLatency = $CloudFlareLatency
            Quad9Result = $Quad9Result
            Quad9Latency = $Quad9Latency
            GoogleResult = $GoogleResult
            GoogleLatency = $GoogleLatency
            MicrosoftResult = $MicrosoftResult
            MicrosoftLatency = $MicrosoftLatency
        }
        
        IF ((Get-Date) -gt $NextExportTime) {
            $NextExportTime = $NextExportTime.AddMinutes($ExportCSVIntervalMinutes)

            MKDir "C:\IntegrisPowerShell\REPORT-InternetPingMonitor\Results\" -ErrorAction SilentlyContinue | Out-Null
            [string]$ExportPath = "C:\IntegrisPowerShell\REPORT-InternetPingMonitor\Results\"
            $FileName = "Network Ping Monitor Report - "
            $FileName += $MonitorStartTime.ToString("yyy_MM_dd h_mm_s")
            $FileName += ".csv"
            $ExportPath += $FileName

            $Results | Select ResultTime, CloudFlareLatency, CloudFlareResult, Quad9Latency, Quad9Result, GoogleLatency, GoogleResult, MicrosoftLatency, MicrosoftResult | Export-Csv -Path $ExportPath
        }

        WHILE ((Get-Date) -le $NextLoopTime) { Sleep -Milliseconds 100 }
    }

    MKDir "C:\IntegrisPowerShell\REPORT-InternetPingMonitor\Results\" -ErrorAction SilentlyContinue | Out-Null
    [string]$ExportPath = "C:\IntegrisPowerShell\REPORT-InternetPingMonitor\Results\"
    $FileName = "Network Ping Monitor Report - "
    $FileName += $MonitorStartTime.ToString("yyy_MM_dd h_mm_s")
    $FileName += ".csv"
    $ExportPath += $FileName
    $Results | Select ResultTime, CloudFlareLatency, CloudFlareResult, Quad9Latency, Quad9Result, GoogleLatency, GoogleResult, MicrosoftLatency, MicrosoftResult | Export-Csv -Path $ExportPath
    
    Write-Progress -ID 1 -Activity "Pinging" -Completed
    RETURN $Results | Select ResultTime, CloudFlareLatency, CloudFlareResult, Quad9Latency, Quad9Result, GoogleLatency, GoogleResult, MicrosoftLatency, MicrosoftResult
}
FUNCTION REPORT-InternetSpeedTestMonitor {

    param(
        [int]$IntervalMinutes = 15,
        [int]$NumberOfTests = 8
    )

    $Results = @()    
    $TestCount = 1
    $StartTime = Get-Date
    $NextTestStartTime = $StartTime
    Write-Progress -ID 4 -Activity "SpeedTest" -Status "Starting Speed Test" -PercentComplete 0


    $EndTime = (Get-Date).AddMinutes($IntervalMinutes * ($NumberOfTests - 1))
    $EndTime = $EndTime.AddSeconds(30)

    $TotalTimeInterval = $EndTime - (Get-Date)
    $TotalDaysLeft = [Math]::Abs($TotalTimeInterval.Days)
    $TotalHoursLeft = [Math]::Abs($TotalTimeInterval.Hours)
    $TotalMinutesLeft = [Math]::Abs($TotalTimeInterval.Minutes)
    $TotalSecondsLeft = [Math]::Abs($TotalTimeInterval.Seconds)
    $TotalTimeRemainingString = $TotalDaysLeft.ToString().Padleft(2,'0') + ":" + $TotalHoursLeft.ToString().Padleft(2,'0') + ":" + $TotalMinutesLeft.ToString().Padleft(2,'0') + ":" + $TotalSecondsLeft.ToString().Padleft(2,'0')
    
            

    WHILE ($TestCount -lt ($NumberOfTests+1)) {
        $NextTestStartTime = $NextTestStartTime.AddMinutes($IntervalMinutes)
        
        $TestTime = GET-Date

        $PercentComplete = ($TestCount - 1) / $NumberOfTests * 100
        Write-Progress -ID 4 -Activity "SpeedTest" -Status "Running Speed Test - Estimated Time Remaining: $TotalTimeRemainingString" -PercentComplete $PercentComplete
        $SpeedTest = REPORT-ComputerPerformance -Category Internet
    
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            TestCount = $TestCount
            TestTime = $TestTime
            DownloadSpeed = ($SpeedTest | Where-Object { $_.PerformanceItem -eq "Download Speed" }).PerformanceResult
            DownloadLatencyAvg = ($SpeedTest | Where-Object { $_.PerformanceItem -eq "Download Latency (Avg)" }).PerformanceResult
            DownloadLatencyHigh = ($SpeedTest | Where-Object { $_.PerformanceItem -eq "Download Latency (High)" }).PerformanceResult
            UploadSpeed = ($SpeedTest | Where-Object { $_.PerformanceItem -eq "Upload Speed" }).PerformanceResult
            UploadSpeedAvg = ($SpeedTest | Where-Object { $_.PerformanceItem -eq "Upload Latency (Avg)" }).PerformanceResult
            UploadSpeedHigh = ($SpeedTest | Where-Object { $_.PerformanceItem -eq "Upload Latency (High)" }).PerformanceResult
            PacketLoss = ($SpeedTest | Where-Object { $_.PerformanceItem -eq "Packet Loss" }).PerformanceResult
        }
        $TestCount++
        $PercentComplete = ($TestCount - 1) / $NumberOfTests * 100

        MKDir "C:\IntegrisPowerShell\REPORT-InternetSpeedTestMonitor\Results\" -ErrorAction SilentlyContinue | Out-Null
        [string]$ExportPath = "C:\IntegrisPowerShell\REPORT-InternetSpeedTestMonitor\Results\"
        $FileName = "SpeedTest Monitor Report - "
        $FileName += $StartTime.ToString("yyy_MM_dd h_mm_s")
        $FileName += ".csv"
        $ExportPath += $FileName
        $Results | Select TestCount, TestTime, DownloadSpeed, DownloadLatencyAvg, DownloadLatencyHigh, UploadSpeed, UploadSpeedAvg, UploadSpeedHigh, PacketLoss | Export-Csv -Path $ExportPath
    

        IF ($TestCount -eq ($NumberOfTests+1)) { break }
        WHILE ((Get-Date) -lt $NextTestStartTime) { 
            $TimeInterval = $NextTestStartTime - (Get-Date)
            $DaysLeft = [Math]::Abs($TimeInterval.Days)
            $HoursLeft = [Math]::Abs($TimeInterval.Hours)
            $MinutesLeft = [Math]::Abs($TimeInterval.Minutes)
            $SecondsLeft = [Math]::Abs($TimeInterval.Seconds)
            $TimeRemainingString = $DaysLeft.ToString().Padleft(2,'0') + ":" + $HoursLeft.ToString().Padleft(2,'0') + ":" + $MinutesLeft.ToString().Padleft(2,'0') + ":" + $SecondsLeft.ToString().Padleft(2,'0')
            
            $TotalTimeInterval = $EndTime - (Get-Date)
            $TotalDaysLeft = [Math]::Abs($TotalTimeInterval.Days)
            $TotalHoursLeft = [Math]::Abs($TotalTimeInterval.Hours)
            $TotalMinutesLeft = [Math]::Abs($TotalTimeInterval.Minutes)
            $TotalSecondsLeft = [Math]::Abs($TotalTimeInterval.Seconds)
            $TotalTimeRemainingString = $TotalDaysLeft.ToString().Padleft(2,'0') + ":" + $TotalHoursLeft.ToString().Padleft(2,'0') + ":" + $TotalMinutesLeft.ToString().Padleft(2,'0') + ":" + $TotalSecondsLeft.ToString().Padleft(2,'0')
   

            Write-Progress -ID 4 -Activity "SpeedTest" -Status "Waiting to Start Next SpeedTest - Next Test: $TimeRemainingString - Estimated Time Remaining: $TotalTimeRemainingString" -PercentComplete $PercentComplete
            Start-Sleep -Seconds 1

        }
    }
    Write-Progress -ID 4 -Activity "SpeedTest" -Status "Running Speed Test" -PercentComplete 100 -Completed
    

    
    MKDir "C:\IntegrisPowerShell\REPORT-InternetSpeedTestMonitor\Results\" -ErrorAction SilentlyContinue | Out-Null
    [string]$ExportPath = "C:\IntegrisPowerShell\REPORT-InternetSpeedTestMonitor\Results\"
    $FileName = "SpeedTest Monitor Report - "
    $FileName += $StartTime.ToString("yyy_MM_dd h_mm_s")
    $FileName += ".csv"
    $ExportPath += $FileName
    $Results | Select TestCount, TestTime, DownloadSpeed, DownloadLatencyAvg, DownloadLatencyHigh, UploadSpeed, UploadSpeedAvg, UploadSpeedHigh, PacketLoss | Export-Csv -Path $ExportPath
    
    RETURN $Results | Select TestCount, TestTime, DownloadSpeed, DownloadLatencyAvg, DownloadLatencyHigh, UploadSpeed, UploadSpeedAvg, UploadSpeedHigh, PacketLoss
}

### ### ==============================================================================================
### ### SEARCH\REPORT EXPORTS Import
### ### ==============================================================================================

New-Alias -Name INTSEARCH-EventLog -Value SEARCH-EventLog
Export-ModuleMember -FUNCTION SEARCH-EventLog -Alias INTSEARCH-EventLog

New-Alias -Name INTSEARCH-AppData -Value SEARCH-AppData
Export-ModuleMember -FUNCTION SEARCH-AppData -Alias INTSEARCH-AppData

New-Alias -Name INTREPORT-ComputerPerformance -Value REPORT-ComputerPerformance
New-Alias -Name REPORT-PCPerformance -Value REPORT-ComputerPerformance
New-Alias -Name INTREPORT-PCComputerPerformance -Value REPORT-ComputerPerformance
Export-ModuleMember -FUNCTION REPORT-ComputerPerformance -Alias INTREPORT-ComputerPerformance,REPORT-PCPerformance,INTREPORT-PCPerformance

New-Alias -Name INTREPORT-PCSummary -Value REPORT-ComputerSummary
New-Alias -Name REPORT-PCSummary -Value REPORT-ComputerSummary
New-Alias -Name INTREPORT-ComputerSummary -Value REPORT-ComputerSummary
Export-ModuleMember -FUNCTION REPORT-ComputerSummary -Alias INTREPORT-ComputerSummary,REPORT-PCSummary,INTREPORT-PCSummary

New-Alias -Name INTREPORT-NTFSPermission -Value REPORT-NTFSPermission
Export-ModuleMember -FUNCTION REPORT-NTFSPermission -Alias INTREPORT-NTFSPermission

New-Alias -Name INTREPORT-ADGroupMembership -Value REPORT-ADGroupMembership
Export-ModuleMember -FUNCTION REPORT-ADGroupMembership -Alias INTREPORT-ADGroupMembership

New-Alias -Name INTREPORT-ADUser -Value REPORT-ADUser
Export-ModuleMember -FUNCTION REPORT-ADUser -Alias INTREPORT-ADUser

New-Alias -Name INTREPORT-SMBShareDataTemp -Value REPORT-SMBShareDataTemp
Export-ModuleMember -FUNCTION REPORT-SMBShareDataTemp -Alias INTREPORT-SMBShareDataTemp

New-Alias -Name INTREPORT-SharePointPreMigationCheck -Value REPORT-SharePointPreMigationCheck
Export-ModuleMember -FUNCTION REPORT-SharePointPreMigationCheck -Alias INTREPORT-SharePointPreMigationCheck

New-Alias -Name INTREPORT-SharePointRenameInvalidSpaceCharacter -Value REPORT-SharePointRenameInvalidSpaceCharacter
Export-ModuleMember -FUNCTION REPORT-SharePointRenameInvalidSpaceCharacter -Alias INTREPORT-SharePointRenameInvalidSpaceCharacter

New-Alias -Name INTREPORT-InternetPingMonitor -Value REPORT-InternetPingMonitor
Export-ModuleMember -FUNCTION REPORT-InternetPingMonitor -Alias INTREPORT-InternetPingMonitor

New-Alias -Name INTREPORT-InternetSpeedTestMonitor -Value REPORT-InternetSpeedTestMonitor
Export-ModuleMember -FUNCTION REPORT-InternetSpeedTestMonitor -Alias INTREPORT-InternetSpeedTestMonitor

### ### ==============================================================================================
### ### DISK CLEANUP FUNCTIONS
### ### ==============================================================================================

FUNCTION CLEANUP-VolumeSystem {
    
    param(
        [int[]]$FreeSpaceThreshold = @(60,50,50,40,40,40,40,35,30,25,25,25,25)
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    $Results = @()

    $StartSpace = GET-OSDiskFreeSpace 

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Windows Apps" -PercentComplete 0
    $Results += CLEANUP-WindowsAppClutter -FreeSpaceThreshold $FreeSpaceThreshold[0]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Ninite Data" -PercentComplete 4
    $Results += CLEANUP-NiniteTempData -FreeSpaceThreshold $FreeSpaceThreshold[1]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Dell Data" -PercentComplete 8
    $Results += CLEANUP-DellData -FreeSpaceThreshold $FreeSpaceThreshold[2]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Windows Temp Files" -PercentComplete 12
    $Results += CLEANUP-WindowsTempLogs -FreeSpaceThreshold $FreeSpaceThreshold[3]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Old Downloads" -PercentComplete 16
    $Results += CLEANUP-ClearOldDownloads -FreeSpaceThreshold $FreeSpaceThreshold[4]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Recycle Bin" -PercentComplete 20
    $Results += CLEANUP-ClearRecycleBin -FreeSpaceThreshold $FreeSpaceThreshold[5]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning ShadowStorage" -PercentComplete 24
    $Results += CLEANUP-ShadowStorage -FreeSpaceThreshold $FreeSpaceThreshold[6]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Office Updates" -PercentComplete 28
    $Results += CLEANUP-OfficeUpdateFolder -FreeSpaceThreshold $FreeSpaceThreshold[7] 

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Clean PageFile" -PercentComplete 32
    $Results += CLEANUP-PageFile -FreeSpaceThreshold $FreeSpaceThreshold[8]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Hiberation Files" -PercentComplete 36
    $Results += CLEANUP-Hibernation -FreeSpaceThreshold $FreeSpaceThreshold[9]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Outlook Files" -PercentComplete 40
    $Results += CLEANUP-MailboxCaching -FreeSpaceThreshold $FreeSpaceThreshold[10]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Cleaning Windows Installer Folder" -PercentComplete 44
    $Results += CLEANUP-WindowsInstallerFolder -FreeSpaceThreshold $FreeSpaceThreshold[11]

    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Running CleanMgr.exe - About 90 Seconds" -PercentComplete 100
    $Results += CLEANUP-CleanMgr -FreeSpaceThreshold $FreeSpaceThreshold[12]

    $EndSpace = GET-OSDiskFreeSpace
    
    $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
    $SpaceFreed = [math]::round($FreedSpace,2).ToString() + " GBs" 

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Total" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = ""
        ActionTaken = ""
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }
    Write-Progress -ID 6 -Activity "Running Disk Cleanup" -Status "Done" -PercentComplete 100 -Completed
    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
}

New-Alias -Name INTCLEANUP-VolumeSystem -Value CLEANUP-VolumeSystem
Export-ModuleMember -FUNCTION CLEANUP-VolumeSystem -Alias INTCLEANUP-VolumeSystem

### ### ==============================================================================================
### ### DISK CLEANUP HELPER FUNCTIONS
### ### ==============================================================================================

FUNCTION CLEANUP-CleanMgr {

    param(
        [int]$FreeSpaceThreshold = 60
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }
    
    FUNCTION SET-RegistryValueForAllUsers { 
    <#
    .SYNOPSIS
        This FUNCTION uses Active Setup to create a "seeder" key which creates or modifies a user-based registry value
        for all users on a computer. If the key path doesn't exist to the value, it will automatically create the key and add the value.
    .EXAMPLE
        PS> SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Setting'; 'Type' = 'String'; 'Value' = 'someval'; 'Path' = 'SOFTWARE\Microsoft\Windows\Something'}
      
        This example would modify the string registry value 'Type' in the path 'SOFTWARE\Microsoft\Windows\Something' to 'someval'
        for every user registry hive.
    .PARAMETER RegistryInstance
         A hash table containing key names of 'Name' designating the registry value name, 'Type' to designate the type
        of registry value which can be 'String,Binary,Dword,ExpandString or MultiString', 'Value' which is the value itself of the
        registry value and 'Path' designating the parent registry key the registry value is in.
    #>
 
    [CmdletBinding()] 
    param ( 
        [Parameter(Mandatory=$True)] 
        [hashtable[]]$RegistryInstance 
    ) 
    try { 
        New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null 
         
        ## Change the registry values for the currently logged on user. Each logged on user SID is under HKEY_USERS
        $LoggedOnSids = (GET-ChildItem HKU: | where { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' }).PSChildName 
        Write-Host "Found $($LoggedOnSids.Count) logged on user SIDs" 
        foreach ($sid in $LoggedOnSids) { 
            Write-Host -Message "Loading the user registry hive for the logged on SID $sid" 
            foreach ($instance in $RegistryInstance) { 
                ## Create the key path if it doesn't exist
                New-Item -ErrorAction SilentlyContinue -Path ("HKU:\$sid\$($instance.Path)" | Split-Path -Parent) -Name ("HKU:\$sid\$($instance.Path)" | Split-Path -Leaf) | Out-Null
                ## Create (or modify) the value specified in the param
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office"
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0"
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0\Outlook"
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode"

                SET-ItemProperty -Path "HKU:\$sid\$($instance.Path)" -Name $instance.Name -Value $instance.Value -Type $instance.Type -Force 
            } 
        } 
         
        ## Create the Active Setup registry key so that the reg add cmd will get ran for each user
        ## logging into the machine.
        ## http://www.itninja.com/blog/view/an-active-setup-primer
        Write-Host "Setting Active Setup registry value to apply to all other users" 
        foreach ($instance in $RegistryInstance) { 
            ## Generate a unique value (usually a GUID) to use for Active Setup
            $Guid = [guid]::NewGuid().Guid 
            $ActiveSetupRegParentPath = 'HKLM:\Software\Microsoft\Active Setup\Installed Components' 
            ## Create the GUID registry key under the Active Setup key
            New-Item -Path $ActiveSetupRegParentPath -Name $Guid | Out-Null 
            $ActiveSetupRegPath = "HKLM:\Software\Microsoft\Active Setup\Installed Components\$Guid" 
            Write-Host "Using registry path '$ActiveSetupRegPath'" 
             
            ## Convert the registry value type to one that reg.exe can understand. This will be the
            ## type of value that's created for the value we want to set for all users
            switch ($instance.Type) { 
                'String' { 
                    $RegValueType = 'REG_SZ' 
                } 
                'Dword' { 
                    $RegValueType = 'REG_DWORD' 
                } 
                'Binary' { 
                    $RegValueType = 'REG_BINARY' 
                } 
                'ExpandString' { 
                    $RegValueType = 'REG_EXPAND_SZ' 
                } 
                'MultiString' { 
                    $RegValueType = 'REG_MULTI_SZ' 
                } 
                default { 
                    throw "Registry type '$($instance.Type)' not recognized" 
                } 
            } 
             
            ## Build the registry value to use for Active Setup which is the command to create the registry value in all user hives
            $ActiveSetupValue = "reg add `"{0}`" /v {1} /t {2} /d {3} /f" -f "HKCU\$($instance.Path)", $instance.Name, $RegValueType, $instance.Value 
            Write-Host -Message "Active setup value is '$ActiveSetupValue'" 
            ## Create the necessary Active Setup registry values
            SET-ItemProperty -Path $ActiveSetupRegPath -Name '(Default)' -Value 'Active Setup Test' 
            SET-ItemProperty -Path $ActiveSetupRegPath -Name 'Version' -Value '1' 
            SET-ItemProperty -Path $ActiveSetupRegPath -Name 'StubPath' -Value $ActiveSetupValue
        } 
    } catch { 
        Write-Warning -Message $_.Exception.Message 
    } 
}

    $GBsFreeSpace = GET-OSDiskFreeSpace
    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $StartSpace = GET-OSDiskFreeSpace
        $results = GET-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches
        $Reset=$False
        FOREACH($result in $results) {
            IF($Reset -eq $False) {
                #this is what is RETURNed in $result.name:
                #HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\<some name>
                #change HKEY_LOCAL_MACHINE to HKLM:
            
                IF($Downloads -eq $False -and $result.name -eq "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\DownloadsFolder") { }
                ELSE {
                    $tmp = 'HKLM:' + $result.Name.Substring( 18 )
                    $tmp2 = $result.Name.SubString( $result.Name.LastIndexOf( '\' ) + 1 )
                    #Write-Host "Setting $tmp2 to 2"
                    $null = New-ItemProperty -Path $tmp -Name 'StateFlags0001' -Value 2 -PropertyType DWORD -Force -EA 0 | Out-Null
                
                    If(!$?) { Write-Warning "`tUnable to set $tmp2" }
                }
            }
            ELSEIF ($Reset -eq $True) {
                $tmp = 'HKLM:' + $result.Name.Substring( 18 )
                $tmp2 = $result.Name.SubString( $result.Name.LastIndexOf( '\' ) + 1 )
                #Write-Host "Resetting $tmp2 to 0"
                $null = New-ItemProperty -Path $tmp -Name 'StateFlags0001' -Value 0 -PropertyType DWORD -Force -EA 0 | Out-Null
            
                IF(!$?) { Write-Warning "`tUnable to set $tmp2" }
            }
        }
        cleanmgr /sagerun:1 | Out-Null
        
        
        Start-Sleep -Seconds 60
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = [Math]::Round($FreedSpace,2).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $OutResults += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "CleanMgr.exe Cleanup" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $OutResults | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
 
}
FUNCTION CLEANUP-WindowsAppClutter {
    
    param(
        [int]$FreeSpaceThreshold = 60
    )
    $Results = @()
    
    $GBsFreeSpace = GET-OSDiskFreeSpace

    IF (ErrorCheck-AdministratorElevation) { RETURN }
    
    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {        
        $StartSpace = GET-OSDiskFreeSpace
        $Now = GET-Date
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*xbox*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*disney*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*netflix*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue 
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*warships*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*yourphone*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*candy*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*office.desktop*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*skype*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*zune*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*bing*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*print3d*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*mixedreality*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*feedback*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*solitaire*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*office.onenote*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*minecraft*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*marchofempires*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*bubblewitch*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*cookings*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*candy*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*whiteboard*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*HiddenCity*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*MysteryofShadow*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Mahjong*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Facebook*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*King.com*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Bingo*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*KeeperS*" } -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
            
                      
        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*HPPrinterControl*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Microsoft.Todos*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Microsoft.Windows.Photos*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*microsoft.windowscommunicationsapps*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*HPPrinterControl*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*AppUp.IntelManagement*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Microsoft.MicrosoftEdge.Stable*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*HPPrinterControl*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Microsoft.NET.Native.Framework*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Microsoft.NET.Native.Runtime*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }

        $Items = GET-ChildItem -Path "C:\Program Files\WindowsApps" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*Microsoft.UI.Xaml*" } -ErrorAction SilentlyContinue
        IF ($Items.Count -gt 1) { $Items | Sort CreationTime -Descending | Select -Last ($Items.Count-1) | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
                
        $EndSpace = GET-OSDiskFreeSpace
        [int]$FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        
        $SpaceFreed = ([Math]::Round($FreedSpace,2)).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Windows Apps" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
 }
FUNCTION CLEANUP-NiniteTempData {

    param(
        [int]$FreeSpaceThreshold = 50
    )
    $GBsFreeSpace  = GET-OSDiskFreeSpace

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $Now = GET-Date
        $Time = $Now.AddDays(-360)
        $StartSpace = GET-OSDiskFreeSpace
        GET-ChildItem -Path "C:\Windows\LTSvc\packages" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*DiskSpeedTest*" } | Remove-Item -Recurse -Force
        GET-ChildItem -Path "C:\Windows\LTSvc\packages" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*MITPSpeedTest*" } | Remove-Item -Recurse -Force
        GET-ChildItem -Path "C:\Windows\LTSvc\packages\MP\Ninite" -Directory -ErrorAction SilentlyContinue | where { $_.Name -like "*NiniteDownloads*" } | Remove-Item -Recurse -Force
        GET-Item -Path "C:\BJN" -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = ([Math]::Round($FreedSpace,2)).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Ninite Temp Data" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
 }
FUNCTION CLEANUP-DellData {

    param(
        [int]$FreeSpaceThreshold = 50
    )
    $GBsFreeSpace  = GET-OSDiskFreeSpace

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $Now = GET-Date
        $Time = $Now.AddDays(-360)
        $StartSpace = GET-OSDiskFreeSpace
        GET-Item -Path "C:\Windows\Internet Logs"  -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        GET-Item -Path "C:\ProgramData\Dell\SARemediation"  -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = ([Math]::Round($FreedSpace,2)).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Dell Data" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
 }
FUNCTION CLEANUP-WindowsTempLogs {

    param(
        [int]$FreeSpaceThreshold = 40
    )
    $GBsFreeSpace  = GET-OSDiskFreeSpace

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $Now = GET-Date
        $StartSpace = GET-OSDiskFreeSpace
        
        Get-ChildItem -Path C:\Windows\Temp -Name "*.evtx" | Remove-Item -Force -ErrorAction SilentlyContinue


        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = ([Math]::Round($FreedSpace,2)).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Windows Temp Logs" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
 }
FUNCTION CLEANUP-ClearOldDownloads {

    param(
        [int]$FreeSpaceThreshold = 40,
        [int]$DaysOldThreshold = 60
    )
    $GBsFreeSpace  = GET-OSDiskFreeSpace

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $Now = GET-Date
        $Time = $Now.AddDays(-$DaysOldThreshold)
        $StartSpace = GET-OSDiskFreeSpace
        $Users = GET-ChildItem -Path "C:\Users\" -Directory 
        FOREACH ($User in $Users) {    
            $Dir = "C:\Users\"
            $Dir += $User.Name
            $Dir += "\Downloads"
            $Items = GET-ChildItem -Path $Dir -Recurse -ErrorAction SilentlyContinue | Where { $_.LastWriteTime -lt $Time } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        }
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = ([Math]::Round($FreedSpace,2)).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Old Downloads" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
 }
FUNCTION CLEANUP-ClearRecycleBin {

    param(
        [int]$FreeSpaceThreshold = 40
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    $GBsFreeSpace  = GET-OSDiskFreeSpace

    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $Now = GET-Date
        $Time = $Now.AddDays(-$DaysOldThreshold)
        $StartSpace = GET-OSDiskFreeSpace
        

        Clear-RecycleBin -DriveLetter C: -Force -ErrorAction SilentlyContinue
        GET-ChildItem -Path 'C:\$Recycle.Bin' -Force | Remove-Item -Recurse -ErrorAction SilentlyContinue


        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = [Math]::Round($FreedSpace,2).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Recycle Bin" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
 }
FUNCTION CLEANUP-ShadowStorage {
    param(
        [int]$FreeSpaceThreshold = 40
    )
    $GBsFreeSpace = GET-OSDiskFreeSpace

    IF (ErrorCheck-AdministratorElevation) { RETURN }
    
    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $StartSpace = GET-OSDiskFreeSpace
        vssadmin resize shadowstorage /For=C: /On=C: /MaxSize=10% | Out-Null
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = [Math]::Round($FreedSpace,2).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "VSS Shadow Storage" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
}
FUNCTION CLEANUP-Hibernation {
    param(
        [int]$FreeSpaceThreshold = 25
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }
    
    $GBsFreeSpace = GET-OSDiskFreeSpace
    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $StartSpace = GET-OSDiskFreeSpace
        PowerCFG /H Off
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = [Math]::Round($FreedSpace,2).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Disable Hibernation" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
}
FUNCTION CLEANUP-MailboxCaching {

    param(
        [int]$FreeSpaceThreshold = 25,
        [int]$UserThreshold = 3
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    FUNCTION SET-RegistryValueForAllUsers { 
    [CmdletBinding()] 
    param ( 
        [Parameter(Mandatory=$True)] 
        [hashtable[]]$RegistryInstance 
    ) 
    try { 
        New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null 
         
        ## Change the registry values for the currently logged on user. Each logged on user SID is under HKEY_USERS
        $LoggedOnSids = (GET-ChildItem HKU: | where { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' }).PSChildName 
        Write-Host "Found $($LoggedOnSids.Count) logged on user SIDs" 
        foreach ($sid in $LoggedOnSids) { 
            Write-Host -Message "Loading the user registry hive for the logged on SID $sid" 
            foreach ($instance in $RegistryInstance) { 
                ## Create the key path if it doesn't exist
                New-Item -ErrorAction SilentlyContinue -Path ("HKU:\$sid\$($instance.Path)" | Split-Path -Parent) -Name ("HKU:\$sid\$($instance.Path)" | Split-Path -Leaf) | Out-Null
                ## Create (or modify) the value specified in the param
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office" | Out-Null
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0" | Out-Null
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0\Outlook" | Out-Null
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode" | Out-Null

                SET-ItemProperty -Path "HKU:\$sid\$($instance.Path)" -Name $instance.Name -Value $instance.Value -Type $instance.Type -Force 
            } 
        } 
         
        ## Create the Active Setup registry key so that the reg add cmd will get ran for each user
        ## logging into the machine.
        ## http://www.itninja.com/blog/view/an-active-setup-primer
        Write-Host "Setting Active Setup registry value to apply to all other users" 
        foreach ($instance in $RegistryInstance) { 
            ## Generate a unique value (usually a GUID) to use for Active Setup
            $Guid = [guid]::NewGuid().Guid 
            $ActiveSetupRegParentPath = 'HKLM:\Software\Microsoft\Active Setup\Installed Components' 
            ## Create the GUID registry key under the Active Setup key
            New-Item -Path $ActiveSetupRegParentPath -Name $Guid | Out-Null 
            $ActiveSetupRegPath = "HKLM:\Software\Microsoft\Active Setup\Installed Components\$Guid" 
            Write-Host "Using registry path '$ActiveSetupRegPath'" 
             
            ## Convert the registry value type to one that reg.exe can understand. This will be the
            ## type of value that's created for the value we want to set for all users
            switch ($instance.Type) { 
                'String' { 
                    $RegValueType = 'REG_SZ' 
                } 
                'Dword' { 
                    $RegValueType = 'REG_DWORD' 
                } 
                'Binary' { 
                    $RegValueType = 'REG_BINARY' 
                } 
                'ExpandString' { 
                    $RegValueType = 'REG_EXPAND_SZ' 
                } 
                'MultiString' { 
                    $RegValueType = 'REG_MULTI_SZ' 
                } 
                default { 
                    throw "Registry type '$($instance.Type)' not recognized" 
                } 
            } 
             
            ## Build the registry value to use for Active Setup which is the command to create the registry value in all user hives
            $ActiveSetupValue = "reg add `"{0}`" /v {1} /t {2} /d {3} /f" -f "HKCU\$($instance.Path)", $instance.Name, $RegValueType, $instance.Value 
            Write-Host -Message "Active setup value is '$ActiveSetupValue'" 
            ## Create the necessary Active Setup registry values
            SET-ItemProperty -Path $ActiveSetupRegPath -Name '(Default)' -Value 'Active Setup Test' 
            SET-ItemProperty -Path $ActiveSetupRegPath -Name 'Version' -Value '1' 
            SET-ItemProperty -Path $ActiveSetupRegPath -Name 'StubPath' -Value $ActiveSetupValue
        } 
    } catch { 
        Write-Warning -Message $_.Exception.Message 
    } 
}
    
    $GBsFreeSpace = GET-OSDiskFreeSpace
    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $StartSpace = GET-OSDiskFreeSpace
        $Profiles = GET-ChildItem -Path "C:\Users" -Directory | where { $_.Name -notlike "*admin*" -and $_.Name -notlike "*cyberhawk*" -and $_.Name -notlike "*defaultapppool*" -and $_.Name -notlike "*labtechservice*" -and $_.Name -notlike "*public*" }
        $Count = 0
        FOREACH ($Profile in $Profiles) {
            $SearchPath = $Profile.FullName + "\AppData\Local\Microsoft\Outlook"
            $OSTs = GET-ChildItem -Path $SearchPath -ErrorAction SilentlyContinue | where { $_.Name -like "*.ost*" } 
            FOREACH ($OST in $OSTs) {
                $Count++
                break
            }
        }
        IF ($Count -ge $UserThreshold) {
            While (GET-Process "Outlook" -ErrorAction SilentlyContinue) {
                taskkill /IM “outlook.exe” /f | Out-Null
                Start-Sleep -Seconds 5
            }
            SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'CacheOthersMail'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'} -ErrorAction SilentlyContinue
            SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Enable'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'} -ErrorAction SilentlyContinue
            SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'DownloadSharedFolders'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'} -ErrorAction SilentlyContinue
            SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'NoOST'; 'Type' = 'DWORD'; 'Value' = '2'; 'Path' = 'SOFTWARE\Microsoft\Office\16.0\Outlook\OST'} -ErrorAction SilentlyContinue
            FOREACH ($Profile in $Profiles) {
                $SearchPath = $Profile.FullName + "\AppData\Local\Microsoft\Outlook"
                $OSTs = GET-ChildItem -Path $SearchPath -ErrorAction SilentlyContinue | where { $_.Name -like "*.ost*" } 
                FOREACH ($OST in $OSTs) {
                    Remove-Item $OST.FullName
                }
            }
        }
        ELSE { RETURN "Outlook Mailbox Cache Cleanup Skipped" }
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = [Math]::Round($FreedSpace,2).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Disable Mailbox Caching" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
 
}
FUNCTION CLEANUP-WindowsInstallerFolder {

    param(
        [int]$FreeSpaceThreshold = 20,
        [int]$DaysOldThreshold = 180
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    $GBsFreeSpace = GET-OSDiskFreeSpace
    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $StartSpace = GET-OSDiskFreeSpace
        $Time = GET-Date
        $Time = $Time.AddDays(-$DaysOldThreshold)
        GET-ChildItem -Path "C:\Windows\Installer" | where { $_.LastWriteTime -lt $Time } | Remove-Item -Recurse -Force
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = [Math]::Round($FreedSpace,2).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Windows Installer Data" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
}
FUNCTION CLEANUP-OfficeUpdateFolder {

    param(
        [int]$FreeSpaceThreshold = 35
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    $GBsFreeSpace = GET-OSDiskFreeSpace
    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $StartSpace = GET-OSDiskFreeSpace
        $Time = GET-Date
        $Time = $Time.AddDays(-14)
        GET-ChildItem -Path "C:\Program Files\Microsoft Office\Updates\Download\PackageFiles" -ErrorAction SilentlyContinue | where { $_.LastWriteTime -lt $Time } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
        $EndSpace = GET-OSDiskFreeSpace
        $FreedSpace = [Math]::Abs($StartSpace - $EndSpace)
        $SpaceFreed = [Math]::Round($FreedSpace,2).ToString() + " GBs"
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Office Temp Data" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = $SpaceFreed
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
}
FUNCTION CLEANUP-PageFile {
    param(
        [int]$FreeSpaceThreshold = 30,
        [int64]$InitialSize = 2GB,
        [int64]$MaximumSize = 4GB
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }
    
    $GBsFreeSpace = GET-OSDiskFreeSpace
    IF ($GBsFreeSpace -lt $FreeSpaceThreshold) {
        $StartSpace = GET-OSDiskFreeSpace

        $pagefile = GET-CimInstance -ClassName Win32_ComputerSystem
        $pagefile.AutomaticManagedPagefile = $False
        SET-CimInstance -InputObject $pagefile

        $pagefileset = GET-CimInstance -ClassName Win32_PageFileSetting | Where-Object {$_.name -eq "$ENV:SystemDrive\pagefile.sys"}
        $pagefileset.InitialSize = $InitialSize / 1KB / 1KB
        $pagefileset.MaximumSize = $MaximumSize / 1KB / 1KB
        SET-CimInstance -InputObject $pagefileset -ErrorAction SilentlyContinue
        
        $EndSpace = GET-OSDiskFreeSpace
    }
    ELSE { $ActionTaken = "Skipped"; $SpaceFreed = ""; $EndSpace = $StartSpace }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        CleanupType = "Page File" 
        StartingFreeSpace = [Math]::Round($StartSpace,2).ToString() + " GBs"
        Threshold = $FreeSpaceThreshold.ToString() + " GBs"
        ActionTaken = $ActionTaken
        EndingFreeSpace = [Math]::Round($EndSpace,2).ToString() + " GBs"
        SpaceFreed = ""
    }

    RETURN $Results | SELECT CleanupType, StartingFreeSpace, Threshold, ActionTaken, EndingFreeSpace, SpaceFreed
}

### ### ==============================================================================================
### ### HELPER FUNCTIONS
### ### ==============================================================================================

FUNCTION Check-OSName {
    $RETURNVar = @("", "")
    $var1 = (GET-CIMInstance -class Win32_OperatingSystem).Caption
    IF ($var1 -like "*Home*") { $RETURNVar[0] = $var1; $RETURNVar[1] = "Red"; RETURN $RETURNVar }
    IF ($var1 -like "*XP*") { $RETURNVar[0] = $var1; $RETURNVar[1] = "Yellow"; RETURN $RETURNVar }
    IF ($var1 -like "*Vista*") { $RETURNVar[0] = $var1; $RETURNVar[1] = "Yellow"; RETURN $RETURNVar }
    IF ($var1 -like "*7*") { $RETURNVar[0] = $var1; $RETURNVar[1] = "Yellow"; RETURN $RETURNVar }
    $RETURNVar[0] = $var1
    $RETURNVar[1] = "White"
    RETURN $RETURNVar
}
FUNCTION Check-OSBuildVersion {
    $RETURNVar = @("", "")
    $var1 = [System.Environment]::OSVersion.Version.Build
    IF($var1 -eq "19045") { $RETURNVar[0] = $var1; $RETURNVar[1] = "White"; RETURN $RETURNVar }
    IF($var1 -eq "22000") { $RETURNVar[0] = $var1; $RETURNVar[1] = "White"; RETURN $RETURNVar }
    IF($var1 -eq "22621") { $RETURNVar[0] = $var1; $RETURNVar[1] = "White"; RETURN $RETURNVar }
    $RETURNVar[0] = $var1; $RETURNVar[1] = "Yellow"; RETURN $RETURNVar
}
FUNCTION Check-NetworkProfile {
    $RETURNVar = @("", "")
    $var1 = GET-NetConnectionProfile
    IF($var1.NetworkCategory -like "*Public*") { $RETURNVar[0] = $var1.NetworkCategory; $RETURNVar[1] = "Yellow"; RETURN $RETURNVar }
    IF($var1.NetworkCategory -like "*Private*") { $RETURNVar[0] = $var1.NetworkCategory; $RETURNVar[1] = "Yellow"; RETURN $RETURNVar }
    ELSE { $RETURNVar[0] = $var1.NetworkCategory; $RETURNVar[1] = "White"; RETURN $RETURNVar }
}
FUNCTION Check-OSDriveFreeSpace {
    $RETURNVar = @("", "")
    $Partition = GET-Partition | Where IsBoot -EQ True

    $OSDriveLetter = $Partition.DriveLetter
    $OSDriveLetter += ":"

    $Drive = GET-CimInstance -ClassName CIM_LogicalDisk | Where DeviceID -EQ $OSDriveLetter

    [int]$FreeGBs = $Drive.FreeSpace / 1000000000

    IF ($FreeGBs -LT 25 ) { $RETURNVar[0] = $FreeGBs.ToString() + " GBs"; $RETURNVar[1] = "Yellow"; RETURN $RETURNVar }
    IF ($FreeGBs -LT 10 ) { $RETURNVar[0] = $FreeGBs.ToString() + " GBs"; $RETURNVar[1] = "Red"; RETURN $RETURNVar }
    ELSE { $RETURNVar[0] = $FreeGBs.ToString() + " GBs"; $RETURNVar[1] = "White"; RETURN $RETURNVar }
}
FUNCTION Check-OSDriveType {
    $RETURNVar = @("", "")
    $DriveLetter = $env:windir
    $DriveLetter = $DriveLetter.Substring(0,1)
    $Partition = GET-Partition -DriveLetter $DriveLetter

    $DiskNumber = GET-Partition -DriveLetter $DriveLetter
    $DiskNumber = $DiskNumber.DiskNumber

    $PhysicalDisk = GET-PhysicalDisk -DeviceNumber $DiskNumber
    IF ($PhysicalDisk.MediaType -like "*SSD*") {
        $RETURNVar[0] = $PhysicalDisk.BusType + " " + $PhysicalDisk.MediaType
        $RETURNVar[1] = "White"
    }
    ELSE {
        $RETURNVar[0] = $PhysicalDisk.BusType + " " + $PhysicalDisk.MediaType
        $RETURNVar[1] = "Yellow"
    }
    RETURN $RETURNVar
}
FUNCTION Check-LastSecurityUpdateDate {
   $RETURNVar = @("", "")
    
   $LastSecurityUpdateDate = GET-HotFix -Description "Security Update" | Sort-Object -Property InstalledOn -Descending | Select-Object -First 1
   $RETURNVar[0] = $LastSecurityUpdateDate.InstalledOn.ToShortDateString()
   
   $Now = GET-Date
   $ElapsedTime = $Now - $LastSecurityUpdateDate.InstalledOn
   IF($ElapsedTime.TotalDays -gt 90) { $RETURNVar[1] = "Red" }
   ELSEIF($ElapsedTime.TotalDays -gt 35) { $RETURNVar[1] = "Yellow" }
   ELSE { $RETURNVar[1] = "White" }
   
   RETURN $RETURNVar
}
FUNCTION Check-CryptoProtocols {
    $RETURNVar = @("", "")

    $Protocols = GET-CryptoProtocols

    $RETURNVar[0] = $Protocols
    IF ($Protocols -like "*SSL*" -or $Protocols -like "*TLS 1.0*") { $RETURNVar[1] = "Yellow" }
    ELSE { $RETURNVar[1] = "White" }

    RETURN $RETURNVar
}
Function GET-CPUUsage {

    <#
    .SYNOPSIS
        Measures an average current CPU usage of a period of time.
 
    .DESCRIPTION
 
        PARAMETERS
            -Seconds [int] (Specifies how long to measure average CPU usage, default is 5 seconds)
 
        NOTES
            N/A
 
        TIPS
            N/A
 
    .EXAMPLE
        Get-CPUUsage -Seconds 15
 
        Measure average CPU usage over the next 15 seconds.
     
    .LINK
        https://bjn.itglue.com/1902395/docs/14305861
    #>


    param(
        [Parameter()]
        [int]$Seconds = 5
    )


    [int]$Count = 0
    [int]$CPUUsageTotal = 0

    $Now = Get-Date
    
    WHILE ((Get-Date) -le ($Now).AddSeconds($Seconds)) {
        $CPUUsageTotal += (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
        $Count++
        Start-Sleep -Milliseconds 250
    }

    return [int]($CPUUsageTotal / $Count)
}
FUNCTION GET-OSDiskFreeSpace {
    $Partition = GET-Partition | Where IsBoot -EQ True
    $OSDriveLetter = $Partition.DriveLetter
    $OSDriveLetter += ":"
    $Drive = GET-CimInstance -ClassName CIM_LogicalDisk | Where DeviceID -EQ $OSDriveLetter
    $GBsFreeSpace = $Drive.FreeSpace / 1024 / 1024 / 1024
    RETURN $GBsFreeSpace
}
FUNCTION CHECK-DNSResolution {

    param (
        [int]$CriticalThreshold = 3,
        [int]$ErrorThreshold = 2,
        [int]$WarningThreshold = 1,
        [int]$TestCount = 10,
        [Parameter(Mandatory)]
        [string[]]$Name = ""
    )

    $Results = @()
    $TotalTestCount = $TestCount * $Name.Length
    $Count = 0
    $FailCount = 0
    $CurrentCount = 0
    
    FOREACH ($Item in $Name) {
        IF ($Item -like "*reddog*") { continue }
        $Count = 0
        $FailCount = 0
        FOR ($i = 0; $i -lt $TestCount; $i++) {
            $Count++
            $CurrentCount++
            $ProgressPercent = (($CurrentCount-1) / $TotalTestCount) * 100
            Write-Progress -ID 8 -Activity "Testing DNS" -Status "$ProgressPercent% - Testing Resolution of $Item" -PercentComplete $ProgressPercent
            $DNSResult = $null
            $DNSResult = Resolve-DNSName -Name Google.com -Type A -QuickTimeout -ErrorAction SilentlyContinue
            IF ($DNSResult -eq $null) { $FailCount++; IF ($FailCount -ge $CriticalThreshold) { break } }
            Start-Sleep -Milliseconds 100
        }

        IF ($FailCount -ge $CriticalThreshold) { $Verdict = "Critical" }
        ELSEIF ($FailCount -ge $ErrorThreshold) { $Verdict = "Error" }
        ELSEIF ($FailCount -ge $WarningThreshold) { $Verdict = "Warning" }
        ELSE { $Verdict = "Normal" }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Name = $Item
            TestCount = $Count
            FailCount = $FailCount
            FailPercentage = $FailCount / $Count * 100
            Verdict = $Verdict
        }
    }

    Write-Progress -ID 8 -Activity "Checking External DNS" -Status "99% - Preparing Results" -PercentComplete 100 -Completed

    RETURN $Results | Select Name, TestCount, FailCount, FailPercentage, Verdict
}

New-Alias -Name INTCHECK-DNSResolution -Value CHECK-DNSResolution
Export-ModuleMember -FUNCTION CHECK-DNSResolution -Alias INTCHECK-DNSResolution

### ### ==============================================================================================
### ### BIOS FUNCTIONS
### ### ==============================================================================================

FUNCTION GET-BIOSSettingsHP { 
        $Script:Get_BIOS_Settings = GET-CIMInstance -Namespace root/hp/instrumentedBIOS -Class hp_biosEnumeration -ErrorAction SilentlyContinue |  % { New-Object psobject -Property @{    
        Setting = $_."Name"
        Value = $_."currentvalue"
        Available_Values = $_."possiblevalues"
        }}  | select-object Setting, Value, possiblevalues

        FOREACH ($Setting in $Get_BIOS_Settings) {

            $Value = $Setting.Value
            $Value = $Value.Replace("Enable","Enabled")
            $Value = $Value.Replace("Disable","Disabled")

            IF ($Setting.Setting -eq "AMT") { $AMT = $Value } 
            IF ($Setting.Setting -eq "Virtualization Technology (VTx)") { $VirtualizationTechnology = $Value } 
            IF ($Setting.Setting -eq "Data Execution Prevention") { $DataExecutionPrevention = $Value }
            IF ($Setting.Setting -eq "Network Boot") { $NetworkBoot = $Value }
            IF ($Setting.Setting -eq "Intel(R) VT-d") { $IntelVTd = $Value }
            IF ($Setting.Setting -eq "Intel TXT(LT) Support") { $IntelTrustedExecutionTechnology = $Value }
            IF ($Setting.Setting -eq "Fast Boot") { $FastBoot = $Value }
            IF ($Setting.Setting -eq "Turbo Mode") { $TurboMode = $Value }
            IF ($Setting.Setting -eq "Hyper-Threading") { $HyperThreading = $Value }
            IF ($Setting.Setting -eq "Restrict USB Devices") { $RestrictUSBDevices = $Value }
            IF ($Setting.Setting -eq "Removable Media Boot") { $RemovableMediaBoot = $Value }
            IF ($Setting.Setting -eq "S5 Wake on LAN") { $WakeOnLAN = $Value }
            IF ($Setting.Setting -eq "After Power Loss") { $AfterPowerLoss = $Value }
        }   

        
        
        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            AMT = $AMT
            VirtualizationTechnology = $VirtualizationTechnology
            DataExecutionPrevention = $DataExecutionPrevention
            IntelVTd = $IntelVTd 
            IntelTXTSupport = $IntelTrustedExecutionTechnology
            IntelTME = $IntelTME
            NetworkBoot = $NetworkBoot
            RemovableMediaBoot = $RemovableMediaBoot
            RestrictUSBDevices = $RestrictUSBDevices
            FastBoot = $FastBoot
            TurboMode = $TurboMode
            HyperThreading = $HyperThreading
            AfterPowerLossAction = $AfterPowerLoss
            BootSequence = ""
            BlockSleep = ""
            WakeOnLAN = $WakeOnLAN
        }

    RETURN $Results
    } 
FUNCTION GET-BIOSSettingsDell {
        IF ((GET-PackageProvider -Name NuGet) -eq $null) { Install-PackageProvider NuGet -Force }
        IF ((GET-PackageSource -Name PSGallery) -eq $null) { Register-PackageSource -Name PSGallery -ProviderName PowerShellGet -ErrorAction SilentlyContinue }
        IF ((GET-Module -Name DellBIOSProvider).Version -ne "2.7.0") { Remove-Module DellBIOSProvider -ErrorAction SilentlyContinue ; Install-Module -Name DellBIOSProvider}
        IF ((GET-Module -Name SMBIOS) -eq $null) { Install-Module -Name SMBIOS -Force -AllowClobber -ErrorAction SilentlyContinue }
        Start-Sleep -Seconds 3
        Import-Module DellBIOSProvider -ErrorAction SilentlyContinue
        Import-Module SMBIOS -ErrorAction SilentlyContinue

        GET-Command -Module DellBIOSProvider | out-null
        $Script:Get_BIOS_Settings = GET-childitem -path DellSmbios:\ | select-object category |
    
        FOREACH {
            GET-Childitem -path @("DellSmbios:\" + $_.Category) -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | select-object attribute, currentvalue
        } 
        $Script:Get_BIOS_Settings = $Get_BIOS_Settings |  % { New-Object psobject -Property @{
        Setting = $_."attribute"
        Value = $_."currentvalue"
        }}  | select-object Setting, Value
        

        FOREACH ($Setting in $Get_BIOS_Settings) {
            IF ($Setting.Setting -eq "Virtualization") { $VirtualizationTechnology = $Setting.Value } 
            IF ($Setting.Setting -eq "Fastboot") { $FastBoot = $Setting.Value }
            IF ($Setting.Setting -eq "WakeOnLAN") { $WakeOnLAN = $Setting.Value }
            IF ($Setting.Setting -eq "BootSequence") { $BootSequence = $Setting.Value }
            IF ($Setting.Setting -eq "TurboMode") { $TurboMode = $Setting.Value }
            IF ($Setting.Setting -eq "AcPwrRcvry") { $AfterPowerLoss = $Setting.Value }
            IF ($Setting.Setting -eq "BlockSleep") { $BlockSleep = $Setting.Value }
            IF ($Setting.Setting -eq "VtForDirectIo") { $IntelVTd = $Setting.Value }
            IF ($Setting.Setting -eq "TrustExecution") { $IntelTrustedExecutionTechnology = $Setting.Value }
            IF ($Setting.Setting -eq "IntelTME") { $IntelTME = $Setting.Value }            
        }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            AMT = $AMT
            VirtualizationTechnology = $VirtualizationTechnology
            DataExecutionPrevention = ""
            IntelVTd = $IntelVTd 
            IntelTXTSupport = $IntelTrustedExecutionTechnology
            IntelTME = $IntelTME
            NetworkBoot = ""
            RemovableMediaBoot = ""
            RestrictUSBDevices = ""
            FastBoot = $FastBoot
            TurboMode = $TurboMode
            HyperThreading = ""
            AfterPowerLossAction = $AfterPowerLoss
            BootSequence = $BootSequence
            BlockSleep = $BlockSleep
            WakeOnLAN = $WakeOnLAN
        }

        RETURN $Results
    }  
FUNCTION GET-BIOSSettingsLenovo {     
        $BIOSSettings = (GET-CIMInstance -Class Lenovo_BiosSetting -Namespace root\wmi).CurrentSetting | Where-Object {$_ -ne ""} | Sort-Object
    
        FOREACH ($Setting in $BIOSSettings) {
            $Item = $Setting.Split(',')
            
            IF ($Item[0] = "WakeOnLAN") { $WakeOnLAN = $Item[1] }
            #IF ($Item[0] = "WiFiNetworkBoot") { $WiFiNetworkBoot = $Item[1] }
            IF ($Item[0] = "VTdFeature") { $IntelVTd = $Item[1] }
            IF ($Item[0] = "VirtualizationTechnology") { $VirtualizationTechnology = $Item[1] }
            IF ($Item[0] = "TXTFeature") { $IntelTrustedExecutionTechnology = $Item[1] }
            IF ($Item[0] = "TotalMemoryEncryption") { $IntelTME = $Item[1] }
            IF ($Item[0] = "NetworkBoot") { $NetworkBoot = $Item[1] }
            IF ($Item[0] = "AMTControl") { $AMT = $Item[1] }
            IF ($Item[0] = "BootMode") { $BootMode = $Item[1] }
            IF ($Item[0] = "BootOrder") { $BootOrder = $Item[1] }
            IF ($Item[0] = "DataExecutionPrevention") { $DataExecutionPrevention = $Item[1] }
            IF ($Item[0] = "HyperThreadingTechnology") { $HyperThreadingTechnology = $Item[1] }
        }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            AMT = $AMT
            VirtualizationTechnology = $VirtualizationTechnology
            DataExecutionPrevention = $DataExecutionPrevention
            IntelVTd = $IntelVTd
            IntelTXTSupport = $IntelTrustedExecutionTechnology
            IntelTME = $IntelTME
            NetworkBoot = $NetworkBoot
            RemovableMediaBoot = ""
            RestrictUSBDevices = ""
            FastBoot = $BootMode
            TurboMode = ""
            HyperThreading = $HyperThreadingTechnology
            AfterPowerLossAction = ""
            BootSequence = $BootOrder
            BlockSleep = ""
            WakeOnLAN = $WakeOnLAN
        }

        RETURN $Results
    }

### ### ==============================================================================================
### ### UNDER DEVELOPMENT FUNCTIONS
### ### ==============================================================================================

FUNCTION SET-BIOSSettings {
    # ========================================================
    # ============== Determine Manufacturer ==================
    # ========================================================

    $Manufacturer = GET-CimInstance -ClassName Win32_ComputerSystem | Select Manufacturer
    $Manufacturer = $Manufacturer.Manufacturer

    # ========================================================
    # ==================== HP Commands =======================
    # ========================================================

    #Show BIOS Config and Options
    #GET-CIMInstance -Namespace root/hp/instrumentedBIOS -Class hp_biosEnumeration |Format-Table Name,Value -AutoSize



    # ========================================================
    # ================= Config Automation ====================
    # ========================================================
    FUNCTION SET-BIOSSettings {
        IF ($Manufacturer -like "*Hewlett*") { 
            Write-Host "Started Configuring HP Bios Settings"

            $BIOSSettings = GET-CIMInstance -Namespace root/hp/instrumentedBIOS -Class HP_BIOSSettingInterface

            $BIOSSettings.SetBIOSSetting("AMT","Enable","")
            $BIOSSettings.SetBIOSSetting("Virtualization Technology (VTx)","Enable","")
            $BIOSSettings.SetBIOSSetting("Virtualization Technology Directed I/O (VTd)","Enable","")
            $BIOSSettings.SetBIOSSetting("Intel(R) VT-d","Enable","")
            $BIOSSettings.SetBIOSSetting("TPM State","Enable","")
            $BIOSSettings.SetBIOSSetting("TPM Device","Available","")
            $BIOSSettings.SetBIOSSetting("After Power Loss","On","")
            $BIOSSettings.SetBIOSSetting("S5 Wake on LAN","Enable","")

            Write-Host "Finished Configuring HP Bios Settings"        
        }

        IF ($Manufacturer -like "*Dell*") { 
            Write-Host "Started Configuring Dell Bios Settings"

            $Policy = GET-ExecutionPolicy
            SET-ExecutionPolicy -ExecutionPolicy Unrestricted -Force
            Install-PackageProvider NuGet -Force
            Install-Module -Name DellBIOSProvider -Force
            Install-Module -Name SMBIOS -Force
            Import-Module DellBIOSProvider
            SET-ExecutionPolicy -ExecutionPolicy $Policy -Force

            SET-Item -Path DellSmbios:\VirtualizationSupport\Virtualization -Value "Enabled"
            SET-Item -Path DellSmbios:\VirtualizationSupport\VtForDirectIo -Value "Enabled"
            SET-Item -Path DellSmbios:\PowerManagement\BlockSleep -Value "Disabled"
            SET-Item -Path DellSmbios:\PowerManagement\WakeOnLan -Value "LanOnly"
            SET-Item -Path DellSmbios:\PowerManagement\AcPwrRcvry "On"
            SET-Item -Path DellSmbios:\PowerManagement\WakeOnAC "Enabled"
            SET-Item -Path DellSmbios:\SystemConfiguration\UefiNwStack -Value "Enabled"
            SET-Item -Path DellSmbios:\TPMSecurity\TpmSecurity "Enabled"
            SET-Item -Path DellSmbios:\TPMSecurity\TpmActivation "Enabled"
            SET-Item -Path DellSmbios:\SystemConfiguration\SmartErrors "Enabled"

            Write-Host "Finished Configuring Dell Bios Settings"
        }

        IF ($Manufacturer -like "*Lenovo*") { 
            Write-Host "Started Configuring Lenovo Bios Settings"

            (GET-CIMInstance -Class Lenovo_SetBiosSetting -Namespace root\wmi -ErrorAction Stop).SetBiosSetting("Wake On LAN,Automatic")
            (GET-CIMInstance -Class Lenovo_SetBiosSetting -Namespace root\wmi -ErrorAction Stop).SetBiosSetting("VT-d,Enabled")
            (GET-CIMInstance -Class Lenovo_SetBiosSetting -Namespace root\wmi -ErrorAction Stop).SetBiosSetting("Intel(R) Virtualization Technology,Enabled")
            (GET-CIMInstance -Class Lenovo_SetBiosSetting -Namespace root\wmi -ErrorAction Stop).SetBiosSetting("Intel(R) SpeedStep(TM) Technology,Enabled")
            (GET-CIMInstance -Class Lenovo_SetBiosSetting -Namespace root\wmi -ErrorAction Stop).SetBiosSetting("After Power Loss,Power On,")

            (GET-CIMInstance -Class Lenovo_SaveBiosSettings -Namespace root\wmi -ErrorAction Stop).SaveBiosSettings()

            Write-Host "Finished Configuring Lenovo Bios Settings"
        }

        IF ($Manufacturer -notlike "*Lenovo*" -and $Manufacturer -notlike "*Dell*" -and $Manufacturer -notlike "*Hewlett*") { 
            Write-Host "Script Does Not Support BIOS Configuration For This Computer"
        }
    }
}
FUNCTION GET-CryptoProtocols {

    <#
    .SYNOPSIS
        Checks which crypto security procotols are enabled.
 
    .DESCRIPTION
 
        PARAMETERS
            N/A
 
        NOTES
            N/A
 
        TIPS
            N/A
 
    .EXAMPLE
        GET-CryptoProtocols
     
    .LINK
        https://bjn.itglue.com/1902395/docs/14305861
    #>


    $Protocols = ""

    $Key = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Client\' 
    IF (Test-Path $Key) { 
        $Value = GET-ItemProperty $Key 
        IF ($Value.DisabledByDefault -eq 0 -and $Value.Enabled -ne 0) { $Protocols += ", PCT 1.0" } 
    }
    ELSE { $Protocols += ", PCT 1.0" }

    $Key = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client\' 
    IF (Test-Path $Key) { 
        $Value = GET-ItemProperty $Key 
        IF ($Value.DisabledByDefault -eq 0 -and $Value.Enabled -ne 0) { $Protocols += ", SSL 2.0" } 
    }
    ELSE { $Protocols += ", SSL 2.0" }

    $Key = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client\' 
    IF (Test-Path $Key) { 
        $Value = GET-ItemProperty $Key 
        IF ($Value.DisabledByDefault -eq 0 -and $Value.Enabled -ne 0) { $Protocols += ", SSL 3.0" } 
    }
    ELSE { $Protocols += ", SSL 3.0" }

    $Key = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client\' 
    IF (Test-Path $Key) { 
        $Value = GET-ItemProperty $Key 
        IF ($Value.DisabledByDefault -eq 0 -and $Value.Enabled -ne 0) { $Protocols += ", TLS 1.0" } 
    }
    ELSE { $Protocols += ", TLS 1.0" }

    $Key = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client\' 
    IF (Test-Path $Key) { 
        $Value = GET-ItemProperty $Key 
        IF ($Value.DisabledByDefault -eq 0 -and $Value.Enabled -ne 0) { $Protocols += ", TLS 1.1" } 
    }
    ELSE { $Protocols += ", TLS 1.1" }

    $Key = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client\' 
    IF (Test-Path $Key) { 
        $Value = GET-ItemProperty $Key 
        IF ($Value.DisabledByDefault -eq 0 -and $Value.Enabled -ne 0) { $Protocols += ", TLS 1.2" } 
    }
    ELSE { $Protocols += ", TLS 1.2" }

    RETURN $Protocols.Substring(2,$Protocols.Length-2)
}
FUNCTION CHECK-All {

    param (
        [string]$Status = @("","Warning","Error")
    )

   
    IF ($PSVersionTable.PSVersion.Major -ge 7) { } ELSE {
        Write-Warning "PowerShell 5 doesn't not support the color orange in output text. The color orange will be substituted with the color magenta."
    }

    Write-Progress -ID 13 -Activity "Checking All" -Status "0% - Initializing Variables" -PercentComplete 0

    $Results = @()
    $NetworkAdaptersChecked = @()

    ### Variables
    $NoIssuesFound = ""
    
    ### Collect Info
    Write-Progress -ID 13 -Activity "Checking All" -Status "5% - Getting Date\Time" -PercentComplete 5
    $Now = Get-Date  
    Write-Progress -ID 13 -Activity "Checking All" -Status "10% - Collecting Windows Info" -PercentComplete 10     
    $OSInfo = GET-WindowsInfo
    Write-Progress -ID 13 -Activity "Checking All" -Status "15% - Collecting System Volume Info" -PercentComplete 15
    $SystemVolume = GET-VolumeSystem
    Write-Progress -ID 13 -Activity "Checking All" -Status "20% - Collecting Network Connection Info" -PercentComplete 20
    $NetworkConnections = GET-NetworkConnection -IPType IPv4,IPv6
    Write-Progress -ID 13 -Activity "Checking All" -Status "50% - Testing DNS" -PercentComplete 50
    $ExternalDNS = CHECK-DNSResolution -Name Google.com,Microsoft.com
    $DNSSuffixSearchList = (GET-DNSClientGlobalSetting).SuffixSearchList
    IF ($DNSSuffixSearchList.Count -eq 0) { $InternalDNS = $Null }
    ELSE { $InternalDNS = CHECK-DNSResolution -Name $DNSSuffixSearchList }
    Write-Progress -ID 13 -Activity "Checking All" -Status "75% - Collecting CPU Info" -PercentComplete 75
    $CPUs = GET-CPUDevice
    Write-Progress -ID 13 -Activity "Checking All" -Status "85% - Collecting Memory Info" -PercentComplete 85
    $AvailableMemoryGBs = [math]::round((Get-CIMInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB,2)
    $PageFileSize = [math]::round((Get-CIMInstance Win32_PagefileUsage).AllocatedBaseSize / 1KB,2)
    
    
    Write-Progress -ID 13 -Activity "Checking All" -Status "90% - Processing Results" -PercentComplete 90
    ### Windows Type Home/Pro Enterprise
    IF ($True) {
        IF ($OSInfo.Name -like "*Home*") {
            $AlertLlevel = "Critial"
            $Details = "Workstation Computers Should be Windows Pro or Enterprise"
        }
        ELSE {
            $AlertLlevel = "Normal"
            $Details = $NoIssuesFound
        }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Category = "Operating System"
            Item = "Windows"
            ItemDetails = "Windows Type"
            Result = $OSInfo.Name
            ResultDetails = $Details
            AlertLevel = $AlertLlevel
        }
    }  
    
    ### Windows Build
    IF ($True) {
        IF ($OSInfo.Name -like "*Windows 10*") {
            IF ($OSInfo.BuildNumber -eq 19045) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Operating System"
                    Item = "Windows"
                    ItemDetails = "Windows Build Number"
                    Result = $OSInfo.BuildNumber
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound 
                }   
            }
        }

    }     

    ### Last Security Update
    IF ($True) {

        $SecurityTimespan = $Now - $OSInfo.LastWindowsUpdate
        
        IF ($SecurityTimespan.TotalDays -le 45) {
            $AlertLevel = "Normal"
            $Details = $NoIssuesFound
        }
        ELSEIF ($SecurityTimespan.TotalDays -le 90) {
            $AlertLevel = "Warning"
            $Details = "Windows Security Last Applied $([int]$($SecurityTimeSpan.TotalDays)) Days Ago"
        }
        ELSEIF ($SecurityTimespan.TotalDays -le 135) {
            $AlertLevel = "Error"
            $Details = "Windows Security Last Applied $([int]$($SecurityTimeSpan.TotalDays)) Days Ago"
        }
        ELSE {
            $AlertLevel = "Critical"
            $Details = "Windows Security Last Applied $([int]$($SecurityTimeSpan.TotalDays)) Days Ago"
        }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Category = "Operating System"
            Item = "Windows"
            ItemDetails = "Most Recent Update"
            Result = $OSInfo.LastWindowsUpdate
            ResultDetails = $Details
            AlertLevel = $AlertLevel
        }
    }

    ### Page File Size
    IF ($True) {
        IF ($PageFileSize -gt 12) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Operating System"
                    Item = "Page File"
                    ItemDetails = "Page File Size"
                    Result = $PageFileSize.ToString() + " GBs"
                    AlertLevel = "Normal"
                    ResultDetails = "Extremely Large Page File"
                }
            }
        ELSEIF ($PageFileSize -gt 8) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Operating System"
                    Item = "Page File"
                    ItemDetails = "Page File Size"
                    Result = $PageFileSize.ToString() + " GBs"
                    AlertLevel = "Error"
                    ResultDetails = "Very Large Page File"
                }
            }
        ELSEIF ($PageFileSize -gt 4.5) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Operating System"
                    Item = "Page File"
                    ItemDetails = "Page File Size"
                    Result = $PageFileSize.ToString() + " GBs"
                    AlertLevel = "Warning"
                    ResultDetails = "Large Page File"
                }
            }
        ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Operating System"
                    Item = "Page File"
                    ItemDetails = "Page File Size"
                    Result = $PageFileSize.ToString() + " GBs"
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }
            }
    }

    ### Days Since Last Reboot
    IF ($True) {
        $LastRebootTimeSpan = $Now - $OSInfo.LastBootTime
        IF ($LastRebootTimeSpan.TotalDays -gt 30) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Operating System"
                    Item = "Boot Time"
                    ItemDetails = "Days Since Last Reboot"
                    Result = [math]::round($LastRebootTimeSpan.TotalDays,0).ToString() + " Days"
                    AlertLevel = "Error"
                    ResultDetails = [math]::round($LastRebootTimeSpan.TotalDays,0).ToString() + " Days Since Last Reboot"
                }
            }
        ELSEIF ($LastRebootTimeSpan.TotalDays -gt 15) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Operating System"
                    Item = "Boot Time"
                    ItemDetails = "Days Since Last Reboot"
                    Result = [math]::round($LastRebootTimeSpan.TotalDays,0).ToString() + " Days"
                    AlertLevel = "Warning"
                    ResultDetails = [math]::round($LastRebootTimeSpan.TotalDays,0).ToString() + " Days Since Last Reboot"
                }
            }
        ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Operating System"
                    Item = "Boot Time"
                    ItemDetails = "Days Since Last Reboot"
                    Result = [math]::round($LastRebootTimeSpan.TotalDays,0).ToString() + " Days"
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }
            }
    }

    ### CPU Score
    IF ($True) {
        FOREACH ($CPU in $CPUs) {
            IF ($CPU.CPUScore -lt 3000) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Score"
                    ItemDetails = $CPU.CPUModel
                    Result = $CPU.CPUScore
                    AlertLevel = "Critical"
                    ResultDetails = "Extremely Slow CPU"
                }
            }
            ELSEIF ($CPU.CPUScore -lt 3000) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Score"
                    ItemDetails = $CPU.CPUModel
                    Result = $CPU.CPUScore
                    AlertLevel = "Error"
                    ResultDetails = "Very Slow CPU"
                }
            }
            ELSEIF ($CPU.CPUScore -lt 3000) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Score"
                    ItemDetails = $CPU.CPUModel
                    Result = $CPU.CPUScore
                    AlertLevel = "Warning"
                    ResultDetails = "Slow CPU"
                }
            }
            ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Score"
                    ItemDetails = $CPU.CPUModel
                    Result = $CPU.CPUScore
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }
            }
        }
    }

    ### CPU Age
    IF ($True) {
        FOREACH ($CPU in $CPUs) {
            IF ($CPU.YearsOld -eq "Unknown") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Age"
                    ItemDetails = $CPU.CPUModel
                    Result = "Unknown"
                    AlertLevel = "Warning"
                    ResultDetails = "Unknown Computer Age"
                }
            }
            ELSEIF ($CPU.YearsOld -lt 6) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Age"
                    ItemDetails = $CPU.CPUModel
                    Result = $CPU.YearsOld.ToString() + " Years"
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }
            }
            ELSEIF ($CPU.YearsOld -lt 7) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Age"
                    ItemDetails = $CPU.CPUModel
                    Result = $CPU.YearsOld.ToString() + " Years"
                    AlertLevel = "Warning"
                    ResultDetails = "Old Computer"
                }
            }
            ELSEIF ($CPU.YearsOld -lt 8) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Age"
                    ItemDetails = $CPU.CPUModel
                    Result = $CPU.YearsOld.ToString() + " Years"
                    AlertLevel = "Error"
                    ResultDetails = "Very Old Computer"
                }
            }
            ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "CPU Age"
                    ItemDetails = $CPU.CPUModel
                    Result = $CPU.YearsOld.ToString() + " Years"
                    AlertLevel = "Normal"
                    ResultDetails = "Extremely Old Computer"
                }
            }
        }
    }

    ### Disk Free Space
    IF ($True) {
        IF ($SystemVolume.VolumeFreeSizeInGBs -lt 2) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "Disk Space"
                    ItemDetails = "C: Volume Free Space"
                    Result = $SystemVolume.VolumeFreeSizeInGBs.ToString() + " GBs"
                    AlertLevel = "Critical"
                    ResultDetails = "Extremely Low Disk Space"
                }
            }
        ELSEIF ($SystemVolume.VolumeFreeSizeInGBs -lt 5) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "Disk Space"
                    ItemDetails = "C: Volume"
                    Result = $SystemVolume.VolumeFreeSizeInGBs.ToString() + " GBs"
                    AlertLevel = "Error"
                    ResultDetails = "Very Low Disk Space"
                }
            }
        ELSEIF ($SystemVolume.VolumeFreeSizeInGBs -lt 25) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "Disk Space"
                    ItemDetails = "C: Volume"
                    Result = $SystemVolume.VolumeFreeSizeInGBs.ToString() + " GBs"
                    AlertLevel = "Warning"
                    ResultDetails = "Low Disk Space"
                }
            }
        ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "Disk Space"
                    ItemDetails = "C: Volume"
                    Result = $SystemVolume.VolumeFreeSizeInGBs.ToString() + " GBs"
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }
            }
    }

    ### Available RAM
    IF ($True) {
        IF ($AvailableMemoryGBs -gt 1) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "RAM"
                    ItemDetails = "Available RAM"
                    Result = $AvailableMemoryGBs.ToString() + " GBs"
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }
            }
        ELSEIF ($AvailableMemoryGBs -gt .5) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "RAM"
                    ItemDetails = "Available RAM"
                    Result = $AvailableMemoryGBs.ToString() + " GBs"
                    AlertLevel = "Warning"
                    ResultDetails = "Low Available RAM"
                }
            }
        ELSEIF ($AvailableMemoryGBs -gt .25) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "RAM"
                    ItemDetails = "Available RAM"
                    Result = $AvailableMemoryGBs.ToString() + " GBs"
                    AlertLevel = "Error"
                    ResultDetails = "Very Low Available RAM"
                }
            }
        ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Hardware"
                    Item = "RAM"
                    ItemDetails = "Available RAM"
                    Result = $AvailableMemoryGBs.ToString() + " GBs"
                    AlertLevel = "Critical"
                    ResultDetails = "Extremely Low Available RAM"
                }
            }
    }

    ### DNS
    IF ($True) {
        FOREACH ($Item in $ExternalDNS) {

            IF ($Item.FailCount -gt 0) {
                $AlertLlevel = $Item.Verdict
                $Details = "DNS is Not Properly Resolving External Names"
            }
            ELSE {
                $AlertLlevel = "Normal"
                $Details = $NoIssuesFound
            }

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Category = "DNS"
                Item = "External DNS"
                ItemDetails = $Item.Name
                Result = "$($Item.FailCount.ToString()) of $($Item.TestCount.ToString()) DNS Queries Failed"
                AlertLevel = $AlertLlevel
                ResultDetails = $Details
            }
        }
        FOREACH ($Item in $InternalDNS) {

            IF ($Item.FailCount -gt 0) {
                $AlertLlevel = $Item.Verdict
                $Details = "DNS is Not Properly Resolving External Names"
            }
            ELSE {
                $AlertLlevel = "Normal"
                $Details = $NoIssuesFound
            }

            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Category = "DNS"
                Item = "Internal DNS"
                ItemDetails = $Item.Name
                Result = "$($Item.FailCount.ToString()) of $($Item.TestCount.ToString()) DNS Queries Failed"
                AlertLevel = $AlertLlevel
                ResultDetails = $Details
            }
        }
    }

    ### Network Connection
    IF ($True) {
        FOREACH ($NetworkConnection in $NetworkConnections) {

            ### This Prevents Adapters with Both IPv4 and IPv6 Enabled From Being Shown Twice
            IF ($NetworkAdaptersChecked -contains $NetworkConnection.Name) { continue }
                $NetworkAdaptersChecked += $NetworkConnection.Name

            IF ($NetworkConnection.Type -like "*WiFi*" -and $NetworkConnection.Status -eq "Connected") {
                
                ### Check SSID for Guest
                IF ($True) {
                    IF ($NetworkConnection.SSID -like "*guest*") {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "WiFi SSID"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.SSID
                            AlertLevel = "Warning"
                            ResultDetails = "Connected to Guest Network"
                        }
                    } 
                    ELSE {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "WiFi SSID"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.SSID
                            AlertLevel = "Normal"
                            ResultDetails = $NoIssuesFound
                        }
                    }
                }

                ### Check WIFI Protocol
                IF ($True) {
                    IF ($NetworkConnection.Protocol -like "*ac*" -or $NetworkConnection.Protocol -like "*ax*") {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "WiFi Protocol"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.Protocol
                            AlertLevel = "Normal"
                            ResultDetails = $NoIssuesFound
                        }
                    } 
                    ELSE {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "WiFi Protocol"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.SSID
                            AlertLevel = "Error"
                            ResultDetails = "Connected with WiFi 4 or Below"
                        }
                    }
                }

                ### Check Signal Strength
                IF ($True) {
                    $SignalStrength = $NetworkConnection.SignalStrength.Replace("%","")
                    [int]$SignalStrength = [int]$SignalStrength.Replace(" ","")

                    IF ($SignalStrength -ge 70) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Signal Strength"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.SignalStrength
                            AlertLevel = "Normal"
                            ResultDetails = $NoIssuesFound
                        }
                    }
                    ELSEIF ($SignalStrength -ge 60) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Signal Strength"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.SignalStrength
                            AlertLevel = "Warning"
                            ResultDetails = "Low Signal Strength"
                        }
                    }
                    ELSEIF ($SignalStrength -ge 50) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Signal Strength"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.SignalStrength
                            AlertLevel = "Error"
                            ResultDetails = "Very Low Signal Strength"
                        }
                    }
                    ELSE {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Signal Strength"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.SignalStrength
                            AlertLevel = "Critial"
                            ResultDetails = "Extremely Low Signal Strength"
                        }
                    }
                }

                ### Check Link Speed
                IF ($True) {
                    $LinkSpeedCalc = 0
                    $LinkSpeed = $NetworkConnection.LinkSpeed.Split("\")

                    IF (($LinkSpeed[0]/4) -lt $LinkSpeed[1]) { [int]$LinkSpeedCalc = $LinkSpeed[0] / 4 }
                    ELSE { [int]$LinkSpeedCalc = $LinkSpeed[1] } 

                    IF ($LinkSpeedCalc -gt 100) {
                            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Normal"
                            ResultDetails = $NoIssuesFound
                        }
                    }
                    ELSEIF ($LinkSpeedCalc -gt 75) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Warning"
                            ResultDetails = "Slow Link Speed"
                        }
                    }
                    ELSEIF ($LinkSpeedCalc -gt 50) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Error"
                            ResultDetails = "Very Slow Link Speed"
                        }
                    }
                    ELSE {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Critical"
                            ResultDetails = "Extremely Slow Link Speed"
                        }
                    }
                }
            }
            IF ($NetworkConnection.Type -like "*WiFi*" -and $NetworkConnection.Status -ne "Connected") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Network Connection"
                    Item = "WiFi Connection"
                    ItemDetails = $NetworkConnection.Name
                    Result = $NetworkConnection.Status
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }
            }
            IF ($NetworkConnection.Type -like "*Wired*" -and $NetworkConnection.Status -eq "Connected") {
                
                ### Check Link Speed
                IF ($True) {
                    $LinkSpeedCalc = 0
                    $LinkSpeed = $NetworkConnection.LinkSpeed.Split("\")

                    [int]$LinkSpeedCalc = $LinkSpeed[0]

                    IF ($LinkSpeedCalc -gt $LinkSpeed[1]) { $LinkSpeedCalc = $LinkSpeed[1] }

                    IF ($LinkSpeedCalc -gt 900) {
                            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Normal"
                            ResultDetails = $NoIssuesFound
                        }
                    }
                    ELSEIF ($LinkSpeedCalc -gt 500) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Warning"
                            ResultDetails = "Slow Link Speed"
                        }
                    }
                    ELSEIF ($LinkSpeedCalc -gt 50) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Error"
                            ResultDetails = "Very Slow Link Speed"
                        }
                    }
                    ELSE {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Critical"
                            ResultDetails = "Extremely Slow Link Speed"
                        }
                    }
                }
            }
            IF ($NetworkConnection.Type -like "*Wired*" -and $NetworkConnection.Status -ne "Connected") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Network Connection"
                    Item = "Wired Connection"
                    ItemDetails = $NetworkConnection.Name
                    Result = $NetworkConnection.Status
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }    
            }
            IF ($NetworkConnection.Type -like "*Hyper*" -and $NetworkConnection.Status -eq "Connected") {
                
                ### Check Link Speed
                IF ($True) {
                    $LinkSpeedCalc = 0
                    $LinkSpeed = $NetworkConnection.LinkSpeed.Split("\")

                    [int]$LinkSpeedCalc = $LinkSpeed[0]

                    IF ($LinkSpeedCalc -gt $LinkSpeed[1]) { $LinkSpeedCalc = $LinkSpeed[1] }

                    IF ($LinkSpeedCalc -gt 900) {
                            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Normal"
                            ResultDetails = $NoIssuesFound
                        }
                    }
                    ELSEIF ($LinkSpeedCalc -gt 500) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Warning"
                            ResultDetails = "Slow Link Speed"
                        }
                    }
                    ELSEIF ($LinkSpeedCalc -gt 50) {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Error"
                            ResultDetails = "Very Slow Link Speed"
                        }
                    }
                    ELSE {
                        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                            Category = "Network Connection"
                            Item = "Link Speed"
                            ItemDetails = $NetworkConnection.Name
                            Result = $NetworkConnection.LinkSpeed
                            AlertLevel = "Critical"
                            ResultDetails = "Extremely Slow Link Speed"
                        }
                    }
                }
            }
            IF ($NetworkConnection.Type -like "*Hyper*" -and $NetworkConnection.Status -ne "Connected") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Category = "Network Connection"
                    Item = "Wired Connection"
                    ItemDetails = $NetworkConnection.Name
                    Result = $NetworkConnection.Status
                    AlertLevel = "Normal"
                    ResultDetails = $NoIssuesFound
                }    
            }
        }
    }

    Write-Progress -ID 13 -Activity "Checking All" -Status "100% - Complete" -PercentComplete 100 -Completed
    
    IF ($PSVersionTable.PSVersion.Major -ge 7) {
        RETURN $Results | Select Category, Item, ItemDetails, Result, AlertLevel, ResultDetails | FT -GroupBy Category | Out-String -Stream | ForEach-Object {
            IF ($_ -match 'Warning') { "$($PSStyle.Foreground.FromRgb(200,200,0))$_$($PSStyle.Reset)" } 
            ELSEIF ($_ -match 'Category:') { "$($PSStyle.Foreground.FromRgb(255,255,255))$_$($PSStyle.Reset)" } 
            ELSEIF ($_ -like '*----*') { "$($PSStyle.Foreground.FromRgb(255,255,255))$_$($PSStyle.Reset)" } 
            ELSEIF ($_ -match 'AlertLevel') { "$($PSStyle.Foreground.FromRgb(255,255,255))$_$($PSStyle.Reset)" } 
            ELSEIF ($_ -match 'Error') { "$($PSStyle.Foreground.FromRgb(200,100,0))$_$($PSStyle.Reset)" } 
            ELSEIF ($_ -match 'Critical') { "$($PSStyle.Foreground.FromRgb(225,0,0))$_$($PSStyle.Reset)" } 
            ELSE { "$($PSStyle.Foreground.FromRgb(255,255,255))$_$($PSStyle.Reset)" }
        }
    }
    ELSE {
        RETURN $Results | Select Category, Item, ItemDetails, Result, AlertLevel, ResultDetails | FT -GroupBy Category | Out-String -Stream | ForEach-Object {
        $OutA = IF ($_ -match 'Warning') { @{ 'ForegroundColor' = 'Yellow' } } 
                ELSEIF ($_ -match 'Category:') { @{ 'ForegroundColor' = 'White' } } 
                ELSEIF ($_ -like '*----*') { @{ 'ForegroundColor' = 'White' } } 
                ELSEIF ($_ -match 'AlertLevel') { @{ 'ForegroundColor' = 'White' } } 
                ELSEIF ($_ -match 'Error') { @{ 'ForegroundColor' = 'Magenta' } } 
                ELSEIF ($_ -match 'Critical') { @{ 'ForegroundColor' = 'Red' } } 
                ELSE { @{ 'ForegroundColor' = 'White' } }
        Write-Host @OutA $_
        }    
    }
}
FUNCTION FIX-MicrosoftOfficeLogin {

    <#
    .SYNOPSIS
        Fixes various issues with Microsoft Office application logins.
 
    .DESCRIPTION
 
        PARAMETERS
            -DisableAADWAM (Generally Fixes Issues with Office Login Window Not Appearing)
            -ClearAppData (Try This Option If Nothing Else Works, Forces Logoff)
            -ForceLogoff (Required to Use the ClearAppData Parameter)
 
        NOTES
            N/A
 
        TIPS
            N/A
 
    .EXAMPLE
        Fix-MicrosoftOfficeLogin -DisableAADWAM (Disables WAM Related Registry Keys)
 
        This fix is often effective when login prompts are not appearing when the should be.
 
    .EXAMPLE
        Fix-MicrosoftOfficeLogin -ClearAppData -ForceLogoff (Clears WAM Related AppData and Forces Logoff)
 
        This fix can usually resolve most errors. Usually when you log in but it gives the the "something went wrong" with a random error number. This forces the user to log out so make sure to have them save anything they're working on. NOTE: After running this you may receive TPM errors after logging in to office but you will still be able to log in.
 
    .LINK
        https://bjn.itglue.com/1902395/docs/14305861
    #>


    param(
        [Parameter(ParameterSetName = 'DisableAADWAM')]
        [Switch]$DisableAADWAM = $False,

        [Parameter(ParameterSetName = 'ClearAppData')]
        [Switch]$ClearAppData = $False,

        [Parameter(ParameterSetName = 'ClearAppData')]
        [Switch]$ForceLogoff = $False
    )

    FUNCTION SET-RegistryValueForAllUsers { 
    <#
    .SYNOPSIS
        This FUNCTION uses Active Setup to create a "seeder" key which creates or modifies a user-based registry value
        for all users on a computer. If the key path doesn't exist to the value, it will automatically create the key and add the value.
    .EXAMPLE
        PS> SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Setting'; 'Type' = 'String'; 'Value' = 'someval'; 'Path' = 'SOFTWARE\Microsoft\Windows\Something'}
      
        This example would modify the string registry value 'Type' in the path 'SOFTWARE\Microsoft\Windows\Something' to 'someval'
        for every user registry hive.
    .PARAMETER RegistryInstance
         A hash table containing key names of 'Name' designating the registry value name, 'Type' to designate the type
        of registry value which can be 'String,Binary,Dword,ExpandString or MultiString', 'Value' which is the value itself of the
        registry value and 'Path' designating the parent registry key the registry value is in.
    #>
 
    [CmdletBinding()] 
    param ( 
        [Parameter(Mandatory=$True)] 
        [hashtable[]]$RegistryInstance 
    ) 
    try { 
        New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null 
         
        ## Change the registry values for the currently logged on user. Each logged on user SID is under HKEY_USERS
        $LoggedOnSids = (GET-ChildItem HKU: | where { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' }).PSChildName 
        Write-Host "Found $($LoggedOnSids.Count) logged on user SIDs" 
        foreach ($sid in $LoggedOnSids) { 
            Write-Host -Message "Loading the user registry hive for the logged on SID $sid" 
            foreach ($instance in $RegistryInstance) { 
                ## Create the key path if it doesn't exist
                New-Item -ErrorAction SilentlyContinue -Path ("HKU:\$sid\$($instance.Path)" | Split-Path -Parent) -Name ("HKU:\$sid\$($instance.Path)" | Split-Path -Leaf) | Out-Null 
                ## Create (or modify) the value specified in the param
                SET-ItemProperty -Path "HKU:\$sid\$($instance.Path)" -Name $instance.Name -Value $instance.Value -Type $instance.Type -Force -ErrorAction SilentlyContinue
            } 
        } 
         
        ## Create the Active Setup registry key so that the reg add cmd will get ran for each user
        ## logging into the machine.
        ## http://www.itninja.com/blog/view/an-active-setup-primer
        Write-Host "Setting Active Setup registry value to apply to all other users" 
        foreach ($instance in $RegistryInstance) { 
            ## Generate a unique value (usually a GUID) to use for Active Setup
            $Guid = [guid]::NewGuid().Guid 
            $ActiveSetupRegParentPath = 'HKLM:\Software\Microsoft\Active Setup\Installed Components' 
            ## Create the GUID registry key under the Active Setup key
            New-Item -Path $ActiveSetupRegParentPath -Name $Guid -ErrorAction SilentlyContinue | Out-Null -ErrorAction SilentlyContinue
            $ActiveSetupRegPath = "HKLM:\Software\Microsoft\Active Setup\Installed Components\$Guid" 
            Write-Host "Using registry path '$ActiveSetupRegPath'" 
             
            ## Convert the registry value type to one that reg.exe can understand. This will be the
            ## type of value that's created for the value we want to set for all users
            switch ($instance.Type) { 
                'String' { 
                    $RegValueType = 'REG_SZ' 
                } 
                'Dword' { 
                    $RegValueType = 'REG_DWORD' 
                } 
                'Binary' { 
                    $RegValueType = 'REG_BINARY' 
                } 
                'ExpandString' { 
                    $RegValueType = 'REG_EXPAND_SZ' 
                } 
                'MultiString' { 
                    $RegValueType = 'REG_MULTI_SZ' 
                } 
                default { 
                    throw "Registry type '$($instance.Type)' not recognized" 
                } 
            } 
             
            ## Build the registry value to use for Active Setup which is the command to create the registry value in all user hives
            $ActiveSetupValue = "reg add `"{0}`" /v {1} /t {2} /d {3} /f" -f "HKCU\$($instance.Path)", $instance.Name, $RegValueType, $instance.Value 
            Write-Host -Message "Active setup value is '$ActiveSetupValue'" 
            ## Create the necessary Active Setup registry values
            SET-ItemProperty -Path $ActiveSetupRegPath -Name '(Default)' -Value 'Active Setup Test' -ErrorAction SilentlyContinue
            SET-ItemProperty -Path $ActiveSetupRegPath -Name 'Version' -Value '1' -ErrorAction SilentlyContinue
            SET-ItemProperty -Path $ActiveSetupRegPath -Name 'StubPath' -Value $ActiveSetupValue -ErrorAction SilentlyContinue
        } 
    } catch { 
        Write-Warning -Message $_.Exception.Message 
    } 
}

    IF ($DisableAADWAM -eq $True) {

        IF (ErrorCheck-AdministratorElevation) { RETURN }

        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'DisableAADWAM'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'Software\Microsoft\Office\16.0\Common\Identity'} 
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'DisableADALatopWAMOverride'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'Software\Microsoft\Office\16.0\Common\Identity'} 
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'EnableADAL'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'Software\Microsoft\Office\16.0\Common\Identity'} 

        New-ItemProperty -Path "SOFTWARE\Microsoft\Cryptography\Protect\Providers\df9d8cd0-1501-11d1-8c7a-00c04fc297eb" -Name ProtectionPolicy -Value 1 -ErrorAction SilentlyContinue
        SET-ItemProperty -Path "SOFTWARE\Microsoft\Cryptography\Protect\Providers\df9d8cd0-1501-11d1-8c7a-00c04fc297eb" -Name ProtectionPolicy -Value 1 -ErrorAction SilentlyContinue
        
        Write-Host "DisableAADWAM Successful"
        Write-Host  
    }
       
    IF ($ClearAppData -eq $True -and $ForceLogoff -eq $False) {
        IF (ErrorCheck-AdministratorElevation) { RETURN }      

        Write-Warning “You must specify the -ForceLogoff parameter to run the -ClearAppData parameter.”
        RETURN
    }

    IF ($ClearAppData -eq $True -and $ForceLogoff -eq $True) {

        IF (ErrorCheck-AdministratorElevation) { RETURN }     
        
        quser | Select-Object -Skip 1 | ForEach-Object {
            $id = ($_ -split ' +')[-6]
            logoff $id
        }

        While ( (GET-Process -Name Outlook -ErrorAction SilentlyContinue) -ne $null) { Stop-Process -Name Outlook -ErrorAction SilentlyContinue } 
        While ( (GET-Process -Name WinWord -ErrorAction SilentlyContinue) -ne $null) { Stop-Process -Name WinWord -ErrorAction SilentlyContinue } 
        While ( (GET-Process -Name Excel -ErrorAction SilentlyContinue) -ne $null) { Stop-Process -Name Excel -ErrorAction SilentlyContinue } 
        While ( (GET-Process -Name OneDrive -ErrorAction SilentlyContinue) -ne $null) { Stop-Process -Name OneDrive -ErrorAction SilentlyContinue } 
        While ( (GET-Process -Name PowerPnt -ErrorAction SilentlyContinue) -ne $null) { Stop-Process -Name PowerPnt -ErrorAction SilentlyContinue } 
        While ( (GET-Process -Name Teams -ErrorAction SilentlyContinue) -ne $null) { Stop-Process -Name Teams -ErrorAction SilentlyContinue } 

        $TokenSet = @{
                U = [Char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                L = [Char[]]'abcdefghijklmnopqrstuvwxyz'
                N = [Char[]]'0123456789'
            }

        $Upper = GET-Random -Count 5 -InputObject $TokenSet.U
        $Lower = GET-Random -Count 5 -InputObject $TokenSet.L
        $Number = GET-Random -Count 5 -InputObject $TokenSet.N
        $StringSet = $Upper + $Lower + $Number
        $Random1 = (GET-Random -Count 10 -InputObject $StringSet) -join ''
        $Upper = GET-Random -Count 5 -InputObject $TokenSet.U
        $Lower = GET-Random -Count 5 -InputObject $TokenSet.L
        $Number = GET-Random -Count 5 -InputObject $TokenSet.N
        $StringSet = $Upper + $Lower + $Number
        $Random2 = (GET-Random -Count 10 -InputObject $StringSet) -join ''

        $Users = GET-Item -Path "C:\Users\*"

        FOREACH ($User in $Users) { 
            $UserFolder = $User.Name
            Rename-Item C:\Users\$UserFolder\AppData\Local\Packages\Microsoft.AAD.BrokerPlugin_cw5n1h2txyewy C:\Users\$UserFolder\AppData\Local\Packages\Microsoft.AAD.BrokerPlugin.bak.$Random1 -ErrorAction SilentlyContinue
            Rename-Item C:\Users\$UserFolder\AppData\Local\Packages\Microsoft.AAD.BrokerPlugin_cw5n1h2txyewy C:\Users\$UserFolder\AppData\Local\Packages\Microsoft.AAD.BrokerPlugin.bak.$Random2 -ErrorAction SilentlyContinue
            Rename-Item C:\Users\$UserFolder\AppData\Local\Packages\Microsoft.AccountsControl_cw5n1h2txyewy C:\Users\$UserFolder\AppData\Local\Packages\Microsoft.AccountsControl.bak.$Random1 -ErrorAction SilentlyContinue
            Rename-Item C:\Users\$UserFolder\AppData\Local\Packages\Microsoft.AccountsControl_cw5n1h2txyewy C:\Users\$UserFolder\AppData\Local\Packages\Microsoft.AccountsControl.bak.$Random2 -ErrorAction SilentlyContinue
        }

        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'DisableAADWAM'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'Software\Microsoft\Office\16.0\Common\Identity'} 
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'DisableADALatopWAMOverride'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'Software\Microsoft\Office\16.0\Common\Identity'} 
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'EnableADAL'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'Software\Microsoft\Office\16.0\Common\Identity'} 

        New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
        New-ItemProperty -Path "SOFTWARE\Microsoft\Cryptography\Protect\Providers\df9d8cd0-1501-11d1-8c7a-00c04fc297eb" -Name ProtectionPolicy -Value 1
        SET-ItemProperty -Path "SOFTWARE\Microsoft\Cryptography\Protect\Providers\df9d8cd0-1501-11d1-8c7a-00c04fc297eb" -Name ProtectionPolicy -Value 1
    }
}
FUNCTION SET-OutlookMailboxCacheMode {

    <#
    .SYNOPSIS
        Sets Outlook cache mode for all users on the computer.
 
    .DESCRIPTION
 
        PARAMETERS
            -CacheMode PrimaryAndShared (Sets the Cache Mode to Primary and Shared Mailboxes)
            -CacheMode PrimaryOnly (Sets the Cache Mode to Primary Mailbox Only)
            -CacheMode None (Sets the Cache Mode to None, Online Mode Only)
 
        NOTES
            N/A
 
        TIPS
            N/A
 
    .EXAMPLE
        SET-OutlookMailboxCacheMode -CacheMode None (Sets the Cache Mode to None, Online Mode Only)
 
        Sets all user's Outlook to online mode only.
 
    .EXAMPLE
        SET-OMCM -CacheMode PrimaryAndShared (Sets the Cache Mode to Primary and Shared Mailboxes)
 
        Enabled cache mode for all users for all mailboxes.
     
    .LINK
        https://bjn.itglue.com/1902395/docs/14305861
    #>


    param(
        [Parameter(Mandatory, ParameterSetName = 'CacheMode')]
        [ValidateSet("PrimaryAndShared","PrimaryOnly","None")]
        [String]$CacheMode
    )    
    
    IF (ErrorCheck-AdministratorElevation) { RETURN }

    FUNCTION SET-RegistryValueForAllUsers { 
    <#
    .SYNOPSIS
        This FUNCTION uses Active Setup to create a "seeder" key which creates or modifies a user-based registry value
        for all users on a computer. If the key path doesn't exist to the value, it will automatically create the key and add the value.
    .EXAMPLE
        PS> SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Setting'; 'Type' = 'String'; 'Value' = 'someval'; 'Path' = 'SOFTWARE\Microsoft\Windows\Something'}
      
        This example would modify the string registry value 'Type' in the path 'SOFTWARE\Microsoft\Windows\Something' to 'someval'
        for every user registry hive.
    .PARAMETER RegistryInstance
         A hash table containing key names of 'Name' designating the registry value name, 'Type' to designate the type
        of registry value which can be 'String,Binary,Dword,ExpandString or MultiString', 'Value' which is the value itself of the
        registry value and 'Path' designating the parent registry key the registry value is in.
    #>
 
    [CmdletBinding()] 
    param ( 
        [Parameter(Mandatory=$True)] 
        [hashtable[]]$RegistryInstance 
    ) 
    try { 
        New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null 
         
        ## Change the registry values for the currently logged on user. Each logged on user SID is under HKEY_USERS
        $LoggedOnSids = (GET-ChildItem HKU: | where { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' }).PSChildName 
        Write-Host "Found $($LoggedOnSids.Count) logged on user SIDs" 
        foreach ($sid in $LoggedOnSids) { 
            Write-Host -Message "Loading the user registry hive for the logged on SID $sid" 
            foreach ($instance in $RegistryInstance) { 
                ## Create the key path if it doesn't exist
                New-Item -ErrorAction SilentlyContinue -Path ("HKU:\$sid\$($instance.Path)" | Split-Path -Parent) -Name ("HKU:\$sid\$($instance.Path)" | Split-Path -Leaf) | Out-Null
                ## Create (or modify) the value specified in the param
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office" -ErrorAction SilentlyContinue
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0" -ErrorAction SilentlyContinue
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0\Outlook" -ErrorAction SilentlyContinue
                New-Item -Path "HKU:\$sid\SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode" -ErrorAction SilentlyContinue

                SET-ItemProperty -Path "HKU:\$sid\$($instance.Path)" -Name $instance.Name -Value $instance.Value -Type $instance.Type -Force 
            } 
        } 
         
        ## Create the Active Setup registry key so that the reg add cmd will get ran for each user
        ## logging into the machine.
        ## http://www.itninja.com/blog/view/an-active-setup-primer
        Write-Host "Setting Active Setup registry value to apply to all other users" 
        foreach ($instance in $RegistryInstance) { 
            ## Generate a unique value (usually a GUID) to use for Active Setup
            $Guid = [guid]::NewGuid().Guid 
            $ActiveSetupRegParentPath = 'HKLM:\Software\Microsoft\Active Setup\Installed Components' 
            ## Create the GUID registry key under the Active Setup key
            New-Item -ErrorAction SilentlyContinue -Path $ActiveSetupRegParentPath -Name $Guid | Out-Null 
            $ActiveSetupRegPath = "HKLM:\Software\Microsoft\Active Setup\Installed Components\$Guid" 
            Write-Host "Using registry path '$ActiveSetupRegPath'" 
             
            ## Convert the registry value type to one that reg.exe can understand. This will be the
            ## type of value that's created for the value we want to set for all users
            switch ($instance.Type) { 
                'String' { 
                    $RegValueType = 'REG_SZ' 
                } 
                'Dword' { 
                    $RegValueType = 'REG_DWORD' 
                } 
                'Binary' { 
                    $RegValueType = 'REG_BINARY' 
                } 
                'ExpandString' { 
                    $RegValueType = 'REG_EXPAND_SZ' 
                } 
                'MultiString' { 
                    $RegValueType = 'REG_MULTI_SZ' 
                } 
                default { 
                    throw "Registry type '$($instance.Type)' not recognized" 
                } 
            } 
             
            ## Build the registry value to use for Active Setup which is the command to create the registry value in all user hives
            $ActiveSetupValue = "reg add `"{0}`" /v {1} /t {2} /d {3} /f" -f "HKCU\$($instance.Path)", $instance.Name, $RegValueType, $instance.Value 
            Write-Host -Message "Active setup value is '$ActiveSetupValue'" 
            ## Create the necessary Active Setup registry values
            SET-ItemProperty -Path $ActiveSetupRegPath -Name '(Default)' -Value 'Active Setup Test' -ErrorAction SilentlyContinue
            SET-ItemProperty -Path $ActiveSetupRegPath -Name 'Version' -Value '1' -ErrorAction SilentlyContinue
            SET-ItemProperty -Path $ActiveSetupRegPath -Name 'StubPath' -Value $ActiveSetupValue -ErrorAction SilentlyContinue
        } 
    } catch { 
        Write-Warning -Message $_.Exception.Message 
    } 
}

    IF($CacheMode -eq "PrimaryAndShared") {
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'CacheOthersMail'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'DownloadSharedFolders'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Enable'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'NoOST'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Microsoft\Office\16.0\Outlook\OST'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'SyncWindowSetting'; 'Type' = 'DWORD'; 'Value' = '36'; 'Path' = 'Software\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
     }

    IF($CacheMode -eq "PrimaryOnly") {
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'CacheOthersMail'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'DownloadSharedFolders'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Enable'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'NoOST'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Microsoft\Office\16.0\Outlook\OST'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'SyncWindowSetting'; 'Type' = 'DWORD'; 'Value' = '36'; 'Path' = 'Software\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
    }

    IF($CacheMode -eq "None") {
        While (GET-Process "Outlook" -ErrorAction SilentlyContinue) {
        taskkill /IM “outlook.exe” /f
        Start-Sleep -Seconds 5
        }
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'CacheOthersMail'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Enable'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'DownloadSharedFolders'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Policies\Microsoft\Office\16.0\Outlook\Cached Mode'}
        SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'NoOST'; 'Type' = 'DWORD'; 'Value' = '2'; 'Path' = 'SOFTWARE\Microsoft\Office\16.0\Outlook\OST'}
        FOREACH ($Profile in $Profiles) {
            $SearchPath = $Profile.FullName + "\AppData\Local\Microsoft\Outlook"
            $OSTs = GET-ChildItem -Path $SearchPath -ErrorAction SilentlyContinue | where { $_.Name -like "*.ost*" } 
            FOREACH ($OST in $OSTs) {
                Remove-Item $OST.FullName
            }
        }
    } 
}
FUNCTION GET-DNSInfo {

}
FUNCTION SET-WindowsLocalAccountEnumerationSetting { 

    <#
    .SYNOPSIS
        Sets the status of the Local Account Enumeration feature.
 
    .DESCRIPTION
 
        PARAMETERS
            N/A
 
        NOTES
            Enabling this setting allows users to see local accounts in the bottom left of the screen on a domain joined computer. Without this setting the only options that will show are the last logged in user\currently logged in users, and 'Other User'.
 
        TIPS
            N/A
 
    .EXAMPLE
        SET-LocalAccountEnumeration -Enable
 
        Enables the Local Account Enumeration feature.
 
    .EXAMPLE
        SET-LocalAccountEnumeration -Disable
 
        Disables the Local Account Enumeration feature.
     
    .LINK
        https://bjn.itglue.com/1902395/docs/14305861
    #>


    param(
        [Parameter(Mandatory, ParameterSetName="Enable")]
        [Switch]$Enable = $False,

        [Parameter(Mandatory, ParameterSetName="Disable")]
        [Switch]$Disable = $False
    )
    
    IF (ErrorCheck-AdministratorElevation) { RETURN }
    
    IF ($Enable -eq $True) {
        New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name EnumerateLocalUsers -Value 1 -ErrorAction SilentlyContinue
        SET-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name EnumerateLocalUsers -Value 1 -ErrorAction SilentlyContinue

        $Action
    }

    IF ($Disable -eq $True) {
        New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name EnumerateLocalUsers -Value 0 -ErrorAction SilentlyContinue
        SET-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name EnumerateLocalUsers -Value 0 -ErrorAction SilentlyContinue
    }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        RegistryPurpose = "Blocks Other Users From Logging In Unless Current User Logs Out"
        RegistryKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
        RegistryName = "HideFastUserSwitching"
        CurrentValue = $Current.CurrentValue
        CurrentValueString = $Current.CurrentValueString
        ActionRequested = $ActionRequested
        ActionResult = $ActionResult 
        EndingValue = $Ending.CurrentValue      
        EndingValueString = $Ending.CurrentValueString
        EndingValueMeaning = $EndingValueMeaning
    }

    RETURN $Results | select RegistryPurpose, RegistryKey, RegistryName, CurrentValue,  CurrentValueString, ActionRequested, ActionResult, EndingValue, EndingValueString, EndingValueMeaning
}
FUNCTION GET-NetworkAdapterIPv6 {

    $Results = GET-NetAdapterBinding | Where-Object ComponentID -EQ 'ms_tcpip6' | Select Name, InterfaceDescription, DisplayName, Enabled

    RETURN $Results
}
FUNCTION SET-NetworkAdapterIPv6 { 
    
    param(
        [Parameter(Mandatory, ParameterSetName="Enable")]
        [Switch]$Enable = $False,

        [Parameter(Mandatory, ParameterSetName="Disable")]
        [Switch]$Disable = $False
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    $IPv6Bindings = GET-NetAdapterBinding | Where-Object ComponentID -EQ 'ms_tcpip6'
    
    IF ($Enable -eq $True) {
        FOREACH ($IPv6Binding in $IPv6Bindings) {
            Enable-NetAdapterBinding -Name $IPv6Binding.Name -ComponentID 'ms_tcpip6'
        }
    }

    IF ($Disable -eq $True) {
        FOREACH ($IPv6Binding in $IPv6Bindings) {
            Disable-NetAdapterBinding -Name $IPv6Binding.Name -ComponentID 'ms_tcpip6'
        }
    }
}
FUNCTION GET-OneDriveBackupSetting {

    $Results = @()
 
    $ItemProp = GET-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -Name KFMBLockOptIn -ErrorAction SilentlyContinue
    IF ($ItemProp.KFMBLockOptIn -eq 0 -or $ItemProp -eq $null) {
        $CurrentStatus = "Disabled"
        $RegistryValue = 0
        $RegistryImplication = "All Users Are Allowed to Enable the OneDrive Backup Feature"
    }
    ELSE { 
        $CurrentStatus = "Enabled"
        $RegistryValue = 1 
        $RegistryImplication = "All Users Are Blocked From Enabling the OneDrive Backup Feature"
    }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        RegistryPurpose = "Blocks the OneDrive Backup Feature for All Users"
        RegistryKey = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
        RegistryName = "KFMBLockOptIn"
        CurrentValue = $RegistryValue
        CurrentValueString = $CurrentStatus
        ActionRequested = "Get"
        ActionResult = "N/A"
        EndingValue = $RegistryValue       
        EndingValueString = $CurrentStatus
        EndingValueMeaning = $RegistryImplication
    }

    RETURN $Results | select RegistryPurpose, RegistryKey, RegistryName, CurrentValue,  CurrentValueString, ActionRequested, ActionResult, EndingValue, EndingValueString, EndingValueMeaning
}
FUNCTION SET-OneDriveBackupSetting {
 
    param(
        [Parameter(Mandatory, ParameterSetName="Enable")]
        [Switch]$Enable = $False,

        [Parameter(Mandatory, ParameterSetName="Disable")]
        [Switch]$Disable = $False
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }

    $Results = @()

    $GetStartResults = GET-OneDriveBackupSetting
    
    IF ($Enable -eq $True) {
        New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -ErrorAction SilentlyContinue
        New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -Name KFMBlockOptIn -Value 1 -ErrorAction SilentlyContinue
        SET-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -Name KFMBlockOptIn -Value 1 -ErrorAction SilentlyContinue

        $GetEndResults = GET-OneDriveBackupSetting
        $EndingValue = $GetEndResults.EndingValue
        $EndingValueString = $GetEndResults.EndingValueString
        $ActionRequested = "Enable"
        IF ($GetEndResults.EndingValue -eq 1) { 
            $ActionResult = "Success"
        }
        ELSE {  
            $ActionResult = "Failure"
        }
        $EndingValue = $GetEndResults.EndingValue
        $EndingValueString = $GetEndResults.EndingValueString
        $EndingValueMeaning = $GetEndResults.EndingValueMeaning
    }

    IF ($Disable -eq $True) {
        New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -ErrorAction SilentlyContinue
        New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -Name KFMBlockOptIn -Value 0 -ErrorAction SilentlyContinue
        SET-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -Name KFMBlockOptIn -Value 0 -ErrorAction SilentlyContinue

        $GetEndResults = GET-OneDriveBackupSetting

        $ActionRequested = "Enable"
        IF ($GetEndResults.EndingValue -eq 0) { 
            $ActionResult = "Success"
        }
        ELSE {  
            $ActionResult = "Failure"
        }
        $EndingValue = $GetEndResults.EndingValue
        $EndingValueString = $GetEndResults.EndingValueString
        $EndingValueMeaning = $GetEndResults.EndingValueMeaning
    }

    $GetResults = GET-OneDriveBackupSetting

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        RegistryPurpose = "Blocks the OneDrive Backup Feature for All Users"
        RegistryKey = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
        RegistryName = "KFMBLockOptIn"
        CurrentValue = $GetStartResults.CurrentValue
        CurrentValueString = $GetStartResults.CurrentValueString
        ActionRequested = $ActionRequested
        ActionResult = $ActionResult
        EndingValue = $EndingValue       
        EndingValueString = $EndingValueString
        EndingValueMeaning = $EndingValueMeaning
    }

    RETURN $Results | select RegistryPurpose, RegistryKey, RegistryName, CurrentValue,  CurrentValueString, ActionRequested, ActionResult, EndingValue, EndingValueString, EndingValueMeaning
}
FUNCTION GET-WindowsSecurityInfo {

    $FWProfiles = GET-NetFirewallProfile
    RETURN $FWProfiles | select Name, Enabled
}
FUNCTION GET-WindowsHideFastUserSwitchingSetting {

    $Results = @()
    
    $FastUserSwitching = GET-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name HideFastUserSwitching -ErrorAction SilentlyContinue
    IF ($FastUserSwitching.HideFastUserSwitching -eq 1) { 
        $CurrentValue = 1
        $CurrentValueString = "Enabled" 
        $EndingVaueMeaning = "Fast User Switching is Not Allowed"
    }
    ELSE { 
        $CurrentValue = 0
        $CurrentValueString = "Disabled"
        $EndingVaueMeaning = "Fast User Switching is Allowed" 
    }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        RegistryPurpose = "Blocks Other Users From Logging In Unless Current User Logs Out"
        RegistryKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
        RegistryName = "HideFastUserSwitching"
        CurrentValue = $CurrentValue
        CurrentValueString = $CurrentValueString
        ActionRequested = "None"
        ActionResult = "N/A"
        EndingValue = $CurrentValue       
        EndingValueString = $CurrentValueString
        EndingValueMeaning = $EndingVaueMeaning
    }

    RETURN $Results | select RegistryPurpose, RegistryKey, RegistryName, CurrentValue,  CurrentValueString, ActionRequested, ActionResult, EndingValue, EndingValueString, EndingValueMeaning
}
FUNCTION SET-WindowsHideFastUserSwitchingSetting { 

    param(
        [Parameter(Mandatory, ParameterSetName="Enable")]
        [Switch]$Enable = $False,

        [Parameter(Mandatory, ParameterSetName="Disable")]
        [Switch]$Disable = $False
    )

    IF (ErrorCheck-AdministratorElevation) { RETURN }
    
    $Current = GET-WindowsHideFastUserSwitchingSetting

    IF ($Enable -eq $True) {
        New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies" -ErrorAction SilentlyContinue 
        New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -ErrorAction SilentlyContinue 
        New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name HideFastUserSwitching -Value 1 -ErrorAction SilentlyContinue
        SET-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name HideFastUserSwitching -Value 1 -ErrorAction SilentlyContinue

        $ActionRequested = "Enable"
        $Ending = GET-WindowsRegistryHideFastUserSwitching

        IF ($Ending.CurrentValue -eq 1) {
            $ActionResult = "Success"
            $EndingValueMeaning = "Fast User Switching is Not Allowed" 
        }
        ELSE
        {
            $ActionResult = "Failure"
            $EndingValueMeaning = "Fast User Switching is Allowed" 
        }
    }

    IF ($Disable -eq $True) {
        New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies" -ErrorAction SilentlyContinue 
        New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -ErrorAction SilentlyContinue
        New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name HideFastUserSwitching -Value 0 -ErrorAction SilentlyContinue
        SET-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name HideFastUserSwitching -Value 0 -ErrorAction SilentlyContinue

        $ActionRequested = "Disable"
        $Ending = GET-WindowsRegistryHideFastUserSwitching

        IF ($Ending.CurrentValue -eq 0) {
            $ActionResult = "Success"
            $EndingValueMeaning = "Fast User Switching is Allowed" 
        }
        ELSE
        {
            $ActionResult = "Failure"
            $EndingValueMeaning = "Fast User Switching is Not Allowed" 
        }
    }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        RegistryPurpose = "Blocks Other Users From Logging In Unless Current User Logs Out"
        RegistryKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
        RegistryName = "HideFastUserSwitching"
        CurrentValue = $Current.CurrentValue
        CurrentValueString = $Current.CurrentValueString
        ActionRequested = $ActionRequested
        ActionResult = $ActionResult 
        EndingValue = $Ending.CurrentValue      
        EndingValueString = $Ending.CurrentValueString
        EndingValueMeaning = $EndingValueMeaning
    }

    RETURN $Results | select RegistryPurpose, RegistryKey, RegistryName, CurrentValue,  CurrentValueString, ActionRequested, ActionResult, EndingValue, EndingValueString, EndingValueMeaning
}
FUNCTION GET-WindowsLocalAccountEnumerationSetting {

    $Results = @()
    
    $LocalAccountEnumeration = GET-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name EnumerateLocalUsers -ErrorAction SilentlyContinue
    IF ($LocalAccountEnumeration.EnumerateLocalUsers -eq 1) { 
        $CurrentValue = 1
        $CurrentValueString = "Enabled" 
        $EndingVaueMeaning = "Enumerate Local Users Enabled"
    }
    ELSE { 
        $CurrentValue = 0
        $CurrentValueString = "Disabled"
        $EndingVaueMeaning = "Enumerate Local Users Disabled" 
    }

    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
        RegistryPurpose = "Blocks Other Users From Logging In Without Unless Other Users Log Out"
        RegistryKey = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System"
        RegistryName = "EnumerateLocalUsers"
        CurrentValue = $CurrentValue
        CurrentValueString = $CurrentValueString
        ActionRequested = "None"
        ActionResult = "N/A"
        EndingValue = $CurrentValue       
        EndingValueString = $CurrentValueString
        EndingValueMeaning = $EndingVaueMeaning
    }

    RETURN $Results | select RegistryPurpose, RegistryKey, RegistryName, CurrentValue,  CurrentValueString, ActionRequested, ActionResult, EndingValue, EndingValueString, EndingValueMeaning
}

New-Alias -Name INTCHECK-All -Value CHECK-All
Export-ModuleMember -FUNCTION CHECK-All -Alias INTCHECK-All

### ### ==============================================================================================
### ### OLD FUNCTIONS
### ### ==============================================================================================

FUNCTION GET-RAMInstalledTotalGB {

    (GET-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum / 1gb
}
FUNCTION GET-CPUUsagePercent {

    param(
        [Parameter()]
        [int]$Seconds = 5
    )


    [int]$Count = 0
    [int]$CPUUsageTotal = 0

    $Now = GET-Date
    
    WHILE ((GET-Date) -le ($Now).AddSeconds($Seconds)) {
        $CPUUsageTotal += (GET-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
        $Count++
        Start-Sleep -Milliseconds 250
    }

    RETURN [int]($CPUUsageTotal / $Count)
}
FUNCTION CHECK-All-Old {

    param (
        [string]$Status = @("","Warning","Error")
    )

$OSInfo = GET-WindowsInfo





$LeftPadding = 30
Write-Host ""
Write-Host " Operating System Information"
Write-Host "============================================================"
$OSName = Check-OSName
Write-Host ("Operating System: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $OSName[0] -ForegroundColor $OSName[1]

$OSBuildVersion = Check-OSBuildVersion
Write-Host ("OS Build Version: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $OSBuildVersion[0] -ForegroundColor $OSBuildVersion[1]

$OSDriveFreeSpace = Check-OSDriveFreeSpace
Write-Host ("OS Free Drive Space: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $OSDriveFreeSpace[0] -ForegroundColor $OSDriveFreeSpace[1] -NoNewline
Write-Host ""
Write-Host ""
Write-Host " Hardware Information"
Write-Host "============================================================"
$OSDriveType = Check-OSDriveType
Write-Host ("OS Drive Type: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $OSDriveType[0] -ForegroundColor $OSDriveType[1] -NoNewline
Write-Host ""
Write-Host ""
Write-Host " Network Information"
Write-Host "============================================================"
$WiredNetwork = Check-WiredNetwork
Write-Host ("Wired Connection: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $WiredNetwork[0] -ForegroundColor $WiredNetwork[1]

$WiredLinkSpeed = Check-WiredLinkSpeed
Write-Host ("Wired Link Speed: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $WiredLinkSpeed[0] -ForegroundColor $WiredLinkSpeed[1]

$WiFiAdapterSSID = Check-WiFiAdapterSSID
Write-Host ("WiFi SSID: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $WiFiAdapterSSID[0] -ForegroundColor $WiFiAdapterSSID[1]

$WiFiProtocol = Check-WiFiProtocol
Write-Host ("WiFi Protocol: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $WiFiProtocol[0] -ForegroundColor $WiFiProtocol[1]

$WiFiSignalStrength = Check-WiFiSignalStrength
Write-Host ("WiFi Signal Strength: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $WiFiSignalStrength[0] -ForegroundColor $WiFiSignalStrength[1]

$WiFiLinkSpeed = Check-WiFiLinkSpeed
Write-Host ("WiFi Link Speed: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $WiFiLinkSpeed[0] -ForegroundColor $WiFiLinkSpeed[1]

$NetworkProfile = Check-NetworkProfile
Write-Host ("Network Profile: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $NetworkProfile[0] -ForegroundColor $NetworkProfile[1]

Write-Host ""
Write-Host " DNS Information"
Write-Host "============================================================"
$DNSSuffixes = Check-DNSSuffixes
Write-Host ("DNS Suffixes: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $DNSSuffixes[0] -ForegroundColor $DNSSuffixes[1]

$DNSResolutionInternal = Check-DNSResolutionInternal
Write-Host ("Internal DNS Test: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $DNSResolutionInternal[0] -ForegroundColor $DNSResolutionInternal[1]

$DNSResolutionExternal = Check-DNSResolutionExternal
Write-Host ("External DNS Test: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $DNSResolutionExternal[0] -ForegroundColor $DNSResolutionExternal[1]

$DNSType = Check-DNSType
Write-Host ("DNS Assignment Type: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $DNSType[0] -ForegroundColor $DNSType[1]
Write-Host ""
Write-Host " Security Information"
Write-Host "============================================================"
$LastSecurityUpdateDate = Check-LastSecurityUpdateDate
Write-Host ("Last Security Update: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $LastSecurityUpdateDate[0] -ForegroundColor $LastSecurityUpdateDate[1]
$CheckCryptoProtocols = Check-CryptoProtocols
Write-Host ("Enabled Crypto Protocols: ").PadLeft($LeftPadding,' ') -NoNewline
Write-Host $CheckCryptoProtocols[0] -ForegroundColor $CheckCryptoProtocols[1]
Write-Host ""

}