SCONFIG.ps1


<#PSScriptInfo
 
.VERSION 2.0
 
.GUID 5ffe2680-c8f3-4e65-8376-e25560f59fe3
 
.AUTHOR Peter Remstad
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 Description: Provides SCONFIG functionality through PowerShell. Has added features including, cleaned up UI, NIC Teaming setup, Firewall and Defender configuration. Script operates correctly on Windows Server 2016 and newer server operating systems. As of verions 2.0, script has been designed to function on both Windows PowerShell 5.x and PowerShell 7.0.
 
 I recommend placing the script file at C:\Windows\System32\ and then modifying C:\Windows\System32\sconfig.cmd so that this script replaces the built-in .vbs sconfig.
 For Windows PowerShell 5.x, change the .cmd file content to:
    echo off
    powershell -File "%windir%\System32\SCONFIG.ps1"
 For PowerShell 7.0, change the .cmd file content to:
    echo off
    pwsh -File "%windir&\System32\SCONFIG.ps1"
 
 NOTE - You will likely need to take ownership and alter permissions on C:\Windows\System32\sconfig.cmd in order to modify the contents of that file.
#>
 

Param()

############################################################################################
# Script Name: SCONFIG.ps1
# Current Version: 2.0
# Written By: Peter Remstad
# Date Created: 2018-03-28
# Date Revised: 2020-05-17
#
# Notes: v1.0 - Feature complete when comparing to old sconfig.vbs that ships with Windows
# Server.
# v1.1 - Improvement: Updated input text for options 1-7 to be more consistent
# v1.2 - Set ideal buffer size for script. Prevents awkward text wrapping.
# v1.3 - Re-ordered main menu options to a more logical order. Added in two options
# which will be developed soon.
# v1.4 - Firewall toggling added.
# v1.5 - Windows Defender toggling added.
# v1.6 - NIC Teaming configurations added, updated network config to handle teaming.
# v1.7 - Bug fixes
# v1.8 - Added requirement for Computer renaming, name may not consist of only
# digits. Update sc_Set-Domain function to be consistent with new Computer
# naming error and change where an error returns the prompt.
# v2.0 - Modifications to ensure script functions under both Windows PowerShell
# 5.x and PowerShell 7.0. Modified IPv6 code to make it a true toggle rather
# than sub-menu. Fixed bug if a NIC is disabled. Added option to
# disable/enable NIC. Replaced WMI calls with CIM calls. Fixed an issue displaying
# firewall status in Windows evaluation versions.
#
############################################################################################

###################################################### EXECUTE SYSTEM INFO QUERY #######################################################
function sc_Create-MainMenu (

)
{
    # RESETS ALL VARIABLES FOR FUNCTION
    $ErrorActionPreference = "SilentlyContinue"
    $Domain = $null
    $CompSys = $null
    $Remote = $null
    $AU = $null
    $Update = $null
    $TSConnect = $null
    $UserAuth = $null
    $RDP = $null
    $TelReg = $null
    $Telem = $null
    $TimeZone = $null
    $ConProf = $null
    $FWStatus = $null
    $Firewall = $null

    Write-Host -ForegroundColor Cyan "Gathing information..."

    # GATHERS ALL DATA
    $CompSys = Get-CimInstance -ClassName Win32_ComputerSystem
    $Remote = Configure-SMRemoting.exe -Get
    $AU = Get-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
    $NoAU = $AU.NoAutoUpdate
    $AU = $AU.AUOptions
    $TSConnect = (Get-ItemProperty -Path "HKLM:\\SYSTEM\CurrentControlSet\Control\Terminal Server").fDenyTSConnections
    $UserAuth = (Get-ItemProperty -Path "HKLM:\\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-TCP").UserAuthentication
    $TelReg = (Get-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\DataCollection").AllowTelemetry
    $TimeZone = Get-TimeZone | Select -Property DisplayName

    # GETS LOCAL TELEMETRY SETTING IF GROUP POLICY SETTING DOESN'T EXIST/APPLY
    If ($TelReg -eq $null) {
        $TelReg = (Get-ItemProperty -Path "HKLM:\\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection").AllowTelemetry
    }

    # MANIPULATES DATA FOR DOMAIN
    If (($CompSys.DomainRole -eq 0) -or ($CompSys.DomainRole -eq 2)) {
        $Domain = "Workgroup: $($CompSys.Domain)"
    } ElseIf (($CompSys.DomainRole -eq 1) -or ($CompSys.DomainRole -eq 3) -or ($CompSys.DomainRole -eq 4) -or ($CompSys.DomainRole -eq 5)) {
        $Domain = "Domain: $($CompSys.Domain)"
    }

    # PROVIDES OUTPUT IF QUERY FAILED FOR REMOTE MANAGEMENT SETTINGS
    If ($Remote -eq $null) {
        $Remote = "Failed query"
    } ElseIf ($Remote -match "disabled") {
        $Remote = "Disabled"
    } ElseIf ($Remote -match "enabled") {
        $Remote = "Enabled"
    }

    # TRANSLATES REGISTRY FOR WINDOWS UPDATE TO USER FRIENDLY OUTPUT
    Switch ($AU) {
        $null {If ($NoAU -eq 1) {$Update = "Manual"} ElseIf ($NoAU -eq $null) {$Update = "Failed Query"} ; break}
        1 {$Update = "Never check for updates" ; break}
        2 {$Update = "Notify before download" ; break}
        3 {$Update = "DownloadOnly" ; break}
        4 {$Update = "Automatic" ; break}
    }

    # TRANSLATES REGISTRY FOR RDP CONFIG TO USER FRIENDLY OUTPUT
    Switch ($TSConnect) {
        $null {$RDP = "Failed Query" ; break}
        0 {If ($UserAuth -eq 0) {$RDP = "Enabled (all clients)"} ElseIf ($UserAuth -eq 1) {$RDP = "Enabled (more secure clients only)"} Else {$RDP = "Failed Query"} ; break}
        1 {$RDP = "Disabled" ; break}
    }

    # TRANSLATES TELEMETRY SETTINGS TO USER FRIENDLY OUTPUT
    Switch ($TelReg) {
        $null {$Telem = "Failed Query" ; break}
        0 {$Telem = "Security" ; break}
        1 {$Telem = "Basic" ; break}
        2 {$Telem = "Enhanced" ; break}
        3 {$Telem = "Full" ; break}
    }

    # GATHERS CONNECTED NETWORK PROFILES
    $ConProf = Get-NetConnectionProfile
    $ConProf = $ConProf.NetworkCategory | Select -Unique

    # GATHERS THE FIREWALL STATUS OF ALL CONNECTED FIREWALL PROFILES
    If ($ConProf.count -eq 1) {

        Switch ($ConProf) {
            0 {$ConProf = "Public"}
            1 {$ConProf = "Private"}
            2 {$ConProf = "DomainAuthenticated"}
        }

        # MODIFIES CONNECTED PROFILE TO USABLE VALUE
        If ($ConProf -eq "DomainAuthenticated") {
            $ConProf = "Domain"
        }

        # GATHERS ASSOCIATED FIREWALL PROFILE
        $FWStatus = (Get-NetFirewallProfile -Name $ConProf).Enabled

        # TRANSLATES STATUS
        If ($FWStatus -eq 0) {
            $FWStatus = $false
        }

        If ($FWStatus -eq 1) {
            $FWStatus = $true
        }

        Switch ($FWStatus) {
            $true {$FWStatus = "Enabled" ; break}
            $false {$FWStatus = "Disabled" ; break}
        }

        # GENERATES STRING
        $Firewall = "$ConProf`: $FWStatus"
    } Else {
        Foreach ($Prof in $ConProf) {

            # CONVERTS A NUMERIC VALUE TO A LEGIBLE VALUE IF NEEDED
            Switch ($ConfProf) {
                0 {$Prof = "Public"}
                1 {$Prof = "Private"}
                2 {$Prof = "DomainAuthenticated"}
            }
                
            # MODIFIES CONNECTED PROFILE TO USABLE VALUE
            If ($Prof -eq "DomainAuthenticated") {
                $Prof = "Domain"
            }

            # GATHERS ASSOCIATED FIREWALL PROFILE
            $FWStatus = (Get-NetFirewallProfile -Name $Prof).Enabled

            # TRANSLATES STATUS
            If ($FWStatus -eq 0) {
                $FWStatus = $false
            }

            If ($FWStatus -eq 1) {
                $FWStatus = $true
            }
            
            Switch ($FWStatus) {
                $true {$FWStatus = "Enabled" ; break}
                $false {$FWStatus = "Disabled" ; break}
            }

            # GENERATES STRING
            $Firewall += "$Prof`: $FWStatus "
        }
    }

    $TextArray = @()

    $TextArray += New-Object -TypeName psobject -Property @{Item = "1) Domain/Workgroup:"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "$Domain"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "2) Computer Name:"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "$($CompSys.Name)"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "3) Add Local Administrator"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "4) Date and Time:"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "$($TimeZone.DisplayName)"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "5) Network Settings"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "6) NIC Teaming"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "7) Firewall Settings:"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "$Firewall"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "8) Telemetry Settings:"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "$Telem"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "9) Windows Activation"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "10) Windows Defender"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "11) Configure Remote Management:"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "$Remote"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "12) Remote Desktop:"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "$RDP"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "13) Windows Update Settings:"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "$Update"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "14) Download and Install Updates"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "15) Log Off User"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "16) Restart Server"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "17) Shut Down Server"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}
    $TextArray += New-Object -TypeName psobject -Property @{Item = "18) Exit SCONFIG"}
    $TextArray += New-Object -TypeName psobject -Property @{Item = ""}

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
====================================================================================
                                Server Configuration
===================================================================================="


    # RETURNS TEXT DATA
    Write-Output $OutputText
    $TextArray | Format-Wide -Property Item -Column 2

    # DEFINES VALID OPTIONS
    $ValidInput = @(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)

    # GATHERS SELECTED OPTION
    [int]$Choice = Read-Host "Enter number to select an option"

    # VALIDATES SELECTED OPTION ; RETURNS TO MAIN MENU ON BAD INPUT
    If ($ValidInput -notcontains $Choice) {
        Write-Host -ForegroundColor Yellow "Invalid input, returning to main menu..."

        Start-Sleep -Seconds 1

        sc_Create-MainMenu
    }

    # EXECUTES SELECTED OPTION
    Switch ($Choice) {

        1 {sc_Set-Domain ; break}
        2 {sc_Set-ComputerName ; break}
        3 {sc_Add-LocalAdmin ; break}
        4 {sc_Set-DateTime ; break}
        5 {sc_Set-Network ; break}
        6 {sc_Config-NICTeaming ; break}
        7 {sc_Set-Firewall ; break}
        8 {sc_Set-Telemetry ; break}
        9 {sc_Set-WinAct ; break}
        10 {sc_Set-WinDefend ; break}
        11 {sc_Set-RemoteMgmt ; break}
        12 {sc_Set-RDP ; break}
        13 {sc_Set-WindowsUpdate ; break}
        14 {sc_Execute-WindowsUpdate ; break}
        15 {sc_Logoff ; break}
        16 {sc_Restart ; break}
        17 {sc_Shutdown ; break}
        18 {sc_Exit ; break}
    }
}

######################################################## CHANGE DOMAIN/WORKGROUP #######################################################
function sc_Set-Domain (

)
{
    # RESETS VARIABLES FOR FUNCTION
    $DomOrWork = $null
    $DWname = $null
    $NewName = $null
    $ValidDW = $null
    $OutputText = $null

    # EXECUTES DOMAIN JOIN
    function sc_Join-Domain (
        [parameter(Mandatory=$true)]$DName
    )
    {
        # RESETS VARIABLES FOR FUNCTION
        $DCred = $null

        # DEFINES VALID COMPUTER CHARCATERS
        $Characters = "[][\\/;:*?`"`'<>|,~!@#$%^&.(){}_``=+ ]"

        # GETS CREDENTIALS AND NEW NAME
        $DCred = Get-Credential -Message "Specify an authorized domain\user"

        # GATHERS INPUT
        $NewName = $null
        $NewName = Read-Host "Enter new name for this computer (Blank = keep current name)"

        # THROWS ERROR MESSAGE AND RETURNS TO SET DOMAIN MENU
        If ($NewName -match $Characters) {
            Write-Host -ForegroundColor Red "Invalid characters used. The following characters are illegal:"
            Write-Host -ForegroundColor Yellow "$Characters"
            Write-Host -ForegroundColor Yellow "Returning to Set Domain menu..."

            Start-Sleep -Seconds 2

            sc_Set-Domain
        }

        # THROWS ERROR MESSAGE AND RETURNS TO SET DOMAIN MENU
        If ($NewName.Length -ge 16) {
            Write-Host -ForegroundColor Red "Name is too long. A valid name must be 15 characters or shorter."
            Write-Host -ForegroundColor Yellow "Returning to Set Domain menu..."

            Start-Sleep 2

            sc_Set-Domain
        }

        # THROWS ERROR MESSAGE AND RETURNS TO SET DOMAIN MENU
        If ($NewName -match "^\d+$") {
            Write-Host -ForegroundColor Red "Name may not contain only digits"
            Write-Host -ForegroundColor Yellow "Returning to Set Domain menu..."

            Start-Sleep -Seconds 2

            sc_Set-Domain
        }

        # EXECUTES DOMAIN JOIN
        If ($NewName -eq "") {
            Add-Computer -DomainName $DName -Credential $DCred
            sc_Create-MainMenu
        } Else {
            Add-Computer -DomainName $DName -NewName $NewName -Credential $DCred
            sc_Create-MainMenu
        }
    }

    # EXECUTES WORKGROUP JOIN
    function sc_Join-Workgroup (
        [parameter(Mandatory=$true)]$WName
    )
    {
        # RESETS VARIABLES FOR FUNCTION
        $DCred = $null
        $DCheck = $null
        $NewName = $null

        # CHECKS IF CURRENTLY IN A DOMAIN AND GETS NEW NAME
        $DCheck = Get-CimInstance -ClassName Win32_ComputerSystem

        # DEFINES VALID COMPUTER CHARCATERS
        $Characters = "[][\\/;:*?`"`'<>|,~!@#$%^&.(){}_``=+ ]"

        # GATHERS INPUT
        $NewName = $null
        $NewName = Read-Host "Enter new name for this computer (Blank = keep current name)"

        # THROWS ERROR MESSAGE AND RETURNS TO SET DOMAIN MENU
        If ($NewName -match $Characters) {
            Write-Host -ForegroundColor Red "Invalid characters used. The following characters are illegal:"
            Write-Host -ForegroundColor Yellow "$Characters"
            Write-Host -ForegroundColor Yellow "Returning to Set Domain menu..."

            Start-Sleep -Seconds 2

            sc_Set-Domain
        }

        # THROWS ERROR MESSAGE AND RETURNS TO SET DOMAIN MENU
        If ($NewName.Length -ge 16) {
            Write-Host -ForegroundColor Red "Name is too long. A valid name must be 15 characters or shorter."
            Write-Host -ForegroundColor Yellow "Returning to Set Domain menu..."

            Start-Sleep 2

            sc_Set-Domain
        }

        # THROWS ERROR MESSAGE AND RETURNS TO SET DOMAIN MENU
        If ($NewName -match "^\d+$") {
            Write-Host -ForegroundColor Red "Name may not contain only digits"
            Write-Host -ForegroundColor Yellow "Returning to Set Domain menu..."

            Start-Sleep -Seconds 2

            sc_Set-Domain
        }

        # IF IN A DOMAIN, GATHERS CREDS ; EXECUTES WORKGROUP JOIN
        If (($DCheck.DomainRole -ne 0) -and ($DCheck.DomainRole -ne 2)) {
            $DCred = Get-Credential -Message "Specify credentials to unjoin domain"
            If ($NewName -eq "") {
                Add-Computer -DomainName $WName -Credential $DCred
                sc_Create-MainMenu
            } Else {
                Add-Computer -DomainName $WName -NewName $NewName -Credential $DCred
                sc_Create-MainMenu
            }
        } Else {
            If ($NewName -eq "") {
                Add-Computer -DomainName $WName
                sc_Create-MainMenu
            } Else {
                Add-Computer -DomainName $WName -NewName $NewName
                sc_Create-MainMenu
            }
        }
    }

    $ValidDW = @(1,2,3)

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
------ JOIN DOMAIN/WORKGROUP ------
 
1) Join Domain
2) Join Workgroup
 
3) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS OPTION UNTIL VALID CHOICE IS MADE
    Do {
        $DomOrWork = $null
        $DomOrWork = Read-Host "Enter selection"
    } While ($ValidDW -notcontains $DomOrWork)

    # EXECUTES SELECTED OPTION
    Switch ($DomOrWork) {
        1 {$DWname = Read-Host "Name of domain to join" ; sc_Join-Domain -DName $DWname ; break}
        2 {$DWname = Read-Host "Name of workgroup to join" ; sc_Join-Workgroup -WName $DWname ; break}
        3 {sc_Create-MainMenu ; break}
    }
}

########################################################## CHANGE COMPUTER NAME ########################################################
function sc_Set-ComputerName (

)
{
    # RESETS VARIABLES FOR FUNCTION
    $NewName = $null
    $DCheck = $null
    $Characters = $null

    # CHECKS IF CURRENTLY IN A DOMAIN AND GETS NEW NAME
    $DCheck = Get-CimInstance -ClassName Win32_ComputerSystem

    # DEFINES VALID COMPUTER CHARCATERS
    $Characters = "[][\\/;:*?`"`'<>|,~!@#$%^&.(){}_``=+ ]"

    # GATHERS INPUT
    $NewName = $null
    $NewName = Read-Host "Enter new computer name (Blank=Cancel)"

    # IF BLANK RETURNS TO MAIN MENU
    If ($NewName -eq "") {
        sc_Create-MainMenu
    }

    # THROWS ERROR MESSAGE AND RETURNS TO MAIN MENU
    If ($NewName -match $Characters) {
        Write-Host -ForegroundColor Red "Invalid characters used. The following characters are illegal:"
        Write-Host -ForegroundColor Red "$($Characters.Substring(1,32))"
        Write-Host -ForegroundColor Yellow "Returning to main menu..."

        Start-Sleep -Seconds 2

        sc_Create-MainMenu
    }

    # THROWS ERROR MESSAGE AND RETURNS TO MAIN MENU
    If ($NewName.Length -ge 16) {
        Write-Host -ForegroundColor Red "Name is too long. A valid name must be 15 characters or shorter."
        Write-Host -ForegroundColor Yellow "Returning to main menu..."

        Start-Sleep -Seconds 2

        sc_Create-MainMenu
    }

    # THROWS ERROR MESSAGE AND RETURNS TO MAIN MENU
    If ($NewName -match "^\d+$") {
        Write-Host -ForegroundColor Red "Name may not contain only digits"
        Write-Host -ForegroundColor Yellow "Returning to main menu..."

        Start-Sleep -Seconds 2

        sc_Create-MainMenu
    }

    # IF IN A DOMAIN, GATHERS CREDS ; CHANGES SYSTEM NAME
    If (($DCheck.DomainRole -ne 0) -and ($DCheck.DomainRole -ne 2)) {
        $DCred = Get-Credential -Message "Specify credentials to update computer object"
        Rename-Computer -NewName $NewName -DomainCredential $DCred
        sc_Create-MainMenu
    } Else {
        Rename-Computer -NewName $NewName
        sc_Create-MainMenu
    }
}

######################################################## ADD LOCAL ADMINISTRATOR #######################################################
function sc_Add-LocalAdmin (

)
{
    # RESETS VARIABLES FOR FUNCTION
    $CompSys = $null
    $LocAdmin = $null
    $LocUser = $null
    $Pass = $null
    $OutputText = $null
    $Characters = $null

    # GATHERS DATA
    $CompSys = Get-CimInstance -ClassName Win32_ComputerSystem

    # DEFINES VALID COMPUTER CHARCATERS
    $Characters = "[][\\/:*?`"<>|,;@]"

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
In a domain environment, specify domain\username.
In a workgroup environment, specify username.
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS ADMIN ACCOUNT NAME
    $LocAdmin = Read-Host "Enter account to join local Administrators group (Blank=Cancel)"

    # ADDS ACCOUNT TO LOCAL ADMIN GROUP ; WILL CREATE USER IF IN A WORKGROUP AND USER DOESN'T EXIST
    If ($LocAdmin -ne "") {
        # WORKGROUP/NON-DOMAIN PROCESS
        If (($CompSys.DomainRole -eq 0) -or ($CompSys.DomainRole -eq 2)) {

            # ERRORS IF INVALID CHARACTERS ARE USED
            If ($LocAdmin -match $Characters) {
                Write-Host -ForegroundColor Yellow "Invalid characters used. The following characters are illegal:"
                Write-Host -ForegroundColor Yellow "$($Characters.Substring(1,14))"
                Write-Host -ForegroundColor Yellow "Returning to main menu..."

                Start-Sleep -Seconds 2

                sc_Create-MainMenu
            }

            If ($LocAdmin.Length -ge 16) {
                Write-Host -ForegroundColor Yellow "Name is too long. A valid name must be 15 characters or shorter."
                Write-Host -ForegroundColor Yellow "Returning to main menu..."

                Start-Sleep -Seconds 2

                sc_Create-MainMenu
            }

            # CHECKS FOR USER ACCOUNT, CREATES IF MISSING, OTHERWISE ADDS TO ADMINISTRATORS
            $LocUser = Get-LocalUser -Name $LocAdmin -ErrorAction SilentlyContinue
            If ($LocUser -eq $null) {
                $Pass = Read-Host -AsSecureString "Enter password for user account"
                New-LocalUser -Name $LocAdmin -Password $Pass | Add-LocalGroupMember -Group Administrators

                sc_Create-MainMenu
            } Else {
                Add-LocalGroupMember -Group Administrators -Member $LocAdmin

                sc_Create-MainMenu
            }
        # DOMAIN PROCESS
        } Else {
            # VALIDATES A DOMAIN WAS PROVIDED
            If ($LocAdmin.Split('\\')[1] -eq $null) {
                Write-Host -ForegroundColor Yellow "Domain systems may only add domain accounts."
                Write-Host -ForegroundColor Yellow "No domain provide in input. Returning to main menu..."

                Start-Sleep -Seconds 1

                sc_Create-MainMenu
            }

            Add-LocalGroupMember -Group Administrators -Member $LocAdmin -Verbose

            sc_Create-MainMenu
        }
    } Else {
        sc_Create-MainMenu
    }
}

