IntegrisDeploymentTool.psm1

### Support Functions
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-Verbose "$($(Get-Date).ToShortTimeString()): Found $($LoggedOnSids.Count) logged on user SIDs" 
        foreach ($sid in $LoggedOnSids) { 
            Write-Verbose -Message "$($(Get-Date).ToShortTimeString()): 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 
            } 
        } 
         
        ## 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-Verbose "$($(Get-Date).ToShortTimeString()): 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-Verbose "$($(Get-Date).ToShortTimeString()): 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-Verbose -Message "$($(Get-Date).ToShortTimeString()): 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 
    } 
}
FUNCTION Test-IsPrivateIP {
    PARAM (
        [Parameter(Mandatory)]
        [System.Net.IPAddress]$IPAddress
    )

    $Split = $IPAddress.IPAddressToString.Split('.')

    IF ($IPAddress -eq "127.0.0.1") { RETURN $True }
    IF ($Split[0] -eq 10) { RETURN $True }
    IF ($Split[0] -eq 192 -and $Split[1] -eq 168) { RETURN $True }
    IF ($Split[0] -eq 172 -and $Split[1] -ge 16 -and $Split[1] -le 31) { RETURN $True }
    IF ($Split[0] -eq 169 -and $Split[1] -eq 254) { RETURN $True }
    
    RETURN $False
}
FUNCTION Test-IsPublicIP {
    PARAM (
        [Parameter(Mandatory)]
        [System.Net.IPAddress]$IPAddress
    )

    IF ((Test-IsPrivateIP $IPAddress) -eq $False) { RETURN $True }
    ELSE { RETURN $False }
}
FUNCTION Test-IsDomainController {
    $ProductType = (GET-CIMInstance Win32_OperatingSystem).ProductType

    IF ($ProductType -eq 2) { RETURN $True }

    RETURN $False    
}
FUNCTION Get-AutomateAgentConfig {
   
    [CmdletBinding()]
    PARAM ( )
 
    $Results = [PSCustomObject]@{
        ServerAddress = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue)."Server Address"
        ServerPassword = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue).ServerPassword        
        ClientID = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue).ClientID
        LocationID = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue).LocationID
        DeviceID = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue).ID        
        ProductCode = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue).ProductCode
        BasePath = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue).BasePath
        Version = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue).Version
        LastCheckIn = (Get-ItemProperty -Path "HKLM:\SOFTWARE\LabTech\Service" -ErrorAction SilentlyContinue).LastSuccessStatus
    }

    RETURN $Results | Select ServerAddress, ServerPassword, DeviceID, ClientID, LocationID, ProductCode, BasePath, Version, LastCheckIn
}
FUNCTION Get-DomainInfo {

    ### Declare Variables
    ### =================
    $Results = @()
    $DomainFQDN = $Null
    $DomainResolves = $False
    $DomainType = $Null
    $DomainServicesRegistration = dsregcmd /status
    $ResolvedIPs = @()
    $DomainControllers = @()
    $DomainJoinHealth = $Null

    ### Begin Script
    ### ============
    IF ($DomainServicesRegistration -like "*DomainJoined : YES*") { $DomainType = "AD" }
    ELSEIF ($DomainServicesRegistration -like "*AzureAdJoined : YES*" -and $DomainServicesRegistration -like "*DomainJoined : NO*") { $DomainType = "AAD" }
    ELSEIF ($DomainServicesRegistration -like "*AzureAdJoined : NO*" -and $DomainServicesRegistration -like "*DomainJoined : NO*") { $DomainType = "Workgroup" }
    ELSE { RETURN $False }

    IF ($DomainType -eq "AD") {
        $DomainFQDN = (GET-CIMInstance Win32_ComputerSystem -Verbose:$false).Domain

        $Records = Resolve-DnsName $DomainFQDN -ErrorAction SilentlyContinue

        FOREACH ($Record in $Records) { IF ((Test-IsPrivateIP $Record.IPAddress) -or $Record.Name -like "*.local*" ) { $DomainResolves = $True; $ResolvedIPs += $Record.IPAddress } }

        FOREACH ($IP in $ResolvedIPs) { TRY { $DomainControllers += (((Resolve-DNSName $IP).NameHost).Replace(".$($DomainFQDN)","").ToUpper()) } CATCH { "[Name Not Available]" } }

        IF ($ResolvedIPs.Count -ge 1) {
            TRY {
                IF (Test-IsDomainController) { $DomainJoinHealth = "Domain Controller" }
                ELSEIF (Test-ComputerSecureChannel) { $DomainJoinHealth = "Healthy" } 
                ELSE { $DomainJoinHealth = "Unhealthy" }
            } CATCH {
                $DomainJoinHealth = "Unhealthy"
            }
        }
        ELSE { $DomainJoinHealth = "Domain Unavailable" }
                        
        $Results += [PSCustomObject]@{
            Hostname = $env:COMPUTERNAME
            DomainType = $DomainType
            FQDN = $DomainFQDN
            TenantName = $Null
            TenantID = $Null
            ActiveDomainConnection = $DomainResolves
            ResolvedDomainControllerIP = $ResolvedIPs
            ResolvedDomainControllerName = $DomainControllers
            DomainJoinHealth = $DomainJoinHealth
        }

        RETURN $Results | Select Hostname, DomainType, FQDN, ActiveDomainConnection, ResolvedDomainControllerIP, ResolvedDomainControllerName, DomainJoinHealth
    }
    ELSEIF ($DomainType -eq "AAD") { 

        IF ((($DomainServicesRegistration | Select-String -Pattern "DeviceAuthStatus :").ToString().Replace("DeviceAuthStatus :","").Replace(" ","")) -eq "SUCCESS") { $DomainJoinHealth = "Healthy" } ELSE { $DomainJoinHealth = "Unhealthy" }

        $Results += [PSCustomObject]@{
            Hostname = $env:COMPUTERNAME
            DomainType = $DomainType
            FQDN = "Login.Windows.Net"
            TenantName = ($DomainServicesRegistration | Select-String -Pattern " TenantName :").ToString().Replace("TenantName :","").Replace(" ","")
            TenantID = ($DomainServicesRegistration | Select-String -Pattern " TenantId :").ToString().Replace("TenantId :","").Replace(" ","")
            ActiveDomainConnection = $Null
            ResolvedDomainControllerIP = $Null
            ResolvedDomainControllerName = $Null
            DomainJoinHealth = $DomainJoinHealth
        }

        RETURN $Results | Select Hostname, DomainType, FQDN, TenantName, TenantID, DomainJoinHealth
    }
    ELSEIF ($DomainType -eq "Workgroup") { 
        $Results += [PSCustomObject]@{
            Hostname = $env:COMPUTERNAME
            DomainType = $DomainType
            FQDN = $Null
            TenantName = $Null
            TenantID = $Null
            ActiveDomainConnection = $Null
            ResolvedDomainControllerIP = $Null
            ResolvedDomainControllerName = $Null
            DomainJoinHealth = $Null
        }

        RETURN $Results | Select Hostname, DomainType
    }
    ELSE {
        $Results += [PSCustomObject]@{
            Hostname = $env:COMPUTERNAME
            DomainType = "Error"
            FQDN = $Null
            TenantName = $Null
            TenantID = $Null
            ActiveDomainConnection = $Null
            ResolvedDomainControllerIP = $Null
            ResolvedDomainControllerName = $Null
            DomainJoinHealth = $Null
        }

        RETURN $Results | Select Hostname, DomainType
    }
}
FUNCTION Test-IsLaptop {
    IF ((GET-CIMInstance Win32_SystemEnclosure -Verbose:$false).ChassisTypes -eq 8 -or
        (GET-CIMInstance Win32_SystemEnclosure -Verbose:$false).ChassisTypes -eq 9 -or
        (GET-CIMInstance Win32_SystemEnclosure -Verbose:$false).ChassisTypes -eq 10 -or
        (GET-CIMInstance Win32_SystemEnclosure -Verbose:$false).ChassisTypes -eq 14 -or
        (GET-CIMInstance Win32_SystemEnclosure -Verbose:$false).ChassisTypes -eq 30) {
        RETURN $True
    }
    RETURN $False
}
FUNCTION Get-ApplicationInstalled {
    
    [CmdletBinding()]
    PARAM (
        [STRING]$Name = "*",
        [SWITCH]$ExactMatch = $false
    )

    FUNCTION Convert-ToVersion {
    PARAM (
        $VersionString
    )

    TRY {
        $VersionString = $VersionString.Replace("v","")
        $VersionString = $VersionString -Split '\.'

        SWITCH ($VersionString.Count) {
            0 { RETURN $Null }
            1 { $Version = "$($VersionString[0])" }
            2 { $Version = "$($VersionString[0]).$($VersionString[1])" }
            3 { $Version = "$($VersionString[0]).$($VersionString[1]).$($VersionString[2])" }
            Default { $Version = "$($VersionString[0]).$($VersionString[1]).$($VersionString[2]).$($VersionString[3])" }
        }

        RETURN [VERSION]$Version
    } 
    CATCH {
        RETURN $null
    }
}

    $Results = @()
    $Apps = @()
    $Apps += Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" # 32 Bit
    $Apps += Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"             # 64 Bit


    FOREACH ($App in $Apps) {

        

        IF ($App.DisplayName -eq "" -or $App.DisplayName -eq $Null) { continue }
        TRY { $InstallDate = ([DateTime](($App.InstallDate).SubString(4,2)+"/"+($App.InstallDate).SubString(6,2)+"/"+($App.InstallDate).SubString(0,4))).ToString("MM/dd/yy") } Catch { $InstallDate = "" }
          
        $Results += [PSCustomObject]@{
            Name = $App.DisplayName
            Publisher = $App.Publisher
            Version = (Convert-ToVersion $App.DisplayVersion)
            InstallDate = $InstallDate
            UninstallCommand = $App.UninstallString
        }
    }
 
    IF ($ExactMatch) { RETURN $Results | Select Name, Publisher, Version, InstallDate, UninstallCommand | Where-Object { $_.Name -like "$($Name)" } | Sort-Object Name }
    ELSE { RETURN $Results | Select Name, Publisher, Version, InstallDate, UninstallCommand | Where-Object { $_.Name -like "*$($Name)*" } | Sort-Object Name }
}
FUNCTION Test-ContextNotAdminElevated {
    IF (Test-ContextIsAdminElevated -eq $true) { RETURN $False }
    ELSE {$True}
}
FUNCTION Test-ContextIsAdminElevated {
    IF (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(` [Security.Principal.WindowsBuiltInRole] “Administrator”)) { RETURN $True }
    RETURN $False
}
FUNCTION Ensure-WinGet {
    # Check if Winget is already installed
    $ProgressPreferenceTemp = $ProgressPreference
    $ProgressPreference = "SilentlyContinue"
    try {
        $wingetVersion = winget --version
        
        IF ([VERSION]$wingetVersion.Replace("v","") -le [VERSION]"1.10") { 
            #Write-Verbose "Winget found, but is an old version: $wingetVersion";
        }
        ELSE { 
            #Write-Verbose "Winget is already installed. Version: $wingetVersion"
            return $true
        }
    }
    catch {
        #Write-Verbose "Winget not found. Attempting to install..."
    }

    try {
        # Install Winget
        #Write-Verbose "Attempting to Install Winet."
        Add-AppxPackage -Path "https://aka.ms/getwinget" -ErrorAction SilentlyContinue
        $ProgressPreference = $ProgressPreferenceTemp
        # Verify installation
        $wingetVersion = winget --version
        if ($?) {
            #Write-Verbose "Winget successfully installed. Version: $wingetVersion"
            return $true
        } else {
            #Write-Verbose "Failed to verify Winget installation"
            return $false
        }
    }
    catch {
        #Write-Verbose "Error during installation: $_"
        return $false
    }
}
FUNCTION Get-IPInfo {
    <#
    .SYNOPSIS
    Retrieves geographic information.
 
    .DESCRIPTION
    Retrieves geographic information about .
 
    .PARAMETER None
 
    .EXAMPLE
    Get-GeoInfo
 
    .NOTES
    The function uses a web API to cpllect geographic data.
    #>

    
    [CmdletBinding()]
    PARAM (
        [System.Net.IPAddress[]]$IPAddress = "127.0.0.1"
    )
    
    $Results = @()

    ### IP and Geo Location Data
    FOREACH ($IP in $IPAddress) {
        IF ($IP -eq "127.0.0.1") { 
            $GeoData = Invoke-RestMethod -Method Get -Uri "http://ip-api.com/json/$null" -Verbose:$false
            
            $Results += [PSCustomObject]@{
                IP = $GeoData.Query
                IPClass = "Public"
                Country = $GeoData.Country
                State = $GeoData.RegionName
                City = $GeoData.City
                ZipCode = $GeoData.Zip
                Org = $GeoData.Org
                ISP = $GeoData.ISP
            }        
        }
        ELSEIF ((TEST-IsPublicIP $IP)) {
            $GeoData = Invoke-RestMethod -Method Get -Uri "http://ip-api.com/json/$IP" -Verbose:$false
            
            $Results += [PSCustomObject]@{
                IP = $IP
                IPClass = "Public"
                Country = $GeoData.Country
                State = $GeoData.RegionName
                City = $GeoData.City
                ZipCode = $GeoData.Zip
                Org = $GeoData.Org
                ISP = $GeoData.ISP
            }
        }
        ELSE {
            $Results += [PSCustomObject]@{
                IP = $IP
                IPClass = "Private"
                Country = $null
                State = $null
                City = $null
                ZipCode = $null
                Org = $null
                ISP = $null
            }
        }
        
    }

    RETURN $Results | Select IP, IPClass, Country, State, City, ZipCode, Org, ISP
}
FUNCTION Test-VirusTotalHash {
    <#
    .SYNOPSIS
        Checks a file's hash against the VirusTotal database.
 
    .DESCRIPTION
        This function calculates the SHA256 hash of a specified file and queries the VirusTotal API to retrieve the analysis report, including the number of antivirus engines that detect it as malicious.
 
    .PARAMETER FilePath
        The full path to the file to be checked.
 
    .PARAMETER ApiKey
        Your VirusTotal API key. Obtain it from https://www.virustotal.com/gui/my-apikey.
 
    .EXAMPLE
        Get-VirusTotalFileReport -FilePath "C:\Downloads\example.exe" -ApiKey "your-api-key-here"
        Checks the SHA256 hash of example.exe against VirusTotal and displays the analysis results.
 
    .NOTES
        - Requires a VirusTotal API key.
        - Free API keys have rate limits (e.g., 4 requests per minute, 500 per day). Ensure compliance with VirusTotal's terms.
        - Ensure the file exists and is accessible.
        - Internet connectivity is required to query the VirusTotal API.
    #>

    
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$FilePath,        
        [string]$ApiKey = "938762c1c51c4d3825db13df683cbd4e3b3ad2d514bf79dcdb5a34eca32555b4",
        [int]$FailThreshold = 2,
        [SWITCH]$AllowUnknown = $False
    )

    # Get-VirusTotalFileReport -FilePath "C:\Downloads\example.exe" -ApiKey "your-api-key-here" -Verbose

    try {
        # Verify the file exists
        if (-not (Test-Path -Path $FilePath -PathType Leaf)) {
            throw "The file '$FilePath' does not exist or is not accessible."
        }

        # Calculate the SHA256 hash of the file
        #Write-Verbose "Calculating SHA256 hash for '$FilePath'..."
        $sha256 = Get-FileHash -Path $FilePath -Algorithm SHA256
        $fileHash = $sha256.Hash.ToLower()
        #Write-Verbose "SHA256 Hash: $fileHash"

        # Define VirusTotal API endpoint and headers
        $url = "https://www.virustotal.com/api/v3/files/$fileHash"
        $headers = @{
            "x-apikey" = $ApiKey
            "Accept"   = "application/json"
        }

        # Query VirusTotal API
        #Write-Verbose "Querying VirusTotal for hash '$fileHash'..."
        $response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers -ErrorAction Stop -Verbose:$false

        # Parse the response
        $attributes = $response.data.attributes
        $lastAnalysisStats = $attributes.last_analysis_stats
        $totalEngines = $lastAnalysisStats.malicious + $lastAnalysisStats.suspicious + $lastAnalysisStats.undetected + $lastAnalysisStats.harmless
        $maliciousCount = $lastAnalysisStats.malicious
        $suspiciousCount = $lastAnalysisStats.suspicious

        # Prepare output
        $result = [PSCustomObject]@{
            FilePath         = $FilePath
            SHA256           = $fileHash
            TotalEngines     = $totalEngines
            MaliciousCount   = $maliciousCount
            SuspiciousCount  = $suspiciousCount
            DetectionRate    = "$maliciousCount/$totalEngines"
            LastAnalysisDate = (Get-Date -Date $attributes.last_analysis_date -Format "yyyy-MM-dd HH:mm:ss")
            VirusTotalLink   = "https://www.virustotal.com/gui/file/$fileHash"
        }

        # Output results
        #Write-Output "VirusTotal Analysis Report for '$FilePath':"
        #Write-Output $result | Format-Table -AutoSize
        if ($maliciousCount -gt 0 -or $suspiciousCount -gt 0) {
            #Write-Warning "File flagged as potentially malicious or suspicious by $maliciousCount/$totalEngines engines. Review the report at: https://www.virustotal.com/gui/file/$fileHash"
        } else {
            #Write-Output "No malicious or suspicious detections found."
        }

        IF ($result.MaliciousCount -gt $FailThreshold) { RETURN $False }
        ELSE { RETURN $True }
    }
    catch {
        RETURN $Null
        if ($_.Exception.Response.StatusCode -eq 404) {
            #Write-Warning "Hash '$fileHash' not found in VirusTotal database. Consider uploading the file for analysis."
        } elseif ($_.Exception.Response.StatusCode -eq 429) {
            #Write-Error "API rate limit exceeded. Wait and try again later or upgrade your VirusTotal API plan."
        } else {
            #Write-Error "An error occurred: $_"
        }

    }
}
FUNCTION Get-TimeDifferenceToString {
    
    [CmdletBinding()]
    PARAM (
        [DateTime]$Time
    )

    $TimeSpan = (Get-Date) - $Time

    IF ($TimeSpan.TotalHours -ge 1) {
        RETURN $Timespan.ToString("%h\:mm\:ss")
    }
    ELSE {
        RETURN $Timespan.ToString("%m\:ss")
    }
}
FUNCTION Remove-NullEntriesInObject {
    param (
        [Parameter(Mandatory=$true)]
        $InputArray
    )

   
        # Initialize an array list to store non-null entries
        $result = @()
  

  
        foreach ($item in $InputArray) {
            if ($null -ne $item.Action) {
                # Add non-null items to the result
                $result += $item
            }
        }
  

        # Return the filtered array
        return $result
 
}
Function Test-IPInCIDR {
    [cmdletbinding()]
    [outputtype([System.Boolean])]
    param(
        # IP Address to find.
        [parameter(Mandatory,
                   Position=0)]
        [validatescript({
            ([System.Net.IPAddress]$_).AddressFamily -eq 'InterNetwork'
        })]
        [string]
        $IPAddress,

        # Range in which to search using CIDR notation. (ippaddr/bits)
        [parameter(Mandatory,
                   Position=1)]
        [validatescript({
            $IP   = ($_ -split '/')[0]
            $Bits = ($_ -split '/')[1]

            (([System.Net.IPAddress]($IP)).AddressFamily -eq 'InterNetwork')

            if (-not($Bits)) {
                throw 'Missing CIDR notiation.'
            } elseif (-not(0..32 -contains [int]$Bits)) {
                throw 'Invalid CIDR notation. The valid bit range is 0 to 32.'
            }
        })]        
        [string]$CIDR
    )

    # Split range into the address and the CIDR notation
    [String]$CIDRAddress = $CIDR.Split('/')[0]
    [int]$CIDRBits       = $CIDR.Split('/')[1]

    # Address from range and the search address are converted to Int32 and the full mask is calculated from the CIDR notation.
    [int]$BaseAddress    = [System.BitConverter]::ToInt32((([System.Net.IPAddress]::Parse($CIDRAddress)).GetAddressBytes()), 0)
    [int]$Address        = [System.BitConverter]::ToInt32(([System.Net.IPAddress]::Parse($IPAddress).GetAddressBytes()), 0)
    [int]$Mask           = [System.Net.IPAddress]::HostToNetworkOrder(-1 -shl ( 32 - $CIDRBits))

    # Determine whether the address is in the range.
    if (($BaseAddress -band $Mask) -eq ($Address -band $Mask)) {
        $true
    } else {
        $false
    }
}
Function Test-NotNull {

    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory)]
        [AllowNull()]
        $Value
    )

    TRY {
        IF ($Value -eq $True) { RETURN $True }
        IF ($Value -eq $null) { RETURN $False }
        IF ($Value -eq "") { RETURN $False } 
        IF ($Value -eq " ") { RETURN $False }
        IF ($Value.count -eq 0) { RETURN $False }
        IF ($Value -eq $False) { RETURN $False }
    }
    CATCH {
        RETURN $False
    }

    RETURN $True
}
FUNCTION Test-IsDesktop {

    IF ((Test-IsLaptop) -or (Test-IsServer) -or (Test-IsVirtual)) { Return $False }
    ELSE { Return $True }
}
FUNCTION Test-IsLaptop {
    IF ((GET-CIMInstance Win32_SystemEnclosure -Verbose:$False).ChassisTypes -eq 8 -or
    (GET-CIMInstance Win32_SystemEnclosure -Verbose:$False).ChassisTypes -eq 9 -or
    (GET-CIMInstance Win32_SystemEnclosure -Verbose:$False).ChassisTypes -eq 10 -or
    (GET-CIMInstance Win32_SystemEnclosure -Verbose:$False).ChassisTypes -eq 14 -or
    (GET-CIMInstance Win32_SystemEnclosure -Verbose:$False).ChassisTypes -eq 30) {
        RETURN $True
    }
    RETURN $False
}
FUNCTION Test-IsVirtual {
    IF ((Get-WmiObject -Class Win32_ComputerSystem -Verbose:$False).Model -like "*Virtual*") { RETURN $True }
    IF ((Get-WmiObject -Class Win32_ComputerSystem -Verbose:$False).Model -like "*AWS*") { RETURN $True }
    IF ((Get-WmiObject -Class Win32_ComputerSystem -Verbose:$False).Model -like "*Google*") { RETURN $True }
    IF ((Get-WmiObject -Class Win32_ComputerSystem -Verbose:$False).Model -like "*VMWare*") { RETURN $True }
    IF ((Get-WmiObject -Class Win32_ComputerSystem -Verbose:$False).Model -like "*Xen*") { RETURN $True }
    RETURN $False
}
FUNCTION Test-IsPhysical {
    IF (Test-IsVirtual) { RETURN $False }
    ELSE { RETURN $True }
}
FUNCTION Test-IsServer {
    $ProductType = (GET-CIMInstance Win32_OperatingSystem -Verbose:$False).ProductType

    IF ($ProductType -eq 2) { RETURN $True }
    IF ($ProductType -eq 3) { RETURN $True }

    RETURN $False    
} 
FUNCTION Get-DuoForWindowsConfig {
   
    [CmdletBinding()]
    PARAM ( )

    $App = Get-ApplicationInstalled "Duo Auth"
 
    $Results = [PSCustomObject]@{
        AppName = $App.Name
        AppVersion = $App.Version
        IKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).IKey
        SKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).Skey
        HostAPI = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).Host
        AutoPush = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).AutoPush
        FailOpen = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).FailOpen
        RDPOnly = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).RDPOnly
        SmartCard = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).EnableSmartCards
        WrapSmartCard = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).WrapSmartCards
        EnableOffline = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).OfflineAvailable
        UserNameFormat = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).UserNameFormatForService        
        LogFile_MaxCount = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).LogFileMaxCount
        LogFile_MaxSizeMB = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).LogFileMaxSizeMB
        UAC_ProtectMode = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).ElevationProtectionMode
        UAC_Offline = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).ElevationOfflineEnable
        UAC_Offline_Enroll = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).ElevationOfflineEnrollment
        ProxyHost = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).ProxyHost
        ProxyPort = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Duo Security\DuoCredProv" -ErrorAction SilentlyContinue).ProxyPort
    }

    RETURN $Results
}
FUNCTION Send-Keystroke {
    PARAM (
        [Parameter(Mandatory)]
        [STRING]$Title,
        [Parameter(Mandatory)]
        [STRING[]]$Key,
        [INT]$Delay = 10
    )

    $Count = 0
    FOREACH ($Item in $Key) { 
        
        $AppShell = New-Object -ComObject wscript.shell
        $AppShell.AppActivate($Title) | Out-Null
        Start-Sleep -Milliseconds 100
        $AppShell.SendKeys($Item)

        $Count++
        IF ($Count -lt $Key.Count) { Start-Sleep -Seconds $Delay }
    }
}
FUNCTION Install-Font {
    <#
    .SYNOPSIS
        Installs a font on the system.
    .DESCRIPTION
        Copies a font file to the Windows Fonts directory and registers it in the system.
    .PARAMETER FontPath
        The full path to the font file (.ttf or .otf).
    .EXAMPLE
        Install-Font -FontPath "C:\Fonts\MyFont.ttf"
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateScript({Test-Path $_ -PathType Leaf})]
        [string]$FontPath
    )

    try {
        # Get font file details
        $fontFile = Get-Item $FontPath
        $fontName = $fontFile.BaseName
        $fontExtension = $fontFile.Extension.ToLower()
        
        # Validate font file type
        if ($fontExtension -notin @('.ttf', '.otf')) {
            throw "Invalid font file type. Only .ttf and .otf files are supported."
        }

        # Windows Fonts directory
        $fontsFolder = [System.Environment]::GetFolderPath('Fonts')
        $destinationPath = Join-Path $fontsFolder $fontFile.Name

        # Copy font to Windows Fonts directory
        Copy-Item -Path $FontPath -Destination $destinationPath -Force

        # Register the font
        $shell = New-Object -ComObject Shell.Application
        $fontsNamespace = $shell.Namespace(0x14) # 0x14 is the Fonts folder
        $Job = Start-Job -ScriptBlock { $fontsNamespace.CopyHere($FontPath) }     
        

        # Add to registry
        $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"
        $fontRegistryName = if ($fontExtension -eq '.ttf') { "$fontName (TrueType)" } else { "$fontName (OpenType)" }
        Set-ItemProperty -Path $registryPath -Name $fontRegistryName -Value $fontFile.Name -Force

        #Write-Output "Font '$fontName' installed successfully."

        Send-Keystroke -Title "Install Font" -Key "{Tab}","{Enter}" -Delay 3
    }
    catch {
        #Write-Error "Failed to install font: $_"
    }
}
FUNCTION Test-FontInstalled {
    <#
    .SYNOPSIS
        Checks if a font is installed on the system.
    .DESCRIPTION
        Verifies if a specified font is present in the Windows Fonts directory or registry.
    .PARAMETER FontName
        The name of the font to check (without file extension).
    .EXAMPLE
        Test-FontInstalled -FontName "Arial"
    .OUTPUTS
        Boolean: $true if the font is installed, $false otherwise.
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true, Position=0)]
        [string]$FontName
    )

    try {
        # Check Windows Fonts directory
        $fontsFolder = [System.Environment]::GetFolderPath('Fonts')
        $fontFiles = Get-ChildItem -Path $fontsFolder -Include "$FontName*.ttf", "$FontName*.otf" -File

        if ($fontFiles) {
            Write-Verbose "Font file for '$FontName' found in Fonts directory."
            return $true
        }

        # Check registry
        $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"
        $fontRegistryNameTTF = "$FontName (TrueType)"
        $fontRegistryNameOTF = "$FontName (OpenType)"
        
        $fontInRegistry = (Get-ItemProperty -Path $registryPath -ErrorAction SilentlyContinue).PSObject.Properties.Name |
            Where-Object { $_ -eq $fontRegistryNameTTF -or $_ -eq $fontRegistryNameOTF }

        if ($fontInRegistry) {
            Write-Verbose "Font '$FontName' found in registry."
            return $true
        }

        Write-Verbose "Font '$FontName' not found."
        return $false
    }
    catch {
        Write-Error "Error checking font installation: $_"
        return $false
    }
}
FUNCTION Install-WindowsUpdates {

    <#
    .SYNOPSIS
    Installs Windows updates.
 
    .DESCRIPTION
    This function installs windows updates and optionally reboots the computer.
 
    .PARAMETER RetryCount
    This specifies additional install attempts if updates remain uninstalled after the first attempt. Default 2.
 
    .PARAMETER ForceReboot
    This specifies a forced reboot if needed when updates are finished installing.
 
    .PARAMETER RebootTime
    This specifies a future time to reboot the computer once updates are finished installing.
 
    .EXAMPLE
    Install-WindowsUpdates -ForceReboot -RebootTime "5/5/25 20:00"
    Installs updates and forces a reboot at 8PM on 5/5/25.
 
    .NOTES
    The function will install driver updates if available, but doesn't care if they don't install successfully.
    #>


    [CmdletBinding(DefaultParameterSetName='Default')]
    PARAM (
        [Parameter(Mandatory,ParameterSetName = 'Reboot')]
        [SWITCH]$ForceReboot = $False,
        [Parameter(ParameterSetName = 'Default')]
        [Parameter(ParameterSetName = 'Reboot')]
        [INT]$RetryCount = 0,
        [Parameter(ParameterSetName = 'Reboot')]
        [DATETIME]$RebootTime = "1/1/1"
    )
    
    IF ($RebootTime -le (Get-Date) -and $RebootTime -ne "1/1/1") { Write-Host ""; Write-Warning "Specified time has already passed. Please specify a time in the future or no time for immediate reboot when done."; RETURN }
    ELSEIF ($RebootTime -ne "1/1/1") { Write-Verbose "Reboot scheduled for $RebootTime. (Approximately $([Math]::Round(($RebootTime - (Get-Date)).TotalHours,0)) Hour(s) from Now)" }
    ELSE { }

    Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -force

    Write-Verbose "Checking for Windows updates..."
    $TryCount = 0    

    $UpdatesRemaining = 0
    $Searcher = New-Object -ComObject Microsoft.Update.Searcher
    $SearchResult = $Searcher.Search("IsInstalled=0 and RebootRequired=0").Updates
    FOREACH ($Result in $SearchResult) { IF ($Result.Type -eq 1) { $UpdatesRemaining++ } }      
        
    WHILE ($UpdatesRemaining -gt 0 -and $TryCount -le $RetryCount) {
        
        IF ($TryCount -gt 0) { Write-Verbose "Some updates found not installed. Trying again." }
        $TryCount++
        Write-Verbose "Updates found. Attempt $TryCount of $($RetryCount + 1)"


        Write-Verbose "Downloading updates..."
        #Download updates.
        $Session = New-Object -ComObject Microsoft.Update.Session
        $Downloader = $Session.CreateUpdateDownloader()
        $Downloader.Updates = $SearchResult
        $Downloader.Download()

        Write-Verbose "Done downloading updates. Installing..."
        #Install updates.
        $Installer = New-Object -ComObject Microsoft.Update.Installer
        $Installer.Updates = $SearchResult
        $InstallerResults = $Installer.Install() | Out-Null
        Write-Verbose "Finished installing. Checking results..."

        $Searcher = New-Object -ComObject Microsoft.Update.Searcher
        $SearchResult = $Searcher.Search("IsInstalled=0 and RebootRequired=0").Updates | Out-Null
        $UpdatesRemaining = 0
        FOREACH ($Result in $SearchResult) { IF ($Result.Type -eq 1) { $UpdatesRemaining++ } }   
        IF ($UpdatesRemaining -eq 0) { continue }
    }

    IF ($TryCount -eq 0) { Write-Verbose "No Updates Found. Checking if reboot is needed..." }

    FOREACH ($Result in $SearchResult) { IF ($Result.Type -eq 1 -and $Result.IsInstalled -eq $False) { Write-Verbose "Retry count exceeded. Some updates failed to install." } }

    ### Reboot if Required by Updates
    
    IF ((($Searcher.Search("RebootRequired=1").Updates) | select RebootRequired).RebootRequired -contains $true)
    { 
        IF ($ForceReboot -eq $False) { Write-Verbose "Reboot required but no reboot requested. Done." }
        ELSEIF ($RebootTime -ne "1/1/1") { 
            [int]$Delay = [MATH]::Round(($RebootTime - (Get-Date)).TotalSeconds,0) 
            Write-Verbose "Reboot required. Scheduled Reboot for $RebootTime."
            Start-Process -FilePath "Shutdown.exe" -ArgumentList "-r -t $Delay" -ErrorAction SilentlyContinue -WindowStyle Hidden
        }
        ELSE {
            Write-Verbose "Reboot required. Rebooting in 5 seconds..."
            Start-Process -FilePath "Shutdown.exe" -ArgumentList "-r -t 5" -ErrorAction SilentlyContinue -WindowStyle Hidden 
        }
    }
    ELSE {
        Write-Verbose "No reboot required. Done."
    }

    $VerbosePreference = $VerbosePreferenceTemp
}
FUNCTION Convert-IDTResults { 
    
    PARAM (
        [Parameter(Mandatory = $true)]
        $InputResult
    )
    $OutputResult = @()

    FOREACH ($Item in $InputResult) {    
        $OutputResult += [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResults'
            Action = $Item.Action
            Duration = $Item.Duration
            Name = $Item.Name
            Version = $Item.Version                
            Success = $Item.Success    
            Details = $Item.Details  
        }
    }

    RETURN $OutputResult
}
FUNCTION Set-WindowsAutoLogon {
    <#
    .SYNOPSIS
        Configures Windows autologon by setting registry keys.
     
    .DESCRIPTION
        Sets registry values to enable automatic logon for a specified user account.
     
    .PARAMETER Username
        The username of the account to automatically log in.
     
    .PARAMETER Password
        The password for the specified user account.
     
    .PARAMETER Domain
        The domain for the user account (optional, defaults to local machine).
     
    .EXAMPLE
        Set-WindowsAutoLogon -Username "User1" -Password "Pass123" -Domain "CONTOSO"
     
    .NOTES
        Requires administrative privileges to modify registry.
        Stores password in plain text in registry (security consideration).
    #>

    
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string]$Username,
        
        [Parameter(Mandatory=$true)]
        [string]$Password,
        
        [Parameter(Mandatory=$false)]
        [string]$Domain = $env:COMPUTERNAME
    )
    
    try {
        # Define registry path
        $regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
        
        # Check if running as administrator
        $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
        if (-not $isAdmin) {
            #throw "This function requires administrative privileges."
        }
        
        # Set registry values
        Set-ItemProperty -Path $regPath -Name "AutoAdminLogon" -Value "1"
        Set-ItemProperty -Path $regPath -Name "DefaultUserName" -Value $Username
        Set-ItemProperty -Path $regPath -Name "DefaultPassword" -Value $Password
        Set-ItemProperty -Path $regPath -Name "DefaultDomainName" -Value $Domain
        
        #Write-Output "Autologon configured successfully for user: $Username"
    }
    catch {
        #Write-Error "Failed to set autologon: $_"
    }
}
FUNCTION Clear-WindowsAutoLogon {
    <#
    .SYNOPSIS
        Clears Windows autologon registry keys to disable automatic logon.
     
    .DESCRIPTION
        Removes registry values that enable automatic logon for Windows.
     
    .EXAMPLE
        Clear-WindowsAutoLogon
     
    .NOTES
        Requires administrative privileges to modify registry.
    #>

    
    [CmdletBinding()]
    param ()
    
    try {
        # Define registry path
        $regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
        
        # Check if running as administrator
        $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
        if (-not $isAdmin) {
            #throw "This function requires administrative privileges."
        }
        
        # Remove registry values
        $properties = @("AutoAdminLogon", "DefaultUserName", "DefaultPassword", "DefaultDomainName")
        foreach ($prop in $properties) {
            if (Get-ItemProperty -Path $regPath -Name $prop -ErrorAction SilentlyContinue) {
                Remove-ItemProperty -Path $regPath -Name $prop -ErrorAction Stop
            }
        }
        
        #Write-Output "Autologon registry keys cleared successfully."
    }
    catch {
        #Write-Error "Failed to clear autologon keys: $_"
    }
}
FUNCTION Get-Param { 
    RETURN (Import-CLIXML -Path C:\Integris\Temp\Resume\Parameters.xml) 
}
FUNCTION New-IsoFile {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true,Position=0)]
        [string] $Path,
        [Parameter(Mandatory=$true,Position=1)]
        [string] $Destination,
        [Parameter(Mandatory=$true)]
        [string] $VolumeName,
        [switch] $IncludeRoot,
        [switch] $Force
    )

    # http://msdn.microsoft.com/en-us/library/windows/desktop/aa364840.aspx
    $fsi = New-Object -ComObject IMAPI2FS.MsftFileSystemImage
    $fsi.FileSystemsToCreate = 4 # FsiFileSystemUDF
    $fsi.FreeMediaBlocks = 0
    $fsi.VolumeName = $VolumeName
    $fsi.Root.AddTree($Path, $IncludeRoot)
    $istream = $fsi.CreateResultImage().ImageStream

    $Options = if ($PSEdition -eq 'Core') {
        @{ CompilerOptions = "/unsafe" }
    } else {
        $cp = New-Object CodeDom.Compiler.CompilerParameters
        $cp.CompilerOptions = "/unsafe"
        $cp.WarningLevel = 4
        $cp.TreatWarningsAsErrors = $true
        @{ CompilerParameters = $cp }
    }

    Add-Type @Options -TypeDefinition @"
using System;
using System.IO;
using System.Runtime.InteropServices.ComTypes;
namespace IsoHelper {
    public static class FileUtil {
        public static void WriteIStreamToFile(object i, string fileName) {
            IStream inputStream = i as IStream;
            FileStream outputFileStream = File.OpenWrite(fileName);
            int bytesRead = 0;
            int offset = 0;
            byte[] data;
            do {
                data = Read(inputStream, 2048, out bytesRead);
                outputFileStream.Write(data, 0, bytesRead);
                offset += bytesRead;
            } while (bytesRead == 2048);
            outputFileStream.Flush();
            outputFileStream.Close();
        }
        unsafe static private byte[] Read(IStream stream, int toRead, out int read) {
            byte[] buffer = new byte[toRead];
            int bytesRead = 0;
            int* ptr = &bytesRead;
            stream.Read(buffer, toRead, (IntPtr)ptr);
            read = bytesRead;
            return buffer;
        }
    }
}
"@


    [IsoHelper.FileUtil]::WriteIStreamToFile($istream, $Destination)
}


### Core Functions
FUNCTION Set-RegistryValue {
    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory=$true)]
        [ValidateSet("HKLM", "HKCU", "HKCR", "HKU", "HKCC")]
        [string]$Hive,

        [Parameter(Mandatory=$true)]
        [string]$Path,

        [Parameter(Mandatory=$true)]
        [string]$Name,

        [Parameter(Mandatory=$true)]
        $Value,

        [Parameter(Mandatory=$true)]
        [ValidateSet("String", "DWORD", "QWORD", "MultiString", "Binary", "ExpandString")]
        [string]$Type
    )

    try {
        # Convert hive shorthand to full registry path
        $hivePath = switch ($Hive) {
            "HKLM" { "HKLM:\" }
            "HKCU" { "HKCU:\" }
            "HKCR" { "HKEY_CLASSES_ROOT\" }
            "HKU"  { "HKEY_USERS\" }
            "HKCC" { "HKEY_CURRENT_CONFIG\" }
        }

        # Construct full registry path
        $fullPath = Join-Path $hivePath $Path

        # Check if path exists, create if it doesn't
        if (-not (Test-Path $fullPath)) {
            New-Item -Path $fullPath -Force -ErrorAction SilentlyContinue | Out-Null
        }

        # Set the registry value
        Set-ItemProperty -Path $fullPath -Name $Name -Value $Value -Type $Type -ErrorAction SilentlyContinue     

        # Verify the value was set
        $setValue = Get-ItemProperty -Path $fullPath -Name $Name -ErrorAction SilentlyContinue
        $actualValue = $setValue.$Name

        # Compare set value with requested value
        if ($actualValue -eq $Value) {
            Write-Verbose "Registry key set successfully: $fullPath\$Name = $actualValue"
            return $true
        } else {
            Write-Verbose "Verification failed: Expected '$Value', but got '$actualValue'"
            return $false
        }



    }
    catch {
        Write-Verbose "Failed to set registry key: $($_.Exception.Message)"
        return $false
    }
}
FUNCTION Run-FileDownload {
    
    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory=$true)]
        [STRING]$URL,
        [Parameter(Mandatory=$true)]
        [STRING]$FileName,
        [STRING]$SavePath = "C:\Integris\Temp",
        [STRING]$FileHash,
        [SWITCH]$Force = $False,
        [SWITCH]$BasicOutput = $False
    )

    $Result = [PSCustomObject]@{
        DownloadURL = $URL
        FileName = $FileName
        SavePath = $SavePath
        FullName = "$($SavePath)\$($FileName)"
        FileHash = $FileHash
        DownloadHash = $null
        HashMatch = $null
        DownloadSuccess = $null
    }

    FUNCTION OutputFunctionResults {
        ### Set Progress Bar Back to Original Setting
        $ProgressPreference = $ProgressPreferenceTemp

        IF ($BasicOutput) { RETURN $Result.DownloadSuccess }
        ELSE { RETURN $Result | Select DownloadURL, SavePath, FileName, FullName, FileHash, DownloadHash, HashMatch, DownloadSuccess }
    }
        
    TRY {

        ### Progress Bar Needs to Be Disabled
        ### If Not Disabled, The GUI Attempts to Update on Every Byte Downloaded which Makes it Run Extremely Slow As a Download could Easily Be Millions of Bytes
        $ProgressPreferenceTemp = $ProgressPreference
        $ProgressPreference = "SilentlyContinue"


        ### Create Download Directory
        $SavePathSplit = $SavePath.Split("\")
        $NewFolderName = $null
        $NewFolderPath = $null
        IF ($SavePathSplit[$SavePathSplit.Count-1] -eq "") {
            $NewFolderName = $SavePathSplit[$SavePathSplit.Count-2]
            $Count = 2
            $NewFolderPath = ""
            While ($Count -lt $SavePathSplit.Count) { 
                $NewFolderPath += $SavePathSplit[$Count-2]
                $NewFolderPath += "\"
                $Count++
            }
            New-Item -Name $NewFolderName -Path $NewFolderPath -ItemType Directory -ErrorAction SilentlyContinue | Out-Null 
        }
        ELSE {
            $NewFolderName = $SavePathSplit[$SavePathSplit.Count-1]
            $Count = 1
            $NewFolderPath = ""
            While ($Count -lt $SavePathSplit.Count) { 
                $NewFolderPath += $SavePathSplit[$Count-1]
                $NewFolderPath += "\"
                $Count++
            }
            New-Item -Name $NewFolderName -Path $NewFolderPath -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
        }


        ### Check if Already Downloaded
        $DownloadFile = GET-Item "$($SavePath)\$($FileName)" -ErrorAction SilentlyContinue
        $DownloadHash = (Get-FileHash -Path "$($SavePath)\$($FileName)" -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash

        ### If File Exists and Hash Matches
        IF ($DownloadFile -and $DownloadHash -eq $FileHash) {
            $Result.DownloadHash = $DownloadHash; $Result.HashMatch = $true; $Result.DownloadSuccess = $true;
            #Write-Verbose "$($(Get-Date).ToShortTimeString()): File found. Already downloaded."
            IF ($Force) { 
                #Write-Verbose "$($(Get-Date).ToShortTimeString()): Download found and hash matches, but force download was specified."
            } ELSE { RETURN OutputFunctionResults }
        }

        ## IF File Exists and Hash Wasn't Specified
        IF ($DownloadFile -and ($FileHash -eq $null -or $FileHash -eq "")) {
            $Result.DownloadHash = $DownloadHash; $Result.HashMatch = $null; $Result.DownloadSuccess = $true;
            #Write-Verbose "$($(Get-Date).ToShortTimeString()): File found. Already downloaded."
            IF ($Force) { 
                #Write-Verbose "$($(Get-Date).ToShortTimeString()): Download found but force download was specified."
            } ELSE { RETURN OutputFunctionResults }
        }

        ### If File Exists and Hash Doesn't Match
        ELSEIF ($DownloadFile -and $DownloadHash -ne $FileHash) { 
            #Write-Verbose "$($(Get-Date).ToShortTimeString()): Download found and but Hash doesn't match. Attempting download."
        }
        

        ### Download the file
        #Write-Verbose "$($(Get-Date).ToShortTimeString()): Downloading file from $URL..."
        TRY { Invoke-WebRequest $URL -OutFile "$($SavePath)\$($FileName)" -UseBasicParsing -ErrorAction SilentlyContinue -Verbose:$false }
        catch { }

        #Write-Verbose "$($(Get-Date).ToShortTimeString()): File downloaded to $($SavePath)\$($FileName)"

        $DownloadFile = GET-Item "$($SavePath)\$($FileName)" -ErrorAction SilentlyContinue
        $DownloadHash = (Get-FileHash -Path "$($SavePath)\$($FileName)" -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
        
        ### If File Exists and Hash Matches
        IF ($DownloadFile -and $DownloadHash -eq $FileHash) {
            $Result.DownloadHash = $DownloadHash; $Result.HashMatch = $true; $Result.DownloadSuccess = $true; 
            #Write-Verbose "$($(Get-Date).ToShortTimeString()): Download Successful. Hash Matches. Done."
            RETURN OutputFunctionResults
        }
        ### If File Exists and Hash Doesn't Match
        ELSEIF ($DownloadFile -and $FileHash -ne $null -and $FileHash -ne "") {
            $Result.DownloadHash = $DownloadHash; $Result.HashMatch = $false; $Result.DownloadSuccess = $false; 
            #Write-Verbose "$($(Get-Date).ToShortTimeString()): Download Failure. Hash Doesn't Match. Fail."
            RETURN OutputFunctionResults   
        }
        ### If File Exists and Hash Wasn't Specified
        ELSEIF ($DownloadFile -and ($FileHash -eq $null -or $FileHash -eq "")) {
            $Result.DownloadHash = $DownloadHash; $Result.HashMatch = $null; $Result.DownloadSuccess = $true; 
            #Write-Verbose "$($(Get-Date).ToShortTimeString()): Download Successful. Verification hash not provided. Done."
            RETURN OutputFunctionResults   
        }
        ### If File Doesn't Exist and Hash wasn't specified
        ELSEIF ($DownloadFile -eq $null -and ($FileHash -eq $null -or $FileHash -eq "")) {
            $Result.DownloadHash = $null; $Result.HashMatch = $null; $Result.DownloadSuccess = $false; 
            #Write-Verbose "$($(Get-Date).ToShortTimeString()): Download Unsuccessful. Fail."
            RETURN OutputFunctionResults   
        }
        ### If File Doesn't Exist and Hash was specified
        ELSE {
            $Result.DownloadHash = $null; $Result.HashMatch = $false; $Result.DownloadSuccess = $false; 
            #Write-Verbose "$($(Get-Date).ToShortTimeString()): Download Unsuccessful. Fail."
            RETURN OutputFunctionResults
        }

    }
    CATCH {
        #Write-Error "Error occurred: $_"
        RETURN OutputFunctionResults
    }
}
FUNCTION Run-PackageHandler {

    [CmdletBinding(DefaultParameterSetName='Install')]
    PARAM (
        ### General
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [Parameter(Mandatory)]  
        [STRING]$ApplicationName = $null,
        [VERSION]$ApplicationVersion = $null,
        [SWITCH]$ExactVersion = $False, 
        [STRING]$CustomVersionCommand = $null,
        [SWITCH]$VerifyOnly = $False, 
        [STRING]$DownloadLink = $null,
        [STRING]$BackupDownloadLink = $DownloadLink,
        [STRING]$FileName = $null,
        [STRING]$BackupFileName = $FileName,
        [STRING]$ZipInstallerPath = $null,
        [STRING]$SavePath = "C:\Integris\Temp",
        [ValidateSet("Always","AfterSuccess","Never")]
        [STRING]$CleanupMode = "AfterSuccess", 
        [SWITCH]$ForceDownload = $False,    
        [ValidateSet("NoUpdate","InstallOver","UninstallReinstall")]
        [STRING]$UpdateMethod = "NoUpdate",   


        ### Run Specific
        [STRING]$RunPath = $null,
        [STRING]$RunArguements = $null,


        ### Install Specific
        [STRING]$CustomInstallCommand = $null,
        [SWITCH]$InvokeInstallCommand = $False,
        [STRING]$InstallArguments = $null,   
        [INT]$InstallTimeout = 480,               
        [INT]$PostInstallDelay = 5,
        [STRING[]]$PreInstallEndProcess = $null, 
        [STRING[]]$PostInstallEndProcess = $null, 
        [STRING]$CustomInstallVerification = $null,  
        [STRING]$InstallKeystrokes = $null,


        ### Uninstall Specific
        [STRING]$UninstallCommand = $null,
        [SWITCH]$InvokeUninstallCommand = $False,
        [STRING]$UninstallArguments = $null,
        [INT]$UninstallTimeout = 240,
        [INT]$PostUninstallDelay = 10,
        [STRING[]]$PreUninstallEndProcess = @(),
        [STRING[]]$PostUninstallEndProcess = @(),
        [STRING]$CustomUninstallVerification = $null,  
        [STRING]$UninstallKeystrokes = $null,
               

        ### Smart Features Specific
        [AllowNull()]
        [STRING[]]$IncludeDeviceType = $null,
        [AllowNull()]
        [STRING[]]$ExcludeDeviceType = $null,
        [AllowNull()]
        [STRING[]]$IncludeHostname = $null,
        [AllowNull()]
        [STRING[]]$ExcludeHostname = $null,
        [AllowNull()]
        [STRING[]]$IncludeDN = $null,
        [AllowNull()]
        [STRING[]]$ExcludeDN = $null,
        [AllowNull()]
        [STRING[]]$IncludeADSite = $null,
        [AllowNull()]
        [STRING[]]$ExcludeADSite = $null,
        [AllowNull()]
        [STRING[]]$IncludeIPAddress = $null,
        [AllowNull()]
        [STRING[]]$ExcludeIPAddress = $null,
        [AllowNull()]
        [STRING[]]$IncludeGeoLocation = $null,
        [AllowNull()]
        [STRING[]]$ExcludeGeoLocation = $null,


        ### Security Specific
        [STRING]$DownloadHash = $null,
        [STRING]$BackupDownloadHash = $null,
        [SWITCH]$CertVerification = $null,
        [STRING]$CertName = $null,
        [SWITCH]$VirusTotal = $null,
           

        ### WinGet Specific
        [STRING]$WinGetAppName = $null
    ) 

    ### ================
    ### === Defaults ===
    ### ================
    IF (!(Test-NotNull $CustomInstallVerification)) { $CustomInstallVerification = "(Get-ApplicationInstalled '$ApplicationName' -ExactMatch)" }
    IF (!(Test-NotNull $CustomUninstallVerification)) { $CustomUninstallVerification = "!($CustomInstallVerification)" }

    IF ($Action -eq "Install") { $Action = "Install" }
    IF ($Action -eq "Uninstall") { $Action = "Uninstall" }
    IF ($Action -eq "Reinstall") { $Action = "Reinstall" }
    IF ($Action -eq "Update") { $Action = "Update" }
    IF ($Action -eq "Download") { $Action = "Download" }
    IF ($Action -eq "Run") { $Action = "Run" }


    ### ====================================
    ### === Dependacy and Error Checking ===
    ### ====================================

    ### Not Running in Elevated Context
    IF (Test-ContextNotAdminElevated) { Write-Warning "Script requires Admin elevation. Please re-run as an administrator."; $Result.Success = $False; $Result.Details = "Need Admin Elevation"; RETURN }

    ### Zip Download Missing Zip Installer Path
    IF ($FileName -like "*.zip" -and ($ZipInstallerPath -eq $null -or $ZipInstallerPath -eq "") ) { 
        Write-Warning "If the download is a zip file you must include the file and path of the installer inside the zip file. ex: 'foldername\setup.exe'"
        $Result.Success = $False; $Result.Details = "Missing Zip Installer Path"; RETURN
    }
    

    ### ===============================
    ### === Results Return Function ===
    ### ===============================
    FUNCTION RETURN-Results { 

        ### Check Results
        IF ($Result.Name -eq $ApplicationName) {
            $TempName = Get-ApplicationInstalled $ApplicationName -ExactMatch
            IF ($TempName) { $Result.Name = $TempName.Name }
        }
        IF (!(Test-NotNull $Result.Version)) {

            IF (Test-NotNull $CustomVersionCommand) {
                $Result.Version = Invoke-Expression -Command $CustomVersionCommand
            }
            ELSE { 
                $TempVersion = Get-ApplicationInstalled $ApplicationName -ExactMatch
                IF ($TempVersion) { $Result.Version = $TempVersion.Version }
            }
        }

        
        ### Use WinGet if Install Failed
        IF (Test-NotNull $VerifyOnly) { }
        ELSEIF ((Test-NotNull $WinGetAppName) -and $Result.Success -ne $True -and ($Action -eq "Install" -or $Action -eq "Update" -or $Action -eq "Reinstall" -or $Action -eq "Run")) {
            
            Write-Host "$($(Get-Date).ToShortTimeString()): Attempting Install via WinGet... " -NoNewline
            IF (Ensure-Winget) {            

                
                WinGet Install $WinGetAppName --accept-package-agreements --accept-source-agreements | Out-Null
                

                $GetAppInstall = GET-ApplicationInstalled -Name $ApplicationName -ExactMatch
                IF ((Test-NotNull $CustomVersionCommand)) { $GetAppInstall.Version = Invoke-Expression -Command $CustomVersionCommand }

                ### =========================
                ### === Post WinGet Check ===
                ### =========================

                ### Reinstall
                IF ($Action -eq "Reinstall") {
                    IF ($InstallResult) {
                        Write-Host "Application reinstall successful. Done." -ForegroundColor Green
                        $Result.Name = $GetAppInstall.Name
                        $Result.Version = $GetAppInstall.Version       
                        $Result.Success = $True
                        $Result.Details = $null

                        IF ($GetAppInstall.Version -lt $ApplicationVersion) { $Result.Success = $False; $Result.Details = "Application Reinstalled, but Old Version" }
                    }      
                    ELSE {
                        Write-Host "Application reinstall unsuccesful."
                        $Result.Success = $False
                        $Result.Details = "Reinstall Unsuccessful"
                    }
                }
                ### Update
                ELSEIF ($Action -eq "Update") {
                    IF ($InstallResult) {
                        Write-Host "Application update successful. Done." -ForegroundColor Green
                        $Result.Name = $GetAppInstall.Name
                        $Result.Version = $GetAppInstall.Version       
                        $Result.Success = $True
                        $Result.Details = $null

                        IF ($GetAppInstall.Version -lt $ApplicationVersion) { $Result.Success = $False; $Result.Details = "Application is Updated, but Old Version" }
                    }
                    ELSE {
                        Write-Host "Application update unsuccesful."
                        $Result.Success = $False
                        $Result.Details = "Update Unsuccessful"
                    }    
                }
                ### Install
                ELSE {
                    IF ($InstallResult) {
                        Write-Host "Application install successful. Done." -ForegroundColor Green
                        $Result.Name = $GetAppInstall.Name
                        $Result.Version = $GetAppInstall.Version       
                        $Result.Success = $True
                        $Result.Details = $null

                        IF ($GetAppInstall.Version -lt $ApplicationVersion) { $Result.Success = $False; $Result.Details = "Application is Installed, but Old Version" }
                    }
                    ELSE {
                        Write-Host "Application install unsuccesful."
                        $Result.Success = $False
                        $Result.Details = "Install Unsuccessful"
                    }
                }
                
            }       
            ELSE { Write-Host "WinGet not found. Skipping install attempt." }
        }

        IF ($Action -eq "Run" -and (Test-NotNull $RunPath) -and $VerifyOnly -eq $False) { 
            TRY { 
                IF (!(Test-NotNull $RunArguments)) { Start-Process -FilePath $RunPath -PassThru | Out-Null }
                ELSE { Start-Process -FilePath $RunPath -ArgumentList $RunArguments -PassThru | Out-Null }
                Write-Host "$($(Get-Date).ToShortTimeString()): File ran successfully."
            }
            CATCH {
                $Result.Success = $False
                $Result.Details = "Run File not Found"
                Write-Host "$($(Get-Date).ToShortTimeString()): Fail to run. Run file not found."; $Result.Success = $False; $Result.Details = "Run File Not Found"
            }
        }

        $Duration = $(((Get-Date) - $StartTime))
        IF ($Duration.Hours -gt 0) { $Result.Duration = $(((Get-Date) - $StartTime).ToString("h\:m\:ss")) }
        ELSE { $Result.Duration = $(((Get-Date) - $StartTime).ToString("m\:ss")) }

        IF (($CleanupMode -eq "Always" -or ($Result.Success -eq $true -and $CleanupMode -eq "AfterSuccess")) -and ($ApplicationIsInstalled -eq $False -or $ApplicationNeedsUpdated -eq $True) -and $Action -ne "Download") { 
            #Write-Host "$($(Get-Date).ToShortTimeString()): Deleting Installer Files."
            IF ($ZipInstallerPath -ne $null -and $ZipInstallerPath -ne "") { Remove-Item -Path "$($SavePath)\$($($ApplicationName).Replace('*',''))\" -Recurse -ErrorAction SilentlyContinue }
            Remove-Item -Path "$($SavePath)\$($FileName)" -ErrorAction SilentlyContinue }        

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { 
            RETURN $Result
        }
        ELSE { 
            
            $ResultA = [PSCustomObject]@{
                PSTypeName = 'IntegrisDeploymentTool.IDTResults'
                Action = $Result.Action
                Duration = $Result.Duration
                Name = $Result.Name
                Version = $Result.Version                
                Success = $Result.Success    
                Details = $Result.Details    
            }
            
            RETURN $ResultA
        }
    }


    ### ==========================
    ### === Starting Variables ===
    ### ==========================
    $StartTime = Get-Date              ### Start time for tracking duration.
    $ApplicationIsInstalled = $null    ### Tracking if Application is Installed
    $ApplicationNeedsUpdated = $null   ### Tracking if Application Needs Updated
    $IPInfo = Get-IPInfo               ### Public IP and Geographic Info
    $RetryCount = 2


    ### ========================
    ### === Results Variable ===
    ### ========================
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = $Action
        Duration = $null
        RequestedName = $ApplicationName
        Name = $ApplicationName
        RequestedVersion = $ApplicationVersion
        Version = $null        
        Success = $null
        Details = $null
    }


    ### ==================
    ### === Log Header ===
    ### ==================
    $Callstack = Get-PSCallStack 
    IF (!((($Callstack).Command) -contains "Run-DeploymentSet")) {
        $PackageName = ($Callstack | Where-Object { ($_.Command -like "App-*" -or $_.Command -like "Driver-*" -or $_.Command -like "Font-*") -and $_.Command -notlike "*PackageHandler*" }).Command

        Write-Host ""
        Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
        Write-Host "### ==================================================== ###" -ForegroundColor Red -BackgroundColor Black
        Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
        Write-Host "### Starting Integris Deployment Tool Session ###" -ForegroundColor Red -BackgroundColor Black
        Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
        Write-Host "### Action: $($Action.PadRight(41,' '))###" -ForegroundColor Red -BackgroundColor Black
        Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
        Write-Host "### Package: $($($PackageName).PadRight(41,' '))###" -ForegroundColor Red -BackgroundColor Black
        Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
        Write-Host "### ==================================================== ###" -ForegroundColor Red -BackgroundColor Black
        Write-Host ""
    }
    

    ### =======================
    ### === Smart Targeting ===
    ### =======================
    IF ($True) {
        

        ### ===========================
        ### === Include Device Type ===
        ### ===========================
        IF (Test-NotNull $IncludeDeviceType) {
            ### Check
            $CheckStatus = $False
            $CheckDevice = $null
            IF (Test-IsDesktop) { $CheckDevice = "Desktop" }
            IF (Test-IsLaptop) { $CheckDevice = "Laptop" }
            IF (Test-IsServer) { $CheckDevice = "Server" }
            FOREACH ($Device in $IncludeDeviceType) { IF ($Device -eq $CheckDevice) { $CheckStatus = $True } }

            ### Pass
            IF ($CheckStatus) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Device Type for inclusion. Device type [$CheckDevice] matches include [$IncludeDeviceType]." }
            
            ### Fail
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Device Type for inclusion. Device type [$CheckDevice] does not match include [$IncludeDeviceType]. Skipping install."; $Result.Success = $True; $Result.Details = "Device Type [$CheckDevice] Skipped"; RETURN RETURN-Results }
        }


        ### ===========================
        ### === Exclude Device Type ===
        ### ===========================
        IF (Test-NotNull $ExcludeDeviceType) {
            ### Check
            $CheckStatus = $False
            $CheckDevice = $null
            IF (Test-IsDesktop) { $CheckDevice = "Desktop" }
            IF (Test-IsLaptop) { $CheckDevice = "Laptop" }
            IF (Test-IsServer) { $CheckDevice = "Server" }
            FOREACH ($Device in $ExcludeDeviceType) { IF ($Device -eq $CheckDevice) { $CheckStatus = $True } }

            ### Pass
            IF (!$CheckStatus) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Device Type for exclusion. Device type [$CheckDevice] does not match exclude [$ExcludeDeviceType]." }
            
            ### Fail
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Device Type for exclusion. Device type [$CheckDevice] matches exclude [$ExcludeDeviceType]. Skipping install."; $Result.Success = $True; $Result.Details = "Device Type [$CheckDevice] Skipped"; RETURN RETURN-Results }
        }

        ### ========================
        ### === Include Hostname ===
        ### ========================
        IF (Test-NotNull $IncludeHostname) {
            $Hostname = $env:COMPUTERNAME
            $HostnameMatch = $False
            FOREACH ($Entry in $IncludeHostname) {
                IF ($Hostname -like $Entry) { 
                    $HostnameMatch = $True; break
                }
            }

            IF ($HostnameMatch) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking hostname for inclusion. Hostname [$Hostname] matches [$IncludeHostname]." }
            ### Fail No Match
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking hostname for inclusion. Hostname [$Hostname] doesn't match [$IncludeHostname]. Skipping install."; $Result.Success = $True; $Result.Details = "Hostname Not Included"; RETURN RETURN-Results }
        }

        ### ========================
        ### === Exclude Hostname ===
        ### ========================
        IF (Test-NotNull $ExcludeHostname) {
            $Hostname = $env:COMPUTERNAME
            $HostnameMatch = $False
            FOREACH ($Entry in $ExcludeHostname) {
                IF ($Hostname -like $Entry) { 
                    $HostnameMatch = $True; break
                }
            }

            IF (!$HostnameMatch) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking hostname for exclusion. Hostname [$Hostname] doesn't match [$ExcludeHostname]." }
            ### Fail No Match
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking hostname for exclusion. Hostname [$Hostname] matches [$ExcludeHostname]. Skipping install."; $Result.Success = $True; $Result.Details = "Hostname Excluded"; RETURN RETURN-Results }
        }


        ### ==================
        ### === Include DN ===
        ### ==================
        IF (Test-NotNull $IncludeDN) {
            $DN = (gpresult /r /scope:computer) -Match "CN="
            $DN = $DN.Replace(" ","")
            IF (Test-NotNull $DN) {
                $DNMatch = $False
                FOREACH ($Entry in $IncludeDN) {
                    IF ($DN -like $Entry) {
                        $DNMatch = $True
                        break
                    }
                }
                ### Pass Match
                IF ($DNMatch) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Distinguished Name for inclusion. Distinguished Name [$DN] matches [$IncludeDN]." }
                ### Fail No Match
                ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Distinguished Name for inclusion. Distinguished Name [$DN] doesn't match [$IncludeDN]. Skipping install."; $Result.Success = $True; $Result.Details = "Distinguished Name Not Included"; RETURN RETURN-Results }
            }
            ### Fail Unknown
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Distinguished Name for inclusion. Distinguished Name not found and doesn't match [$IncludeDN]. Skipping install."; $Result.Success = $False; $Result.Details = "Distinguished Name Not Found"; RETURN RETURN-Results }
        }


        ### ==================
        ### === Exclude DN ===
        ### ==================
        IF (Test-NotNull $ExcludeDN) {
            $DN = (gpresult /r /scope:computer) -Match "CN="
            $DN = $DN.Replace(" ","")
            IF (Test-NotNull $DN) {
                $DNMatch = $False
                FOREACH ($Entry in $ExcludeDN) {
                    IF ($DN -like $Entry) {
                        $DNMatch = $True
                        break
                    }
                }
                ### Pass Match
                IF (!$DNMatch) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Distinguished Name for exclusion. Distinguished Name [$DN] doesn't match [$ExcludeDN]." }
                ### Fail No Match
                ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Distinguished Name for exclusion. Distinguished Name [$DN] matches [$ExcludeDN]. Skipping install."; $Result.Success = $True; $Result.Details = "Distinguished Name Excluded"; RETURN RETURN-Results }
            }
            ### Fail Unknown
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Distinguished Name for exclusion. Distinguished Name not found and not excluded." }
        }

        
        ### =======================
        ### === Include AD Site ===
        ### =======================
        IF (Test-NotNull $IncludeADSite) {
            $ADSite = ((nltest /dsgetsite) -split "The command completed successfully")[0]
            IF (Test-NotNull $ADSite) {
                $ADSiteMatch = $False
                FOREACH ($Entry in $IncludeADSite) {
                    IF ($ADSite -like $Entry) {
                        $ADSiteMatch = $True
                        break
                    }
                }
                ### Pass Match
                IF ($ADSiteMatch) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking AD Site for inclusion. AD Site [$ADSite] matches [$IncludeADSite]." }
                ### Fail No Match
                ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking AD Site for inclusion. AD Site [$ADSite] doesn't match [$IncludeADSite]. Skipping install."; $Result.Success = $True; $Result.Details = "AD Site Not Included"; RETURN RETURN-Results }
            }
            ### Fail Unknown
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking AD Site for inclusion. AD Site not found and doesn't match [$IncludeADSite]. Skipping install."; $Result.Success = $False; $Result.Details = "AD Site Not Found"; RETURN RETURN-Results }
        }


        ### =======================
        ### === Exclude AD Site ===
        ### =======================
        IF (Test-NotNull $ExcludeADSite) {
            $ADSite = ((nltest /dsgetsite) -split "The command completed successfully")[0]
            IF (Test-NotNull $ADSite) {
                $ADSiteMatch = $False
                FOREACH ($Entry in $ExcludeADSite) {
                    IF ($ADSite -like $Entry) {
                        $ADSiteMatch = $True
                        break
                    }
                }
                ### Pass Match
                IF (!$ADSiteMatch) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking AD Site for exclusion. AD Site [$ADSite] doesn't match [$ExcludeADSite]." }
                ### Fail No Match
                ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking AD Site for exclusion. AD Site [$ADSite] matches [$ExcludeADSite]. Skipping install."; $Result.Success = $True; $Result.Details = "AD Site Excluded"; RETURN RETURN-Results }
            }
            ### Fail Unknown
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking AD Site for exclusion. AD Site not found and not excluded." }
        }


        ### ==========================
        ### === Include IP Address ===
        ### ==========================
        IF (Test-NotNull $IncludeIPAddress) {
            $CurrentIPAddresses = @()
            $CurrentIPAddresses += $IPInfo.IP
            $CurrentIPAddresses += (get-netipaddress).IPv4Address | Where-Object { $_ -ne $null -and $_ -ne "" }
            $MatchFound = $False
            FOREACH ($IncludeEntry in $IncludeIPAddress) {
                FOREACH ($CurrentEntry in $CurrentIPAddresses) {
                    IF ($IncludeEntry -like "*/*") { IF ((Test-IPInCIDR -IPAddress $CurrentEntry -CIDR $IncludeEntry)) { $MatchFound = $True; break } }
                    ELSEIF ($IncludeEntry -eq $CurrentEntry) { $MatchFound = $True; break }
                }
                IF ($MatchFound) { break }
            }

            ### Pass Match
            IF ($MatchFound) {Write-Host "$($(Get-Date).ToShortTimeString()): Checking for IP address inclusion. IP Address [$CurrentIPAddresses] matches [$IncludeIPAddress]." }
            ### Fail No Match
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking for IP address inclusion. IP Address [$CurrentIPAddresses] doesn't match [$IncludeIPAddress]. Skipping install."; $Result.Success = $True; $Result.Details = "IP Address not Included"; RETURN RETURN-Results }
        }


        ### ==========================
        ### === Exclude IP Address ===
        ### ==========================
        IF (Test-NotNull $ExcludeIPAddress) {
            $CurrentIPAddresses = @()
            $CurrentIPAddresses += $IPInfo.IP
            $CurrentIPAddresses += (get-netipaddress).IPv4Address | Where-Object { $_ -ne $null -and $_ -ne "" }
            $MatchFound = $False
            FOREACH ($ExcludeEntry in $ExcludeIPAddress) {
                FOREACH ($CurrentEntry in $CurrentIPAddresses) {
                    IF ($ExcludeEntry -like "*\*") { IF ((Test-IPInCIDR -IPAddress $CurrentEntry -CIDR $ExcludeEntry)) { $MatchFound = $True; break } }
                    ELSEIF ($ExcludeEntry -eq $CurrentEntry) { $MatchFound = $True; break }
                }
                IF ($MatchFound) { break }
            }

            ### Pass Match
            IF (!$MatchFound) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking for IP address exclusion. IP Address [$CurrentIPAddresses] doesn't match [$ExcludeIPAddress]." }
            ### Fail No Match
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking for IP address exclusion. IP Address [$CurrentIPAddresses] doesn't match [$ExcludeIPAddress]. Skipping install."; $Result.Success = $True; $Result.Details = "IP Address Excluded"; RETURN RETURN-Results }
        }


        ### ============================
        ### === Include Geo Location ===
        ### ============================
        IF (Test-NotNull $IncludeGeoLocation) {
            $LocationMatch = $False
            $CurrentLocation = $IPInfo
            FOREACH ($Location in $IncludeGeoLocation) {
                IF ($CurrentLocation.State -like $Location -or $CurrentLocation.Country -like $Location) {
                    $LocationMatch = $True
                    break
                }
            }

            ### Pass Match
            IF ($LocationMatch) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking for geo location inclusion. Geo location [$($CurrentLocation.State), $($CurrentLocation.Country)] matches [$IncludeGeoLocation]." }
            ### Fail No Match
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking for geo location inclusion. Geo location [$($CurrentLocation.State), $($CurrentLocation.Country)] doesn't match [$IncludeGeoLocation]. Skipping install."; $Result.Success = $True; $Result.Details = "Geo Location not Included"; RETURN RETURN-Results }
        }


        ### ============================
        ### === Exclude Geo Location ===
        ### ============================
        IF (Test-NotNull $ExcludeGeoLocation) {
            $LocationMatch = $False
            $CurrentLocation = $IPInfo
            FOREACH ($Location in $ExcludeGeoLocation) {
                IF ($CurrentLocation.State -like $Location -or $CurrentLocation.Country -like $Location) {
                    $LocationMatch = $True
                    break
                }
            }

            ### Pass Match
            IF (!$LocationMatch) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking for geo location exclusion. Geo location [$($CurrentLocation.State), $($CurrentLocation.Country)] doesn't match [$ExcludeGeoLocation]." }
            ### Fail No Match
            ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): Checking for geo location exclusion. Geo location [$($CurrentLocation.State), $($CurrentLocation.Country)] matches [$ExcludeGeoLocation]. Skipping install."; $Result.Success = $True; $Result.Details = "Geo Location Excluded"; RETURN RETURN-Results }
        }
    }

    
    ### ========================
    ### === Action Pre-Check ===
    ### ========================
    $ApplicationIsInstalled = $null
    $ApplicationNeedsUpdated = $null
    $CustomVersionResult = $null

    IF ($True) {
        IF ($Action -eq "Uninstall") { $Result.RequestedVersion = $null }

        ### Check if App is Installed
        IF ((Test-NotNull $CustomInstallVerification)) {
            $CustomInstallResult = Invoke-Expression -Command $CustomInstallVerification
            IF ((Test-NotNull $CustomInstallResult)) { $ApplicationIsInstalled = $True }
            ELSE { $ApplicationIsInstalled = $False }    
        }
        ELSE {
            $GetApp = GET-ApplicationInstalled -Name $ApplicationName -ExactMatch
            IF ((Test-NotNull $GetApp)) { $ApplicationIsInstalled = $True }
            ELSE { $ApplicationIsInstalled = $False }  
        }
    
        ### Check if App Needs Updated
        IF ((Test-NotNull $ApplicationIsInstalled)) {
            IF ((Test-NotNull $CustomVersionCommand)) {
                $CustomVersionResult = Invoke-Expression -Command $CustomVersionCommand
                IF ($ExactVersion) {
                    IF ([Version]$CustomVersionResult -eq [Version]$ApplicationVersion) { $ApplicationNeedsUpdated = $False }
                    ELSE { $ApplicationNeedsUpdated = $True }     
                }
                ELSE { 
                    IF ([Version]$CustomVersionResult -ge [Version]$ApplicationVersion) { $ApplicationNeedsUpdated = $False }
                    ELSE { $ApplicationNeedsUpdated = $True }   
                } 
            }
            ELSE {
                $CustomVersionResult = (GET-ApplicationInstalled -Name $ApplicationName -ExactMatch).Version
                IF ($ExactVersion) {
                    IF ([Version]$CustomVersionResult -eq [Version]$ApplicationVersion) { $ApplicationNeedsUpdated = $False }
                    ELSE { $ApplicationNeedsUpdated = $True }  
                }
                ELSE {
                    IF ([Version]$CustomVersionResult -ge [Version]$ApplicationVersion) { $ApplicationNeedsUpdated = $False }
                    ELSE { $ApplicationNeedsUpdated = $True }   
                }
            }
        } 
        ELSE { $ApplicationNeedsUpdated = $True }
        IF ($UpdateMethod -eq "NoUpdate") { $ApplicationNeedsUpdated = $False }
        
        ### If Verify Only
        IF ($VerifyOnly) {
            ### Uninstall
            IF ($ApplicationIsInstalled -eq $False -and $Action -eq "Uninstall") { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application already uninstalled. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "Already Uninstalled"; RETURN RETURN-Results }
            IF ($ApplicationIsInstalled -eq $True -and $Action -eq "Uninstall") { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application not uninstalled. Verify only. Done." -ForegroundColor Red; $Result.Success = $False; $Result.Details = "Not Uninstalled (Verify Only)"; RETURN RETURN-Results }

            ### Install
            IF ($ApplicationIsInstalled -eq $True -and $Action -eq "Install" -and $ApplicationNeedsUpdated -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application already installed. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "Already Installed"; RETURN RETURN-Results }
            IF ($ApplicationIsInstalled -eq $False -and $Action -eq "Install" -and $ApplicationNeedsUpdated -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application not installed. Verify only. Done." -ForegroundColor Red; $Result.Success = $False; $Result.Details = "Not Installed (Verify Only)"; RETURN RETURN-Results }
            IF ($ApplicationIsInstalled -eq $True -and $Action -eq "Install" -and $ApplicationNeedsUpdated -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application not up to date. Verify only. Done." -ForegroundColor Red; $Result.Success = $False; $Result.Details = "Needs Updated (Verify Only)"; RETURN RETURN-Results }
            IF ($ApplicationIsInstalled -eq $False -and $Action -eq "Install" -and $ApplicationNeedsUpdated -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application not installed. Verify only. Done." -ForegroundColor Red; $Result.Success = $False; $Result.Details = "Not Installed (Verify Only)"; RETURN RETURN-Results }

            ### Update
            IF ($ApplicationIsInstalled -eq $True -and $Action -eq "Update" -and $ApplicationNeedsUpdated -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application already up to date. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "Already Up to Date"; RETURN RETURN-Results }
            IF ($ApplicationIsInstalled -eq $True -and $Action -eq "Update" -and $ApplicationNeedsUpdated -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application not up to date. Verify only. Done." -ForegroundColor Green; $Result.Success = $False; $Result.Details = "Needs Updated (Verify Only)"; RETURN RETURN-Results }
            IF ($ApplicationIsInstalled -eq $False -and $Action -eq "Update" -and $ApplicationNeedsUpdated -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application not installed, no update needed. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "No Update Needed (Not Installed)"; RETURN RETURN-Results }
            IF ($ApplicationIsInstalled -eq $False -and $Action -eq "Update" -and $ApplicationNeedsUpdated -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application not installed, no update needed. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "No Update Needed (Not Installed)"; RETURN RETURN-Results }

            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Verify requested but not applicable for $Action action. Done." -ForegroundColor Red; $Result.Success = $False; $Result.Details = "Verify Action Not Applicable"; RETURN RETURN-Results
        }
        
        ### If Uninstall and Already Uninstalled
        IF ($ApplicationIsInstalled -eq $false -and $Action -eq "Uninstall") { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application already uninstalled. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "Already Uninstalled"; RETURN RETURN-Results }
    
        ### If Install and Already Installed
        IF ($ApplicationIsInstalled -eq $true -and $Action -eq "Install" -and $ApplicationNeedsUpdated -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application already installed. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "Already Installed"; RETURN RETURN-Results }

        ### If Update and Already Up to Date
        IF ($ApplicationIsInstalled -eq $true -and $Action -eq "Update" -and $ApplicationNeedsUpdated -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application already up to date. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "Already Up to Date"; RETURN RETURN-Results }
        IF ($ApplicationIsInstalled -eq $false -and $Action -eq "Update") { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application not installed. No update needed. Done." -ForegroundColor Green; $Result.Success = $True; $Result.Details = "Not Installed, No Update Needed"; RETURN RETURN-Results }

        ### If Run and Already Installed
        IF ($Action -eq "Run" -and $ApplicationIsInstalled) { $Result.Success = $True; $Result.Details = "Already Installed"; RETURN RETURN-Results }
    }

    ### =======================
    ### === Initial Message ===
    ### =======================

    IF ($Action -eq "Install") {
        IF ($ApplicationIsInstalled -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Not installed. Processing request." }
        ELSEIF ($ApplicationIsInstalled -eq $True -and $ApplicationNeedsUpdated -eq $True -and $ExactVersion -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Old version [$CustomVersionResult] found. Processing [$Action] request." }
        ELSEIF ($ApplicationIsInstalled -eq $True -and $ApplicationNeedsUpdated -eq $True -and $ExactVersion -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Incorrect version [$CustomVersionResult] found. Processing [$Action] request." }
    }
    ELSEIF ($Action -eq "Uninstall") {
        IF ($ApplicationIsInstalled -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Install found. Processing [$Action] request." }
    }
    ELSEIF ($Action -eq "Download") {
        IF ($ApplicationIsInstalled -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Processing [$Action] request." }
    }
    ELSEIF ($Action -eq "Reinstall") { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Processing [$Action] request." }
    ELSEIF ($Action -eq "Update") {
        IF ($ApplicationNeedsUpdated -eq $True -and $ExactVersion -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Old version [$CustomVersionResult] found. Processing [$Action] request." }
        ELSEIF ($ApplicationNeedsUpdated -eq $True -and $ExactVersion -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Incorrect version [$CustomVersionResult] found. Processing [$Action] request." }
    }
    ELSEIF ($Action -eq "Run") {
        IF ($ApplicationIsInstalled -eq $True) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Install found. Processing [$Action] request." }
        ELSEIF ($ApplicationIsInstalled -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): [$Action] of [$ApplicationName] requested. Install not found. Processing [$Action] request." }
    }

    ### ==============================
    ### === Action Processing Loop ===
    ### ==============================
    $TryCount = 0
    $Success = $False
    $ApplicationInstallerPath = $null
    WHILE (!$Success) {

        ### =========================
        ### === Trycount Tracking ===
        ### =========================
        IF ($TryCount -gt $RetryCount) { Write-Host "$($(Get-Date).ToShortTimeString()): Retry count exceeded."; RETURN RETURN-Results }
        IF ($TryCount -gt 0) { Write-Host "$($(Get-Date).ToShortTimeString()): Attempt $($TryCount) failed. Trying again..." }
        IF ($TryCount -gt 0) { $ForceDownload = $True } ### Sets Force Download so any Subsequent Download Attempts Force a Redownload (in case of corrupt downloads causing a problem)
        IF ($TryCount -gt 1) { 
            IF (!(Test-NotNull $BackupDownloadLink)) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Retry count exceeded. Done." -ForegroundColor Red; RETURN RETURN-Results }
            $DownloadLink = $BackupDownloadLink
            $FileName = $BackupFileName
            $DownloadHash = $BackupDownloadHash
        }

        IF ((Test-NotNull $CustomInstallCommand) -and $InvokeInstallCommand -eq $False) { $ApplicationInstallerPath = $CustomInstallCommand }         
        ELSEIF ($FileName -like "*.zip") { $ApplicationInstallerPath = "$($SavePath)\$($($ApplicationName).Replace('*',''))\$($ZipInstallerPath)" } 
        ELSE { $ApplicationInstallerPath = "$SavePath\$FileName" }
        
        $TryCount++

        
        ### ======================
        ### === Download Phase ===
        ### ======================
        IF ($Action -eq "Uninstall" -or !(Test-NotNull $DownloadLink)) { $Result.Version = $null }
        ELSE {
            $DownloadStart = Get-Date   


            Write-Host "$($(Get-Date).ToShortTimeString()): Starting Download of [$FileName] from [$DownloadLink]... " -NoNewline
            IF ((Run-FileDownload -FileName $FileName -SavePath $SavePath -URL $DownloadLink -Force:$ForceDownload -BasicOutput) -eq $false) { 
                Write-Host "Download attempt failed after $([MATH]::Round($(((Get-Date) - $DownloadStart).TotalSeconds),0)) second(s)." -ForegroundColor Red
                $Result.Success = $False; $Result.Details = "Download Failed"
                CONTINUE 
            }            
            Write-Host "Download completed successfully in $([MATH]::Round($(((Get-Date) - $DownloadStart).TotalSeconds),0)) second(s)."    
                

            ### Check for Zip File
            IF ($FileName -like "*.zip") { 

                IF ($ForceDownload -or !(GET-ChildItem -Path $ApplicationInstallerPath -ErrorAction SilentlyContinue)) {                
                    Write-Host "$($(Get-Date).ToShortTimeString()): Unzipping files to ["$SavePath\$($($ApplicationName).Replace('*',''))\"]."
                    Expand-Archive -Path "$($SavePath)\$($FileName)" -DestinationPath "$SavePath\$($($ApplicationName).Replace('*',''))\" -Force 
                }

                IF ((GET-ChildItem -Path $ApplicationInstallerPath -ErrorAction SilentlyContinue)) { 
                    Write-Host "$($(Get-Date).ToShortTimeString()): Verifying Zip Installer File... Installer File Found: [$($ApplicationInstallerPath)]" }
                ELSE { 
                    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Verifying Zip Installer File... Installer File Not Found: [$($ApplicationInstallerPath)]" -ForegroundColor Red
                    CONTINUE 
                }  
            }          
            
            ### If Download Only
            IF ($Action -eq "Download") { $Result.Action = "Download"; $Result.Success = $True; Write-Host "$($(Get-Date).ToShortTimeString()): Download only specified. Done."; RETURN RETURN-Results }
        }   
        
        
        ### =======================
        ### === Security Checks ===
        ### =======================
       
        IF ($True -and $Action -ne "Uninstall") {       
            ### Virus Total Hash Verification
            IF ($VirusTotal) {
                $VirusTotalResult = (Test-VirusTotalHash -FilePath "$($SavePath)\$($FileName)")           
                IF ($VirusTotalResult) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking file hash against VirusTotal database. Found. Clean." }
                ELSEIF ($VirusTotalResult -eq $False) { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Checking file hash against VirusTotal database. Found. Not Clean. Blocking install." -ForegroundColor Red; CONTINUE }
                ELSE { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Checking file hash against VirusTotal database. Not found. Blocking install." -ForegroundColor Red; CONTINUE }
            }
            
            ### Cert Verification
            IF ($CertVerification -or $CertName) {
                
                $CertCheck = $null
                IF (Test-NotNull $ZipInstallerPath) { $CertCheck = (Get-AuthenticodeSignature -FilePath "$SavePath\$ApplicationName\$ZipInstallerPath") }
                ELSE { $CertCheck = (Get-AuthenticodeSignature -FilePath "$($SavePath)\$($FileName)") }
            
                IF ($CertCheck.Status -eq "Valid") { Write-Host "$($(Get-Date).ToShortTimeString()): Checking cert validity... cert is valid." }
                ELSE { 
                    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
                    Write-Host "Signature on installer file is not valid. Blocking install." -ForegroundColor Red
                    $Result.Success = $False; $Result.Details = "Cert Not Valid"; CONTINUE 
                }     
                IF ($CertName -ne $null) { 
                    IF ($CertCheck.SignerCertificate.SubjectName.Name -like $CertName) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking cert name for [$Certname]... cert name matches." }
                    ELSE { 
                        Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
                        Write-Host "Signer name did not match [$CertName]. Blocking install." -ForegroundColor Red 
                        $Result.Success = $False; $Result.Details = "Cert Name Doesn't Match"; 
                        CONTINUE 
                    }
                }            
            }
            
            ### Download Hash Check
            IF ($DownloadHash) {
                $DownloadedHash = (Get-FileHash -Path "$($SavePath)\$($FileName)" -Algorithm SHA256).Hash
                IF ($DownloadedHash -eq $DownloadHash) { Write-Host "$($(Get-Date).ToShortTimeString()): Checking Hash. Requested hash [$DownloadHash] matches download hash [$DownloadedHash]." }
                ELSE { 
                    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
                    Write-Host "Checking Hash. Requested hash [$DownloadHash] doesn't match download hash [$DownloadedHash]. Blocking install." -ForegroundColor Red 
                    $Result.Success = $False; $Result.Details = "Hash Doesn't Match"; 
                    CONTINUE
                }
            }            
        }


        ### =======================
        ### === Uninstall Phase ===
        ### =======================
         
        IF ($True) {       
            ### Check for Uninstall Action Missing Uninstall Command
            IF ($Action -eq "Uninstall" -or 
                ($Action -eq "Reinstall" -and $ApplicationIsInstalled -eq $True) -or 
                ($Action -eq "Update" -and ($UpdateMethod -eq "UninstallReinstall" -or $ExactVersion) -and $ApplicationNeedsUpdated -eq $True) -or
                ($Action -eq "Install" -and $ApplicationIsInstalled -eq $True -and $ApplicationNeedsUpdated -eq $True -and ($UpdateMethod -eq "UninstallReinstall" -or $ExactVersion))) {
                IF (!(Test-NotNull $UninstallCommand)) { 
                    $GetApp = Get-ApplicationInstalled -Name $ApplicationName -ExactMatch
                    IF ($GetApp.UninstallCommand -like "msiexec.exe*") { $Split = ($GetApp.UninstallCommand -split " ").Replace("/X {","/X{"); $UninstallCommand = $Split[0]; $UninstallArguments = $Split[1].Replace("/I{","/X{") + " /QN" }
                    ELSEIF ($GetApp.UninstallCommand -like "*unins000.exe*") { $Split = $GetApp.UninstallCommand -split '"'; $UninstallCommand = $Split[1]; $UninstallArguments = "/silent /verysilent /norestart /SUPPRESSMSGBOXES" }
                    ELSE {
                        Write-Host "$($(Get-Date).ToShortTimeString()): Unable to uninstall. No uninstall command provided. Use the -UninstallCommand and -UninstallArguements parameters."
                        $Result.Success = $False
                        $Result.Details = "Uninstall Command Not Found"
                        RETURN RETURN-Results   
                    }
                }
            }

            ### Uninstall If Needed
            IF ($Action -eq "Uninstall" -or 
                ($Action -eq "Reinstall" -and $ApplicationIsInstalled -eq $True) -or 
                ($Action -eq "Update" -and ($UpdateMethod -eq "UninstallReinstall" -or $ExactVersion) -and $ApplicationNeedsUpdated -eq $True) -or
                ($Action -eq "Install" -and $ApplicationIsInstalled -eq $True -and $ApplicationNeedsUpdated -eq $True -and ($UpdateMethod -eq "UninstallReinstall" -or $ExactVersion))) {
            
                ### End Requested PreProcesses
                IF (Test-NotNull $PreUninstallEndProcess) {
                    #Write-Host "$($(Get-Date).ToShortTimeString()): Ending Requested Processses..."
                    $Now = (Get-Date).AddSeconds(20)
                    While ((Get-Date) -lt $Now -and (Get-Process $PreUninstallEndProcess -ErrorAction SilentlyContinue) -ne $null) { Get-Process $PreUninstallEndProcess -ErrorAction SilentlyContinue | Stop-Process -ErrorAction SilentlyContinue -Force; Start-Sleep -Seconds 2 }
                    IF (Get-Process $PreUninstallEndProcess -ErrorAction SilentlyContinue) { Write-Host "$($(Get-Date).ToShortTimeString()): Pre-Uninstall processess not ended. Attempting uninstall anyway." }
                    ELSE { #Write-Host "$($(Get-Date).ToShortTimeString()): Pre-uninstall processes ended successfully."
                    }
                }   

                ### Starting Uninstall
                Get-Process MSIEXEC -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
                Start-Sleep -Seconds 1
                $StartUninstall = Get-Date
                $UninstallProcess = $null

                IF ($InvokeUninstallCommand) { Invoke-Expression -Command $UninstallCommand }
                ELSE {
                    IF (!(Test-NotNull $UninstallArguments)) { 
                        $UninstallProcess = Start-Process -FilePath $UninstallCommand -PassThru 
                    }
                    ELSE { 
                        $UninstallProcess = Start-Process -FilePath $UninstallCommand -ArgumentList $UninstallArguments -PassThru 
                    }                
                    IF ($UninstallTimeout -eq 0) { 
                        Write-Host "$($(Get-Date).ToShortTimeString()): Started uninstall. Waiting for Uninstall to Complete..."
                        Start-Sleep -Seconds 1
                        IF (Test-NotNull $UninstallKeystrokes) { Invoke-Expression -Command $UninstallKeystrokes }
                        Wait-Process -ID $UninstallProcess.ID -ErrorAction SilentlyContinue 
                    }
                    ELSE { 
                        Write-Host "$($(Get-Date).ToShortTimeString()): Started uninstall. Waiting up to $UninstallTimeout seconds for uninstall to complete..."
                        Start-Sleep -Seconds 1
                        IF (Test-NotNull $UninstallKeystrokes) { Invoke-Expression -Command $UninstallKeystrokes }
                        Wait-Process -ID $UninstallProcess.ID -Timeout $UninstallTimeout -ErrorAction SilentlyContinue 
                    }
                                
                    Stop-Process -ID $UninstallProcess.ID -Force -ErrorAction SilentlyContinue
                    Get-Process MSIEXEC -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
                }

                ### End Requested PostProcesses
                IF (Test-NotNull $PostUninstallEndProcess) {
                    #Write-Host "$($(Get-Date).ToShortTimeString()): Ending Requested Processses..."
                    $Now = (Get-Date).AddSeconds(20)
                    While ((Get-Date) -lt $Now -and (Get-Process $PostUninstallEndProcess -ErrorAction SilentlyContinue) -ne $null) { Get-Process $PostUninstallEndProcess -ErrorAction SilentlyContinue | Stop-Process -ErrorAction SilentlyContinue -Force; Start-Sleep -Seconds 2 }
                    IF (Get-Process $PostUninstallEndProcess -ErrorAction SilentlyContinue) { Write-Host "$($(Get-Date).ToShortTimeString()): Post-Uninstall processess not ended. Continuing anyway." }
                    ELSE { #Write-Host "$($(Get-Date).ToShortTimeString()): Post-uninstall processes ended successfully."
                    }
                }  

                

                Start-Sleep -Seconds $PostUninstallDelay
                Write-Host "$($(Get-Date).ToShortTimeString()): Uninstall finished in $([MATH]::Round($(((Get-Date) - $StartUninstall).TotalSeconds),0)) second(s). Verifying..."            
                
                $GetAppUninstall = Invoke-Expression -Command $CustomUninstallVerification 

                ### Checking if Uninstall was Successful
                IF (!$GetAppUninstall -and $Action -eq "Uninstall") {
                    Write-Host "$($(Get-Date).ToShortTimeString()): Uninstall failed. Application Still Installed." 
                    $Result.Success = $False
                    $Result.Details = "Uninstall Failed"
                    CONTINUE
                }
                ELSEIF (!$GetAppUninstall -and $Action -eq "Reinstall") {
                    Write-Host "$($(Get-Date).ToShortTimeString()): Uninstall failed. Application Still Installed." 
                    $Result.Success = $False
                    $Result.Details = "Uninstall for Reinstall Failed"
                    CONTINUE
                }
                ELSEIF (!$GetAppUninstall -and $Action -eq "Update") {
                    Write-Host "$($(Get-Date).ToShortTimeString()): Uninstall failed. Application Still Installed." 
                    $Result.Success = $False
                    $Result.Details = "Uninstall for Update Failed"
                    CONTINUE
                }  
                ELSEIF (!$GetAppUninstall -and $Action -eq "Install") {
                    Write-Host "$($(Get-Date).ToShortTimeString()): Uninstall failed. Application Still Installed." 
                    $Result.Success = $False
                    $Result.Details = "Uninstall for Update Failed"
                    CONTINUE
                }           
                ELSEIF ($Action -eq "Uninstall") { Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline; Write-Host "Application Uninstalled Successfully. Done." -ForegroundColor Green ; $Result.Success = $True; $Result.Details = $null; RETURN RETURN-Results }

                Write-Host "$($(Get-Date).ToShortTimeString()): Application Uninstalled Successfully."
            }
        }

   
        ### =====================
        ### === Install Phase ===
        ### =====================

        ### End Requested PostProcesses
        $Now = (Get-Date).AddSeconds(20)
        IF ((Test-NotNull $PreInstallEndProcess)) {
            #Write-Host "$($(Get-Date).ToShortTimeString()): Ending Requested Install Processses."
            While ((Get-Date) -lt $Now -and (Get-Process $PreInstallEndProcess -ErrorAction SilentlyContinue) -ne $null) { Get-Process $PreInstallEndProcess -ErrorAction SilentlyContinue | Stop-Process -ErrorAction SilentlyContinue -Force; Start-Sleep -Seconds 2 }
            IF (Get-Process $PreInstallEndProcess -ErrorAction SilentlyContinue) { Write-Host "$($(Get-Date).ToShortTimeString()): Pre-install processess not ended. Continuing anyway." }
            ELSE { #Write-Host "$($(Get-Date).ToShortTimeString()): Pre-install processes ended successfully."
            }
        }

        ### Install Application
        Get-Process MSIEXEC -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
        Start-Sleep -Seconds 1
        Write-Host "$($(Get-Date).ToShortTimeString()): Starting [$ApplicationName] install." -NoNewline
        $StartInstall = Get-Date
        $InstallProcess = $null
        $InvokeJob = $null

        IF ($InvokeInstallCommand) { 
            $InvokeJob = Start-Job -ScriptBlock { Invoke-Expression -Command $($Using:CustomInstallCommand) } -ErrorAction SilentlyContinue
            Wait-Job -Job $InvokeJob -Timeout $InstallTimeout -ErrorAction SilentlyContinue | Out-Null
            Stop-Job -Job $InvokeJob -ErrorAction SilentlyContinue | Out-Null
        }
        ELSE {
            IF (!(Test-NotNull $InstallArguments)) { $InstallProcess = Start-Process -FilePath $ApplicationInstallerPath -PassThru }
            ELSE { $InstallProcess = Start-Process -FilePath $ApplicationInstallerPath -Args $InstallArguments -PassThru }
            IF ($InstallTimeout -eq 0) { 
            Write-Host " Waiting for install to complete..." -NoNewline
            Start-Sleep -Seconds 1
            IF (Test-NotNull $InstallKeystrokes) { Invoke-Expression -Command $InstallKeystrokes }
            Wait-Process $InstallProcess.ID -ErrorAction SilentlyContinue 
        }        
            ELSE { 
            Write-Host " Waiting up to [$InstallTimeout] seconds for install to complete..." -NoNewline
            Start-Sleep -Seconds 1 
            IF (Test-NotNull $InstallKeystrokes) { Invoke-Expression -Command $InstallKeystrokes }
            Wait-Process $InstallProcess.ID -Timeout $InstallTimeout -ErrorAction SilentlyContinue 
        }               
                
            Stop-Process -ID $InstallProcess.ID -Force -ErrorAction SilentlyContinue
        }
        Get-Process MSIEXEC -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue

        Start-Sleep -Seconds $PostInstallDelay
        Write-Host " Install finished in $([MATH]::Round($(((Get-Date) - $StartInstall).TotalSeconds),0)) second(s)."    
        
        ### End Requested PostProcesses
        $Now = (Get-Date).AddSeconds(20)
        IF ((Test-NotNull $PostInstallEndProcess)) {
            #Write-Host "$($(Get-Date).ToShortTimeString()): Ending Requested Install Processses."
            While ((Get-Date) -lt $Now -and (Get-Process $PostInstallEndProcess -ErrorAction SilentlyContinue) -ne $null) { Get-Process $PostInstallEndProcess -ErrorAction SilentlyContinue | Stop-Process -ErrorAction SilentlyContinue -Force; Start-Sleep -Seconds 2 }
            IF (Get-Process $PostInstallEndProcess -ErrorAction SilentlyContinue) { Write-Host "$($(Get-Date).ToShortTimeString()): Post-install processess not ended. Continuing anyway." }
            ELSE { #Write-Host "$($(Get-Date).ToShortTimeString()): Post-install processes ended successfully."
            }
        }
        Write-Host "$($(Get-Date).ToShortTimeString()): Verifying install of [$ApplicationName]... " -NoNewline
        ### Check Results
        $InstallResult = Invoke-Expression -Command "$CustomInstallVerification"
        $InstallVersion = $null
        IF ((Test-NotNull $CustomVersionCommand)) { $InstallVersion = Invoke-Expression -Command $CustomVersionCommand }
        ELSE { $InstallVersion = (Get-ApplicationInstalled "$ApplicationName" -ExactMatch).Version }

        $InstalledAppName = $null
        $InstalledApp = (Get-ApplicationInstalled -Name $ApplicationName -ExactMatch)
        IF ($InstalledApp) { $InstalledAppName = $InstalledApp.Name }
        ELSE { $InstalledAppName = $ApplicationName } 

        ### If Reinstall
        IF ($Action -eq "Reinstall") {
            IF ($InstallResult) {
                Write-Host "Application reinstall successful. Done." -ForegroundColor Green
                $Result.Name = $InstalledAppName
                $Result.Version = $InstallVersion       
                $Result.Success = $True
                $Result.Details = $null

                IF ($InstallVersion -lt $ApplicationVersion) { $Result.Success = $False; $Result.Details = "Application Reinstalled, but Old Version" }

                RETURN RETURN-Results
            }      
            ELSE {
                Write-Host "Application reinstall unsuccessful." -ForegroundColor Red
                $Result.Success = $False
                $Result.Details = "Reinstall Unsuccessful"
                CONTINUE
            }
        }
        ### If Update
        ELSEIF ($Action -eq "Update") {
            IF ($InstallResult) {
                Write-Host "Application update successful. Done." -ForegroundColor Green
                $Result.Name = $InstalledAppName
                $Result.Version = $InstallVersion      
                $Result.Success = $True
                $Result.Details = $null

                IF ($InstallVersion -lt $ApplicationVersion) { $Result.Success = $False; $Result.Details = "Application is Updated, but Old Version" }

                RETURN RETURN-Results
            }
            ELSE {
                Write-Host "Application update unsuccessful." -ForegroundColor Red
                $Result.Success = $False
                $Result.Details = "Update Unsuccessful"
                CONTINUE
            }    
        }
        ### If Install
        ELSE {
            IF ($InstallResult) {
                Write-Host "Application install successful. Done." -ForegroundColor Green
                $Result.Name = $InstalledAppName
                $Result.Version = $InstallVersion       
                $Result.Success = $True
                $Result.Details = $null

                IF ($InstallVersion -lt $ApplicationVersion) { $Result.Success = $False; $Result.Details = "Application is Installed, but Old Version" }

                RETURN RETURN-Results
            }
            ELSE {
                Write-Host "Application Install Unsuccessful." -ForegroundColor Red
                $Result.Success = $False
                $Result.Details = "Install Unsuccessful"
                CONTINUE
            }
        }

        ### Set Progress Bar Back to Original Setting
        $ProgressPreference = $ProgressPreferenceTemp

        RETURN RETURN-Results
    }
}
FUNCTION Run-DeploymentSet {
    
    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory)]
        [STRING[]]$Deployments,
        #[SWITCH]$RunWinGetUpdate = $False,
        [SWITCH]$ResultsToDesktop = $True,
        [SWITCH]$RunWindowsUpdates = $False,
        
        ### Restart Parameters
        [SWITCH]$RestartWhenComplete = $False,
        [INT]$RestartTimeout = $null,

        ### Rerun Parameters
        [SWITCH]$RerunOnFail = $False,
        [INT]$RerunCount = 2,
        [SWITCH]$ResetCount = $False
    )

    IF ($ResetCount) { 
        Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunCount" -Value 0 -Type DWORD | Out-Null 
        Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunSuccess" -Value 0 -Type DWORD | Out-Null
    }
    IF (Test-NotNull $RestartTimeout) { 
        $Seconds = (60 * $RestartTimeout)
        Start-Process -FilePath "Shutdown.exe" -ArgumentList "-r -t $Seconds" -ErrorAction SilentlyContinue -WindowStyle Hidden
    } 
    IF ($RerunOnFail -and ((Get-ItemProperty -Path "HKLM:\SOFTWARE\IntegrisDeploymentTool").RunCount) -le $RerunCount ) {
        Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunSuccess" -Value 0 -Type DWORD | Out-Null
        $Count = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\IntegrisDeploymentTool").RunCount)
        $Count++
        Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunCount" -Value $Count -Type DWORD | Out-Null
        New-Item -Path "C:\Integris\Temp\" -ItemType Directory -Name Resume -ErrorAction SilentlyContinue | Out-Null
        $SessionArguments = @{
            Deployments = $Deployments
            ResultsToDesktop = $ResultsToDesktop
            RunWindowsUpdates = $RunWindowsUpdates
            RestartWhenComplete = $RestartWhenComplete
            RestartTimeout = $RestartTimeout
            RerunOnFail = $RerunOnFail
            RerunCount = $RerunCount
            ResetCount = $False
        }
        $SessionArguments | Export-CLIXML "C:\Integris\Temp\Resume\Parameters.xml"
        New-LocalUser -Name "IDTAdmin" -Password (ConvertTo-SecureString "Reddragon782^" -AsPlainText -Force) -ErrorAction SilentlyContinue | Out-Null
        Add-LocalGroupMember -Group "Administrators" -Member "IDTAdmin" -ErrorAction SilentlyContinue | Out-Null        
        Set-WindowsAutoLogon -Username "IDTAdmin" -Password "Reddragon782^"
        Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name "RunOnceIDT" -Value 'Powershell.exe -noexit -c "Run-DeploymentSet -Deployments ((Get-Param).Deployments) -RerunCount ((Get-Param).RerunCount) -ResultsToDesktop:((Get-Param).ResultsToDesktop) -RunWindowsUpdates:((Get-Param).RunWindowsUpdates) -RestartWhenComplete:((Get-Param).RestartWhenComplete) -RestartTimeout:((Get-Param).RestartTimeout) -RerunOnFail"' -Type String | Out-Null
    }
    ELSE {
        Clear-WindowsAutoLogon
        Remove-LocalUser -Name IDTAdmin -ErrorAction SilentlyContinue | Out-Null        
        IF ($Results.Success -contains "False") { Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunSuccess" -Value 0 -Type DWORD | Out-Null }
        ELSE { Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunSuccess" -Value 1 -Type DWORD | Out-Null }
        Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name "RunOnceIDT" -Force -ErrorAction SilentlyContinue | Out-Null
    }
   
    $SessionStartTime = (Get-Date)

    $Results = @()
    $DeploymentCount = $Deployments.Count
    $CurrentCount = 0

    $DateText = $(Get-Date).ToString()
    $IPInfo = Get-IPInfo -Verbose:$false
    $LocationLength = ($IPInfo.City).Length + ($IPInfo.State).Length


    $ResultsFileName = "IDTResults $($(Get-Date).ToString('yyyy_MM_dd h_mmm_ss_tt')).txt"
    $TranscriptFileName = $ResultsFileName.Replace("IDTResults","IDTTranscript")
    New-Item -Path "C:\Users\Public\Desktop\" -Name "IDTResults" -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null
    Start-Transcript -Path "C:\Users\Public\Desktop\IDTResults\$TranscriptFileName" -ErrorAction SilentlyContinue | Out-Null


    Write-Host ""
    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
    Write-Host "### ========================================================== ###" -ForegroundColor Red -BackgroundColor Black
    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
    Write-Host "### Starting New Integris Deployment Tool Session ###" -ForegroundColor Red -BackgroundColor Black
    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
    Write-Host "### ###" -ForegroundColor Red -BackgroundColor Black
    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
    Write-Host "### Start Time : $($($DateText).PadRight(42," "))###" -ForegroundColor Red -BackgroundColor Black
    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
    Write-Host "### Public IP : $($($IPInfo.IP).PadRight(42," "))###" -ForegroundColor Red -BackgroundColor Black
    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
    Write-Host "### Location : $($IPInfo.City), $($IPInfo.State) $($($IPInfo.ZipCode).PadRight(39-$LocationLength," "))###" -ForegroundColor Red -BackgroundColor Black
    Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
    Write-Host "### ========================================================== ###" -ForegroundColor Red -BackgroundColor Black


    $WindowsUpdateJob = $null
    IF ($RunWindowsUpdates) {


        Write-Host ""
        Write-Host "$($(Get-Date).ToShortTimeString()): ### ========================================= ###"
        Write-Host "$($(Get-Date).ToShortTimeString()): ### Running Windows Updates ###"
        Write-Host "$($(Get-Date).ToShortTimeString()): ### ========================================= ###"
        Write-Host ""
        Write-Host "$($(Get-Date).ToShortTimeString()): Starting Windows Update Job in the Background..." 
        $WindowsUpdateJob = Start-Job -ScriptBlock { Invoke-Expression -Command "Install-WindowsUpdates" } -ErrorAction SilentlyContinue
    }
    
    
    FOREACH ($Deployment in $Deployments) {    
    
        $CurrentCount++
        $CountLength = $CurrentCount.ToString().Length
        $ActionText = $Deployment -split " "
        Write-Host ""
        Write-Host "$($(Get-Date).ToShortTimeString()): ### ========================================= ###"
        Write-Host "$($(Get-Date).ToShortTimeString()): ### Step: $CurrentCount of $($DeploymentCount.ToString().PadRight(26-$CountLength," ")) ###"
        Write-Host "$($(Get-Date).ToShortTimeString()): ### Package: $($($ActionText[0]).PadRight(30," ")) ###"
        Write-Host "$($(Get-Date).ToShortTimeString()): ### ========================================= ###"
        
        $Results += Invoke-Expression "$Deployment"

        $Results | Select Action, Duration, Name, Version, Success, Details | FT | Out-File "C:\Users\Public\Desktop\IDTResults\$ResultsFileName" -Force
    }
    
    IF ($RunWinGetUpdate -eq $True -and (Ensure-Winget) -eq $true) {

        $WinGetStartTime = (Get-Date)
        $Results2 = Run-WinGetAppUpdates $Results
        $Results3 = Remove-NullEntriesInObject $Results2

        $Results3 += [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Update"
            Duration = (Get-TimeDifferenceToString $WinGetStartTime)
            RequestedName = $Null
            Name = "WinGet Update All"
            RequestedVersion = $Null
            Version = $Null
            UpdatedVersion = $Null
            Success = $True
            Details = $Null
        }

        $Results3 += [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Total"
            Duration = (Get-TimeDifferenceToString $SessionStartTime)
            RequestedName = $Null
            Name = $Null
            RequestedVersion = $Null
            Version = $Null
            UpdatedVersion = $Null
            Success = $Null
            Details = $Null
        }

        IF ($ResultsToDesktop) { $Results3 | Select Action, Duration, Name, Version, UpdatedVersion, Success, Details | FT | Out-File "C:\Users\Public\Desktop\IDTResults\$ResultsFileName" }
        RETURN $Results3 | Select Action, Duration, Name, Version, UpdatedVersion, Success, Details
    } 
    IF ($RunWindowsUpdates) {
        Write-Host ""
        Write-Host "$($(Get-Date).ToShortTimeString()): ### ============================================== ###"
        Write-Host "$($(Get-Date).ToShortTimeString()): ### Running Windows Updates ###"
        Write-Host "$($(Get-Date).ToShortTimeString()): ### ============================================== ###"
        Write-Host ""
        Write-Host "$($(Get-Date).ToShortTimeString()): Waiting for Windows Update to Complete..." -NoNewline
        Wait-Job -Job $WindowsUpdateJob | Out-Null
        Write-Host "Windows Update Finished."

        $Searcher = New-Object -ComObject Microsoft.Update.Searcher
        $SearchResult = $Searcher.Search("IsInstalled=0 and RebootRequired=0").Updates

        IF ((($Searcher.Search("RebootRequired=1").Updates) | select RebootRequired).RebootRequired -contains $true) { $UpdateDetails = "Reboot Required" }
        ELSE { $UpdateDetails = "" } 

        IF ($SearchResult.Count -eq 0) { 
            $Results += [PSCustomObject]@{
                PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
                Action = "Install"
                Duration = (Get-TimeDifferenceToString $SessionStartTime)
                RequestedName = $Null
                Name = "Windows Updates"
                RequestedVersion = $Null
                Version = $Null
                Success = $True
                Details = $UpdateDetails
            }
        }
        ELSE { 
            $Results += [PSCustomObject]@{
                PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
                Action = "Install"
                Duration = (Get-TimeDifferenceToString $SessionStartTime)
                RequestedName = $Null
                Name = "Windows Updates"
                RequestedVersion = $Null
                Version = $Null
                Success = $False
                Details = $UpdateDetails
            }
        }
        
    }      
        
    $Results += [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Total"
        Duration = (Get-TimeDifferenceToString $SessionStartTime)
        RequestedName = $Null
        Name = $Null
        RequestedVersion = $Null
        Version = $Null
        Success = $Null
        Details = $Null
    }
        
    IF ($ResultsToDesktop) { $Results | Select Action, Duration, Name, Version, Success, Details | FT -AutoSize | Out-File -Width 9999 "C:\Users\Public\Desktop\IDTResults\$ResultsFileName" }
        
    $ResultsNoVerify = $Results | Where-Object { $_.Action -ne "Verify" }
    IF ($RerunOnFail -and $ResultsNoVerify.Success -contains $False -and ((Get-ItemProperty -Path "HKLM:\SOFTWARE\IntegrisDeploymentTool").RunCount) -le $RerunCount ) {
        Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunSuccess" -Value 0 -Type DWORD | Out-Null
        $Count = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\IntegrisDeploymentTool").RunCount)
        $Count++
        Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunCount" -Value $Count -Type DWORD | Out-Null
        New-Item -Path "C:\Integris\Temp\" -ItemType Directory -Name Resume -ErrorAction SilentlyContinue | Out-Null
        $SessionArguments = @{
            Deployments = $Deployments
            ResultsToDesktop = $ResultsToDesktop
            RunWindowsUpdates = $RunWindowsUpdates
            RestartWhenComplete = $RestartWhenComplete
            RestartTimeout = $RestartTimeout
            RerunOnFail = $RerunOnFail
            RerunCount = $RerunCount
            ResetCount = $False
        }
        $SessionArguments | Export-CLIXML "C:\Integris\Temp\Resume\Parameters.xml"
        New-LocalUser -Name "IDTAdmin" -Password (ConvertTo-SecureString "Reddragon782^" -AsPlainText -Force) -ErrorAction SilentlyContinue | Out-Null
        Add-LocalGroupMember -Group "Administrators" -Member "IDTAdmin" -ErrorAction SilentlyContinue | Out-Null
        Remove-LocalUser -Name defaultuser0 -ErrorAction SilentlyContinue | Out-Null
        Set-WindowsAutoLogon -Username "IDTAdmin" -Password "Reddragon782^"
        Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name "RunOnceIDT" -Value 'Powershell.exe -noexit -c "Run-DeploymentSet -Deployments ((Get-Param).Deployments) -RerunCount ((Get-Param).RerunCount) -ResultsToDesktop:((Get-Param).ResultsToDesktop) -RunWindowsUpdates:((Get-Param).RunWindowsUpdates) -RestartWhenComplete:((Get-Param).RestartWhenComplete) -RestartTimeout:((Get-Param).RestartTimeout) -RerunOnFail"' -Type String | Out-Null
        IF (!($RestartWhenComplete)) { 
            Write-Host ""
            Write-Host "$($(Get-Date).ToShortTimeString()): RestartWhenComplete is enabled. Attempting Restart..."
            Shutdown -r -t 15
        }
    }
    ELSE {
        Clear-WindowsAutoLogon
        Remove-LocalUser -Name IDTAdmin -ErrorAction SilentlyContinue | Out-Null
        Remove-LocalUser -Name defaultuser0 -ErrorAction SilentlyContinue | Out-Null
        IF ($Results.Success -contains "False") { Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunSuccess" -Value 0 -Type DWORD | Out-Null }
        ELSE { Set-RegistryValue -Hive HKLM -Path "SOFTWARE\IntegrisDeploymentTool" -Name "RunSuccess" -Value 1 -Type DWORD | Out-Null }
        Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name "RunOnceIDT" -Force -ErrorAction SilentlyContinue | Out-Null
    }
        
    IF ($RestartWhenComplete) { 
        Write-Host ""
        Write-Host "$($(Get-Date).ToShortTimeString()): RestartWhenComplete is enabled. Attempting Restart..."
        Start-Process -FilePath "Shutdown.exe" -ArgumentList "-a" -ErrorAction SilentlyContinue -WindowStyle Hidden
        Start-Process -FilePath "Shutdown.exe" -ArgumentList "-r -t 15" -ErrorAction SilentlyContinue -WindowStyle Hidden
    }
    ELSE { Start-Process -FilePath "Shutdown.exe" -ArgumentList "-a" -ErrorAction SilentlyContinue -WindowStyle Hidden }
    
    Stop-Transcript -ErrorAction SilentlyContinue | Out-Null
    RETURN (Convert-IDTResults $Results)
}
FUNCTION Run-WinGetAppUpdates {
    
    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory)]
        $Results
    )

    $NewResults = @()

    IF (Ensure-Winget) { } ELSE { IF (Ensure-Winget) { Write-Host "Found WinGet" } ELSE { Write-Warning "Unable to install WinGet. You must install WinGet before you can use this command." } }

    
    Write-Host ""
    Write-Host "$($(Get-Date).ToShortTimeString()): ### ============================================== ###"
    Write-Host "$($(Get-Date).ToShortTimeString()): ### Starting WinGet Update Session ###"
    Write-Host "$($(Get-Date).ToShortTimeString()): ### This Could Take a While... ###"
    Write-Host "$($(Get-Date).ToShortTimeString()): ### ============================================== ###"
    winget update --all --accept-package-agreements --accept-source-agreements | Out-Null

    Write-Host ""
    Write-Host "$($(Get-Date).ToShortTimeString()): WinGet Update is Done Running. Finalizing Results." 
    Start-Sleep 3


    FOREACH ($Result in $Results) {
        
        ### All Configured
        IF ($Result.Action -eq "Configure") {
            $NewResults += [PSCustomObject]@{
                PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
                Action = $Result.Action
                Duration = $Result.Duration
                RequestedName = $Result.RequestedName
                Name = $Result.Name
                RequestedVersion = $Result.RequestedVersion
                Version = $Result.Version
                UpdatedVersion = $null
                Success = $Result.Success
                Details = $Result.Details
            }
            continue
        }
        ### All Uninstalled
        IF ($Result.Action -eq "Uninstall") {
            $NewResults += [PSCustomObject]@{
                PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
                Action = $Result.Action
                Duration = $Result.Duration
                RequestedName = $Result.RequestedName
                Name = $Result.Name
                RequestedVersion = $Result.RequestedVersion
                Version = $Result.Version
                UpdatedVersion = $null
                Success = $Result.Success
                Details = $Result.Details
            }
            continue
        }
        ### All Uninstalled
        IF ($Result.Action -eq "Verify") {
            $NewResults += [PSCustomObject]@{
                PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
                Action = $Result.Action
                Duration = $Result.Duration
                RequestedName = $Result.RequestedName
                Name = $Result.Name
                RequestedVersion = $Result.RequestedVersion
                Version = $Result.Version
                UpdatedVersion = $null
                Success = $Result.Success
                Details = $Result.Details
            }
            continue
        }

        $NewApplicationInfo = Get-ApplicationInstalled | Where-Object { $_.Name -like "$($Result.RequestedName)" }
        $ResultDetails = $null
        $UpdatedVersion = $Null

        ### If Updated Version is Greater than Original Version
        IF ([VERSION]$NewApplicationInfo.Version -gt [VERSION]$Result.Version) { $UpdatedVersion = [VERSION]$NewApplicationInfo.Version }

        ### If Requested Version is NULL
        IF ($Result.RequestedVersion -eq $null) { $ResultSuccess = $Result.Success } 
        ### If Installed Version >= Requested Version
        ELSEIF ([VERSION]$Result.RequestedVersion -le [VERSION]$Result.Version -or
            [VERSION]$Result.RequestedVersion -le [VERSION]$NewApplicationInfo.Version) {
            $ResultSuccess = $True   
            $ResultDetails = $null     
        }
        ELSE { $ResultSuccess = $False; $ResultDetails = "Version Older than Requested" }  

        $NewResults += [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = $Result.Action
            Duration = $Result.Duration 
            RequestedName = $Result.RequestedName
            Name = $Result.Name
            RequestedVersion = $Result.RequestedVersion
            Version = $Result.Version
            UpdatedVersion = $UpdatedVersion
            Success = $ResultSuccess
            Details = $ResultDetails
        }
    }

    RETURN $NewResults
}


### Package Templates
FUNCTION App-PackageTemplate {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = $null
        ApplicationVersion          = $null
        DownloadLink                = $null   
        FileName                    = $null 
        InstallArguments            = $null  
        ZipInstallerPath            = $null
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = $null        
        UninstallArguments          = $null
        UninstallTimeout            = 180
        InvokeUninstallCommand      = $False
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = $null

        ### Custom Override Parameters
        CustomInstallCommand        = $null     
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = $null
        InstallKeystrokes           = $null                        
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION Verify-PackageTemplate {
    
    [CmdletBinding()]
    PARAM ( )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Verify"
        Duration = $null
        RequestedName = $null
        Name = $null
        RequestedVersion = $null
        Version = $null
        Success = $False
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

   
    
   

    ### End
    RETURN Return-Results
}
FUNCTION Configure-PackageTemplate {
    
    [CmdletBinding()]
    PARAM ( )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = $null
        RequestedVersion = $null
        Version = $null
        Success = $False
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

   
    
   

    ### End
    RETURN Return-Results
}


### Completed Configuration Packages
FUNCTION Configure-AcrobatDC {
    
    [CmdletBinding()]
    PARAM ( 
        [SWITCH]$DisableUpsell = $False,
        [SWITCH]$DisableForcedSignIn = $False,
        [SWITCH]$DisableDesktopNotifications = $False
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "Adobe Acrobat DC"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }
   
    ### Disable Forced Signin
    IF ($DisableForcedSignIn) { 
        IF ((Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Adobe\Adobe Acrobat\DC\FeatureLockDown" -Name "bIsSCReducedModeEnforcedEx" -Value "1" -Type DWord)) { 
            #Write-Host "Successfully set registry key bIsSCReducedModeEnforcedEx to disable forced signin."
        } 
        ELSE { 
            $Result.Success = $False 
            #Write-Host "Failed to set registry key bIsSCReducedModeEnforcedEx to disable forced signin."
            $Result.Details = "Setting Registry Value Failed"
        } 
    } ELSE { }
    
    ### Disable Upsell
    IF ($DisableUpsell) { 
        IF ((Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Adobe\Adobe Acrobat\DC\FeatureLockDown" -Name "bAcroSuppressUpsell" -Value "1" -Type DWord)) { 
            #Write-Host "Successfully set registry key bAcroSuppressUpsell to disable upsell advertisements."
        } 
        ELSE { 
            $Result.Success = $False 
            #Write-Host "Failed to set registry key bAcroSuppressUpsell to disable upsell advertisements."
            $Result.Details = "Setting Registry Value Failed"
        } 
    } ELSE { }
    
    ### Disable Notifications
    IF ($DisableDesktopNotifications) { 
        IF ((Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Adobe\Adobe Acrobat\DC\FeatureLockDown\cServices" -Name "bToggleNotificationToasts" -Value "1" -Type DWord)) { 
            #Write-Host "Successfully set registry key bToggleNotificationToasts to disable desktop notifications."
        } 
        ELSE { 
            $Result.Success = $False 
            #Write-Host "Failed to set registry key bToggleNotificationToasts to disable desktop notifications."
            $Result.Details = "Setting Registry Value Failed"
        } 
    } ELSE { }
   
    ### End
    RETURN Return-Results
}
FUNCTION Configure-BatteryMode {
    
    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory)]
        [ValidateSet('Best Power Efficiency', 'Balanced', 'Best Performance')]
        [string]$Mode
    )
    $StartTime = (Get-Date)

    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    IF ((Test-IsLaptop) -eq $False) {
        $Result = [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Configure"
            Duration = (Get-TimeDifferenceToString $StartTime)
            RequestedName = $null
            Name = "Battery Mode"
            RequestedVersion = $null
            Version = $Null
            Success = $True
            Details = "Not a Laptop"
        }
        RETURN Return-Results
    }

    FUNCTION GET-PowerMode {
$function = @'
[DllImport("powrprof.dll", EntryPoint="PowerGetEffectiveOverlayScheme")]
public static extern int PowerGetEffectiveOverlayScheme(out Guid EffectiveOverlayGuid);
'@

$power = Add-Type -MemberDefinition $function -Name "Power" -PassThru -Namespace System.Runtime.InteropServices

$effectiveOverlayGuid = [Guid]::NewGuid()
$ret = $power::PowerGetEffectiveOverlayScheme([ref]$effectiveOverlayGuid)

    if ($ret -eq 0) {
        IF ($effectiveOverlayGuid -eq "961cc777-2547-4f9d-8174-7d86181b8a7a") {
            $Results += [PSCustomObject]@{
                Hostname = $env:COMPUTERNAME
                PowerModeName = "Best Power Efficiency"
                PowerModeGUID = $effectiveOverlayGuid
            }
        }
        ELSEIF ($effectiveOverlayGuid -eq "00000000-0000-0000-0000-000000000000") { 
            $Results += [PSCustomObject]@{
                Hostname = $env:COMPUTERNAME
                PowerModeName = "Balanced"
                PowerModeGUID = $effectiveOverlayGuid
            }
        }
        ELSEIF ($effectiveOverlayGuid -eq "ded574b5-45a0-4f42-8737-46345c09c238") {
            $Results += [PSCustomObject]@{
                Hostname = $env:COMPUTERNAME
                PowerModeName = "Best Performance"
                PowerModeGUID = $effectiveOverlayGuid
            }
        }
        ELSE { 
            $Results += [PSCustomObject]@{
                Hostname = $env:COMPUTERNAME
                PowerModeName = "Unknown"
                PowerModeGUID = $effectiveOverlayGuid
            }
        }
    } 
    ELSE {
        $Results += [PSCustomObject]@{
            Hostname = $env:COMPUTERNAME
            PowerModeName = "Unknown"
            PowerModeGUID = $effectiveOverlayGuid
        }
    }

    RETURN $Results | Select Hostname, PowerModeName, PowerModeGUID
}
    FUNCTION SET-PowerMode {
    PARAM (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Best Power Efficiency', 'Balanced', 'Best Performance')]
        [string]$Mode
    )

    $ModeToGuid = @{
        "Best Power Efficiency" = [guid] "961cc777-2547-4f9d-8174-7d86181b8a7a";
        "Balanced" = [guid] "00000000-0000-0000-0000-000000000000";
        "Best Performance" = [guid] "ded574b5-45a0-4f42-8737-46345c09c238"
    }
    
    function Set-Power-Mode-By-GUID {
    param (
        [Guid]$guid
    )

    $function = @'
    [DllImport("powrprof.dll", EntryPoint="PowerSetActiveOverlayScheme")]
    public static extern int PowerSetActiveOverlayScheme(Guid OverlaySchemeGuid);
'@


    $power = Add-Type -MemberDefinition $function -Name "Power" -PassThru -Namespace MyNamespace.PowerModeManager

    $ret = $power::PowerSetActiveOverlayScheme($guid)

    if ($ret -ne 0) {
        Write-Error "Failed to set the power mode profile ID."
    }
}

    Set-Power-Mode-By-GUID -guid $ModeToGuid[$Mode]
}

    $StartMode = (Get-PowerMode).PowerModeName 
        
    IF ($StartMode -eq $Mode) {
        $Result = [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Configure"
            Duration = (Get-TimeDifferenceToString $StartTime)
            RequestedName = $null
            Name = "Battery Mode - $Mode"
            RequestedVersion = $null
            Version = $Null
            Success = $True
            Details = $Mode + " Already Set"
        }
        RETURN Return-Results
    }

    Set-PowerMode -Mode $Mode
    
    IF ((Get-PowerMode).PowerModeName -eq $Mode) {
        $Result = [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Configure"
            Duration = (Get-TimeDifferenceToString $StartTime)
            RequestedName = $null
            Name = "Battery Mode - $Mode"
            RequestedVersion = $null
            Version = $Null
            Success = $True
            Details = $Mode + " Already Set"
        }
        RETURN Return-Results
    }
    ELSE {
        $Result = [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Configure"
            Duration = (Get-TimeDifferenceToString $StartTime)
            RequestedName = $null
            Name = "Battery Mode - $Mode"
            RequestedVersion = $null
            Version = $Null
            Success = $False
            Details = "Failed to Set Battery Mode"
        }

        RETURN Return-Results
    }

    
}
FUNCTION Configure-EnvironmentVariable {
    
    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory=$true)]
        [STRING]$Name,
        
        [Parameter(Mandatory=$true)]
        [STRING]$Value,
        
        [ValidateSet("User", "Machine", "Process")]
        [STRING]$Scope = "Machine",

        [ValidateSet("Overwrite", "Append", "Prefix")]
        [STRING]$Method = "Overwrite"
    )

    FUNCTION Set-EnvironmentVariable {
    param (
        [Parameter(Mandatory=$true)]
        [string]$Name,
        
        [Parameter(Mandatory=$true)]
        [string]$Value,
        
        [ValidateSet("User", "Machine", "Process")]
        [string]$Scope = "User"
    )
    
    try {
        # Set the environment variable based on scope
        switch ($Scope) {
            "User" {
                [Environment]::SetEnvironmentVariable($Name, $Value, [EnvironmentVariableTarget]::User)
            }
            "Machine" {
                # Requires admin privileges for Machine scope
                if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
                    throw "Setting Machine environment variables requires administrative privileges."
                }
                [Environment]::SetEnvironmentVariable($Name, $Value, [EnvironmentVariableTarget]::Machine)
            }
            "Process" {
                [Environment]::SetEnvironmentVariable($Name, $Value, [EnvironmentVariableTarget]::Process)
            }
        }
        
        Write-Output "Environment variable '$Name' set to '$Value' in $Scope scope successfully."
    }
    catch {
        Write-Error "Failed to set environment variable: $_"
    }
}

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "Environment Variable - $Name"
        RequestedVersion = $null
        Version = $null
        Success = $False
        Details = $null
    }

    FUNCTION Set-EnvironmentVariable {
    param (
        [Parameter(Mandatory=$true)]
        [string]$Name,
        
        [Parameter(Mandatory=$true)]
        [string]$Value,
        
        [ValidateSet("User", "Machine", "Process")]
        [string]$Scope = "Machine"
    )
    
    try {
        # Set the environment variable based on scope
        switch ($Scope) {
            "User" {
                [Environment]::SetEnvironmentVariable($Name, $Value, [EnvironmentVariableTarget]::User)
            }
            "Machine" {
                # Requires admin privileges for Machine scope
                if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
                    throw "Setting Machine environment variables requires administrative privileges."
                }
                [Environment]::SetEnvironmentVariable($Name, $Value, [EnvironmentVariableTarget]::Machine)
            }
            "Process" {
                [Environment]::SetEnvironmentVariable($Name, $Value, [EnvironmentVariableTarget]::Process)
            }
        }
        
        #Write-Output "Environment variable '$Name' set to '$Value' in $Scope scope successfully."
    }
    catch {
        #Write-Error "Failed to set environment variable: $_"
    }
}       
    FUNCTION Get-EnvironmentVariable {
        param (
            [Parameter(Mandatory=$true)]
            [string]$VariableName,
            [ValidateSet("User","Machine","Process")]
            [string]$Scope = "Machine"
        )
    
        try {
            $value = [Environment]::GetEnvironmentVariable($VariableName, $Scope)
            if ($null -eq $value) {
                #Write-Warning "Environment variable '$VariableName' not found in $Scope scope"
                return $null
            }
            return $value
        }
        catch {
            #Write-Error "Error retrieving environment variable: $_"
            return $null
        }
    } 

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    IF ($Method -eq "Overwrite") { Set-EnvironmentVariable -Name $Name -Value $Value -Scope $Scope }
    IF ($Method -eq "Append") {
        $EVTemp = Get-EnvironmentVariable -VariableName $Name -Scope $Scope
        Set-EnvironmentVariable -Name $Name -Value "$EVTemp;$Value" -Scope $Scope
    }
    IF ($Method -eq "Prefix") {
        $EVTemp = Get-EnvironmentVariable -VariableName $Name -Scope $Scope
        Set-EnvironmentVariable -Name $Name -Value "$Value;$EVTemp" -Scope $Scope
    }

    IF ((Get-EnvironmentVariable -VariableName $Name -Scope Machine) -like "*$Value*") { $Result.Success = $true }

    ### End
    RETURN Return-Results
}
FUNCTION Configure-FileAndPrinterSharing {
    
    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory)]
        [ValidateSet("Enable","Disable")]
        [STRING]$Status
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "File and Printer Sharing - $Status"
        RequestedVersion = $null
        Version = $null
        Success = $False
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }


    IF ($Status -eq "Enable"){ 
        TRY {
            
            IF ((Get-NetFirewallRule -DisplayGroup "File And Printer Sharing").Enabled -contains "False") { }
            ELSE { $Result.Success = $True; RETURN Return-Results }

            Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain
            Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Private

            IF ((Get-NetFirewallRule -DisplayGroup "File And Printer Sharing").Enabled -contains "False") { }
            ELSE { $Result.Success = $True }
        }
        CATCH { }
    }

    IF ($Status -eq "Disable"){ 
        TRY {
            IF ((Get-NetFirewallRule -DisplayGroup "File And Printer Sharing").Enabled -contains "True") { }
            ELSE { $Result.Success = $True; RETURN Return-Results }

            Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled False -Profile Domain
            Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled False -Profile Private

            IF ((Get-NetFirewallRule -DisplayGroup "File And Printer Sharing").Enabled -contains "True") { }
            ELSE { $Result.Success = $True }
        }
        CATCH { }
    }

    
    ### End
    RETURN Return-Results
}
FUNCTION Configure-PowerSettings {

    [CmdletBinding()]
    PARAM (
        [int]$ACMonitorTimeout = $null,
        [int]$ACSleepTimeout = $null,
        [int]$DCMonitorTimeout = $null,
        [int]$DCSleepTimeout = $null
        #[int]$PowerButtonAction = $null,
        #[int]$SleepButtonAction = $null,
        #[int]$LidAction = $null
    )

    $StartTime = (Get-Date)

    $Result = @()
    #$PowerPlans = powercfg /list
            
    #IF ($PowerPlans -like "*($Name)*") { $GUID = ($PowerPlans -like "*$Name*")[0].Replace("Power Scheme GUID: ","").substring(0,36) }
    #ELSE {
    # $GUID = New-GUID
    # powercfg /duplicateScheme 381b4222-f694-41f0-9685-ff5bb260df2e $GUID
    # powercfg /changename $GUID $Name
    #}
    #powercfg -SetActive $GUID
    FUNCTION Return-Results {        
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }


    TRY {

        IF ($ACMonitorTimeout -ne $null) { powercfg -change -monitor-timeout-ac $ACMonitorTimeout }
        IF ($ACSleepTimeout -ne $null) { powercfg -change -standby-timeout-ac $ACSleepTimeout }
        IF ($DCMonitorTimeout -ne $null) { powercfg -change -monitor-timeout-dc $DCMonitorTimeout }
        IF ($DCSleepTimeout -ne $null) { powercfg -change -standby-timeout-dc $DCSleepTimeout }


        IF ($PowerButtonAction -ne $null) {
            powercfg -SETACVALUEINDEX $GUID 4f971e89-eebd-4455-a8de-9e59040e7347 7648efa3-dd9c-4e3e-b566-50f929386280 $PowerButtonAction
            powercfg -SETDCVALUEINDEX $GUID 4f971e89-eebd-4455-a8de-9e59040e7347 7648efa3-dd9c-4e3e-b566-50f929386280 $PowerButtonAction
            powercfg -SETACVALUEINDEX 381b4222-f694-41f0-9685-ff5bb260df2e 4f971e89-eebd-4455-a8de-9e59040e7347 7648efa3-dd9c-4e3e-b566-50f929386280 $PowerButtonAction
            powercfg -SETDCVALUEINDEX 381b4222-f694-41f0-9685-ff5bb260df2e 4f971e89-eebd-4455-a8de-9e59040e7347 7648efa3-dd9c-4e3e-b566-50f929386280 $PowerButtonAction
        }
        IF ($SleepButtonAction -ne $null) {
            powercfg -SETACVALUEINDEX $GUID 4f971e89-eebd-4455-a8de-9e59040e7347 96996bc0-ad50-47ec-923b-6f41874dd9eb $SleepButtonAction
            powercfg -SETDCVALUEINDEX $GUID 4f971e89-eebd-4455-a8de-9e59040e7347 96996bc0-ad50-47ec-923b-6f41874dd9eb $SleepButtonAction
            powercfg -SETACVALUEINDEX 381b4222-f694-41f0-9685-ff5bb260df2e 4f971e89-eebd-4455-a8de-9e59040e7347 96996bc0-ad50-47ec-923b-6f41874dd9eb $SleepButtonAction
            powercfg -SETDCVALUEINDEX 381b4222-f694-41f0-9685-ff5bb260df2e 4f971e89-eebd-4455-a8de-9e59040e7347 96996bc0-ad50-47ec-923b-6f41874dd9eb $SleepButtonAction
        }
        IF ($LidAction -ne $null) { 
            powercfg -SETACVALUEINDEX $GUID 4f971e89-eebd-4455-a8de-9e59040e7347 5ca83367-6e45-459f-a27b-476b1d01c936 $LidAction
            powercfg -SETDCVALUEINDEX $GUID 4f971e89-eebd-4455-a8de-9e59040e7347 5ca83367-6e45-459f-a27b-476b1d01c936 $LidAction
            powercfg -SETACVALUEINDEX 381b4222-f694-41f0-9685-ff5bb260df2e 4f971e89-eebd-4455-a8de-9e59040e7347 5ca83367-6e45-459f-a27b-476b1d01c936 $LidAction
            powercfg -SETDCVALUEINDEX 381b4222-f694-41f0-9685-ff5bb260df2e 4f971e89-eebd-4455-a8de-9e59040e7347 5ca83367-6e45-459f-a27b-476b1d01c936 $LidAction
        }
          
        $Result += [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Configure"
            RequestedName = $null
            Name = "Power Settings"
            RequestedVersion = $null
            Version = $null
            Duration = (Get-TimeDifferenceToString $StartTime)
            Success = $True
            Details = $null
        }
    }
    CATCH {
        $Result += [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Configure"
            RequestedName = $null
            Name = "Power Settings"
            RequestedVersion = $null
            Version = $null
            Duration = (Get-TimeDifferenceToString $StartTime)
            Success = $False
            Details = $null
        }
    }



    RETURN Return-Results
}
FUNCTION Configure-TimeSettings {
    
    [CmdletBinding()]
    PARAM ( 
        [STRING]$InternetTimeServer = "0.us.pool.ntp.org,1.us.pool.ntp.org,2.us.pool.ntp.org,3.us.pool.ntp.org",
        [STRING]$LocalTimeServer = $null,
        [ValidateSet("Enable", "Disable")]
        [STRING]$AutomaticTimeZone = $null
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name ="Time Servers"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    ### Set Time Server
    IF ($True) {
        $ServerString = $null

        IF (Test-NotNull $LocalTimeServer) {       
            $ServerString = "$LocalTimeServer,$InternetTimeServer"
        }
        ELSE {
            $ServerString = "$InternetTimeServer"
        
        }

        Set-Service W32Time -StartupType Automatic | Out-Null
        Start-Service W32Time -ErrorAction SilentlyContinue | Out-Null
        Start-Sleep 3
        Start-Service W32Time -ErrorAction SilentlyContinue | Out-Null
        Start-Sleep 3

        w32tm /config /manualpeerlist:"$InternetTimeServer" /syncfromflags:manual /reliable:yes /update | Out-Null

        Start-Service W32Time -ErrorAction SilentlyContinue | Out-Null
        Start-Sleep 3


        # Force immediate time sync
        w32tm /resync /force | Out-Null
    
        $TimeServers = w32tm /query /configuration
        $TimeServers = $TimeServers | Select-String "NtpServer:"

        IF ((Get-Service W32Time).Status -eq "Stopped" | Out-Null) { $Result.Success = $False; $Result.Details = "Time Service Not Running" }
        ELSEIF ($TimeServers -like "*$ServerString*") {  }
        ELSE { $Result.Success = $False; $Result.Details = "Setting Time Servers Failed" }
    }

        ### Timezone
    IF ($AutomaticTimeZone -eq "Enable") { 
        IF (!(Set-RegistryValue -Hive HKLM -Path "SYSTEM\CurrentControlSet\Services\tzautoupdate" -Name Start -Value 3 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Enable TZAutoUpdate" } 
        IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\location" -Name Value -Value "Allow" -Type String)) { $Result.Success = $False; $Result.Details = "Failed to Enable Location Services" } 
    }
    IF ($AutomaticTimeZone -eq "Disable") { 
        IF (!(SSet-RegistryValue -Hive HKLM -Path "SYSTEM\CurrentControlSet\Services\tzautoupdate" -Name Start -Value 4 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Disable TZAutoUpdatee" }  
    }

   

    ### End
    RETURN Return-Results
}
FUNCTION Configure-WatchGuardSSLVPNClient {
    
    [CmdletBinding()]
    PARAM ( 
        [STRING]$Server,
        [STRING]$Username
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "Watchguard SSL VPN"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }
    
    IF (Test-NotNull $Server) { SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Server'; 'Type' = 'String'; 'Value' = $Server; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue }
    IF (Test-NotNull $Username) { SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Username'; 'Type' = 'String'; 'Value' = $Username; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue }
    SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'AutoReconnect'; 'Type' = 'DWORD'; 'Value' = 1; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue
   
    ### End
    RETURN Return-Results
}
FUNCTION Configure-WindowsUserSettings {
    
    [CmdletBinding()]
    PARAM ( 
        [ValidateSet("Show", "Hide")]
        [STRING]$TaskbarSearch = $null,
        [ValidateSet("Show", "Hide")]
        [STRING]$FileExtensions = $null,
        [ValidateSet("Enable", "Disable")]
        [STRING]$NewsandWeather = $null
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "Windows User Settings"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    IF ($TaskbarSearch -eq "Show") { Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'SearchboxTaskbarMode'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Search'} }
    IF ($TaskbarSearch -eq "Hide") { Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'SearchboxTaskbarMode'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Search'} }

    IF ($FileExtensions -eq "Show") { Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'HideFileExt'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'} }
    IF ($FileExtensions -eq "Hide") { Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'HideFileExt'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'} }

    IF ($NewsandWeather -eq "Show") { Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'ShellFeedsTaskbarViewMode'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'Software\Microsoft\Windows\CurrentVersion\Feeds'} }
    IF ($NewsandWeather -eq "Hide") { Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'ShellFeedsTaskbarViewMode'; 'Type' = 'DWORD'; 'Value' = '2'; 'Path' = 'Software\Microsoft\Windows\CurrentVersion\Feeds'} }
 
   
    ### End
    RETURN Return-Results
}
FUNCTION Configure-WindowsSystemSettings {
    
    [CmdletBinding()]
    PARAM ( 
        [ValidateSet("Enable", "Disable")]
        [STRING]$AllowCortana = $null,
        [ValidateSet("Enable", "Disable")]
        [STRING]$AllowWindowsHello = $null
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "Windows System Settings"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    ### Cortana
    IF ($AllowCortana -eq "Enable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\Windows\Windows Search" -Name AllowCortana -Value 1 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Allow Cortana" } }
    IF ($AllowCortana -eq "Disable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\Windows\Windows Search" -Name AllowCortana -Value 0 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Disable Cortana" } }

    ### Windows Hello
    IF ($AllowWindowsHello -eq "Enable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\PassportForWork" -Name Enabled -Value 1 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Allow Windows Hello" } }
    IF ($AllowWindowsHello -eq "Disable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\PassportForWork" -Name Enabled -Value 0 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Disable Windows Hello" } }
   
    ### End
    RETURN Return-Results
}
FUNCTION Configure-OneDrive {
    
    [CmdletBinding()]
    PARAM (
        [ValidateSet("Enable", "Disable")]
        [STRING]$AllowOneDriveBackup = $null
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "OneDrive"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    ### OneDrive Backup
    IF ($AllowOneDriveBackup -eq "Enable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\OneDrive" -Name KFMBlockOptIn -Value 1 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Allow OneDrive Backup" } }
    IF ($AllowOneDriveBackup -eq "Disable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\OneDrive" -Name KFMBlockOptIn -Value 0 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Disable OneDrive Backup" } }
   
    ### End
    RETURN Return-Results
}
FUNCTION Configure-Screensaver {
    
    [CmdletBinding()]
    PARAM (
        [ValidateSet("Enable", "Disable")]
        [STRING]$Status = $null,
        [INT]$Timeout = $null,
        [ValidateSet("Enable", "Disable")]
        [STRING]$SecureScreensaver = $null
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "Screensaver"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    ### Screensaver Active
    IF ($Status -eq "Enable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\Windows\Control Panel\Desktop" -Name ScreenSaveActive -Value 1 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Enable Screensaver" }  }
    IF ($Status -eq "Disable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\Windows\Control Panel\Desktop" -Name ScreenSaveActive -Value 0 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Disable Screensaver" } }

    ### Screensaver Timeout
    IF (Test-NotNull $Timeout) { 
        IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\Windows\Control Panel\Desktop" -Name ScreenSaveTimeOut -Value $Timeout -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Set Timeout" }
        IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name InactivityTimeoutSecs -Value $Timeout -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Set Timeout" }
    }

    ### Screensaver Active
    IF ($SecureScreensaver -eq "Enable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\Windows\Control Panel\Desktop" -Name ScreenSaverIsSecure -Value 1 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Set Secure" } }
    IF ($SecureScreensaver -eq "Disable") { IF (!(Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Microsoft\Windows\Control Panel\Desktop" -Name ScreenSaverIsSecure -Value 0 -Type DWORD)) { $Result.Success = $False; $Result.Details = "Failed to Set Secure" } }
   
    ### End
    RETURN Return-Results
}
FUNCTION Configure-WiFiProfile {
    <#
    .SYNOPSIS
        Adds a Wi-Fi profile to all user profiles on a Windows 11 computer by generating a Wi-Fi profile XML file.
 
    .DESCRIPTION
        This function creates a Wi-Fi profile XML file based on provided parameters (SSID, security type, and key) and applies it to all user profiles on a Windows 11 system using the netsh wlan command. It requires administrative privileges to modify system-wide Wi-Fi settings.
 
    .PARAMETER SSID
        The name of the Wi-Fi network (SSID) to configure.
 
    .PARAMETER SecurityType
        The security type for the Wi-Fi network. Valid options are 'WPA2PSK', 'WPA3PSK', or 'Open'. Default is 'WPA2PSK'.
 
    .PARAMETER Key
        The Wi-Fi network password or key. Required for WPA2PSK or WPA3PSK; ignored for Open networks.
 
    .PARAMETER XMLFilePath
        The path where the Wi-Fi profile XML file will be saved. Default is "$env:TEMP\WiFiProfile.xml".
 
    .EXAMPLE
        Add-WiFiProfileToAllUsers -SSID "MyWiFi" -SecurityType "WPA2PSK" -Key "MyPassword123"
        Creates and applies a WPA2-PSK Wi-Fi profile for the SSID "MyWiFi" with the specified key to all user profiles.
 
    .EXAMPLE
        Add-WiFiProfileToAllUsers -SSID "GuestWiFi" -SecurityType "Open" -XMLFilePath "C:\WiFi\GuestProfile.xml"
        Creates and applies an open Wi-Fi profile for the SSID "GuestWiFi" to all user profiles, saving the XML file to the specified path.
 
    .NOTES
        - Requires administrative privileges to run.
        - Tested on Windows 11. May not be compatible with earlier Windows versions.
        - The function overwrites the XML file if it already exists at the specified path.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$SSID,

        [Parameter(Mandatory = $false)]
        [ValidateSet('WPA2PSK', 'WPA3PSK', 'Open')]
        [string]$SecurityType = 'WPA2PSK',

        [Parameter(Mandatory = $false)]
        [string]$Key,

        [Parameter(Mandatory = $false)]
        [string]$XMLFilePath = "$env:TEMP\WiFiProfile.xml"
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Configure"
        Duration = $null
        RequestedName = $null
        Name = "Wi-Fi Profile - $SSID"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Configuration unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    FUNCTION Test-WiFiProfile {
    <#
    .SYNOPSIS
        Checks if a Wi-Fi profile exists on a Windows 11 computer.
 
    .DESCRIPTION
        This function uses the netsh wlan command to check if a Wi-Fi profile with the specified SSID exists on the system. It requires administrative privileges to access Wi-Fi profile information.
 
    .PARAMETER SSID
        The name of the Wi-Fi network (SSID) to check for.
 
    .EXAMPLE
        Test-WiFiProfile -SSID "MyWiFi"
        Returns $true if a Wi-Fi profile for "MyWiFi" exists, $false otherwise.
 
    .EXAMPLE
        if (Test-WiFiProfile -SSID "GuestWiFi") { Write-Output "Profile exists!" } else { Write-Output "Profile not found." }
        Checks if the "GuestWiFi" profile exists and outputs a message based on the result.
 
    .NOTES
        - Requires administrative privileges to run.
        - Tested on Windows 11. May work on other Windows versions with netsh support.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$SSID
    )

    # Check for administrative privileges
    $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    if (-not $isAdmin) {
        Write-Error "This function requires administrative privileges. Please run PowerShell as Administrator."
        return $false
    }

    try {
        # Run netsh command to list all Wi-Fi profiles
        $netshOutput = netsh wlan show profiles

        # Check if the SSID exists in the output
        $profileExists = $netshOutput | Where-Object { $_ -match "All User Profile\s*:\s*$SSID\s*$" }

        # Return true if the profile exists, false otherwise
        if ($profileExists) {
            Write-Verbose "Wi-Fi profile for SSID '$SSID' found."
            return $true
        }
        else {
            Write-Verbose "Wi-Fi profile for SSID '$SSID' not found."
            return $false
        }
    }
    catch {
        Write-Error "An error occurred while checking for the Wi-Fi profile: $_"
        return $false
    }
}

    # Check for administrative privileges
    $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    if (-not $isAdmin) {
        Write-Error "This function requires administrative privileges. Please run PowerShell as Administrator."
        return
    }


    # Determine authentication and encryption based on SecurityType
    if ($SecurityType -eq 'Open') {
        $authentication = 'open'
        $encryption = 'none'
        $sharedKeySection = ''
    }
    else {
        $authentication = if ($SecurityType -eq 'WPA2PSK') { 'WPA2PSK' } else { 'WPA3SAE' }
        $encryption = 'AES'
        $sharedKeySection = @"
            <sharedKey>
                <keyType>passPhrase</keyType>
                <protected>false</protected>
                <keyMaterial>$Key</keyMaterial>
            </sharedKey>
"@

    }

    # Define XML content
    $xmlTemplate = @"
<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
    <name>$SSID</name>
    <SSIDConfig>
        <SSID>
            <name>$SSID</name>
        </SSID>
    </SSIDConfig>
    <connectionType>ESS</connectionType>
    <connectionMode>auto</connectionMode>
    <MSM>
        <security>
            <authEncryption>
                <authentication>$authentication</authentication>
                <encryption>$encryption</encryption>
                <useOneX>false</useOneX>
            </authEncryption>
            $sharedKeySection
        </security>
    </MSM>
</WLANProfile>
"@


    # Save the XML file
    $xmlTemplate | Out-File -FilePath $XMLFilePath -Encoding UTF8 -Force
    Write-Verbose "Wi-Fi profile XML file created at $XMLFilePath"

    # Apply the Wi-Fi profile using netsh
    $netshCommand = "netsh wlan add profile filename=`"$XMLFilePath`" user=all"
    $netshresult = Invoke-Expression -Command $netshCommand 2>&1
    
   
    # Clean up the XML file
    if (Test-Path $XMLFilePath) {
        Remove-Item -Path $XMLFilePath -Force -ErrorAction SilentlyContinue
        Write-Verbose "Temporary XML file at $XMLFilePath deleted."
    }
   
    
    IF (Test-WiFiProfile $SSID) { }
    ELSE { $Result.Success = $False; $Result.Details = "Failed to Create Wi-Fi Profile $SSID" }
    
    ### End
    RETURN Return-Results
}


### Completed Cleanup Packages
FUNCTION CleanUp-AppXClutter {
    
    [CmdletBinding()]
    PARAM ( )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "CleanUp"
        Duration = $null
        RequestedName = $null
        Name = "AppX Clutter"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result | Select Action, Duration, RequestedName, Name, RequestedVersion, Version, Success, Details }
        ELSE { RETURN $Result | Select Action, Duration, Name, Version, Success, Details }
    }
       
    Get-AppxPackage -AllUsers -Name *King.com* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
    Get-AppxPackage -AllUsers -Name *Zune* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
    Get-AppxPackage -AllUsers -Name *Solitaire* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
    Get-AppxPackage -AllUsers -Name *MixedReality* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
    Get-AppxPackage -AllUsers -Name *Bing* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
    Get-AppxPackage -AllUsers -Name *microsoft.windowscommunicationsapps* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
    Get-AppxPackage -AllUsers -Name *Microsoft.Microsoft3DViewer* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
    Get-AppxPackage -AllUsers -Name *Microsoft.WindowsMaps* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
    Get-AppxPackage -AllUsers -Name *YourPhone* -ErrorAction SilentlyContinue | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
   
    ### End
    RETURN Return-Results
}
FUNCTION CleanUp-WindowsClutter {
    
    [CmdletBinding()]
    PARAM ( )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "CleanUp"
        Duration = $null
        RequestedName = $null
        Name = "Windows Clutter"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result | Select Action, Duration, RequestedName, Name, RequestedVersion, Version, Success, Details }
        ELSE { RETURN $Result | Select Action, Duration, Name, Version, Success, Details }
    }
       
    
    ### Turn off Application Suggestions
    Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'SubscribedContent-338388Enabled'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager'} 

    ### Turn off Windows Welcome Experience
    Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'SubscribedContent-310093Enabled'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager'} 

    ### Turn off 'Get Even More out of Windows' Popup
    Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'SubscribedContent-338389Enabled'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager'} 

    ### Turn off Windows Promotional Apps
    Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'SoftLandingEnabled'; 'Type' = 'DWORD'; 'Value' = '0'; 'Path' = 'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager'}

    ### Hide Recommended
    Set-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'HideRecommendedSection'; 'Type' = 'DWORD'; 'Value' = '1'; 'Path' = 'SOFTWARE\Policies\Microsoft\Windows\Explorer'}

    ### Other Clutter Items for OOBE
    Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" -Name "DisablePrivacyExperience" -Value 1 -Type DWORD | Out-Null
    Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" -Name "DisableVoice" -Value 1 -Type DWORD | Out-Null
    Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" -Name "PrivacyConsentStatus" -Value 1 -Type DWORD | Out-Null
    Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" -Name "Protectyourpc" -Value 3 -Type DWORD | Out-Null
    Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" -Name "HideEULAPage" -Value 1 -Type DWORD | Out-Null
    Set-RegistryValue -Hive HKLM -Path "Software\Microsoft\Windows\CurrentVersion\Policies\System" -Name "EnableFirstLogonAnimation" -Value 1 -Type DWORD | Out-Null
   
    ### End
    RETURN Return-Results
}