###################################################### CONFIGURE DATE AND TIME ######################################################
function sc_Set-DateTime (

)
{
    # EXECUTES TIME/DATE CPL
    timedate.cpl
    sc_Create-MainMenu
}

###################################################### CONFIGURE NETWORK SETTINGS ######################################################
function sc_Set-Network (

)
{
    # RESETS ALL VARIABLES FOR FUNCTION
    $AdapterArray = @()
    $NetAdapters = @()
    $NetChoice = $null
    $NetInput = $null
    $IP = $null

    # CONVERTS SUBNETS INTO PREFIXES AND PREFIXES INTO SUBNETS
    function sc_Convert-SubnetInfo (
        [parameter(Mandatory=$false)]$Sub,
        [parameter(Mandatory=$false)]$Pre
    )
    {
        # GENERATES OUTPUT TEXT
        [int]$cnt = 0
        [string]$OutArr = ""
        [string]$BinaryOctet = $null
        [string]$BinaryAddress = $null
        [string]$Subnet = $null
        [string]$Prefix = $null

        # EXECUTES IF SUB WAS INPUTTED
        If ($Sub -ne $null) {

            # PROCESSES EACH OCTET SEPARATELY
            $Sub.Split('.') | Foreach {
                $BinaryOctet = [convert]::ToString($_,2)

                # IF OCTET IS 0, CREATES 8-BITS OF 0
                If ($BinaryOctet -eq 0) {
                    $BinaryOctet = "00000000"
                }

                # MERGES WITH EXISTING DATA
                $BinaryAddress = "$BinaryAddress" + "$BinaryOctet"
            }

            # COUNTS 1 BITS IN ADDRESS AND THEN OUTPUTS PREFIX
            $Prefix = ($BinaryAddress.ToCharArray() | Where {$_ -eq '1'}).count
            Return $Prefix
        }

        # EXECUTES IF PRE WAS INPUTTED
        If ($Pre -ne $null) {
            
            # ADDS A 1 AT THE BACK OF THE STRING UNTIL THE PREFIX NUMBER THEN ADDS A 0 UNTIL ALL 32 BITS ARE ACCOUNNTED FOR
            While ($cnt -lt 32) {
                If ($cnt -lt $Pre) {
                    $OutArr = "$OutArr" + "1"
                } Else {
                    $OutArr = "$OutArr" + "0"
                }

                $cnt++
            }

            # ADDS '.' INTO THE BITS TO MAKE A BINARY ADDRESS
            $BinaryAddress = "$($OutArr.Substring(0,8)).$($OutArr.Substring(8,8)).$($OutArr.Substring(16,8)).$($OutArr.Substring(24,8))"
            $cnt = 0

            # CONVERTS EACH BINARY OCTET TO DECIMAL
            $BinaryAddress.Split('.') | Foreach {
                $Octet = [convert]::ToInt32($_,2)
                If ($cnt -eq 0) {
                    $Subnet = "$Octet"
                } Else {
                    $Subnet = "$Subnet" + "." + "$Octet"
                }
                $cnt++
            }

            # OUTPUTS SUBNET MASK
            Return $Subnet
        }
    }

    # PROVIDES THE INTERFACE AFTER ADAPTER IS SELECTED
    function sc_Modify-NetInterface (
        [parameter(Mandatory=$true)][psobject]$Adapter
    )
    {
        # RESETS ALL VARIABLES FOR FUNCTION
        $OutputText = $null
        $ValidNetConf = @()
        $NetConfChoice = $null
        $IPData = $null
        $cnt = 1
        $ValidNetConf = @(1,2,3,4,5)
        $InvalidDisConf = @(1,2,3)

        # GATHERS INTERFACE IP DATA
        $NICStatus = (Get-NetAdapter -Name $Adapter.Name).Status
        $IPData = sc_Get-NetInfo -Name $Adapter.Name -Status $NICStatus

        # GENERATES OUTPUT TEXT
        $OutputText = "
--------------------------------
      $($Adapter.Name) Settings
--------------------------------
 
        $($IPData | Out-String)
1) Modify IPv4 Address Settings
2) Modify DNS Server Settings
3) Enable/Disable IPv6
4) Enable/Disable NIC
 
5) Return to main menu
 
        "


        # RETURNS TEXT DATA
        Write-Output $OutputText

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $NetConfChoice = $null
            [int]$NetConfChoice = Read-Host "Enter selection"

            If (($NICStatus -eq "Disabled") -and ($InvalidDisConf -contains $NetConfChoice)) {
                Write-Host -ForegroundColor Yellow "Option unavaible while NIC is disabled."
                $NetConfChoice = $null
            }

        } While ($ValidNetConf -notcontains $NetConfChoice)

        # EXECUTES FUNCTIONS FOR PROCESSING CHANGES
        Switch ($NetConfChoice) {
            1 {sc_Set-IPv4 -Data $IPData ; sc_Modify-NetInterface -Adapter $Adapter ; break}
            2 {sc_Modify-DNSSettings -Data $IPData ; sc_Modify-NetInterface -Adapter $Adapter ; break}
            3 {sc_Toggle-IPv6 -Adapter $IPData ; break}
            4 {sc_Toggle-NIC -Adapter $Adapter.Name -Status $NICStatus; break}
            5 {sc_Create-MainMenu ; break}
        }
    }

    # EXECUTES CHANGES TO IPV4 ADDRESSES
    function sc_Set-IPv4 (
        [parameter(Mandatory=$true)]$Data
    )
    {
        # RESETS ALL VARIABLES FOR FUNCTION
        $Prefix = $null
        $Octs = $null
        $IP = $null
        $Subnet = $null
        $Gateway = $null
        $ValidOcts = 0..255
        $OutputText = $null
        $ValidDHCP = @(1,2,3)

        # GENERATES OUTPUT TEXT
        $OutputText = "
------ DHCP or STATIC IP ------
 
1) Use DHCP
2) Use and set a static IP
 
3) Return to NIC Settings
 
        "


        # RETURNS TEXT DATA
        Write-Output $OutputText

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $DHCPChoice = $null
            $DHCPChoice = Read-Host "Enter selection"

        } While ($ValidDHCP -notcontains $DHCPChoice)

        # EXECUTES SELECTED OPTION
        If ($DHCPChoice -eq 1) {
            Set-NetIPInterface -InterfaceAlias $Data.Name -Dhcp Enabled
            Start-Sleep -Seconds 2
            sc_Modify-NetInterface -Adapter $Data
        } ElseIf ($DHCPChoice -eq 2) {
            Set-NetIPInterface -InterfaceAlias $Data.Name -Dhcp Disabled
            $IP = Read-Host "Enter static IP address"
            $Octs = $IP.Split('.')

            # VALIDATES IP HAS 4 OCTETS
            If ($Octs.count -ne 4) {
                Write-Host -ForegroundColor Red "Invalid IP. Input must have 4 octects."
                sc_Modify-NetInterface -Adapter $Data
            }

            # VALIDATES IP VALUES FOR EACH OCTET
            Foreach ($Oct in $Octs) {
                If ($ValidOcts -notcontains $Oct) {
                    Write-Host -ForegroundColor Red "Invalid IP. All octets must be between 0 and 255."
                    sc_Modify-NetInterface -Adapter $Data
                }
            }

            $Subnet = Read-Host "Enter subnet mask (Blank = Default 255.0.0.0)"
            $Octs = $Subnet.Split('.')

            # VALIDATES IP HAS 4 OCTETS
            If ($Octs.count -ne 4) {
                Write-Host -ForegroundColor Red "Invalid IP. Input must have 4 octects."
                sc_Modify-NetInterface -Adapter $Data
            }

            # VALIDATES IP VALUES FOR EACH OCTET
            Foreach ($Oct in $Octs) {
                If ($ValidOcts -notcontains $Oct) {
                    Write-Host -ForegroundColor Red "Invalid IP. All octets must be between 0 and 255."
                    sc_Modify-NetInterface -Adapter $Data
                }
            }

            $Gateway = Read-Host "Enter default gateway"
            $Octs = $Gateway.Split('.')

            # VALIDATES IP HAS 4 OCTETS
            If (($Octs.count -ne 4) -and ($Octs -ne "")) {
                Write-Host -ForegroundColor Red "Invalid IP. Input must have 4 octects."
                sc_Modify-NetInterface -Adapter $Data
            } ElseIf ($Octs.count -eq 4) {
                # VALIDATES IP VALUES FOR EACH OCTET
                Foreach ($Oct in $Octs) {
                    If ($ValidOcts -notcontains $Oct) {
                        Write-Host -ForegroundColor Red "Invalid IP. All octets must be between 0 and 255."
                        sc_Modify-NetInterface -Adapter $Data
                    }
                }
            }

            # DELETES OLD IP DATA
            Remove-NetIPAddress -InterfaceAlias $Data.Name -Confirm:$false
            Remove-NetRoute -InterfaceAlias $Data.Name -AddressFamily IPv4 -NextHop $Data.DefaultGateway -Confirm:$false -ErrorAction SilentlyContinue| Out-Null

            # SETS NEW IP DATA
            New-NetIPAddress -InterfaceAlias $Data.Name -AddressFamily IPv4 -IPAddress $IP -PrefixLength (sc_Convert-SubnetInfo -Sub $Subnet) | Out-Null
            New-NetRoute -InterfaceAlias $Data.Name -AddressFamily IPv4 -NextHop $Gateway -DestinationPrefix "0.0.0.0/0" -Confirm:$false -ErrorAction SilentlyContinue| Out-Null

            sc_Modify-NetInterface -Adapter $Data
        } ElseIf ($DHCPChoice -eq 3) {
            sc_Modify-NetInterface -Adapter $Data
        }
    }

    # GATHERS IP INFO FOR AN INTERFACE
    function sc_Get-NetInfo (
        [parameter(Mandatory=$true)]$Name,
        [parameter(Mandatory=$true)]$Status
    )
    {
        # RESETS ALL VARIABLES FOR FUNCTION
        $TempIPInfo = $null
        $IPv4 = $null
        $SM = $null
        $GW = $null
        $DNS1 = $null
        $DNS2 = $null
        $MAC = $null
        $DHCPStatus = $null
        $IPv6Status = $null
        $IPObject = $null

        # GATHERS ALL RELEVANT IP INFORMATION FROM EACH ADAPTER
        $MAC = (Get-NetAdapter -Name $Name).MacAddress

        If ($Status -eq "Disabled") {
            $TempIPInfo = ""
            $IPv4 = ""
            $SM = ""
            $GW = ""
            $DNS1 = ""
            $DNS2 = ""
            $IPv6Status = ""
        } Else {
            $TempIPInfo = Get-NetIPConfiguration -InterfaceAlias $Name
            $IPv4 = $TempIPInfo.IPv4Address.IPAddress
            $SM = sc_Convert-SubnetInfo -Pre $TempIPInfo.IPv4Address.PrefixLength
            $GW = $TempIPInfo.IPv4DefaultGateway.NextHop
            $DNS1 = (Get-DnsClientServerAddress -InterfaceAlias $Name -AddressFamily IPv4).ServerAddresses[0]
            $DNS2 = (Get-DnsClientServerAddress -InterfaceAlias $Name -AddressFamily IPv4).ServerAddresses[1]
            $IPv6Status = (Get-NetAdapterBinding -Name $Name | Where {$_.ComponentID -eq "ms_tcpip6"}).Enabled
        }

        # TRANSLATES PREFIX ORIGIN
        Switch ($TempIPInfo.IPv4Address.PrefixOrigin) {
            "Manual" {$DHCPStatus = "STATIC" ; break}
            "Dhcp" {$DHCPStatus = "DHCP" ; break}
            "WellKnown" {$DHCPStatus = "APIPA" ; break}
        }

        # GENERATES CUSTOM IP OBJECT
        $IPObject += New-Object -TypeName psobject -Property @{
            Name = $Name
            Description = $TempIPInfo.InterfaceDescription
            IPv4 = $IPv4
            SubnetMask = $SM
            DefaultGateway = $GW
            DNSServer1 = $DNS1
            DNSServer2 = $DNS2
            MAC = $MAC
            AddressAssignment = $DHCPStatus
            IPv6Enabled = $IPv6Status
        }

        # RETURNS IP DATA
        Return $IPObject | Select -Property Name,Description,AddressAssignment,MAC,IPv4,SubnetMask,DefaultGateway,DNSServer1,DNSServer2,IPv6Enabled
    }

    # MODIFIES DNS SETTINGS
    function sc_Modify-DNSSettings (
        [parameter(Mandatory=$true)]$Data
    )
    {
    # RESETS ALL VARIABLES FOR FUNCTION
        $DChoice = $null
        $PrefDNS = $null
        $AltDNS = $null
        $Octs = $null
        $OutputText = $null
        $ValidOcts = 0..255
        $ValidD = @(1,2,3)

        # GENERATES OUTPUT TEXT
        $OutputText = "
------ DNS Settings ------
 
1) Clear DNS Servers
2) Set DNS Servers
 
3) Back to NIC Settings
 
        "


        # RETURNS TEXT DATA
        Write-Output $OutputText

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $DChoice = $null
            $DChoice = Read-Host "Enter selection"

        } While ($ValidD -notcontains $DChoice)
        
        # EXECUTES SELECTED OPTION
        If ($DChoice -eq 1) {
            Set-DnsClientServerAddress -InterfaceAlias $Data.Name -ResetServerAddresses
            sc_Modify-NetInterface -Adapter $Data
        } ElseIf ($DChoice -eq 2) {
            # GATHERS DNS DATA
            $PrefDNS = Read-Host "Enter preferred DNS server"
            $Octs = $PrefDNS.Split('.')

            # VALIDATES IP HAS 4 OCTETS
            If ($Octs.count -ne 4) {
                Write-Host -ForegroundColor Red "Invalid IP. Input must have 4 octects."
                sc_Modify-NetInterface -Adapter $Data
            }

            # VALIDATES IP VALUES FOR EACH OCTET
            Foreach ($Oct in $Octs) {
                If ($ValidOcts -notcontains $Oct) {
                    Write-Host -ForegroundColor Red "Invalid IP. All octets must be between 0 and 255."
                    sc_Modify-NetInterface -Adapter $Data
                }
            }

            $AltDNS = Read-Host "Enter alternate DNS server (Blank for no entry)"
            $Octs = $PrefDNS.Split('.')

            # VALIDATES IP HAS 4 OCTETS
            If (($Octs.count -ne 4) -and ($AltDNS -ne "")) {
                Write-Host -ForegroundColor Red "Invalid IP. Input must have 4 octects."
                sc_Modify-NetInterface -Adapter $Data

            } ElseIf ($Octs.count -eq 4) {
                # VALIDATES IP VALUES FOR EACH OCTET
                Foreach ($Oct in $Octs) {
                    If ($ValidOcts -notcontains $Oct) {
                        Write-Host -ForegroundColor Red "Invalid IP. All octets must be between 0 and 255."
                        sc_Modify-NetInterface -Adapter $Data
                    }
                }
            }

            # EXECUTES DNS CHANGE
            Set-DnsClientServerAddress -InterfaceAlias $Data.Name -ServerAddresses ($PrefDNS,$AltDNS)
            sc_Modify-NetInterface -Adapter $Data
        } ElseIf ($DChoice -eq 3) {
            sc_Modify-NetInterface -Adapter $Adapter
        }
    }

    # ENABLES\DISABLES IPv6 ON AN INTERFACE
    function sc_Toggle-IPv6 (
        [parameter(Mandatory=$true)]$Adapter
    )
    {
        # CHECKS CURRENT IPV6 STATUS
        $IPv6Adapter = (Get-NetAdapterBinding -Name $Adapter.Name | Where {$_.ComponentID -match "ms_tcpip6"}).Enabled

        # IF ENABLED, IPV6 IS DISABLED
        If ($IPv6Adapter -eq $true) {
            Disable-NetAdapterBinding -Name $Adapter.Name -ComponentID ms_tcpip6
        }

        # IF DISABLED, IPV6 IS ENABLED
        If ($IPv6Adapter -eq $false) {
            Enable-NetAdapterBinding -Name $Adapter.Name -ComponentID ms_tcpip6
        }

        # LOOPS BACK TO NETWORK MODIFICATION
        sc_Modify-NetInterface -Adapter $Adapter
    }

    # ENABLES\DISABLES NIC ON AN INTERFACE

    function sc_Toggle-NIC (
        [parameter(Mandatory=$true)]$Adapter,
        [parameter(Mandatory=$true)]$Status
    )
    {
        # DISABLES NIC IF UP
        If ($Status -eq "Up") {
            Disable-NetAdapter -Name $Adapter -Confirm:$false
        }

        # ENABLES NIC IF DISABLED
        If ($Status -eq "Disabled") {
            Enable-NetAdapter -Name $Adapter
        }

        # CYCLES BACK TO NIC CONFIGURATION
        sc_Set-Network
    }

    # RESETS CNT VARIABLE
    $cnt = 1

    # GATHERS ALL NETWORK ADAPTERS ON SERVER
    $Teams = Get-NetLbfoTeam
    $NetAdapters += Get-NetAdapter | Sort -Property Name | Foreach {
        If ($Teams.Members -notcontains $_.Name) {
            If ($_.Status -eq "Disabled") {
                New-Object -TypeName psobject -Property @{
                    Name = $_.Name
                    IPv4 = "N/A"
                    Description = "NIC is disabled"
                    "#" = $cnt
                }
            } Else {
                $IP = Get-NetIPConfiguration -InterfaceAlias $_.Name
                New-Object -TypeName psobject -Property @{
                    Name = $_.Name
                    IPv4 = $IP.IPv4Address.IPAddress
                    Description = $_.InterfaceDescription
                    "#" = $cnt
                }
            }
        } Else {
            New-Object -TypeName psobject -Property @{
                Name = $_.Name
                IPv4 = "N/A"
                Description = "NIC is a Team Member"
                "#" = $cnt
            }
        }

        $cnt++
    }

    $NetAdapters += New-Object -TypeName psobject -Property @{
        Name = "Return to Main menu"
        IPv4 = ""
        Description = ""
        "#" = $cnt
    }

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
----Network Adapter Settings----
 