### Verification Packages
FUNCTION Verify-WindowsProEnterprise {
    
    [CmdletBinding()]
    PARAM ( )

    ### Variables
    $StartTime = (Get-Date)

    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Verify"
        Duration = $null
        RequestedName = $null
        Name = "Windows Pro\Enterprise"
        RequestedVersion = $null
        Version = $null
        Success = $False
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    IF (Test-IsServer) {
        $Result.Success = $True
        $Result.Details = "Server, Not a Workstation" 
        RETURN Return-Results
    }
    ELSEIF ((GET-CIMInstance Win32_OperatingSystem -Verbose:$False).Caption -like "*Pro*" -or (GET-CIMInstance Win32_OperatingSystem -Verbose:$False).Caption -like "*Enterprise*") { 
        $Result.Success = $True
        $Result.Details = $null 
        RETURN Return-Results
    }
    ELSE { 
        $Result = $False
        $ResultDetails = "Windows Home" 
        RETURN Return-Results
    }
   

    ### End
    RETURN Return-Results
}
FUNCTION Verify-DomainJoin {
    
    [CmdletBinding()]
    PARAM ( 
        [ValidateSet("AD","AAD","Workgroup")]
        [Parameter(Mandatory)]
        [STRING]$Type,
        [STRING]$Name = $null
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Verify"
        Duration = $null
        RequestedName = $null
        Name = "Domain Join"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    $DomainJoinStatus = Get-DomainInfo

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    IF ($Type -eq "AD") {
        IF ($Type -ne $DomainJoinStatus.DomainType) { $Result.Success = $False; $Result.Details = "Domain Type Doesn't Match"; RETURN Return-Results }
        IF (Test-NotNull $Name) {
            IF ($Name -ne $DomainJoinStatus.FQDN) { $Result.Success = $False; $Result.Details = "Name Doesn't Match"; RETURN Return-Results }
        }
        IF ($DomainJoinStatus.DomainJoinHealth -eq "Unhealthy") { $Result.Success = $False; $Result.Details = "Join Status Unhealthy"; RETURN Return-Results }
    }
    IF ($Type -eq "AAD") {
        IF ($Type -ne $DomainJoinStatus.DomainType) { $Result.Success = $False; $Result.Details = "Domain Type Doesn't Match"; RETURN Return-Results }
        IF (Test-NotNull $Name) {
            IF ($Name -ne $DomainJoinStatus.TenantName) { $Result.Success = $False; $Result.Details = "Name Doesn't Match"; RETURN Return-Results }
        }
        IF ($DomainJoinStatus.DomainJoinHealth -eq "Unhealthy") { $Result.Success = $False; $Result.Details = "Join Status Unhealthy"; RETURN Return-Results }
    }
    IF ($Type -eq "Workgroup") {
        IF ($Type -ne $DomainJoinStatus.DomainType) { $Result.Success = $False; $Result.Details = "Domain Type Doesn't Match"; RETURN Return-Results } 
    }

    ### End
    RETURN Return-Results
}
FUNCTION Verify-BitLockerEncryption {
    
    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [STRING[]]$Volume
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Verify"
        Duration = $null
        RequestedName = $null
        Name = "BitLocker Encryption"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }
    
    $BitLockerVolumes = Get-BitLockerVolume

    FOREACH ($Item in $Volume) {
        $Item = $Item.Replace(':','')
        IF ($Item -eq "All") {
            FOREACH ($Item2 in $BitLockerVolumes.EncryptionPercentage) {
                IF ($Item2 -ne 100) { $Result.Success = $False; $Result.Details = "Not All Volumes Encrypted"; RETURN Return-Results }
            }
        }
        ELSE {
            IF (!(Test-NotNull (Get-Volume $Item -ErrorAction SilentlyContinue))) { continue }            
            ELSEIF (($BitLockerVolumes | Where-Object { $_.MountPoint -like "*$Item*" }).EncryptionPercentage -ne 100) {
                $Result.Success = $False; $Result.Details = "$Item Not Encrypted"; RETURN Return-Results
            } 
        }
    }   

    ### End
    RETURN Return-Results
}
FUNCTION Verify-AutomateAgent {
    
    [CmdletBinding()]
    PARAM ( 
        [ValidateSet('Integris','FortWorth','Dallas','Cranbury','Austin')]
        $Server = $null,
        $ClientID = $null,
        $LocationID = $null        
    )

    ### Variables
    $StartTime = (Get-Date)
    $Result = [PSCustomObject]@{
        PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
        Action = "Verify"
        Duration = $null
        RequestedName = $null
        Name = "Automate Agent"
        RequestedVersion = $null
        Version = $null
        Success = $True
        Details = $null
    }

    ### Return Results Function
    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        $ResultColor = $null
        IF ($Result.Success -eq $True) { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification successful. Done." -ForegroundColor Green
        }
        ELSE { 
            Write-Host "$($(Get-Date).ToShortTimeString()): " -NoNewline
            Write-Host "Verification unsuccessful. Done." -ForegroundColor Red
        }

        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result }
        ELSE { RETURN (Convert-IDTResults $Result) }
    }

    IF ((Get-Item 'C:\Windows\LTSvc\LTSVC.exe' -ErrorAction SilentlyContinue)) { } 
    ELSE { $Result.Success = $False; $Result.Details = "Automate Agent Missing"; RETURN Return-Results }

    $AutomateInfo = Get-AutomateAgentConfig

    IF (Test-NotNull $Server) {
        IF ($Server -eq "Integris" -and $AutomateInfo.ServerAddress -like "*https://rmm.integrisit.com*") { }
        ELSEIF ($Server -eq "FortWorth" -and $AutomateInfo.ServerAddress -like "*https://e08295f568071dcd77.outerspaceproxy.com*") { }
        ELSEIF ($Server -eq "Dallas" -and $AutomateInfo.ServerAddress -like "*https://tech.iconicit.com*") { }
        ELSEIF ($Server -eq "Austin" -and $AutomateInfo.ServerAddress -like "*https://labtech.myitpros.com*") { }
        ELSEIF ($Server -eq "Cranbury" -and $AutomateInfo.ServerAddress -like "*https://noc.computerhelpnj.com*") { }
        ELSE { $Result.Success = $False; $Result.Details = "Incorrect Automate Server"; RETURN Return-Results }
    }

    IF (Test-NotNull $ClientID) {
        IF ($ClientID -eq $AutomateInfo.ClientID) { }
        ELSE { $Result.Success = $False; $Result.Details = "Incorrect Client ID"; RETURN Return-Results }
    }

    IF (Test-NotNull $LocationID) {
        IF ($LocationID -eq $AutomateInfo.LocationID) { }
        ELSE { $Result.Success = $False; $Result.Details = "Incorrect Location ID"; RETURN Return-Results }
    }
    
    TRY { 
        [DateTime]$LastCheckInDate = $AutomateInfo.LastCheckIn
        IF (((Get-Date) - $LastCheckInDate).TotalDays -gt 1) { $Result.Success = $False; $Result.Details = "Automate Not Checking In"; RETURN Return-Results }
    }
    CATCH { 
        $Result.Success = $False; $Result.Details = "Automate Not Checked In"; RETURN Return-Results
    }
   

    ### End
    RETURN Return-Results
}