Available Network Adapters
    "


    # RETURNS TEXT DATA AND BRIEF OF ADAPTER DATA AS STRING
    Write-Output $OutputText
    $NetAdapters | Select -Property "#",Name,IPv4,Description | Sort -Property "#" | Out-String

    # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
    Do {
        $NetChoice = $null
        $NetChoice = Read-Host "Enter selection"

        # Ignores team members selections
        If ($Teams -ne $null) {
            If (($NetAdapters | Where {$_.Description -eq "NIC Team Member"})."#" -contains $NetChoice) {
                Write-Host -ForegroundColor Yellow "Due to NIC Teaming this interface is not allowed to be modified."
                Write-Host -ForegroundColor Yellow "Please select another."
                $NetChoice = $null
            }
        }

        If ($NetChoice -eq $NetAdapters.count) {
            sc_Create-MainMenu
        }

    } While ($NetAdapters."#" -notcontains $NetChoice)

    # GATHERS ONLY ADAPTER TO BE WORKED
    $NetInput = $NetAdapters | Where {$_."#" -like "$NetChoice"}

    # EXECUTES ADAPTER SPECIFIC INTERFACE
    sc_Modify-NetInterface -Adapter $NetInput
}

###################################################### CONFIGURES NIC TEAMING ######################################################
function sc_Config-NICTeaming (

)
{
    # RESETS ALL VARIABLES FOR FUNCTION
    $NICTeams = $null
    $ValidNT = @()
    $NTChoice = $null
    $OutputText = $null
    $NICOutput = $null

    function sc_Create-NICTeam (
        [Parameter(Mandatory=$true)]$Teams
    )
    {
        # RESETS ALL VARIABLES FOR FUNCTION
        $AvailNics = $null
        $TeamName = $null
        $NICChoice = $null
        $Model = $null
        $OutputText = $null
        $NicInput = $null
        $ValidTM = $null
        $OutputText2 = $null
        $TMChoice = $null
        $ValidLBA = $null
        $OutputText3 = $null
        $LBAChoice = $null
        $cnt = 1

        # GATHERS ONLY VALID ADAPTERS
        If ($Teams -eq "NO TEAMS") {
            $AvailNics = Get-NetAdapter | Sort -Property Name
        } Else {
            $AvailNics = Get-NetAdapter | Sort -Property Name | Where {($Teams.Members -notcontains $_.Name) -and ($_.InterfaceDescription -notmatch `
                "Microsoft Network Adapter Multiplexor Driver")}
        }

        If ($AvailNics.count -eq 0) {
            Write-Host -ForegroundColor Yellow "No NICs are available for teaming."
            
            Start-Sleep -Seconds 1

            sc_Config-NICTeaming

        } Else {

            Foreach ($AvailNic in $AvailNics) {
                $AvailNic | Add-Member -MemberType NoteProperty -Name "#" -Value $cnt
                $cnt++
            }
        }
        
        # GATHERS TEAM NAME
        ""
        $TeamName = Read-Host "Input NIC Team Name"

        # GENERATES OUTPUT TEXT
        $OutputText = "
 
----Select First Team Member----
    "


        # RETURNS TEXT DATA AND BRIEF OF ADAPTER DATA AS STRING
        Write-Output $OutputText
        $AvailNics | Select -Property "#",Name | Sort -Property "#" | Out-String

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $NICChoice = $null
            $NICChoice = Read-Host "Enter selection"

        } While ($AvailNics."#" -notcontains $NICChoice)

        # GATHERS ONLY ADAPTER TO BE WORKED
        $NicInput = $AvailNics | Where {$_."#" -like "$NICChoice"}

        # GATHERS COMPUTER MODEL
        $Model = Get-CimInstance -ClassName Win32_ComputerSystem | Select -Property Model
        
        # IF VIRTUAL MACHINE SETS ONLY POSSIBLE TEAM MODE OTHERWISE GATHERS INPUT
        If (($Model.Model -match "Virtual Machine") -or ($Model.Model -match "VMware")) {
            $TeamMode = "SwitchIndependent"
        } Else {

            # DEFINE VALID INPUT
            $ValidTM = @(1,2,3)

            # GENERATES OUTPUT TEXT
            $OutputText2 = "
 
-------Select Teaming Mode------
 
1) Switch Independent (default in GUI)
2) LACP
3) Static
 
    "


            # RETURNS TEXT
            Write-Output $OutputText2

            # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
            Do {
                $TMChoice = $null
                $TMChoice = Read-Host "Enter selection"

            } While ($ValidTM -notcontains $TMChoice)

            # CONVERTS TMCHOICE TO VALID COMMAND STRING
            Switch ($TMChoice) {
                1 {$TeamMode = "SwitchIndependent" ; break}
                2 {$TeamMode = "Lacp" ; break}
                3 {$TeamMode = "Static" ; break}
            }
        }

        # DEFINE VALID INPUT
        $ValidLBA = @(1,2,3,4,5)

        # GENERATES OUTPUT TEXT
        $OutputText3 = "
 
--Select Load Balancing Algorithm--
 
1) Transport Ports (default in GUI)
2) Dynamic
3) Hyper-V Port
4) IP Addresses
5) MAC Addresses
 
    "


        # RETURNS TEXT
        Write-Output $OutputText3

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $LBAChoice = $null
            $LBAChoice = Read-Host "Enter selection"

        } While ($ValidLBA -notcontains $LBAChoice)

        # CONVERTS LBACHOICE TO VALID COMMAND STRING
        Switch ($LBAChoice) {
            1 {$LBA = "TransportPorts" ; break}
            2 {$LBA = "Dynamic" ; break}
            3 {$LBA = "HyperVPort" ; break}
            4 {$LBA = "IPAddresses" ; break}
            5 {$LBA = "MacAddresses" ; break}
        }

        # EXECUTES NIC TEAM CREATION AND THEN RETURNS TO PREVIOUS MENU
        New-NetLbfoTeam -Name $TeamName -TeamMembers $NicInput.Name -TeamingMode $TeamMode -LoadBalancingAlgorithm $LBA -Confirm:$false
        sc_Config-NICTeaming

    }

    function sc_Add-NICTeamMember (
        [Parameter(Mandatory=$true)]$Teams
    )
    {
        # RESETS ALL VARIABLES FOR FUNCTION
        $AvailNics = $null
        $NTChoice = $null
        $TeamInput = $null
        $NICChoice = $null
        $OutputText = $null
        $NicInput = $null
        $OutputText2 = $null
        $ValidNM = @()
        $NMChoice = $null
        $OutputText3 = $null
        $ModeInput = $null
        $cnt = 1

        # VALIDATES THAT THERE ARE AVAILABLE TEAMS
        If ($Teams -eq "NO TEAMS") {
            Write-Host -ForegroundColor Yellow "No NIC Teams are currently created."
            Start-Sleep -Seconds 1

            sc_Config-NICTeaming

        } Else {
            $Teams = $Teams | Sort -Property Name

            Foreach ($Team in $Teams) {
                $Team | Add-Member -MemberType NoteProperty -Name "#" -Value $cnt -Force
                $cnt++
            }
        }

        # GATHERS ONLY VALID ADAPTERS
        $cnt = 1
        $AvailNics = Get-NetAdapter | Where {($Teams.Members -notcontains $_.Name) -and ($_.InterfaceDescription -notmatch `
            "Microsoft Network Adapter Multiplexor Driver")}

        # VALIDATES THAT THERE ARE AVAILABLE NICS, AND GENERATES OUTPUT
        If ($AvailNics.count -eq 0) {
            Write-Host -ForegroundColor Yellow "No NICs are available for teaming."
            Start-Sleep -Seconds 1

            sc_Config-NICTeaming

        } Else {
            $AvailNics = $AvailNics | Sort -Property Name

            Foreach ($AvailNic in $AvailNics) {
                $AvailNic | Add-Member -MemberType NoteProperty -Name "#" -Value $cnt

                $cnt++
            }
        }

        # GENERATES OUTPUT TEXT
        $OutputText = "
 
---Select NIC Team to Modify----
    "

        
        # RETURNS TEAM DATA AS STRING
        Write-Output $OutputText
        $Teams | Select -Property "#",Name,Members | Out-String

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $NTChoice = $null
            $NTChoice = Read-Host "Enter selection"

        } While ($Teams."#" -notcontains $NTChoice)

        # GATHERS ONLY ADAPTER TO BE WORKED
        $TeamInput = $Teams | Where {$_."#" -like "$NTChoice"}

        # GENERATES OUTPUT TEXT
        $OutputText2 = "
 
-----Select NIC to Join Team----
    "


        # RETURNS TEXT DATA AND BRIEF OF ADAPTER DATA AS STRING
        Write-Output $OutputText2
        $AvailNics | Select -Property "#",Name | Sort -Property "#" | Out-String

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $NICChoice = $null
            $NICChoice = Read-Host "Enter selection"

        } While ($AvailNics."#" -notcontains $NICChoice)

        # GATHERS ONLY ADAPTER TO BE WORKED
        $NicInput = $AvailNics | Where {$_."#" -like "$NICChoice"}

        # DEFINES VALID INPUT
        $ValidNM = @(1,2)

        # GENERATES OUTPUT TEXT
        $OutputText3 = "
 
----Select Mode for Adapter-----
 
1) Active
2) Standby
 
    "


        # RETURNS TEXT DATA AND BRIEF OF ADAPTER DATA AS STRING
        Write-Output $OutputText3

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $NMChoice = $null
            $NMChoice = Read-Host "Enter selection"

        } While ($ValidNM -notcontains $NMChoice)

        # CONVERTS NMCHOICE TO VALID COMMAND STRING
        Switch ($NMChoice) {
            1 {$ModeInput = "Active" ; break}
            2 {$ModeInput = "Standby" ; break}
        }

        # EXECUTES NIC TEAM MEMBER ADD AND THEN RETURNS TO PREVIOUS MENU
        Add-NetLbfoTeamMember -Name $NicInput.Name -Team $TeamInput.Name -AdministrativeMode $ModeInput -Confirm:$false | Out-Null
        sc_Config-NICTeaming
    }

    function sc_Remove-NICTeamMember (
        [Parameter(Mandatory=$true)]$Teams
    )
    {
        # RESETS ALL VARIABLES FOR FUNCTION
        $NTChoice = $null
        $TeamInput = $null
        $SelectedTeam = $null
        $TeamMembers = @()
        $NICChoice = $null
        $OutputText = $null
        $NicInput = $null
        $OutputText2 = $null
        $cnt = 1

        # VALIDATES THAT THERE ARE AVAILABLE TEAMS
        If ($Teams -eq "NO TEAMS") {
            Write-Host -ForegroundColor Yellow "No NIC Teams are currently created."

            Start-Sleep -Seconds 1

            sc_Config-NICTeaming

        } Else {
            $Teams = $Teams | Sort -Property Name

            Foreach ($Team in $Teams) {
                $Team | Add-Member -MemberType NoteProperty -Name "#" -Value $cnt -Force

                $cnt++
            }
        }

        # GENERATES OUTPUT TEXT
        $OutputText = "
 
---Select NIC Team to Modify----
    "

        
        # RETURNS TEAM DATA AS STRING
        Write-Output $OutputText
        $Teams | Select -Property "#",Name,Members | Out-String

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $NTChoice = $null
            $NTChoice = Read-Host "Enter selection"

        } While ($Teams."#" -notcontains $NTChoice)

        # GATHERS ONLY ADAPTER TO BE WORKED
        $TeamInput = $Teams | Where {$_."#" -like "$NTChoice"}

        # GATHERS NIC TEAM MEMBERS
        $cnt = 1
        $SelectedTeam = ($Teams | Where {$_.Name -match $TeamInput.Name}).Members | Sort

        # VALIDATES THAT THERE ARE MULTIPLE NICS IN TEAM
        If ($SelectedTeam.count -eq 1) {
            Write-Host -ForegroundColor Yellow "Only 1 member in team. Use `'Delete NIC Team`' option."

            Start-Sleep -Seconds 1

            sc_Config-NICTeaming

        } Else {
            Foreach ($Member in $SelectedTeam) {
                $TeamMembers += New-Object -TypeName psobject -Property @{
                    "#" = $cnt
                    Name = $Member
                }

                $cnt++
            }
        }

        # GENERATES OUTPUT TEXT
        $OutputText2 = "
 
---Select NIC to Remove from Team--
    "


        # RETURNS TEXT DATA AND BRIEF OF ADAPTER DATA AS STRING
        Write-Output $OutputText2
        $TeamMembers | Select -Property "#",Name | Sort -Property "#" | Out-String

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $NICChoice = $null
            $NICChoice = Read-Host "Enter selection"

        } While ($TeamMembers."#" -notcontains $NICChoice)

        # GATHERS ONLY ADAPTER TO BE WORKED
        $NicInput = $TeamMembers | Where {$_."#" -like "$NICChoice"}

        # EXECUTES NIC TEAM MEMBER REMOVAL AND THEN RETURNS TO PREVIOUS MENU
        Remove-NetLbfoTeamMember -Name $NicInput.Name -Team $TeamInput.Name -Confirm:$false | Out-Null
        sc_Config-NICTeaming
    }

    function sc_Remove-NICTeam (
        [Parameter(Mandatory=$true)]$Teams
    )
    {
        # RESETS ALL VARIABLES FOR FUNCTION
        $NTChoice = $null
        $TeamInput = $null
        $OutputText = $null
        $cnt = 1

        # VALIDATES THAT THERE ARE AVAILABLE TEAMS
        If ($Teams -eq "NO TEAMS") {
            Write-Host -ForegroundColor Yellow "No NIC Teams are currently created."

            Start-Sleep -Seconds 1

            sc_Config-NICTeaming

        } Else {
            $Teams = $Teams | Sort -Property Name

            Foreach ($Team in $Teams) {
                $Team | Add-Member -MemberType NoteProperty -Name "#" -Value $cnt -Force

                $cnt++
            }
        }

        # GENERATES OUTPUT TEXT
        $OutputText = "
 
---Select NIC Team to Delete----
    "

        
        # RETURNS TEAM DATA AS STRING
        Write-Output $OutputText
        $Teams | Select -Property "#",Name,Members | Out-String

        # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
        Do {
            $NTChoice = $null
            $NTChoice = Read-Host "Enter selection"

        } While ($Teams."#" -notcontains $NTChoice)

        # GATHERS ONLY ADAPTER TO BE WORKED
        $TeamInput = $Teams | Where {$_."#" -like "$NTChoice"}

        # EXECUTES NIC TEAM DELETION AND THEN RETURNS TO PREVIOUS MENU
        Remove-NetLbfoTeam -Name $TeamInput.Name -Confirm:$false
        sc_Config-NICTeaming
    }

    # GATHERS ALL NIC TEAMS
    $NICTeams = Get-NetLbfoTeam

    # GATHERS NIC TEAM INFO
    If ($NICTeams -eq $null) {
        $NICOutput = "**No NIC Teams are configured**"
        $NICTeams = "NO TEAMS"
    } Else {
        $NICOutput = $NICTeams | Select -Property Name,Members,Status | Out-String
    }

    # DEFINES VALID INPUTS
    $ValidNT = @(1,2,3,4,5)

    # GENERATES OUTPUT TEXT
    $OutputText = "
--------------------------------
         CURRENT TEAMS
--------------------------------
 
$NICOutput
 
-----Configuration Options------
 
1) Create NIC Team
2) Add Member to NIC Team
3) Remove Member of NIC Team
4) Delete NIC Team
 
5) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
    Do {
        $NTChoice = $null
        $NTChoice = Read-Host "Enter selection"

    } While ($ValidNT -notcontains $NTChoice)

    # EXECUTES CHOSEN SUB-FUNCTION
    Switch ($NTChoice) {
        1 {sc_Create-NICTeam -Teams $NICTeams ; break}
        2 {sc_Add-NICTeamMember -Teams $NICTeams ; break}
        3 {sc_Remove-NICTeamMember -team $NICTeams ; break}
        4 {sc_Remove-NICTeam -Teams $NICTeams ; break}
        5 {sc_Create-MainMenu ; break}
    }
}

##################################################### CONFIGURE FIREWALL PROFILES ######################################################
function sc_Set-Firewall (

)
{
    # RESETS ALL VARIABLES FOR FUNCTION
    $DomFW = $null
    $PriFW = $null
    $PubFW = $null
    $OutputText = $null
    $ValidFW = @()
    $FWChoice = $null

    # FUNCTION TO TOGGLE A FIREWALL PROFILE
    function sc_Toggle-Firewall (
        [parameter(Mandatory=$true)]$Profile,
        [parameter(Mandatory=$true)]$Status
    )
    {
        If ($Status -eq "Enabled") {
            Set-NetFirewallProfile -Name $Profile -Enabled False | Out-Null
            sc_Set-Firewall
        } Else {
            Set-NetFirewallProfile -Name $Profile -Enabled True | Out-Null
            sc_Set-Firewall
        }
    }

    # DEFINES VALID INPUTS
    $ValidFW = @(1,2,3,4)

    # GATHERS STATUS OF EACH PROFILE
    If ((Get-NetFirewallProfile -Name Domain).Enabled) {$DomFW = "Enabled"} Else {$DomFW = "Disabled"}
    If ((Get-NetFirewallProfile -Name Private).Enabled) {$PriFW = "Enabled"} Else {$PriFW = "Disabled"}
    If ((Get-NetFirewallProfile -Name Public).Enabled) {$PubFW = "Enabled"} Else {$PubFW = "Disabled"}

    # GENERATES OUTPUT TEXT
    $OutputText = "
--- TOGGLE FIREWALL ---
 
1) Domain: $DomFW
2) Private: $PriFW
3) Public: $PubFW
 
4) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
    Do {
        $FWChoice = $null
        $FWChoice = Read-Host "Enter selection"

    } While ($ValidFW -notcontains $FWChoice)

    Switch ($FWChoice) {
        1 {sc_Toggle-Firewall -Profile "Domain" -Status $DomFW ; break}
        2 {sc_Toggle-Firewall -Profile "Private" -Status $PriFW ; break}
        3 {sc_Toggle-Firewall -Profile "Public" -Status $PubFW ; break}
        4 {sc_Create-MainMenu ; break}
    }
}

######################################################### CONFIGURE TELEMETRY ##########################################################
function sc_Set-Telemetry (

)
{
    # GENERATES OUTPUT TEXT
    $ValidTel = $null
    $TelReg = $null
    $OutputText = $null
    $TelChoice = $null

    # DEFINES VALID OPTIONS
    $ValidTel = @(1,2,3,4,5)

    # GATHERS SETTING IF SET BY GROUP POLICY
    $TelReg = (Get-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\DataCollection").AllowTelemetry

    # EXITS FUNCTION IF CONTROLLED BY GROUP POLICY
    If ($TelReg -ne $null) {
        Write-Host "Telemetry settings are controlled by Group Policy. Returning to main menu..."
        Start-Sleep -Seconds 3
        sc_Create-MainMenu
    }

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
Available telemetry settings:
 
1) Security
2) Basic
3) Enhanced
4) Full
 
5) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS OPTION UNTIL VALID CHOICE IS MADE
    Do {
        $TelChoice = $null
        $TelChoice = Read-Host "Enter selection"

    } While ($ValidTel -notcontains $TelChoice)

    # EXECUTES TELEMETRY ADJUSTMENT
    Switch ($TelChoice) {
        1 {Set-ItemProperty -Path "HKLM:\\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name AllowTelemetry -Value 0 ; sc_Create-MainMenu ; break}
        2 {Set-ItemProperty -Path "HKLM:\\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name AllowTelemetry -Value 1 ; sc_Create-MainMenu ; break}
        3 {Set-ItemProperty -Path "HKLM:\\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name AllowTelemetry -Value 2 ; sc_Create-MainMenu ; break}
        4 {Set-ItemProperty -Path "HKLM:\\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name AllowTelemetry -Value 3 ; sc_Create-MainMenu ; break}
        5 {sc_Create-MainMenu ; break}
    }
}

###################################################### EXECUTE WINDOWS ACTIVATION ######################################################
function sc_Set-WinAct (

)
{
    # RESETS VARIABLES FOR FUNCTION
    $OutputText = $null
    $ValidWA = $null
    $WAChoice = $null
    $Key = $null

    # SETS VALID OPTIONS
    $ValidWA = @(1,2,3,4)

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
 -- Windows Activation --
 
1) Display License Info
2) Activate Windows
3) Install Product Key
 
4) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS OPTION UNTIL VALID CHOICE IS SELECTED
    Do {
        $WAChoice = Read-Host "Enter selection"

    } While ($ValidWA -notcontains $WAChoice)

    # EXECUTES SELECTED OPTION
    Switch ($WAChoice) {
        1 {slmgr /dli ; sc_Set-WinAct ; break}
        2 {Write-Host -ForegroundColor Yellow "Processing activation attempt. This may take awhile..." ; slmgr /ato ; sc_Set-WinAct ; break}
        3 {$Key = Read-Host "Input license key" ; slmgr /ipk $Key ; sc_Set-WinAct ; break}
        4 {sc_Create-MainMenu ; break}
    }
}

###################################################### CONFIGURE WINDOWS DEFENDER ######################################################
function sc_Set-WinDefend (

)
{
    # RESETS VARIABLES FOR FUNCTION
    $OutputText = $null
    $RTPStatus = $null
    $CBPStatus = $null
    $ASSStatus = $null
    $WDChoice = $null
    $ValidWD = $null

    # GATHERS WINDOWS DEFENDER SETTINGS
    $MPInfo = Get-MpPreference
    
    # TRANSLATES DATA FOR REAL-TIME PROTECTION STATUS
    If ($MPInfo.DisableRealtimeMonitoring -eq $false) {
        $RTPStatus = "ON"
    } ElseIf ($MPInfo.DisableRealtimeMonitoring -eq $true) {
        $RTPStatus = "OFF"
    } Else {
        $RTPStatus = "Query failed"
    }

    # TRANSLATES DATA FOR CLOUD-BASED PROTECTION STATUS
    If ($MPInfo.MAPSReporting -eq 2) {
        $CBPStatus = "ON"
    } ElseIf ($MPInfo.MAPSReporting -eq 0) {
        $CBPStatus = "OFF"
    } Else {
        $CBPStatus = "Query failed"
    }

    # TRANSLATES DATA FOR AUTOMATIC SAMPLE SUBMISSION STATUS
    If ($MPInfo.SubmitSamplesConsent -eq 1) {
        $ASSStatus = "ON"
    } ElseIf ($MPInfo.SubmitSamplesConsent -eq 0) {
        $ASSStatus = "OFF"
    } Else {
        $ASSStatus = "Query failed"
    }

    # SETS VALID OPTIONS
    $ValidWD = @(1,2,3,4)

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
----------------------------------
    Configure Windows Defender
----------------------------------
 
Real-time Protection: $RTPStatus
Cloud-based Protection: $CBPStatus
Automatic Sample Submission: $ASSStatus
 
1) Toggle Real-time Protection
2) Toggle Cloud-base Protection
3) Toggle Automatic Sample Submission
 
4) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS OPTION UNTIL VALID CHOICE IS SELECTED
    Do {
        $WDChoice = Read-Host "Enter selection"

    } While ($ValidWD -notcontains $WDChoice)

    # EXECUTES SELECTED OPTION
    Switch ($WDChoice) {
        1 {If ($RTPStatus -eq "ON") {Set-MpPreference -DisableRealtimeMonitoring $true ; sc_Set-WinDefend} ElseIf ($RTPStatus -eq "OFF") `
            {Set-MpPreference -DisableRealtimeMonitoring $false ; sc_Set-WinDefend} Else `
            {Write-Host -ForegroundColor Yellow "Cannot toggle due to failed query" ; sc_Set-WinDefend} ; break}
        2 {If ($CBPStatus -eq "ON") {Set-MpPreference -MAPSReporting 0 ; sc_Set-WinDefend} ElseIf ($CBPStatus -eq "OFF") `
            {Set-MpPreference -MAPSReporting 2 ; sc_Set-WinDefend} Else `
            {Write-Host -ForegroundColor Yellow "Cannot toggle due to failed query" ; sc_Set-WinDefend} ; break}
        3 {If ($ASSStatus -eq "ON") {Set-MpPreference -SubmitSamplesConsent 0 ; sc_Set-WinDefend} ElseIf `
            ($ASSStatus -eq "OFF") {Set-MpPreference -SubmitSamplesConsent 1 ; sc_Set-WinDefend} Else `
            {Write-Host -ForegroundColor Yellow "Cannot toggle due to failed query" ; sc_Set-WinDefend} ; break}
        4 {sc_Create-MainMenu ; break}
    }
}

############################################################# CONFIGURE REMOTE MANAGEMENT ############################################################
function sc_Set-RemoteMgmt (

)
{
    # RESETS ALL VARIABLES FOR FUNCTION
    $RCheck = $null
    $RChoice = $null
    $RValid = $null
    $OutputText = $null

    # GATHERS STATUS AND VALID OPTIONS
    $RCheck = Configure-SMRemoting.exe -GET
    $RValid = @(1,2,3,4)

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
----------------------------------
    Configure Remote Management
----------------------------------
     
Current Status: $RCheck
 
1) Enable Remote Management
2) Disable Remote Management
3) Enable Server Response to PING
 
4) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHER INPUT UNTIL VALID OPTION
    Do {
        $RChoice = $null
        $RChoice = Read-Host "Enter selection"
    } While ($RValid -notcontains $RChoice)

    # EXECUTES SELECTED OPTION
    Switch ($RChoice) {
        1 {Write-Host "Enabling Remote Management..." ; Configure-SMRemoting.exe -ENABLE ; sc_Set-RemoteMgmt ; break}
        2 {Write-Host "Disabling Remote Management..." ; Configure-SMRemoting.exe -DISABLE ; sc_Set-RemoteMgmt ; break}
        3 {Write-Host "Enabling PING requests..." ; Get-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv?-In" | Enable-NetFirewallRule ; sc_Set-RemoteMgmt ; break}
        4 {sc_Create-MainMenu ; break}
    }
}

############################################################# CONFIGURE RDP ############################################################
function sc_Set-RDP (

)
{
    # WHEN ENABLING RDP SETS AUTHENTICATION REQUIREMENT
    function sc_Set-SecureLevel (

    )
    {
        # RESETS ALL VARIABLES FOR FUNCTION
        $OutputText = $null
        $SChoice = $null
        $ValidS = $null

        # SETS VALID OPTIONS
        $ValidS = @(1,2,3)

        # GENERATES OUTPUT TEXT
        $OutputText = "
 
------ RDP Security Level ------
 
1) Allow only clients running Remote Desktop with Network Level Authentication (more secure)
2) Allow clients running any version of Remote Desktop (less secure)
 