### Completed App Packages
FUNCTION App-7Zip {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "7-Zip*"
        ApplicationVersion          = "24.9.0.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://www.7-zip.org/a/7z2409-x64.msi"      
        FileName                    = "7z2409-x64.msi"              
        BackupDownloadLink          = "https://www.7-zip.org/a/7z2301-x64.msi"
        BackupFileName              = "7z2301-x64.msi"
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 100
        PostInstallDelay            = 5
        PreInstallEndProcess        = "7zFM","7z","7zG"
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\7-Zip\7zFM.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "7zFM","7z","7zG"
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-7Zip-23.1 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "7-Zip*"
        ApplicationVersion          = "23.1.0.0"
        ExactVersion                = $True
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://www.7-zip.org/a/7z2301-x64.msi"      
        FileName                    = "7z2301-x64.msi"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 100
        PostInstallDelay            = 5
        PreInstallEndProcess        = "7zFM","7z","7zG"
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\7-Zip\7zFM.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "7zFM","7z","7zG"
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-AcrobatDC {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Adobe Acrobat*"
        ApplicationVersion          = "25.1.20432"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://trials.adobe.com/AdobeProducts/APRO/Acrobat_HelpX/win32/Acrobat_DC_Web_x64_WWMUI.zip"      
        FileName                    = "Acrobat_DC_Web_x64_WWMUI.zip"           
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "Adobe Acrobat\setup.exe"

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "NoUpdate"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/sAll /rs EULA_ACCEPT=YES"
        InstallTimeout              = 1500
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 300
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
    Set-RegistryValue -Hive HKLM -Path "SOFTWARE\Policies\Adobe\Adobe Acrobat\DC\FeatureLockDown" -Name "bIsSCReducedModeEnforcedEx" -Value "1" -Type DWord | Out-Null
}
FUNCTION App-AdvancedIPScanner {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Advanced IP Scanner*"
        ApplicationVersion          = "2.5.4594.1"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.advanced-ip-scanner.com/download/files/Advanced_IP_Scanner_2.5.4594.1.exe"    
        FileName                    = "Advanced_IP_Scanner_2.5.4594.1.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-"
        InstallTimeout              = 240
        PostInstallDelay            = 5
        PreInstallEndProcess        = "advanced_ip_scanner"
        PostInstallEndProcess       = "advanced_ip_scanner"
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files (x86)\Advanced IP Scanner\advanced_ip_scanner.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "advanced_ip_scanner"
        PostUninstallEndProcess     = "advanced_ip_scanner"
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Famatech Corp., O=Famatech Corp., L=Road Town, C=VG*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-AdvancedPortScanner {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Advanced Port Scanner*"
        ApplicationVersion          = "2.5.3869"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.advanced-port-scanner.com/download/files/Advanced_Port_Scanner_2.5.3869.exe"    
        FileName                    = "Advanced_Port_Scanner_2.5.3869.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-"
        InstallTimeout              = 240
        PostInstallDelay            = 5
        PreInstallEndProcess        = "Advanced_Port_Scanner*"
        PostInstallEndProcess       = "Advanced_Port_Scanner*"
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files (x86)\Advanced Port Scanner\advanced_port_scanner.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "Advanced_Port_Scanner*"
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Famatech Corp., O=Famatech Corp., L=Road Town*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-AutoIT {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = "AutoIT*"
        ApplicationVersion          = "3.3.16.1"
        DownloadLink                = "https://www.autoitscript.com/files/autoit3/autoit-v3-setup.zip"   
        FileName                    = "autoit-v3-setup.zip"
        InstallArguments            = "/S /NORESTART"
        ZipInstallerPath            = "autoit-v3-setup.exe"
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = "C:\Program Files (x86)\AutoIt3\Uninstall.exe"        
        UninstallArguments          = "/S /NORESTART"
        UninstallTimeout            = 180
        InvokeUninstallCommand      = $False
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = $null

        ### Custom Override Parameters
        CustomInstallCommand        = $null     
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = $null
        InstallKeystrokes           = $null                        
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=AutoIt Consulting Ltd, O=AutoIt Consulting Ltd, L=Birmingham, C=GB"
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-AutomateAgent {

    [CmdletBinding()]
    PARAM ( 

        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,


        [String]$ServerAddress,
        [String]$ServerPassword,
        [String]$Location,

        
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    IF ((!(Test-NotNull $ServerAddress) -or !(Test-NotNull $ServerPassword) -or !(Test-NotNull $Location)) -and ($Action -eq "Install" -or $Action -eq "Reinstall")) {
        Write-Warning "Installs require ServerAddress, ServerPassword, and Location."
        RETURN
    }

    IF ($Action -eq "Uninstall" -or $Action -eq "Reinstall") {
        Run-FileDownload -URL "https://s3.amazonaws.com/assets-cp/assets/Agent_Uninstaller.zip" -FileName "Agent_Uninstaller.zip" | Out-Null
        Start-Sleep -Seconds 2
        Expand-Archive -Path "C:\Integris\Temp\Agent_Uninstaller.zip" -DestinationPath "C:\Integris\Temp\Agent_Uninstaller\" -Force
    }
    
    $Parameters  = @{
        #Application Info
        ApplicationName             = "Connectwise Automate Agent"
        ApplicationVersion          = "250.204"
        ExactVersion                = $False
        CustomVersionCommand        = "(Get-AutomateAgentConfig).Version"

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/ER45L271hopPm_Y7wz-gOEUBgINlay4vu11Q2HDZFCspew?download=1"       
        FileName                    = "Agent_Install.msi"             
        BackupDownloadLink          = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/Eee1IKvUBtFPrcvxuro6WeABSPca_0lYpH_d_hANYvQFLQ?download=1"
        BackupFileName              = "Agent_Install.msi"
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "NoUpdate"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/quiet /norestart SERVERADDRESS=$ServerAddress SERVERPASS=$ServerPassword LOCATION=$Location"
        InstallTimeout              = 150
        PostInstallDelay            = 60
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = "IF ((Get-Item 'C:\Windows\LTSvc\LTSVC.exe' -ErrorAction SilentlyContinue)) { RETURN `$True } ELSE { RETURN `$False }"
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Integris\Temp\Agent_Uninstaller\Agent_Uninstall.exe"
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 50
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = "IF ((Get-Item 'C:\Windows\LTSvc\LTSVC.exe' -ErrorAction SilentlyContinue)) { RETURN `$False } ELSE { RETURN `$True }"
                       
        ### Security Specific
        DownloadHash                = "EB0835B77AE70CD79BD7DEFC99E08C517DF1704F641993A103E6D5CA81605E46"
        BackupDownloadHash          = "EB0835B77AE70CD79BD7DEFC99E08C517DF1704F641993A103E6D5CA81605E46"
        CertVerification            = $True
        CertName                    = 'CN="Connectwise, LLC", O="Connectwise, LLC*'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters    
} 
FUNCTION App-BoxDrive {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Box"
        ApplicationVersion          = "2.45.187"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://e3.boxcdn.net/box-installers/desktop/releases/win/Box-x64.msi"    
        FileName                    = "BoxDrive.msi"             
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Box\Box\Box.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = 'CN="Box, Inc.", O="Box, Inc.", L=Redwood City, S=California, C=US'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Chrome {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Google Chrome"
        ApplicationVersion          = "137.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://dl.google.com/dl/chrome/install/googlechromestandaloneenterprise64.msi"     
        FileName                    = "googlechromestandaloneenterprise64.msi"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Google\Chrome\Application\chrome.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Google LLC, O=Google LLC, L=Mountain View, S=California*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-CrystalReportsRuntimex32-13.0.2 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = "SAP Crystal Reports Runtime Engine for .NET Framework 4 (32-bit)"
        ApplicationVersion          = "13.0.2"
        DownloadLink                = "https://elt2.autotitleservice.com/CRRuntime_32bit_13_0_2.msi"  
        FileName                    = "CRRuntime_32bit_13_0_2.msi"
        InstallArguments            = "/QN /NORESTART"  
        ZipInstallerPath            = $null
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = $null        
        UninstallArguments          = $null
        UninstallTimeout            = 180
        InvokeUninstallCommand      = $False
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = $null

        ### Custom Override Parameters
        CustomInstallCommand        = $null     
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = $null
        InstallKeystrokes           = $null                        
                       
        ### Security Specific
        DownloadHash                = "C446FEF0E9DD02F6FB133B0E14BBF1C32FEE6D3EB8FF9F18F266ADCD53109401"
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=SAP AG, OU=SAP BusinessObjects Production, OU=Digital ID Class 3 - Microsoft Software Validation v2,*"
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-CrystalReportsRuntimex64-13.0.2 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = "SAP Crystal Reports Runtime Engine for .NET Framework 4 (64-bit)"
        ApplicationVersion          = "13.0.2"
        DownloadLink                = "https://elt2.autotitleservice.com/CRRuntime_64bit_13_0_2.msi"  
        FileName                    = "CRRuntime_64bit_13_0_2.msi"
        InstallArguments            = "/QN /NORESTART"  
        ZipInstallerPath            = $null
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = $null        
        UninstallArguments          = $null
        UninstallTimeout            = 180
        InvokeUninstallCommand      = $False
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = $null

        ### Custom Override Parameters
        CustomInstallCommand        = $null     
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = $null
        InstallKeystrokes           = $null                        
                       
        ### Security Specific
        DownloadHash                = "562CD2051113F2D22F7A57AD04F8BE56CFAA1EF62F376DAF741121A52CB5D145"
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=SAP AG, OU=SAP BusinessObjects Production, OU=Digital ID Class 3 - Microsoft Software Validation v2,*"
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-CutePDFWriter {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "CutePDF Writer"
        ApplicationVersion          = "4.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://www.cutepdf.com/download/CuteWriter.exe"     
        FileName                    = "CuteWriter.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/SP- /VERYSILENT /SUPPRESSMSGBOXS /NORESTART"
        InstallTimeout              = 75
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files (x86)\CutePDF Writer\unInstcpw64.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/uninstall /s"
        UninstallTimeout            = 45
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "*CN=Acro Software Inc., SERIALNUMBER=05095641, O=Acro Software Inc.,*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-DellCommand {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Dell Command | Update*"
        ApplicationVersion          = "5.5.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://downloads.dell.com/FOLDER12925856M/1/Dell-Command-Update-Application_HW0K4_WIN64_5.5.0_A00.EXE"     
        FileName                    = "Dell-Command-Update-Application_HW0K4_WIN64_5.5.0_A00.EXE"             
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "UninstallReinstall"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/s"
        InstallTimeout              = 180
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Dell Technologies Inc., OU=DUP Client Creation Service, O=Dell Technologies Inc.*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = "Dell.CommandUpdate"
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-DotNetFramework35 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft .Net Framework v3.5"
        ApplicationVersion          = "3.5"
        ExactVersion                = $False
        CustomVersionCommand        = 'IF ((Get-ItemPropertyValue -Path "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5" -Name Install -ErrorAction SilentlyContinue) -eq 1) { "3.5" } ELSE { $($null) }'

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = $null
        FileName                    = $null            
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = "Enable-WindowsOptionalFeature -Online -FeatureName NetFx3 -NoRestart"
        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 1800
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF ((Get-ItemPropertyValue -Path "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5" -Name Install -ErrorAction SilentlyContinue) -eq 1) { $($True) } ELSE { $($False) }'
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "Disable-WindowsOptionalFeature -Online -FeatureName NetFx3 -NoRestart"
        InvokeUninstallCommand      = $True 
        UninstallArguments          = $null
        UninstallTimeout            = 1200
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-DynamsoftService {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Dynamsoft Service"
        ApplicationVersion          = "1.0.516"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/Ec_PLZnp-tpCh_S8NXbd73YBqjQgT7Qebk-qrznqS8MhzA?download=1"     
        FileName                    = "DynamsoftServiceSetup.exe"             
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = $null
        InstallTimeout              = 15
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = 'Send-Keystroke -Title "Dynamsoft Service" -Key "{Enter}","{Enter}","{Enter}","{Enter}","{Enter}" -Delay 5'
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Dropbox {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Dropbox"
        ApplicationVersion          = "221.4.5365"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://www.dropbox.com/download?plat=win&type=full"       
        FileName                    = "DropboxOfflineInstaller.exe"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/NOLAUNCH"
        InstallTimeout              = 360
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files (x86)\Dropbox\Client\Dropbox.exe" 
        RunArguements               = "/home"
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files (x86)\Dropbox\Client\DropboxUninstaller.exe"
        UninstallArguments          = "/InstallType:MACHINE /S"
        UninstallTimeout            = 180
        PostUninstallDelay          = 60
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = 'CN="Dropbox, Inc", O="Dropbox, Inc", L=San Francisco, S=California, C=US'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-DuoAuthenticationForWindowsLogon {
    
    [CmdletBinding()]
    PARAM ( 

        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,

        [Parameter()]
        [string]$IKEY,

        [Parameter()]
        [string]$SKEY,

        [Parameter()]
        [string]$HOSTAPI,

        [Parameter()]
        [SWITCH]$AUTOPUSH = $false,

        [Parameter()]
        [SWITCH]$FAILOPEN = $false,

        [Parameter()]
        [SWITCH]$RDPONLY = $false,

        [Parameter()]
        [SWITCH]$SMARTCARD = $false,

        [Parameter()]
        [SWITCH]$WRAPSMARTCARD = $false,        

        [Parameter()]
        [SWITCH]$ENABLEOFFLINE = $false, 

        [Parameter()]
        [ValidateSet(0,1,2)]
        [int]$USERNAMEFORMAT = 0,        

        [Parameter()]
        [int]$LOGFILE_MAXCOUNT = $null,

        [Parameter()]
        [int]$LOGFILE_MAXSIZEMB = $null,

        [Parameter()]
        [ValidateSet(0,1,2)]
        [int]$UAC_PROTECTMODE = 0,

        [Parameter()]
        [SWITCH]$UAC_OFFLINE = $null,

        [Parameter()]
        [SWITCH]$UAC_OFFLINE_ENROLL = $null,

        [Parameter()]
        [string]$PROXYHOST = $null,

        [Parameter()]
        [ValidateRange(1,65535)]
        [int]$PROXYPORT = $null,

        
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )
    
    IF ($Action -eq "Install" -or $Action -eq "Reinstall") {

        IF (!(Test-NotNull $IKEY) -or !(Test-NotNull $SKEY) -or !(Test-NotNull $HOSTAPI)) {
            Write-Warning "Duo installs require IKEY, SKEY, and HOSTAPI."
            RETURN
        }

        $InstallArguments = "/S /V`"/qn"
        $InstallArguments += " IKEY=`"$IKEY`""
        $InstallArguments += " SKEY=`"$SKEY`""
        $InstallArguments += " HOST=`"$HOSTAPI`""
        IF (Test-NotNull $AUTOPUSH) { $InstallArguments += " AUTOPUSH=`"#1`"" }
        IF (Test-NotNull $FAILOPEN) { $InstallArguments += " FAILOPEN=`"#1`"" }
        IF (Test-NotNull $RDPONLY) { $InstallArguments += " RDPONLY=`"#1`"" }   
        IF (Test-NotNull $SMARTCARD) { $InstallArguments += " SMARTCARD=`"#1`"" }
        IF (Test-NotNull $WRAPSMARTCARD) { $InstallArguments += " WRAPSMARTCARD=`"#1`"" }
        IF (Test-NotNull $ENABLEOFFLINE) { $InstallArguments += " ENABLEOFFLINE=`"#1`"" }
        $InstallArguments += " USERNAMEFORMAT=`"#$USERNAMEFORMAT`"" 
        IF (Test-NotNull $PROXYHOST) { $InstallArguments += " PROXYHOST=`"$PROXYHOST`"" }
        IF (Test-NotNull $LOGFILE_MAXCOUNT) { $InstallArguments += " LOGFILE_MAXCOUNT=`"$LOGFILE_MAXCOUNT`"" }
        IF (Test-NotNull $LOGFILE_MAXSIZEMB) { $InstallArguments += " LOGFILE_MAXSIZEMB=`"$LOGFILE_MAXSIZEMB`"" }
        $InstallArguments += " UAC_PROTECTMODE=`"#$UAC_PROTECTMODE`""
        IF (Test-NotNull $UAC_OFFLINE) { $InstallArguments += " UAC_OFFLINE=`"#1`"" }
        IF (Test-NotNull $UAC_OFFLINE_ENROLL) { $InstallArguments += " UAC_OFFLINE_ENROLL=`"#1`"" }
        $InstallArguments += "`""
    }
    ELSEIF ($Action -eq "Update") {
        $InstallArguments = "/qn /norestart"
    }

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Duo Authentication for Windows Logon*"
        ApplicationVersion          = "5.1.1"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://dl.duosecurity.com/duo-win-login-latest.exe"      
        FileName                    = "duo-win-login-latest.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = $InstallArguments
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Duo Security LLC, O=Duo Security LLC, L=Ann Arbor*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-EpsonOposADK {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "EPSON OPOS ADK"
        ApplicationVersion          = "3.26.0.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EWqnCOLDSFxPoDr1pRKAXIwB8JftMcIUuY-fFf37QpnF5w?Download=1"       
        FileName                    = "EPSON_OPOS_ADK_V3.00ER26.zip"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "EPSON_OPOS_ADK_V3.00ER26.exe"

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/INSTALL /QUIET /NORESTART"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\ProgramData\Package Cache\{98ebde93-e9a2-48a5-8ad2-02956e12ec0f}\EPSON_OPOS_ADK_V3.00ER26.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/UNINSTALL /QUIET /NORESTART"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-FileZillaClient {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "FileZilla*"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EYxOgmJCjCpNluKz5fH_ZZ0BcDYFt7AKsK7BfVvVsJSkdg?download=1"     
        FileName                    = "FileZilla_3.69.1_win64-setup.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/S /user=all"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\FileZilla FTP Client\filezilla.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files\FileZilla FTP Client\uninstall.exe"
        UninstallArguments          = "/S"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Tim Kosse, O=Tim Kosse, S=Nordrhein-Westfalen*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Firefox {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Mozilla Firefox*"
        ApplicationVersion          = "139.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.mozilla.org/?product=firefox-msi-latest-ssl&os=win64&lang=en-US"        
        FileName                    = "FirefoxInstaller.msi"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 240
        PostInstallDelay            = 5
        PreInstallEndProcess        = "FireFox"
        PostInstallEndProcess       = "FireFox"
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Mozilla Firefox\firefox.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files\Mozilla Firefox\uninstall\helper.exe"
        UninstallArguments          = "/S /V"
        UninstallTimeout            = 120
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "Firefox"
        PostUninstallEndProcess     = "Firefox"
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Mozilla Corporation, OU=Firefox Engineering Operations*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = "Mozilla.Firefox"
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-FoxitPDFReader {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Foxit PDF Reader"
        ApplicationVersion          = "2024.4.0.27683"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://www.foxit.com/downloads/latest.html?product=Foxit-Reader&platform=Windows&version=&package_type=&language=English&distID="     
        FileName                    = "FoxitPDFReader20244_enu_Setup_Prom.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/VERYSILENT /NORESTART /MERGETASKS=!desktopicon,!setdefaultreader,!displayinbrowser /COMPONENTS=pdfviewer"
        InstallTimeout              = 240
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files (x86)\Foxit Software\Foxit PDF Reader\FoxitPDFReader.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=FOXIT SOFTWARE INC., O=FOXIT SOFTWARE INC.,*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-GoogleEarth {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Google Earth*"
        ApplicationVersion          = "7.3.6.10201"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://dl.google.com/release2/Earth/euzptyrdafdm4mf4kdtyt2ainq_7.3.6.10201/googleearth-win-pro-7.3.6.10201-x64.exe"      
        FileName                    = "googleearth-win-pro-7.3.6.10201-x64.exe"             
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "OMAHA=1"
        InstallTimeout              = 180
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Google\Google Earth Pro\client\googleearth.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 120
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Google LLC, O=Google LLC, L=Mountain View, S=California, C=US,*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Greenshot {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Greenshot*"
        ApplicationVersion          = "1.2.10.6"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://github.com/greenshot/greenshot/releases/download/Greenshot-RELEASE-1.2.10.6/Greenshot-INSTALLER-1.2.10.6-RELEASE.exe"    
        FileName                    = "Greenshot-Installer.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/VERYSILENT"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Greenshot\Greenshot.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "Greenshot"
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = 'E=getgreenshot@gmail.com, CN="Open Source Developer, Robin Krom", O=Open Source Developer, C=DE'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-iNovahCashier {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "iNovah 2 - Cashier"
        ApplicationVersion          = "2.61.80.196"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EWjubX7xxlRFv0XAOCSRTtcBp6L99ArElW8Idpttt0RHgg?Download=1"  
        FileName                    = "CashierInstall.zip"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "setup.exe"

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/swsurl:http://inovahapps.atm.local/iNovah2System/ /instance:Default"
        InstallTimeout              = 5
        PostInstallDelay            = 2
        PreInstallEndProcess        = "setup"
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = 'Start-Sleep 15;
                                       Send-Keystroke -Title "iNovah 2 - Cashier - InstallShield Wizard" -Key "{Enter}","{Enter}" -Delay 25'

        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files (x86)\InstallShield Installation Information\{689994BA-D700-4F98-A9D7-612F3FC74525}\setup.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "-runfromtemp -l0x0409 -removeonly"
        UninstallTimeout            = 45
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = 'Start-Sleep 15;
                                       Send-Keystroke -Title "iNovah 2 - Cashier - InstallShield Wizard" -Key "{Enter}","{Enter}","{Enter}" -Delay 15'

                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-LAVisitQueue {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = "LA_VisitQueue"
        ApplicationVersion          = "3.0.5.206"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EYGN8BEZVLZPgXEv8dJsrYgBC-6slC2K3Q0GHJ0PojpDMg?Download=1"  
        FileName                    = "LA_VisitQueue206.msi" 
        InstallArguments            = "/QN /NORESTART"
        ZipInstallerPath            = $null
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = $null        
        UninstallArguments          = $null
        UninstallTimeout            = 180
        InvokeUninstallCommand      = $False
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = $null

        ### Custom Override Parameters
        CustomInstallCommand        = $null     
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = $null
        InstallKeystrokes           = $null                        
                       
        ### Security Specific
        DownloadHash                = "CC48837485402F95686D2B73EA8E28C14DBD38190A5E771125885062033DF762"
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Java {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Java 8*"
        ApplicationVersion          = "8.0.4510.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://javadl.oracle.com/webapps/download/AutoDL?xd_co_f=NzMxYmFlZmQtNmUxMy00NTJkLWE2ZjAtYzQ1MDViYTA3YWFl&BundleId=252044_8a1589aa0fe24566b4337beee47c2d29"     
        FileName                    = "jre-8u451-windows-x64.exe"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/s"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = 'CN="Oracle America, Inc.", O="Oracle America, Inc.",*'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-MicroDicomDICOMViewer {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "MicroDicom DICOM Viewer*"
        ApplicationVersion          = "2025.1"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://www.microdicom.com/downloads/Software/MicroDicom-2025.3-x64.exe"       
        FileName                    = "MicroDicom-2025.3-x64.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/S"
        InstallTimeout              = 300
        PostInstallDelay            = 30
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files\MicroDicom\uninstall.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/S"
        UninstallTimeout            = 180
        PostUninstallDelay          = 20
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-MSSQLLocalDB2017 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft SQL Server 2017 LocalDB*"
        ApplicationVersion          = "14.0.100.169"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EWUhbFYCfuBGqDI-HuHclqQBxKTLZBKzs87fdhlnipzsMQ?Download=1"       
        FileName                    = "SqlLocalDB.msi"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART IAcceptSqlLocalDBLicenseTerms=YES"
        InstallTimeout              = 200
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-NetExtender {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [ValidateSet("default","alwayson ","onlyone")]
        [STRING]$Mode = "default",
        [STRING]$Server = $null,
        [STRING]$Domain = $null,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $InstallArguments = "/QN /NORESTART"        
    IF (Test-NotNull $Mode) { $InstallArguments += " MODE=$Mode" }
    IF (Test-NotNull $Server) { $InstallArguments += " SERVER=$Server" }
    IF (Test-NotNull $Domain) { $InstallArguments += " DOMAIN=$Domain" }  

    $Parameters  = @{
        #Application Info
        ApplicationName             = "SonicWall NetExtender"
        ApplicationVersion          = "10.3.2"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://software.sonicwall.com/NetExtender/NetExtender-x64-10.3.2.msi"   
        FileName                    = "NetExtender-x64-10.3.2.msi"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "UninstallReinstall"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = $InstallArguments
        InstallTimeout              = 240
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\SonicWall\SSL-VPN\NetExtender\NetExtender.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=SONICWALL INC., O=SONICWALL INC., S=California, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = "SonicWALL.NetExtender"
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-NordLayer {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]        
        [STRING]$Action,
        [STRING]$Organization = $null,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $InstallArguements = "/QN /NORESTART"
    IF (Test-NotNull $Organization) { $InstallArguements += " ORGANIZATION=$Organization" }

    $Parameters  = @{
        #Application Info
        ApplicationName             = "NordLayer"
        ApplicationVersion          = "3.5.2.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://downloads.nordlayer.com/win/releases/NordLayerSetup_v3.5.2.msi"     
        FileName                    = "NordLayerSetup_v3.5.2.msi"             
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = $InstallArguements
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files (x86)\NordLayer\NordLayer.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "E=admin@nordvpn.com, CN=nordvpn s.a., O=nordvpn s.a.*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = "NordSecurity.NordLayer"
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Office365ProPlusx64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft 365 Apps for Enterprise*"
        ApplicationVersion          = "16.0.18000.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_18129-20030.exe"     
        FileName                    = "officedeploymenttool_18129-20030.exe"           
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = 'Start-Process "C:\Integris\Temp\OfficeDeploymentTool_18129-20030.exe" -ArgumentList "/extract:C:\Integris\Temp\MicrosoftODT /quiet" -WindowStyle Hidden -Wait;
                                       Start-Process "C:\Integris\Temp\MicrosoftODT\setup.exe" -ArgumentList "/configure C:\Integris\Temp\MicrosoftODT\configuration.xml" -WindowStyle Hidden -Wait'

        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 900
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    
    [xml]$XMLString = "<Configuration ID='0c2f1074-0110-4338-bb20-42b0a50edf82'>
  <Info Description='' />
  <Add OfficeClientEdition='64' Channel='Current'>
    <Product ID='O365ProPlusRetail'>
      <Language ID='en-us' />
      <ExcludeApp ID='Access' />
      <ExcludeApp ID='Groove' />
      <ExcludeApp ID='Lync' />
      <ExcludeApp ID='Outlook' />
      <ExcludeApp ID='Publisher' />
      <ExcludeApp ID='Bing' />
    </Product>
  </Add>
  <Property Name='SharedComputerLicensing' Value='0' />
  <Property Name='FORCEAPPSHUTDOWN' Value='FALSE' />
  <Property Name='SCLCacheOverride' Value='0' />
  <Updates Enabled='TRUE' />
  <RemoveMSI>
    <IgnoreProduct ID='InfoPath' />
    <IgnoreProduct ID='InfoPathR' />
    <IgnoreProduct ID='PrjPro' />
    <IgnoreProduct ID='PrjStd' />
    <IgnoreProduct ID='SharePointDesigner' />
    <IgnoreProduct ID='VisPro' />
    <IgnoreProduct ID='VisStd' />
  </RemoveMSI>
  <AppSettings>
    <Setup Name='Company' Value='SharedComputerLicensing' />
    <User Key='software\microsoft\office\16.0\excel\options' Name='defaultformat' Value='51' Type='REG_DWORD' App='excel16' Id='L_SaveExcelfilesas' />
    <User Key='software\microsoft\office\16.0\powerpoint\options' Name='defaultformat' Value='27' Type='REG_DWORD' App='ppt16' Id='L_SavePowerPointfilesas' />
    <User Key='software\microsoft\office\16.0\word\options' Name='defaultformat' Value='' Type='REG_SZ' App='word16' Id='L_SaveWordfilesas' />
  </AppSettings>
</Configuration>"

    New-Item -Name "MicrosoftODT" -Path "C:\Integris\Temp" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
    $XMLString.Save("C:\Integris\Temp\MicrosoftODT\Configuration.xml")

    Run-PackageHandler @Parameters
}
FUNCTION App-OneDrive {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft OneDrive"
        ApplicationVersion          = "25.51.317.3"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://go.microsoft.com/fwlink/?linkid=844652"        
        FileName                    = "OneDriveSetup.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/SILENT /ALLUSERS"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files\Microsoft OneDrive\$((GCI "C:\Program Files\Microsoft OneDrive\" -ErrorAction SilentlyContinue | Where-Object { $_ -like "*.*.*.*" } | Select-Object -First 1).Name)\OneDriveSetup.exe"
        UninstallArguments          = "/uninstall /allusers"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation,*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-OpenVPN {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "OpenVPN*"
        ApplicationVersion          = "3.7.2"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://openvpn.net/downloads/openvpn-connect-v3-windows.msi"      
        FileName                    = "openvpn-connect-3.7.2.4253_signed.msi"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "OpenVPNConnect"
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\OpenVPN Connect\OpenVPNConnect.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "OpenVPNConnect"
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=OpenVPN Inc., O=OpenVPN Inc.*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = "OpenVPNTechnologies.OpenVPN"
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-OracleInstantClient {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Oracle Instant Client"
        ApplicationVersion          = "12.1"
        ExactVersion                = $False
        CustomVersionCommand        = "12.1"

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/ERPwUWuerixPtAgXQKexi7sBxltnOHg0FGS4wKvYxzup3w?Download=1"    
        FileName                    = "instantclient_21_1.zip"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "genezi.exe"

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = 'Expand-Archive -Path "C:\Integris\Temp\instantclient_21_1.zip" -DestinationPath "C:\Oracle\instantclient_12_1\"'
        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 500
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF (((Get-ChildItem -Path "C:\Oracle\instantclient_12_1\" -Recurse -File -ErrorAction SilentlyContinue | Measure-Object -ErrorAction SilentlyContinue -Property Length -Sum).Sum / 1MB) -gt 175) { $True } ELSE { $False }'
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = 'Remove-Item -Path "C:\Oracle\instantclient_12_1\" -Recurse -Force -ErrorAction SilentlyContinue'
        InvokeUninstallCommand      = $True
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = 'IF ((Get-Item -Path "C:\Oracle\instantclient_12_1\" -ErrorAction SilentlyContinue)) { $False } ELSE { $True }'
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-OrionServicesCertificate {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Uninstall","Reinstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Orion Services Certificate"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EeQCKwduFzpHnhQMCdcmWwIBChsKdpEvuQhkG6DuwuwBDQ?Download=1" 
        FileName                    = "OrionServices.zip"                  
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "OrionServices.pfx"

        ### Package Preference
        CleanupMode                 = "Never"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = 'netsh http delete sslcert ipport=0.0.0.0:8443 | out-null;
                                       certutil -p b33t%%JU -importPFX "C:\Integris\Temp\Orion Services Certificate\OrionServices.pfx";
                                       netsh http add sslcert ipport=0.0.0.0:8443 certhash=5850451632562b90747964dc7987caab5a925082 appid="{2DD85661-11A0-471B-9C62-2F465B954B8D}";
                                       Start-Sleep 5'
                                      
        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF (Get-ChildItem -Path Cert:\LocalMachine -Recurse | Where-Object { $_.Issuer -like "*andrewweatherspoon@flhsmv.gov*" -and $_.HasPrivateKey -eq $True }) { $True } ELSE { $False }' 
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = 'Get-ChildItem -Path Cert:\LocalMachine -Recurse | Where-Object { $_.Issuer -like "*andrewweatherspoon@flhsmv.gov*" -and $_.HasPrivateKey -eq $True } | Remove-Item'
        InvokeUninstallCommand      = $True
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 2
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = 'IF (Get-ChildItem -Path Cert:\LocalMachine -Recurse | Where-Object { $_.Issuer -like "*andrewweatherspoon@flhsmv.gov*" -and $_.HasPrivateKey -eq $True }) { $False } ELSE { $True }' 
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-OrionHost {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Orion Version 1.0"
        ApplicationVersion          = "1.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EeQCKwduFzpHnhQMCdcmWwIBChsKdpEvuQhkG6DuwuwBDQ?Download=1"     
        FileName                    = "OrionServices.zip"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "OrionHostSetup-2.0.20.0.exe"

        ### Package Preference
        CleanupMode                 = "Never"
        UpdateMethod                = "UninstallReinstall"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/VERYSILENT /NORESTART"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Drive\Host\unins000.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/VERYSILENT /NORESTART"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-OrionServices {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Orion Services Version 1.0"
        ApplicationVersion          = "1.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EeQCKwduFzpHnhQMCdcmWwIBChsKdpEvuQhkG6DuwuwBDQ?Download=1"      
        FileName                    = "OrionServices.zip"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "OrionServicesSetup-2.0.40.0.exe"

        ### Package Preference
        CleanupMode                 = "Never"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/VERYSILENT /NORESTART"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Drive\WindowsServices\unins000.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/VERYSILENT /NORESTART"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-PrinterLogic {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        [String]$HomeURL,
        [String]$AuthCode,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $HomeURL = $HomeURL.Replace("https://","")
    $HomeURL = $HomeURL.Replace("http://","")

    IF ((!(Test-NotNull $HomeURL) -or !(Test-NotNull $AuthCode)) -and ($Action -eq "Install" -or $Action -eq "Reinstall")) {
        Write-Warning "PrinterLogic installs require HomeURL and AuthCode parameters."
        RETURN
    }

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Printer Installer Client"
        ApplicationVersion          = "25.1.0.1168"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EchnH0bqBRhAsBAyGwBA-0QBjIC7BeN6ZGuxOGQfgnbiLQ?download=1"    
        FileName                    = "PrinterInstallerClient.msi"             
        BackupDownloadLink          = "https://claytonchildcare.printercloud.com/client/setup/PrinterInstallerClient.msi"  
        BackupFileName              = "PrinterInstallerClient.msi"
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = $null
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=PrinterLogic, O=PrinterLogic, L=St. George, S=Utah, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-RevoUninstaller {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Revo*"
        ApplicationVersion          = "1.1.1.1"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://f3b1cfc5d488c0384dc3-056ccca39cd416ca6db85fa26f78b9ef.ssl.cf1.rackcdn.com/revosetup.exe"
        FileName                    = "revosetup.exe"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/VERYSILENT /NORESTART"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\VS Revo Group\Revo Uninstaller\RevoUnin.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=VS REVO GROUP OOD, O=VS REVO GROUP OOD, L=Ruse,*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-RingCentral {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "RingCentral"
        ApplicationVersion          = "25.2.2010.684"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://app.ringcentral.com/download/RingCentral-x64.msi"  
        FileName                    = "RingCentral-x64.msi"             
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 600
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\RingCentral\RingCentral.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = 'CN="RingCentral, Inc.", O="RingCentral, Inc.",*'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-SeaMonkey {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "SeaMonkey*"
        ApplicationVersion          = "2.53.20"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://archive.seamonkey-project.org/releases/2.53.20/win64/en-US/seamonkey-2.53.20.en-US.win64.installer.exe"    
        FileName                    = "seamonkey-2.53.20.en-US.win64.installer.exe"             
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/S"
        InstallTimeout              = 180
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\SeaMonkey\seamonkey.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files\SeaMonkey\uninstall\helper.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/S"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "SeaMonkey"
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=SeaMonkey e.V., O=SeaMonkey e.V., S=Bayern, C=DE"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Slack {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Slack (Machine)"
        ApplicationVersion          = "4.43.52"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://downloads.slack-edge.com/desktop-releases/windows/x64/4.43.52/slack-standalone-4.43.52.0.msi"     
        FileName                    = "Slack-Standalone-4.43.52.0.msi"           
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 180
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Slack\slack.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "MsiExec.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/X {15F7A686-AF58-4605-87A6-27D0299E3B5C} /QN /NORESTART"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = 'CN="Slack Technologies, LLC", O="Slack Technologies, LLC",*'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-TBarcodeActiveX {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "TBarCode ActiveX*"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EX2XSJsSZ_hJkaWFncGdJwQBj3PwCreYNNzA52ElZ6y0Bw?Download=1"      
        FileName                    = "Tbarcode2.1.8.zip"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "setup.exe"

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = $null
        InstallTimeout              = 40
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        InstallKeystrokes           = 'Start-Sleep 10;
                                       Send-Keystroke -Title "Question" -Key "{Enter}" -Delay 4;
                                       Start-Sleep 4;
                                       Send-Keystroke -Title "Software License Agreement" -Key "{Enter}" -Delay 4;
                                       Start-Sleep 4;
                                       Send-Keystroke -Title "Choose Destination Location" -Key "{Enter}" -Delay 8;
                                       Start-Sleep 8;
                                       Send-Keystroke -Title "Setup Complete" -Key "{Enter}" -Delay 4;
                                       Start-Sleep 4;
                                       Send-Keystroke -Title "Information" -Key "{Enter}" -Delay 4'

        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\WINDOWS\IsUninst.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = '-f"C:\Program Files (x86)\TEC-IT Datenverarbeitung GmbH\TBarCode2\Uninst.isu"'
        UninstallTimeout            = 20
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = 'Start-Sleep 10;
                                       Send-Keystroke -Title "Confirm File Deletion" -Key "{Enter}","{Enter}" -Delay 4;
                                       Send-Keystroke -Title "Remove Shared File?" -Key "{Enter}","{Enter}" -Delay 4;
                                       Send-Keystroke -Title "Remove Programs From Your Computer" -Key "{Enter}","{Enter}" -Delay 4'

                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Teams {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Teams"
        ApplicationVersion          = "25000.0.0"
        ExactVersion                = $False
        CustomVersionCommand        = '(Get-AppXPackage "MSTeams" -AllUsers).Version | select -First 1'

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://statics.teams.cdn.office.net/production-teamsprovision/lkg/teamsbootstrapper.exe"       
        FileName                    = "teamsbootstrapper.exe"              
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = '-p -o "C:\Integris\Temp\MSTeams-x64.msix"'
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = "ms-teams"
        PostInstallEndProcess       = "ms-teams"
        CustomInstallVerification   = 'IF (GET-AppXProvisionedPackage -Online | Where-Object { $_.DisplayName -like "MSTeams" }) { $True } ELSE { $False }'
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = 'Get-AppXProvisionedPackage -Online | Where-object { $_.DisplayName -like "*MSTeams*" } | Remove-AppXProvisionedPackage -AllUsers | Out-Null; Get-AppXPackage "*MSTeams*" -AllUsers | Remove-AppXPackage | Out-Null'
        InvokeUninstallCommand      = $True
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "ms-teams"
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = 'IF (GET-AppXProvisionedPackage -Online | Where-Object { $_.DisplayName -like "MSTeams" }) { $False } ELSE { $True }'
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-FileDownload -URL "https://go.microsoft.com/fwlink/?linkid=2196106" -FileName "MSTeams-x64.msix" | Out-Null
    Run-PackageHandler @Parameters
}
FUNCTION App-Thunderbird {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Mozilla Thunderbird*"
        ApplicationVersion          = "137.0.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.mozilla.org/?product=thunderbird-latest&os=win64&lang=en-US"     
        FileName                    = "Thunderbird Setup.exe"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/S"
        InstallTimeout              = 180
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Mozilla Thunderbird\thunderbird.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files\Mozilla Thunderbird\uninstall\helper.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/S /V"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Mozilla Corporation, OU=Firefox Engineering Operations,*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VLCMediaPlayer {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "VLC Media Player"
        ApplicationVersion          = "3.0.21"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.videolan.org/videolan/vlc/3.0.21/win64/vlc-3.0.21-win64.exe" 
        FileName                    = "vlc-3.0.21-win64.exe"               
        BackupDownloadLink          = "https://mirrors.ocf.berkeley.edu/videolan-ftp/vlc/3.0.21/win64/vlc-3.0.21-win64.exe"    
        BackupFileName              = "vlc-3.0.21-win64.exe"
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/L=1031 /S"
        InstallTimeout              = 240
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\VideoLAN\VLC\vlc.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files\VideoLAN\VLC\uninstall.exe"
        UninstallArguments          = "/S"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=VideoLAN, O=VideoLAN, L=Paris, C=FR"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-WatchGuardSSLVPNClient {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [STRING]$Server,
        [STRING]$Username,        
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    IF (Test-NotNull $Server) { SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Server'; 'Type' = 'String'; 'Value' = $Server; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue }
    IF (Test-NotNull $Username) { SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Username'; 'Type' = 'String'; 'Value' = $Username; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue }
    SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'AutoReconnect'; 'Type' = 'DWORD'; 'Value' = 1; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue

    $Parameters  = @{
        #Application Info
        ApplicationName             = "WatchGuard Mobile VPN*"
        ApplicationVersion          = "12.11.2"
        ExactVersion                = $False
        CustomVersionCommand        = $null
        
        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://cdn.watchguard.com/SoftwareCenter/Files/MUVPN_SSL/12_11_2/WG-MVPN-SSL_12_11_2.exe"
        FileName                    = "WG-MVPN-SSL_12_11_2.exe"          
        BackupDownloadLink          = "https://cdn.watchguard.com/SoftwareCenter/Files/MUVPN_SSL/12_11/WG-MVPN-SSL_12_11.exe"
        BackupFileName              = "WG-MVPN-SSL_12_11.exe"
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/silent /verysilent /Components=main,tapdriver /tasks=desktopicon /norestart"
        InstallTimeout              = 420
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files (x86)\WatchGuard\WatchGuard Mobile VPN with SSL\wgsslvpnc.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files (x86)\WatchGuard\WatchGuard Mobile VPN with SSL\unins000.exe"
        UninstallArguments          = "/silent /verysilent /norestart"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = "wgsslvpnc","wgsslvpnsrc"
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=WatchGuard Technologies, O=WatchGuard Technologies, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters

    IF (Test-NotNull $Server) { SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Server'; 'Type' = 'String'; 'Value' = $Server; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue }
    IF (Test-NotNull $Username) { SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'Username'; 'Type' = 'String'; 'Value' = $Username; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue }
    SET-RegistryValueForAllUsers -RegistryInstance @{'Name' = 'AutoReconnect'; 'Type' = 'DWORD'; 'Value' = 1; 'Path' = 'SOFTWARE\WatchGuard\SSLVPNClient\Settings'} -ErrorAction SilentlyContinue

}
FUNCTION App-WinSCP {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "WinSCP*"
        ApplicationVersion          = "6.5.1"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EW5kplpD2lVPuL4NKa5IKXQB0J7oObgoZCwYD8e2G4a2Qw?download=1"
        FileName                    = "WinSCP-6.5.1-Setup.exe"             
        BackupDownloadLink          = $null
        BackupFileName              = $null  
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/VERYSILENT /ALLUSERS /NORESTART"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files (x86)\WinSCP\WinSCP.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = "A54ECA431FDFBBF489805D995C1EBEAF7FF5A4E5AD825CC529F1B0F7525815AB"
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Martin Prikryl, O=Martin Prikryl, L=Prague*"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = "WinSCP.WinSCP"
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-NotePad++ {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Notepad++*"
        ApplicationVersion          = "8.7.1"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v8.7.1/npp.8.7.1.Installer.x64.exe"      
        FileName                    = "npp.8.7.1.Installer.x64.exe"               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "UninstallReinstall"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/S"
        InstallTimeout              = 180
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files\Notepad++\notepad++.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = 'CN="Notepad++", O="Notepad++",*'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-ScreenConnectClient {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "ScreenConnect Client*"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = $null       
        FileName                    = $null               
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = $null
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2005Redistributablex86 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2005 Redistributable"
        ApplicationVersion          = "8.0.61001"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/8/b/4/8b42259f-5d70-43f4-ac2e-4b208fd8d66a/vcredist_x86.EXE"      
        FileName                    = "vcredist_x86.EXE"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x86"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2005Redistributablex64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2005 Redistributable (x64)"
        ApplicationVersion          = "8.0.61000"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/8/b/4/8b42259f-5d70-43f4-ac2e-4b208fd8d66a/vcredist_x64.EXE"      
        FileName                    = "vcredist_x64.EXE"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x64"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2008Redistributablex86 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2008 Redistributable - x86*"
        ApplicationVersion          = "9.0.30729.6161"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/5/d/8/5d8c65cb-c849-4025-8e95-c3966cafd8ae/vcredist_x86.exe"      
        FileName                    = "vcredist_x86.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x86"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2008Redistributablex64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2008 Redistributable - x64*"
        ApplicationVersion          = "9.0.30729.6161"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/5/d/8/5d8c65cb-c849-4025-8e95-c3966cafd8ae/vcredist_x64.exe"      
        FileName                    = "vcredist_x64.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x64"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2010Redistributablex86 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2010 x86 Redistributable*"
        ApplicationVersion          = "10.0.40219"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe"      
        FileName                    = "vcredist_x86.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x86"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2010Redistributablex64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2010 x64 Redistributable*"
        ApplicationVersion          = "10.0.40219"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x64.exe"      
        FileName                    = "vcredist_x64.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x64"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2012Redistributablex86 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2012 Redistributable (x86)*"
        ApplicationVersion          = "11.0.61030.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe"      
        FileName                    = "vcredist_x86.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x86"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2012Redistributablex64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2012 Redistributable (x64)*"
        ApplicationVersion          = "11.0.61030.0"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe"      
        FileName                    = "vcredist_x64.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x64"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2013Redistributablex86 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2013 Redistributable (x86)*"
        ApplicationVersion          = "10.0.40219.325"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://aka.ms/highdpimfc2013x86enu"      
        FileName                    = "vcredist_x86.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x86"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++2013Redistributablex64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2013 Redistributable (x64)*"
        ApplicationVersion          = "10.0.40219.325"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://aka.ms/highdpimfc2013x64enu"      
        FileName                    = "vcredist_x64.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x64"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-VisualC++20152022Redistributablex86 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2015-2022 Redistributable (x86)*"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://aka.ms/vs/17/release/vc_redist.x86.exe"     
        FileName                    = "VC_redist.x86.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x86"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\ProgramData\Package Cache\{46c3b171-c15c-4137-8e1d-67eeb2985b44}\VC_redist.x86.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/uninstall /Q"
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
} 
FUNCTION App-VisualC++20152022Redistributablex64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Microsoft Visual C++ 2015-2022 Redistributable (x64)*"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://aka.ms/vs/17/release/vc_redist.x64.exe"     
        FileName                    = "VC_redist.x64.exe"          
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "Always"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InvokeInstallCommand        = $null
        InstallArguments            = "/Q"
        InstallTimeout              = 120
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = "vcredist_x64"
        CustomInstallVerification   = $null
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\ProgramData\Package Cache\{9387bec2-2f2b-48d1-a0ce-692c5df7042d}\VC_redist.x64.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/uninstall /Q"
        UninstallTimeout            = 90
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-Zoom {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "*Zoom*"
        ApplicationVersion          = "6.4.63669"
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://zoom.us/client/6.4.3.63669/ZoomInstallerFull.msi"     
        FileName                    = "ZoomInstallerFull.msi"            
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/QN /NORESTART"
        InstallTimeout              = 200
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = $null
        
        ### Run Specific
        RunPath                     = "C:\Program Files (x86)\Zoom\bin\Zoom.exe"
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = 'CN="Zoom Video Communications, Inc.", O="Zoom Video Communications, Inc.",*'
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}


### Font Packages
FUNCTION Font-ArialRoundedMTBoldTall {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Arial_Rounded_MT_Bold_Tall (Font)"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EdIuTpNomI5DnZ2pE1eKEdEB0qjt1jqrRKMhHwBA1IUcMQ?Download=1"    
        FileName                    = "Arial_Rounded_MT_Bold_Tall.ttf"           
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = "Install-Font 'C:\Integris\Temp\Arial_Rounded_MT_Bold_Tall.ttf'"
        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 15
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF (Test-FontInstalled "Arial_Rounded_MT_Bold_Tall") { $True } ELSE { $False }'
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 15
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION Font-AlphaTypeMS {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Alpha Type MS Regular (Font)"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/ETlNd-At4XRHrBJev-LutwkBnK-bQwAfPxKtuCzEz_-m-Q?Download=1"    
        FileName                    = "Florida Alpha MS.ttf"           
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = "Install-Font 'C:\Integris\Temp\Florida Alpha MS.ttf'"
        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 15
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF (Test-FontInstalled "Florida Alpha MS") { $True } ELSE { $False }'
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 15
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION Font-FloridaVehicleFont {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Personalized Plate Font (Font)"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EbWxqP-kXexOuOTUM1Fm09oBiLJlWfd4Tp9yZd-85CAnnw?Download=1"    
        FileName                    = "Personalized Plate Font.ttf"           
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = "Install-Font 'C:\Integris\Temp\Personalized Plate Font.ttf'"
        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 15
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF (Test-FontInstalled "Personalized Plate Font") { $True } ELSE { $False }'
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 15
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION Font-Swis721CnBT {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Swiss 721 Bold Condensed BT (Font)"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/ETL4iJ88AJ5OqaODKqTYh2EBvOFTquzn2Wp6Ra__fvejeg?Download=1"    
        FileName                    = "Swiss 721 Bold Condensed BT.ttf"           
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = "Install-Font 'C:\Integris\Temp\Swiss 721 Bold Condensed BT.ttf'"
        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 15
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF (Test-FontInstalled "Swiss 721 Bold Condensed BT") { $True } ELSE { $False }'
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 15
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION Font-Swiss911UCmBT {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Swiss 911 Ultra Compressed BT (Font)"
        ApplicationVersion          = $null
        ExactVersion                = $False
        CustomVersionCommand        = $null

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://integristech-my.sharepoint.com/:u:/g/personal/david_mcvicker_integrisit_com/EcXIKM0EM0BNpPSkEWrATgsB2DY2cYeuCm7vMdd_ZWNGDQ?Download=1"    
        FileName                    = "Swiss 911 Ultra Compressed BT.ttf"           
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = $null

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = "Install-Font 'C:\Integris\Temp\Swiss 911 Ultra Compressed BT.ttf'"
        InvokeInstallCommand        = $True
        InstallArguments            = $null
        InstallTimeout              = 15
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF (Test-FontInstalled "Swiss 911 Ultra Compressed BT") { $True } ELSE { $False }'
        InstallKeystrokes           = $null
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 15
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
        UninstallKeystrokes         = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}


### Driver Packages
FUNCTION Driver-DS530II {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Download")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        #Application Info
        ApplicationName             = "Epson DS-530 II Driver"
        ApplicationVersion          = "1.1.0.0"
        ExactVersion                = $False
        CustomVersionCommand        = '(((& "pnputil.exe" /enum-drivers | Out-String).Replace("Published Name:","@Published Name:")).Split("@") | Where-Object { $_ -like "*ES0232.inf*" }) -match "\d+(\.\d+)+" | Out-null; RETURN $Matches[0]'

        #Download Info
        SavePath                    = "C:\Integris\Temp"
        DownloadLink                = "https://ftp.epson.com/drivers/DS530II_EScan2_67820_AM.exe"    
        FileName                    = "DS530II_EScan2_67820_AM.zip"        
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ZipInstallerPath            = "setup.exe"

        ### Package Preference
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        ForceDownload               = $False
        
        ### Install Specific
        CustomInstallCommand        = $null
        InstallArguments            = "/SI -sms /Nodisp"
        InstallTimeout              = 300
        PostInstallDelay            = 5
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        CustomInstallVerification   = 'IF ((((& "pnputil.exe" /enum-drivers | Out-String).Replace("Published Name:","@Published Name:")).Split("@") | Where-Object { $_ -like "*ES0232.inf*" })) { $True } ELSE { $False }'
        
        ### Run Specific
        RunPath                     = $null
        RunArguements               = $null
         
        ### Uninstall Specific
        UninstallCommand            = "C:\Program Files (x86)\epson\escndv\setup\setup.exe"
        InvokeUninstallCommand      = $False
        UninstallArguments          = "/r -sms /Nodisp"
        UninstallTimeout            = 180
        PostUninstallDelay          = 10
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        CustomUninstallVerification = $null
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False
        
        ### WinGet Specific
        WinGetAppName               = $null
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}


### Packages in Progress
FUNCTION App-Office365ProPlusx64_Old {
    
    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory)]
        [ValidateSet("Install")]
        [STRING]$Action
    )

    $StartTime = (Get-Date)

    $Result = @()

    FUNCTION Return-Results {
        $Result.Duration = (Get-TimeDifferenceToString $StartTime)
        IF ((Get-PSCallStack).Command -like "*DeploymentSet*") { RETURN $Result | Select Action, Duration, RequestedName, Name, RequestedVersion, Version, Success, Details }
        ELSE { RETURN $Result | Select Action, Duration, Name, Version, Success, Details }
    }

    IF ($Action -eq "Uninstall" -or $Action -eq "Reinstall") {



    }
    IF ($Action -eq "Install" -or $Action -eq "Reinstall") {
    $InstallCheck = $null
    $InstallCheck = (Get-ApplicationInstalled | Where-Object { $_.Name -eq "Microsoft 365 Apps for Enterprise - en-us" })

    IF ($InstallCheck -ne $null) {

        Write-Verbose "$($(Get-Date).ToShortTimeString()): Already Installed. Done."

        $Result = [PSCustomObject]@{  
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'          
            Action = "Install"
            Duration = $null
            RequestedName = $null
            Name = "Microsoft 365 Apps for Enterprise - en-us"
            RequestedVersion = $null
            Version = [VERSION](Get-ApplicationInstalled | Where-Object { $_.Name -eq "Microsoft 365 Apps for Enterprise - en-us" }).Version
            Success = $True
            Details = "Already Installed"
        }

        RETURN Return-Results
    }

    $DownloadUrl = "https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_18129-20030.exe"
    IF ((GET-Item "C:\Integris\Temp" -ErrorAction SilentlyContinue | Out-Null) -eq $null) { New-Item -Name "Temp" -Path "C:\Integris" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null }
    Invoke-WebRequest -Uri $DownloadUrl -OutFile "C:\Integris\Temp\OfficeDeploymentTool_18129-20030.exe" -UseBasicParsing

    [xml]$XMLString = "<Configuration ID='0c2f1074-0110-4338-bb20-42b0a50edf82'>
  <Info Description='' />
  <Add OfficeClientEdition='64' Channel='Current'>
    <Product ID='O365ProPlusRetail'>
      <Language ID='en-us' />
      <ExcludeApp ID='Access' />
      <ExcludeApp ID='Groove' />
      <ExcludeApp ID='Lync' />
      <ExcludeApp ID='Outlook' />
      <ExcludeApp ID='Publisher' />
      <ExcludeApp ID='Bing' />
    </Product>
  </Add>
  <Property Name='SharedComputerLicensing' Value='0' />
  <Property Name='FORCEAPPSHUTDOWN' Value='FALSE' />
  <Property Name='SCLCacheOverride' Value='0' />
  <Updates Enabled='TRUE' />
  <RemoveMSI>
    <IgnoreProduct ID='InfoPath' />
    <IgnoreProduct ID='InfoPathR' />
    <IgnoreProduct ID='PrjPro' />
    <IgnoreProduct ID='PrjStd' />
    <IgnoreProduct ID='SharePointDesigner' />
    <IgnoreProduct ID='VisPro' />
    <IgnoreProduct ID='VisStd' />
  </RemoveMSI>
  <AppSettings>
    <Setup Name='Company' Value='SharedComputerLicensing' />
    <User Key='software\microsoft\office\16.0\excel\options' Name='defaultformat' Value='51' Type='REG_DWORD' App='excel16' Id='L_SaveExcelfilesas' />
    <User Key='software\microsoft\office\16.0\powerpoint\options' Name='defaultformat' Value='27' Type='REG_DWORD' App='ppt16' Id='L_SavePowerPointfilesas' />
    <User Key='software\microsoft\office\16.0\word\options' Name='defaultformat' Value='' Type='REG_SZ' App='word16' Id='L_SaveWordfilesas' />
  </AppSettings>
</Configuration>"


    New-Item -Name "MicrosoftODT" -Path "C:\Integris\Temp" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
    Start-Process "C:\Integris\Temp\OfficeDeploymentTool_18129-20030.exe" -ArgumentList "/extract:C:\Integris\Temp\MicrosoftODT /quiet" -Wait
    $XMLString.Save("C:\Integris\Temp\MicrosoftODT\Configuration.xml")
 
    & "C:\Integris\Temp\MicrosoftODT\setup.exe" /configure C:\Integris\Temp\MicrosoftODT\configuration.xml

    $InstallCheck = $null
    $InstallCheck = (Get-ApplicationInstalled | Where-Object { $_.Name -eq "Microsoft 365 Apps for Enterprise - en-us" })

    $Duration = $(((Get-Date) - $StartTime))
    IF ($Duration.Hours -gt 0) { $Duration = $(((Get-Date) - $StartTime).ToString("h\:m\:ss")) }
    ELSE { $Duration = $(((Get-Date) - $StartTime).ToString("m\:ss")) }

    get-process OfficeC2RClient | Stop-Process -Force 

    IF ($InstallCheck -eq $null) {
        $Result = [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Install"
            Duration = $null
            RequestedName = $null
            Name = "Microsoft 365 Apps for Enterprise - en-us"
            RequestedVersion = $null
            Version = $null
            Success = $False
            Details = "Application Failed to Install"
        }
    }
    ELSE {
        $Result = [PSCustomObject]@{
            PSTypeName = 'IntegrisDeploymentTool.IDTResultsExtended'
            Action = "Install"
            Duration = $null
            RequestedName = $null
            Name = "Microsoft 365 Apps for Enterprise - en-us"
            RequestedVersion = $null
            Version = [VERSION](Get-ApplicationInstalled | Where-Object { $_.Name -eq "Microsoft 365 Apps for Enterprise - en-us" }).Version
            Success = $True
            Details = $null
        }
    }
}

    RETURN Return-Results
}
FUNCTION App-OMVInterfaceCompanion_Old {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = "OMV Interface Companion"
        ApplicationVersion          = "1.1.0.8"
        DownloadLink                = $null   
        FileName                    = $null 
        InstallArguments            = "https://omvapp.expressomv.com/ExpressOMV.application" 
        ZipInstallerPath            = $null
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = $null
        InvokeUninstallCommand      = $False
        UninstallArguments          = $null
        UninstallTimeout            = 180
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = "ExpressOMV"
        PostInstallEndProcess       = "ExpressOMV"
        PreUninstallEndProcess      = "ExpressOMV"
        PostUninstallEndProcess     = "ExpressOMV"
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = 'Send-Keystroke -Title "Untitled" -Key "{Tab}","{Tab}","{Enter}" -Delay 2; Start-Sleep 6;
                                       Send-Keystroke -Title "Application Install - Security Warning" -Key "{Tab}","{Tab}","{Enter}" -Delay 2; Start-Sleep 45'


        ### Custom Override Parameters
        CustomInstallCommand        = "C:\Program Files\Internet Explorer\iexplore.exe"    
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = $null
        InstallKeystrokes           = $null                
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-UTS {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Run","Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = "*UTS*"
        ApplicationVersion          = $null
        DownloadLink                = "https://url.avanan.click/v2/r01/___http:/kmsys.kmsys.com/products/Releases/UTSeXpress5WithCryptoSetup5.0.101.zip___.YXAzOmF1dG90YWdhZ2VuY3k6YTpvOjVhYTg2OGNiODM5YjQwYjVmZDhlNWQ2MWU3YWRmYmI5Ojc6MWQ0MjpiMzE5N2E0OGVkZGI1MzA4ZTkwYzRmNWU2OWFkODg1ZjJjMjUxNTQ5OWY1Mzk1NTA2MmViNTRjYjU1NTAyNDMyOmg6VDpO"   
        FileName                    = "UTSeXpress5WithCryptoSetup5.0.101.zip"
        InstallArguments            = $null  
        ZipInstallerPath            = "UTSeXpress5WithCryptoSetup.exe"
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = $null        
        UninstallArguments          = $null
        UninstallTimeout            = 180
        InvokeUninstallCommand      = $False
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = $null

        ### Custom Override Parameters
        CustomInstallCommand        = $null     
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = $null
        InstallKeystrokes           = $null                        
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $False
        CertName                    = $null
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-WindowsDesktopRuntimeV8x64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    #$DownloadPage = "https://dotnet.microsoft.com$($(((Invoke-WebRequest -Uri "https://dotnet.microsoft.com/en-us/download/dotnet/9.0").Links) | Where-Object { $_.outerHTML -like "*runtime-desktop-*" } | Select-Object -First 1).href)"
    #$DownloadLink = ((Invoke-WebRequest -Uri $DownloadPage).Links | Where-Object { $_.outerHTML -like "*Direct link*" }).href
    #$FileName = $DownloadLink -split '/' | Select-Object -Last 1

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = "Microsoft Windows Desktop Runtime - 8*(x64)*"
        ApplicationVersion          = "8.0.17"
        DownloadLink                = "https://builds.dotnet.microsoft.com/dotnet/WindowsDesktop/8.0.17/windowsdesktop-runtime-8.0.17-win-x64.exe" 
        FileName                    = "windowsdesktop-runtime-8.0.17-win-x64.exe"
        InstallArguments            = "/install /quiet /norestart"  
        ZipInstallerPath            = $null
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = $null        
        UninstallArguments          = "/install /quiet /norestart"
        UninstallTimeout            = 180
        InvokeUninstallCommand      = $False
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = $null
        BackupFileName              = $null
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = $null

        ### Custom Override Parameters
        CustomInstallCommand        = $null     
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = '(Get-ApplicationInstalled "Microsoft Windows Desktop Runtime - 8*(x64)*" | Select-Object -First 1).Version'
        InstallKeystrokes           = $null                        
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=.NET, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}
FUNCTION App-WindowsDesktopRuntimeV9x64 {

    [CmdletBinding()]
    PARAM ( 
        [Parameter(Mandatory)]
        [ValidateSet("Install","Update","Download","Reinstall","Uninstall")]
        [STRING]$Action,
        [SWITCH]$VerifyOnly,
        ### Smart Features Specific
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$IncludeDeviceType = $null,
        [ValidateSet("Desktop","Laptop","Server")]
        [STRING[]]$ExcludeDeviceType = $null,
        [STRING[]]$IncludeHostname = $null,
        [STRING[]]$ExcludeHostname = $null,
        [STRING[]]$IncludeDN = $null,
        [STRING[]]$ExcludeDN = $null,
        [STRING[]]$IncludeADSite = $null,
        [STRING[]]$ExcludeADSite = $null,
        [STRING[]]$IncludeIPAddress = $null,
        [STRING[]]$ExcludeIPAddress = $null,
        [STRING[]]$IncludeGeoLocation = $null,
        [STRING[]]$ExcludeGeoLocation = $null
    )

    $DownloadPage = "https://dotnet.microsoft.com$($(((Invoke-WebRequest -Uri "https://dotnet.microsoft.com/en-us/download/dotnet/9.0").Links) | Where-Object { $_.outerHTML -like "*runtime-desktop-*" } | Select-Object -First 1).href)"
    $DownloadLink = ((Invoke-WebRequest -Uri $DownloadPage).Links | Where-Object { $_.outerHTML -like "*Direct link*" }).href
    $FileName = $DownloadLink -split '/' | Select-Object -Last 1

    $Parameters  = @{
        ### Most Common Parameters
        ApplicationName             = "Microsoft Windows Desktop Runtime - 9*(x64)*"
        ApplicationVersion          = "9.0.6"
        DownloadLink                = $DownloadLink   
        FileName                    = $FileName
        InstallArguments            = "/install /quiet /norestart"  
        ZipInstallerPath            = $null
        InstallTimeout              = 300

        ### For Uninstall Action
        UninstallCommand            = "C:\ProgramData\Package Cache\{e171d1ec-6909-4d1f-982d-03226d7f7fbe}\windowsdesktop-runtime-9.0.6-win-x64.exe"       
        UninstallArguments          = "/uninstall /quiet /norestart"
        UninstallTimeout            = 180
        InvokeUninstallCommand      = $False
        
        ### Secondary Parameters
        ExactVersion                = $False
        CleanupMode                 = "AfterSuccess"
        UpdateMethod                = "InstallOver"
        BackupDownloadLink          = "https://builds.dotnet.microsoft.com/dotnet/WindowsDesktop/9.0.6/windowsdesktop-runtime-9.0.6-win-x64.exe"
        BackupFileName              = "windowsdesktop-runtime-9.0.6-win-x64.exe"
        ForceDownload               = $False        

        ### For Run Action
        RunPath                     = $null
        RunArguements               = $null

        ### Less Common Parameters
        PreInstallEndProcess        = $null
        PostInstallEndProcess       = $null
        PreUninstallEndProcess      = $null
        PostUninstallEndProcess     = $null
        PostInstallDelay            = 5
        PostUninstallDelay          = 10
        UninstallKeystrokes         = $null

        ### Custom Override Parameters
        CustomInstallCommand        = $null     
        InvokeInstallCommand        = $null            
        CustomInstallVerification   = $null
        CustomUninstallVerification = $null
        CustomVersionCommand        = '(Get-ApplicationInstalled "Microsoft Windows Desktop Runtime - 9*(x64)*" | Select-Object -First 1).Version'
        InstallKeystrokes           = $null                        
                       
        ### Security Specific
        DownloadHash                = $null
        BackupDownloadHash          = $null
        CertVerification            = $True
        CertName                    = "CN=.NET, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
        VirusTotal                  = $False

        ### Shouldn't Need Changed
        SavePath                    = "C:\Integris\Temp"
        
        ### WinGet Specific
        WinGetAppName               = $null        
        
        ### Options Used at Runtime
        Action                      = $Action
        VerifyOnly                  = $VerifyOnly
        IncludeDeviceType           = $IncludeDeviceType
        ExcludeDeviceType           = $ExcludeDeviceType
        IncludeHostname             = $IncludeHostname
        ExcludeHostname             = $ExcludeHostname
        IncludeDN                   = $IncludeDN
        ExcludeDN                   = $ExcludeDN
        IncludeADSite               = $IncludeADSite
        ExcludeADSite               = $ExcludeADSite
        IncludeIPAddress            = $IncludeIPAddress
        ExcludeIPAddress            = $ExcludeIPAddress
        IncludeGeoLocation          = $IncludeGeoLocation
        ExcludeGeoLocation          = $ExcludeGeoLocation
    }
    Run-PackageHandler @Parameters
}


### Test Deployment
<#--
 
 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Find-PackageProvider -Name NuGet -ErrorAction SilentlyContinue -Force | Install-PackageProvider -Force | Out-Null
Register-PackageSource -Provider NuGet -Name nugetRepository -Location https://www.nuget.org/api/v2 -Force | Out-Null
Install-Module IntegrisDeploymentTool -AllowClobber -Force
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force
 
 
Run-DeploymentSet "App-MSSQLLocalDB2017 Install",
                  "App-7Zip Install",
                  "App-Teams Install",
                  "App-Chrome Install",
                  "App-Greenshot Install",
                  "App-Firefox Install",
                  "App-Java Install",
                  "Font-ArialRoundedMTBoldTall Install",
                  "Font-AlphaTypeMS Install",
                  "Font-FloridaVehicleFont Install",
                  "Font-Swis721CnBT Install",
                  "Font-Swiss911UCmBT Install",
                  "App-VisualC++2005Redistributablex86 Install",
                  "App-VisualC++2005Redistributablex64 Install",
                  "App-VisualC++20152022Redistributablex86 Install",
                  "App-VisualC++20152022Redistributablex64 Install",
                  "Driver-DS530II Install",
                  "App-AcrobatDC Install",
                  "App-NotePad++ Install",
                  "App-OneDrive Install",
                  "App-TBarcodeActiveX Install",
                  "App-Slack Install",
                  "App-DynamsoftService Install",
                  "App-Office365ProPlusx64 Install",
                  "App-EpsonOposADK Install" -RestartWhenComplete | FT
 
--#>