3) Return to main menu
 
        "


        # RETURNS TEXT DATA
        Write-Output $OutputText

        # GATHERS OPTION UNTIL VALID CHOICE IS MADE
        Do {
            $SChoice = $null
            $SChoice = Read-Host "Enter selection"
        } While ($ValidS -notcontains $SChoice)

        # EXECUTES SELECTED OPTION
        Switch ($SChoice) {
            1 {Set-ItemProperty -Path "HKLM:\\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-TCP" -Name UserAuthentication -Value 1 ; sc_Create-MainMenu ; break}
            2 {Set-ItemProperty -Path "HKLM:\\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-TCP" -Name UserAuthentication -Value 0 ; sc_Create-MainMenu ; break}
            3 {sc_Create-MainMenu ; break}
        }
    }

    # SETS VALID OPTIONS
    $RDPValid = @(1,2,3)

    # GENERATES OUTPUT TEXT
    $OutputText = "
 
------ RDP Settings ------
 
1) Enable RDP
2) Disable RDP
 
3) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS OPTION UNTIL VALID CHOICE IS MADE
    Do {
        $RDPChoice = $null
        $RDPChoice = Read-Host "Enter selection"
    } While ($RDPValid -notcontains $RDPChoice)

    # EXECUTES SELECTED OPTION
    Switch ($RDPChoice) {
        1 {Set-ItemProperty -Path "HKLM:\\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections -Value 0 ; Write-Host "Enabling RDP..." ; sc_Set-SecureLevel ; break}
        2 {Set-ItemProperty -Path "HKLM:\\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections -Value 1 ; Write-Host "Disabling RDP..." ; sc_Create-MainMenu ; break}
        3 {sc_Create-MainMenu ; break}
    }
}

####################################################### CONFIGURE WINDOWS UPDATES ######################################################
function sc_Set-WindowsUpdate (

)
{
    # RESETS ALL VARIABLES FOR FUNCTION
    $AU = $null
    $NoAU = $null
    $WU = $null
    $WUChoice = $null
    $OutputText = $null
    $ValidWU = $null

    # GATHERS WINDOWS UPDATE DATA
    $AU = Get-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
    $NoAU = $AU.NoAutoUpdate
    $AU = $AU.AUOptions

    # TRANSLATES REGISTRY FOR WINDOWS UPDATE TO USER FRIENDLY OUTPUT
    Switch ($AU) {
        $null {If ($NoAU -eq 1) {$WU = "Manual"} ElseIf ($NoAU -eq $null) {$WU = "Failed Query"} ; break}
        1 {$WU = "Never check for updates" ; break}
        2 {$WU = "Notify before download" ; break}
        3 {$WU = "DownloadOnly" ; break}
        4 {$WU = "Automatic" ; break}
    }

    # SETS VALID OPTIONS
    $ValidWU = @(1,2,3,4)

    # RETURNS WINDOWS UPDATE STATUS
    $OutputText = "
 
------ WINDOWS UPDATE SETTINGS ------
 
Windows Update currently set to: $WU
 
1) Set to Automatic
2) Set to DownloadOnly
3) Set to Manual
 
4) Return to main menu
 
    "


    # RETURNS TEXT DATA
    Write-Output $OutputText

    # GATHERS INPUT UNTIL VALID OPTION IS SELECTED
    Do {
        $WUChoice = $null
        $WUChoice = Read-Host "Enter selection"
    } While ($ValidWU -notcontains $WUChoice)

    # EXECUTES SELECTED OPTION
    Switch ($WUChoice) {
        1 {
            Stop-Service -Name wuauserv
            Remove-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name NoAutoUpdate -ErrorAction SilentlyContinue
            Remove-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name AUOptions -ErrorAction SilentlyContinue
            New-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name AUOptions -Value 4 | Out-Null
            Start-Service -Name wuauserv
            sc_Create-MainMenu
            break
        }
        2 {
            Stop-Service -Name wuauserv
            Remove-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name NoAutoUpdate -ErrorAction SilentlyContinue
            Remove-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name AUOptions -ErrorAction SilentlyContinue
            New-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name AUOptions -Value 3 | Out-Null
            Start-Service -Name wuauserv
            sc_Create-MainMenu
            break
        }
        3 {
            Stop-Service -Name wuauserv
            Remove-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name AUOptions -ErrorAction SilentlyContinue
            New-ItemProperty -Path "HKLM:\\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name NoAutoUpdate -Value 1 | Out-Null
            Start-Service -Name wuauserv
            sc_Create-MainMenu
            break
        }
        4 {sc_Create-MainMenu ; break}
    }
}

######################################################## EXECUTE WINDOWS UPDATES #######################################################
function sc_Execute-WindowsUpdate (

)
{
    # RESETS ALL VARIABLES FOR FUNCTION
    $UpdateSession = $null
    $UpdateSearcher = $null
    $SearchResults = $null
    $cnt = $null
    $UpdateList = @()
    $UpdateSelection = $null
    $UpdatesToDownload = $null
    $UTitle = $null
    $Update = $null
    $Downloader = $null
    $UpdatesToInstall = $null
    $Installer = $null
    $InstallationResult = $null

    # EXECUTES SYSTEM SCAN FOR RELAVENT PATCHES
    Write-Host "Beginning system scan. This may take a while..."
    $UpdateSession = New-Object -ComObject Microsoft.Update.Session
    $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
    $SearchResults = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'")

    # CREATES OUTPUT OBJECT FOR EACH REQUIRED PATCH
    If ($SearchResults.Updates.Count -eq 0) {
        ""
        Write-Host -ForegroundColor Yellow "System is up-to-date. Returning to main menu..."

        Start-Sleep -Seconds 3

        sc_Create-MainMenu
    }

    $cnt = 1
    $SearchResults.Updates | Foreach {$UpdateList += New-Object -TypeName psobject -Property @{
            SelNumber = $cnt
            Title = $_.Title
            Description = "$cnt) $($_.Title)"
        }
        $cnt++
    }

    # RETURNS TEXT DATA
    ""
    $UpdateList.Description
    ""

    # GATHERS OPTION UNTIL VALID CHOICE IS MADE
    Do {
        $UpdateSelection = $null
        $UpdateSelection = Read-Host "Input number to install specific patch or `'A`' for all (Blank=Cancel)"
        If ($UpdateSelection -eq "") {
            Write-Host "Cancelling Windows Update..."
            sc_Create-MainMenu
        }
    } While (($UpdateSelection -notlike 'A') -and (($UpdateList | Where {$_.SelNumber -eq $UpdateSelection}) -eq $null))

    # FILTERS TO ONLY SELECTED UPDATES
    $UpdatesToDownload = New-Object -ComObject Microsoft.Update.UpdateColl
    If ($UpdateSelection -like 'A') {
        Foreach ($KB in $SearchResults.Updates) {
            $UpdatesToDownload.Add($KB) | Out-Null
        }
    } Else {
        $UTitle = ($UpdateList | Where {$_.SelNumber -eq $UpdateSelection}).Title
        $Update = $SearchResults.Updates | Where {$_.Title -eq $UTitle}
        $UpdatesToDownload.Add($Update) | Out-Null
    }

    # EXECUTES DOWNLOAD OF ALL SELECTED UPDATES
    $Downloader = $UpdateSession.CreateUpdateDownloader()
    $Downloader.Updates = $UpdatesToDownload
    ""
    Write-Host "Beginning download of patches. This may take a while..."
    $Downloader.Download() | Out-Null

    # FILTERS TO ONLY DOWNLOADED UPDATES
    $UpdatesToInstall = New-Object -ComObject Microsoft.Update.UpdateColl
    Foreach ($KB in $SearchResults.Updates) {
        If ($KB.IsDownloaded -eq $true) {
            $UpdatesToInstall.Add($KB) | Out-Null
        } Else {
            Write-Host -ForegroundColor Red "$($KB.Title) failed to download. Skipping..."
        }
    }

    # EXECUTES INSTALLATION OF ALL DOWNLOADED UPDATES
    $Installer = $UpdateSession.CreateUpdateInstaller()
    $Installer.Updates = $UpdatesToInstall
    Write-Host "Beginning installation of patches. This may take awhile..."
    $InstallationResult = $Installer.Install()

    # REUTRNS STATUS OF ALL UPDATES ATTEMPTED TO BE INSTALLED
    $cnt = 0
    Foreach ($Result in $Installer.Updates) {
        Switch ($InstallationResult.GetUpdateResult($cnt).ResultCode) {
            0 {Write-Host "$($Result.Title): Not Started" ; break}
            1 {Write-Host "$($Result.Title): In Progress" ; break}
            2 {Write-Host "$($Result.Title): Succeeded" ; break}
            3 {Write-Host "$($Result.Title): Succeeded with errors" ; break}
            4 {Write-Host "$($Result.Title): Failed" ; break}
            5 {Write-Host "$($Result.Title): Process stopped before completing" ; break}
        }
        $cnt++
    }

    # RETURNS TO MAIN MENU AFTER A PAUSE SO RESULTS CAN BE EASILY VIEWED
    Write-Host -ForegroundColor Yellow "Returning to main menu..."

    Start-Sleep -Seconds 3

    sc_Create-MainMenu
}

################################################################ LOGOFF ################################################################
function sc_Logoff (

)
{
    logoff
}

################################################################ RESTART ###############################################################
function sc_Restart (

)
{
    Restart-Computer -Force
}

############################################################### SHUTDOWN ###############################################################
function sc_Shutdown (

)
{
    Stop-Computer -Force
}

################################################################# EXIT #################################################################
function sc_Exit (

)
{
    Exit
}

########################################################### MAIN SCRIPT BODY ###########################################################

# SETS WINDOW AND BUFFER SIZE
$Width = 95
$Buffer = New-Object -TypeName System.Management.Automation.Host.Size ($Width,3000)
$Window = New-Object -TypeName System.Management.Automation.Host.Size ($Width,($Host.UI.RawUI.MaxWindowSize.Height * .7))
$Host.UI.RawUI.WindowSize = $Window
$Host.UI.RawUI.BufferSize = $Buffer

# INITIATES CORE FUNCTION
sc_Create-MainMenu