├── .gitignore ├── .vscode └── settings.json ├── Bitlocker-ForceLock.ps1 ├── Bitlocker_Deploy and Backup Key.ps1 ├── Bitlocker_RetrieveKeys.ps1 ├── BleachBit-DiskCleanup.ps1 ├── CustomerCustomField(Update).ps1 ├── DNSFilters_Comparison.ps1 ├── DNSFilters_Comparison.sh ├── DNSFilters_multi.sh ├── DeleteBitDefenderSetupDownloader.ps1 ├── Deploy_CyberCNS.ps1 ├── DisableWeatherAndNews.ps1 ├── FixSyncroChocoPath.ps1 ├── Get-InstalledAV.ps1 ├── Get-MonitorInfo.ps1 ├── Get-SyncroVars.ps1 ├── Import-SyncroModule.ps1 ├── LICENSE ├── LogPolicy.ps1 ├── Monitor Syncro env vars.ps1 ├── MonitorHostFile.ps1 ├── New-DummyFile.ps1 ├── PrintNightmare-RegFix.ps1 ├── README.md ├── Re-enable WindowsUpdate Registry.ps1 ├── Remove_butil_2_3.sys.ps1 ├── Set-PowerPlan.ps1 ├── SmartMonitoring.ps1 ├── Syncro - Force Full-Large sync.ps1 ├── Syncro API - Customer Custom field.ps1 ├── Test-PendingReboot.ps1 ├── Uninstall Threatlocker.cmd ├── Uninstall-CyberCNS.ps1 ├── Uninstall-Webroot.ps1 ├── UninstallExample.ps1 ├── Upgrade Windows 10 with Enablement Pac.ps1 ├── Windows11CompatibilityCheck.ps1 ├── Write-AVTestFile.ps1 ├── alert or set custom field.ps1 ├── disableActiveX_CVE-2021-40444.cmd ├── disableActiveX_CVE-2021-40444.ps1 ├── enableActiveX_CVE-2021-40444.cmd ├── nable_Cleanup.ps1 └── winget-as-system.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.autofetch": true, 3 | "files.eol": "\r\n", 4 | "files.insertFinalNewline": true, 5 | "files.trimFinalNewlines": true, 6 | "files.trimTrailingWhitespace": true 7 | } -------------------------------------------------------------------------------- /Bitlocker-ForceLock.ps1: -------------------------------------------------------------------------------- 1 | try{ 2 | # Get Bitlocker Volumes or exit. 3 | $BitLockerVolume = Get-BitLockerVolume -ErrorAction stop 4 | 5 | } catch [System.Management.ManagementException] { 6 | "Bitlocker Not Detected" 7 | exit 1 8 | } catch [System.Management.Automation.CommandNotFoundException] { 9 | "Bitlocker Not Detected" 10 | exit 1 11 | } catch { 12 | "Unexpected Error" 13 | (($Error[0] | Select-Object -Property Exception | Out-String).trim() -split '\r')[-1] 14 | } 15 | 16 | foreach ($MountPoint in ($BitLockerVolume | Select-Object -ExpandProperty MountPoint -Unique)) { 17 | # Wipe existing BitLocker protections 18 | Invoke-Command {manage-bde -protectors -delete $MountPoint} 19 | # Create new, randomly generated recovery password 20 | Invoke-Command {manage-bde -protectors -add $MountPoint -RecoveryPassword} 21 | # Verify new recovery password will be required on next reboot 22 | Invoke-Command {manage-bde -protectors -enable $MountPoint} 23 | } 24 | 25 | $Report = Get-BitLockerVolume | 26 | ForEach-Object { 27 | $MountPoint = $_.MountPoint 28 | $_.KeyProtector | Where-Object {$_.RecoveryPassword -notmatch '^\s$' -and $_.RecoveryPassword.Length -gt 5} | 29 | ForEach-Object { 30 | Write-Output "$MountPoint Id:$($_.KeyProtectorId), key:$($_.RecoveryPassword)" 31 | } 32 | } | Out-String 33 | 34 | if ($Report.Length -ge 56){ 35 | $Report 36 | if ($env:SyncroModule){ 37 | Import-Module $env:SyncroModule -WarningAction SilentlyContinue 38 | Set-Asset-Field -Name "Bitlocker Drives" -Value $Report 39 | } 40 | } 41 | 42 | foreach ($MountPoint in (Get-BitLockerVolume | Select-Object -ExpandProperty MountPoint -Unique)) { 43 | # Force the user to be prompted for new recovery password 44 | Invoke-Command {manage-bde -forcerecovery $MountPoint} 45 | } 46 | shutdown -s -t 0 -f 47 | -------------------------------------------------------------------------------- /Bitlocker_Deploy and Backup Key.ps1: -------------------------------------------------------------------------------- 1 | # Copied from Pastebin 2 | # https://pastebin.com/M8WrgsZd?fbclid=IwAR3lt2oyPNzURIc6dpJrunk4RYrPF8YdZzrh_nmS3N1lnGCmp_ZHb8vNRl0 3 | # Origional Author: AJJAXNET (https://pastebin.com/u/AJJaxNet) 4 | # 5 | # Updated for usability and conistent formating. 6 | # Added backup to Azure AD and onprem Domain 7 | 8 | 9 | [cmdletbinding()] 10 | param( 11 | [Parameter()] 12 | [ValidateNotNullOrEmpty()] 13 | [string] $OSDrive = $env:SystemDrive, 14 | [string] $SyncroBL = 'Bitlocker Drives' 15 | ) 16 | 17 | # Set the TLS version used by the PowerShell client to TLS 1.2. 18 | if ([System.Net.ServicePointManager]::SecurityProtocol -lt [System.Net.SecurityProtocolType]::Tls13){ 19 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13 20 | } 21 | 22 | # Set up $env: vars for Syncro Module 23 | if($env:SyncroModule -match '^\s*$'){ 24 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 25 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 26 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 27 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 28 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 29 | $env:RepairTechUUID = $SyncroRegKey.uuid 30 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 31 | } 32 | if (Test-Path -Path $env:SyncroModule) { 33 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 34 | } 35 | 36 | function Save-BitlockerRecoveryPasswords { 37 | param( 38 | [Parameter(Mandatory=$true)] 39 | [string] $SyncroBL 40 | ) 41 | 42 | [bool]$saveToAD = (Get-CimInstance win32_computersystem).PartOfDomain 43 | $dsregcmd = dsregcmd /status 44 | [bool]$SavetoAzAd = $dsregcmd | Where-Object {$_ -match 'AzureAdJoined'} | 45 | ForEach-Object {($_ -split ':' | Select-Object -Last 1).trim() -eq 'YES'} 46 | 47 | $textOutput = "" 48 | 49 | # Identify all the Bitlocker volumes. 50 | [array]$BitlockerVolumes = Get-BitLockerVolume 51 | 52 | # For each volume, get the RecoveryPassword and display it. 53 | $BitlockerVolumes | 54 | ForEach-Object { 55 | $MountPoint = $_.MountPoint 56 | $RecoveryKey = $_.KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' } 57 | foreach($rk in $RecoveryKey){ 58 | [string]$RecoveryPw = $rk.RecoveryPassword 59 | if ($saveToAD -eq $true) { 60 | Backup-BitLockerKeyProtector -MountPoint $MountPoint -KeyProtectorId $rk.KeyProtectorID 61 | } 62 | if ($saveToAzAD -eq $true) { 63 | BackupToAAD-BitLockerKeyProtector -MountPoint $MountPoint -KeyProtectorId $rk.KeyProtectorID 64 | } 65 | if ($RecoveryPw.Length -gt 5) { 66 | Write-Verbose ("The drive $MountPoint has a recovery key $RecoveryPw.") 67 | $textOutput += "$MountPoint\ $RecoveryPw" 68 | $textOutput += "`r`n" 69 | } 70 | } 71 | } 72 | 73 | if ($SyncroBL -notmatch '^\s*$' -and $env:SyncroModule -notmatch '^\s*$') { 74 | Set-Asset-Field -Name $SyncroBL -Value $textOutput 75 | } 76 | } 77 | 78 | try { 79 | $ErrorActionPreference = "stop" 80 | 81 | Write-Host "Enabling BitLocker with TPM." 82 | 83 | # Enable Bitlocker using TPM 84 | Enable-BitLocker -MountPoint $OSDrive -UsedSpaceOnly -TpmProtector -ErrorAction Continue 85 | 86 | # Only add RecoveryPassword if none is already defined 87 | if (((Get-BitLockerVolume -MountPoint $OSDrive).KeyProtector | Where-Object {$_.KeyProtectorType -eq 'RecoveryPassword'} | Measure-Object).Count -eq 0) { 88 | Write-Host "Adding a recovery password..." 89 | Enable-BitLocker -MountPoint $OSDrive -UsedSpaceOnly -RecoveryPasswordProtector 90 | } else { 91 | Write-Host "A recovery password is already defined, skipping creation." 92 | } 93 | 94 | "Sleeping 30 Seconds" 95 | Start-Sleep -Seconds 30 96 | 97 | Save-BitlockerRecoveryPasswords -SyncroBL $SyncroBL 98 | } 99 | catch { 100 | Write-Host "Error while setting up Bitlocker, make sure that you are running the cmdlet as an admin: $_" 101 | Create-Syncro-Ticket -Subject "BitLocker Deployment Issue" -IssueType "PC Issue" -Status "New" 102 | } 103 | -------------------------------------------------------------------------------- /Bitlocker_RetrieveKeys.ps1: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # == Created by Jordan Ritz, Eberly Systems LLC. == 3 | # ============================================================================== 4 | # 5 | # Prerequisites: You must have a custom asset field 6 | # Name: "Bitlocker Drives" 7 | # Type: "Text area" 8 | # 9 | 10 | try{ 11 | # Get Bitlocker Volumes or exit. 12 | $BitLockerVolume = Get-BitLockerVolume -ErrorAction stop 13 | 14 | } catch [System.Management.ManagementException] { 15 | "Bitlocker Not Detected" 16 | } catch [System.Management.Automation.CommandNotFoundException] { 17 | "Bitlocker Not Detected" 18 | } catch { 19 | "Unexpected Error" 20 | (($Error[0] | Select-Object -Property Exception | Out-String).trim() -split '\r')[-1] 21 | exit 1 22 | } 23 | 24 | $Report = $BitLockerVolume | 25 | ForEach-Object { 26 | $MountPoint = $_.MountPoint 27 | $_.KeyProtector | Where-Object {$_.RecoveryPassword -notmatch '^\s$' -and $_.RecoveryPassword.Length -gt 5} | 28 | ForEach-Object { 29 | Write-Output "$MountPoint Id:$($_.KeyProtectorId), key:$($_.RecoveryPassword)" 30 | } 31 | } | Out-String 32 | 33 | if ($Report.Length -ge 56){ 34 | if ($env:SyncroModule){ 35 | Import-Module $env:SyncroModule 36 | Set-Asset-Field -Name "Bitlocker Drives" -Value $Report 37 | } else { 38 | $Report 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /BleachBit-DiskCleanup.ps1: -------------------------------------------------------------------------------- 1 | # Set up $env: vars for Syncro Module 2 | if($env:SyncroModule -match '^\s*$'){ 3 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 4 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 5 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 6 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 7 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 8 | $env:RepairTechUUID = $SyncroRegKey.uuid 9 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 10 | } 11 | if (Test-Path -Path $env:SyncroModule) { 12 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 13 | } 14 | 15 | $workingdir = $env:TEMP 16 | If(!(test-path $workingdir)) 17 | { 18 | New-Item -ItemType Directory -Force -Path $workingdir 19 | } 20 | # Get disk space available BEFORE the Cleanup 21 | $Before = Get-WmiObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq "3" } | Select-Object SystemName, 22 | @{ Name = "Drive" ; Expression = { ( $_.DeviceID ) } }, 23 | @{ Name = "Size (GB)" ; Expression = {"{0:N1}" -f( $_.Size / 1gb)}}, 24 | @{ Name = "FreeSpace (GB)" ; Expression = {"{0:N1}" -f( $_.Freespace / 1gb ) } }, 25 | @{ Name = "PercentFree" ; Expression = {"{0:P1}" -f( $_.FreeSpace / $_.Size ) } } | 26 | Format-Table -AutoSize | Out-String 27 | # Perform Cleanup Tasks 28 | Expand-Archive $workingdir\bleachbit-portable.zip -DestinationPath $workingdir -Force 29 | $Params = "-c adobe_reader.cache adobe_reader.tmp chromium.cache chromium.history chromium.vacuum firefox.cache firefox.url_history firefox.vacuum flash.cache flash.cookies google_chrome.cache google_chrome.history google_chrome.vacuum internet_explorer.cache internet_explorer.downloads java.cache opera.cache opera.history opera.vacuum silverlight.temp silverlight.cookies system.recycle_bin system.tmp system.memory_dump system.logs windows_explorer.mru winrar.history winrar.temp" 30 | $ParsedParams = $Params.Split(" ") 31 | & $workingdir\Bleachbit-Portable\bleachbit_console.exe $ParsedParams 32 | # Get disk space available After the Cleanup 33 | $After = Get-WmiObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq "3" } | Select-Object SystemName, 34 | @{ Name = "Drive" ; Expression = { ( $_.DeviceID ) } }, 35 | @{ Name = "Size (GB)" ; Expression = {"{0:N1}" -f( $_.Size / 1gb)}}, 36 | @{ Name = "FreeSpace (GB)" ; Expression = {"{0:N1}" -f( $_.Freespace / 1gb ) } }, 37 | @{ Name = "PercentFree" ; Expression = {"{0:P1}" -f( $_.FreeSpace / $_.Size ) } } | 38 | Format-Table -AutoSize | Out-String 39 | $LogDate = get-date -format "MM-d-yy-HH" 40 | #Start-Transcript -Path $workingdir\$LogDate.log 41 | #write-output "Space Before" 42 | #write-output $Before 43 | #write-output "space After" 44 | #write-output $After 45 | #stop-transcript 46 | $Disk += "$($LogDate)`rBefore$($Before)After$($After)" 47 | Set-Asset-Field -Name "Weekly Temp Files" -Value $Disk | Out-Null 48 | -------------------------------------------------------------------------------- /CustomerCustomField(Update).ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Update a customer custom field using the Syncro API 4 | .DESCRIPTION 5 | To use this script, you have to create a API Token that has those permissions: 6 | - Customer - Edit 7 | .NOTES 8 | Version: 1.0 9 | Author: Alexandre-Jacques St-Jacques 10 | Creation Date: 14-04-2021 11 | Purpose/Change: Initial script development 12 | #> 13 | 14 | # Set up $env: vars for Syncro Module 15 | if($env:SyncroModule -match '^\s*$'){ 16 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 17 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 18 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 19 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 20 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 21 | $env:RepairTechUUID = $SyncroRegKey.uuid 22 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 23 | } 24 | 25 | # The API token used for the request. Create a API key with permission "Customer - Edit". It is advised to populated it with the "Script variable" feature of syncro 26 | #$ApiToken = "test" 27 | # Will usually be syncromsp.com 28 | $ApiBaseURL = 'syncromsp.com' 29 | # Your account sub domain will magically be imported. 30 | $ApiSubDomain = $env:RepairTechSyncroSubDomain 31 | 32 | function Customer-Update-Field { 33 | param( 34 | [Parameter(Mandatory=$true)] 35 | [String] 36 | $ApiToken, 37 | [Parameter(Mandatory=$true)] 38 | [String] 39 | $CustomerId, 40 | [Parameter(Mandatory=$true)] 41 | [String] 42 | $CustomField, 43 | [Parameter(Mandatory=$true)] 44 | [String] 45 | $CustomFieldValue 46 | ) 47 | 48 | $headers = @{ 49 | Content='application/json' 50 | Authorization="Bearer $ApiToken" 51 | } 52 | 53 | $payload = @" 54 | { 55 | "properties": { 56 | "$CustomField": "$CustomFieldValue" 57 | } 58 | } 59 | "@ 60 | 61 | $ApiPath = "/api/v1/customers" 62 | 63 | $resp = try { 64 | Invoke-RestMethod -Method PUT "https://$($ApiSubDomain).$($ApiBaseURL)$($ApiPath)/$($CustomerId)" -Headers $headers -Body "$payload" -ContentType "application/json" 65 | } catch { 66 | Write-Host "ERROR!" 67 | $result = $_.Exception.Response.GetResponseStream() 68 | $reader = New-Object System.IO.StreamReader($result) 69 | $reader.BaseStream.Position = 0 70 | $reader.DiscardBufferedData() 71 | $responseBody = $reader.ReadToEnd(); 72 | Write-Host $responseBody 73 | } 74 | } 75 | 76 | # This is the function call to update the custom field of a customer. I would recommend you to populate $CustomerID using a script variable that uses the "{{customer_id}}" platform variable 77 | Customer-Update-Field -ApiToken $ApiToken -CustomerId $CustomerID -CustomField "Customer test" -CustomFieldValue "testing" 78 | -------------------------------------------------------------------------------- /DNSFilters_Comparison.ps1: -------------------------------------------------------------------------------- 1 | # Download plain-text recent list from URLhaus https://urlhaus.abuse.ch/api/ 2 | $urlhausRaw = Invoke-WebRequest -Uri 'https://urlhaus.abuse.ch/downloads/text_recent/' | 3 | Select-Object -ExpandProperty Content 4 | $urlhaus = $urlhausRaw.Split() | 5 | .{process {if($_.Length -ge 10){($_ -replace 'https*://','' ) -replace '[:/].*',''}}} | 6 | Where-Object {$_ -notmatch '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'} | Select-Object -Unique 7 | # Download text format list from cert.pl 8 | $certPl = (Invoke-WebRequest -Uri 'https://hole.cert.pl/domains/domains.txt').Content.Split() 9 | 10 | [Linq.Enumerable]::Distinct( 11 | [string[]] ($certPl + $urlhaus), 12 | [StringComparer]::InvariantCultureIgnoreCase 13 | ) | Foreach-Object -ThrottleLimit 5 -Parallel { 14 | #Action that will run in Parallel. Reference the current object via $PSItem and bring in outside variables with $USING:varname 15 | $request = @{ 16 | Name = $_ 17 | Type = 'A' 18 | ErrorAction = 'SilentlyContinue' 19 | } 20 | if ((Resolve-DnsName -Server 8.8.8.8 @request) -or (Resolve-DnsName -Server 1.1.1.1 @request)){ 21 | $ErrorActionPreference = 'SilentlyContinue' 22 | [pscustomobject]@{ 23 | 'Domain' = $_ 24 | 'CloudFlare' = (Resolve-DnsName -Server 1.1.1.1 @request | Select-Object -ExpandProperty IPAddress) -join ';' 25 | 'Google' = (Resolve-DnsName -Server 8.8.8.8 @request | Select-Object -ExpandProperty IPAddress) -join ';' 26 | 'CF-Filtered' = (Resolve-DnsName -Server 1.1.1.2 @request | Select-Object -ExpandProperty IPAddress) -join ';' 27 | 'Quad9' = (Resolve-DnsName -Server 9.9.9.9 @request | Select-Object -ExpandProperty IPAddress) -join ';' 28 | 'CleanBrowsing' = (Resolve-DnsName -Server 185.228.169.9 @request | Select-Object -ExpandProperty IPAddress) -join ';' 29 | 'FlashStart' = (Resolve-DnsName -Server 185.236.104.104 @request | Select-Object -ExpandProperty IPAddress) -join ';' 30 | 'dns0' = (Resolve-DnsName -Server 193.110.81.0 @request | Select-Object -ExpandProperty IPAddress) -join ';' 31 | 'zero.dns0' = (Resolve-DnsName -Server 193.110.81.9 @request | Select-Object -ExpandProperty IPAddress) -join ';' 32 | } 33 | } 34 | } | Export-Csv -Path ~/DNSFilters_Comparison.csv 35 | -------------------------------------------------------------------------------- /DNSFilters_Comparison.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Download URL lists 4 | url_list1=$(curl -sS https://urlhaus.abuse.ch/downloads/text_recent/) 5 | url_list2=$(curl -sS https://hole.cert.pl/domains/domains.txt) 6 | 7 | # Convert URLs to FQDNs, remove ports and IP addresses for the first list 8 | fqdn_list1=$(echo "$url_list1" | grep -oP '(?<=://)[^:/]+(?=\/|$)') 9 | 10 | # Combine the FQDN list from the first list and the second list, and deduplicate 11 | combined_fqdn_list=$(echo -e "$fqdn_list1\n$url_list2" | grep -vE '([0-9]{1,3}\.){3}[0-9]{1,3}' | sort -u) 12 | 13 | # IP addresses of the nameservers used for lookups 14 | # Cloudflare,Google,Cloudflare-Filtered,CleanBrowsing,FlashStart,dns0,Quad9 15 | nameservers=("1.1.1.1" "8.8.8.8" "1.1.1.2" "185.228.169.9" "185.236.104.104" "193.110.81.0" "9.9.9.9") 16 | 17 | # Output CSV header to a file 18 | echo "Domain name,$(IFS=,; echo "${nameservers[*]}")" > output.csv 19 | 20 | # Loop through domains and perform DNS lookups 21 | while read -r domain 22 | do 23 | # IP address lookup for the first nameserver (1.1.1.1) 24 | ip_1_1_1_1=$(dig "@${nameservers[0]}" +short "$domain") 25 | 26 | # Check if the lookup for 1.1.1.1 returned anything 27 | if [ -n "$ip_1_1_1_1" ]; then 28 | # IP address lookup for all nameservers 29 | ip=() 30 | for ns_ip in "${nameservers[@]}"; do 31 | # Perform DNS lookup, filter out errors, and handle line breaks 32 | ip+=("$(dig "@$ns_ip" +short "$domain" 2>/dev/null | tail -n1)") 33 | done 34 | 35 | # Append the results to the CSV file 36 | echo "$domain,$(IFS=,; echo "${ip[*]}")" >> output.csv 37 | fi 38 | done < <(echo -e "$combined_fqdn_list") 39 | 40 | echo "Results written to output.csv" 41 | -------------------------------------------------------------------------------- /DNSFilters_multi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # List of websites for DNS lookups 4 | websites=( 5 | "adobe.com" 6 | "amazon.com" 7 | "apple.com" 8 | "att.com" 9 | "bankofamerica.com" 10 | "bbc.com" 11 | "chase.com" 12 | "costco.com" 13 | "cnn.com" 14 | "dropbox.com" 15 | "ebay.com" 16 | "espn.com" 17 | "facebook.com" 18 | "google.com" 19 | "groupon.com" 20 | "homedepot.com" 21 | "imdb.com" 22 | "linkedin.com" 23 | "microsoft.com" 24 | "netflix.com" 25 | # "nike.com" 26 | # "npr.org" 27 | # "nytimes.com" 28 | # "paypal.com" 29 | # "pinterest.com" 30 | # "reddit.com" 31 | # "snapchat.com" 32 | # "spotify.com" 33 | # "stackoverflow.com" 34 | # "starbucks.com" 35 | # "target.com" 36 | # "tumblr.com" 37 | # "twitter.com" 38 | # "uber.com" 39 | # "usbank.com" 40 | # "verizon.com" 41 | # "walmart.com" 42 | # "weather.com" 43 | # "wellsfargo.com" 44 | # "whatsapp.com" 45 | # "wikipedia.org" 46 | # "yahoo.com" 47 | # "youtube.com" 48 | # "zillow.com" 49 | ) 50 | 51 | # Associative array for resolver names and IP addresses 52 | declare -A resolvers=( 53 | ["Cloudflare"]="1.1.1.1" 54 | ["Google"]="8.8.8.8" 55 | ["Cloudflare-Filtered"]="1.1.1.2" 56 | ["CleanBrowsing"]="185.228.169.9" 57 | ["dns0"]="193.110.81.0" 58 | ["Quad9"]="9.9.9.9" 59 | ) 60 | 61 | # Function to perform DNS lookup and measure time in milliseconds 62 | benchmark_lookup() { 63 | local resolver="$1" 64 | local resolver_ip="${resolvers[$resolver]}" 65 | local total_time=0 66 | 67 | echo -n "Testing $resolver: " 68 | 69 | li=$((${#websites[@]} - 1)) 70 | 71 | for website in "${websites[@]}"; do 72 | start_time=$(date +%s%N) # Start time in nanoseconds 73 | dig +short "@$resolver_ip" "$website" > /dev/null 74 | end_time=$(date +%s%N) # End time in nanoseconds 75 | 76 | # Calculate elapsed time in milliseconds and add to total time 77 | elapsed_time=$(( (end_time - start_time) / 1000000 )) 78 | total_time=$((total_time + elapsed_time)) 79 | if [ "$website" != "${websites[$li]}" ]; then 80 | echo -n "$elapsed_time," 81 | else 82 | echo "$elapsed_time" 83 | fi 84 | done 85 | 86 | # Calculate and print average lookup time in milliseconds 87 | average_time=$((total_time / ${#websites[@]})) 88 | echo "($resolver_ip): ${average_time}ms" 89 | echo 90 | } 91 | 92 | echo "Benchmarking DNS Server Respons times" > dnsBench.csv 93 | 94 | # Perform DNS lookups for each resolver for all websites 95 | for resolver in "${!resolvers[@]}"; do 96 | benchmark_lookup "$resolver" >> dnsBench.csv 97 | done 98 | 99 | # Download URL lists 100 | url_list1=$(curl -sS https://urlhaus.abuse.ch/downloads/text_recent/) 101 | url_list2=$(curl -sS https://hole.cert.pl/domains/domains.txt) 102 | 103 | # Convert URLs to FQDNs, remove ports and IP addresses for the first list 104 | fqdn_list1=$(echo "$url_list1" | grep -oP '(?<=://)[^:/]+(?=\/|$)') 105 | 106 | # Combine the FQDN list from the first list and the second list, and deduplicate 107 | combined_fqdn_list=$(echo -e "$fqdn_list1\n$url_list2" | grep -vE '([0-9]{1,3}\.){3}[0-9]{1,3}' | sort -u) 108 | 109 | # IP addresses of the nameservers used for lookups 110 | # Server Order: Cloudflare, Cloudflare-Filtered, CleanBrowsing, dns0, Quad9 111 | nameservers=("1.1.1.1" "1.1.1.2" "185.228.169.9" "193.110.81.0" "9.9.9.9") 112 | 113 | privdig() { 114 | local resolver="$1" 115 | local domain="$2" 116 | local result="" 117 | 118 | while true; do 119 | result=$(dig "@$resolver" +short "$domain" 2>/dev/null | tail -n1) 120 | if [[ "$result" == *"communications error"* ]]; then 121 | sleep 2 # Sleep for 2 seconds if the condition is true 122 | else 123 | break # Break out of the loop if the condition is false 124 | fi 125 | done 126 | 127 | echo "$result" 128 | } 129 | 130 | dnsLookup() { 131 | # Domain passed as a command-line argument 132 | domain="$1" 133 | # Be sure to match the number of IP addresses to the number of filtered servers 134 | local ip_regex='^(([0-9]{1,3}\.){3}[0-9]{1,3},){3}([0-9]{1,3}\.){3}[0-9]{1,3}$' 135 | 136 | # IP addresses of the nameservers used for lookups 137 | # Server Order: Cloudflare, Cloudflare-Filtered, CleanBrowsing, dns0, Quad9 138 | nameservers=("1.1.1.1" "1.1.1.2" "185.228.169.9" "193.110.81.0" "9.9.9.9") 139 | 140 | ip_1_1_1_1=$(privdig "${nameservers[0]}" "$domain") 141 | 142 | # Check if the lookup for 1.1.1.1 returned anything 143 | if [ -n "$ip_1_1_1_1" ] && [ "$ip_1_1_1_1" != '127.0.0.1' ]; then 144 | # IP address lookup for all nameservers 145 | ip=() 146 | for ((i = 1; i < ${#nameservers[@]}; i++)); do 147 | # Perform DNS lookup using privdig function 148 | ip+=("$(privdig "${nameservers[$i]}" "$domain")") 149 | done 150 | 151 | $ip_string="$(IFS=,; echo "${ip[*]}")" 152 | if [[ ! $ip_string =~ $ip_regex ]]; then 153 | # Append the results to the CSV file 154 | echo "$domain,$ip_1_1_1_1,$(IFS=,; echo "${ip[*]}")" >> dnsFilterTest.csv 155 | fi 156 | fi 157 | } 158 | 159 | export -f privdig 160 | export -f dnsLookup 161 | 162 | # Output CSV header to a file 163 | echo "Domain name,$(IFS=,; echo "${nameservers[*]}")" > dnsFilterTest.csv 164 | 165 | # Loop through domains and perform DNS lookups in parallel 166 | (echo "$combined_fqdn_list") | parallel --jobs 8 "dnsLookup {}" > /dev/null 167 | 168 | echo "Results written to dnsFilterTest.csv 169 | -------------------------------------------------------------------------------- /DeleteBitDefenderSetupDownloader.ps1: -------------------------------------------------------------------------------- 1 | Get-ChildItem -Path C:\ProgramData\Syncro\bin -Filter setupdownloader*.exe | Remove-Item -Force -Verbose 2 | Get-ChildItem -Path C:\Windows\Temp\ -Directory -Filter RarSFX* | Remove-Item -Recurse -Force -Verbose 3 | -------------------------------------------------------------------------------- /Deploy_CyberCNS.ps1: -------------------------------------------------------------------------------- 1 | <#- Start of Script -#> 2 | # Required Variables 3 | # $InstType (recomend Dropdown), Values: 'Probe','LightWeight','Scan','auto' 4 | # $ClientID (recomend Platform variable set to customer custom field) 5 | # $ClientSecret (recomend Platform variable set to customer custom field) 6 | # $Uninstall (recomend Dropdown), Values: 'True', 'False' 7 | # $environment = Should be your environment/domain for -e in installer 8 | # $DLSecret = Any credentials required to access DL URI in format "Username:Password@" 9 | 10 | $Url = 'portaluseast2.mycybercns.com' 11 | # Should Generate a valid download link, but moved to Azure Blob due to reliability issues. 12 | $AgentURI = (Invoke-RestMethod -Method "Get" -URI "https://configuration.mycybercns.com/api/v3/configuration/agentlink?ostype=windows") 13 | $AgentName = $AgentURI.Split('/')[-1] 14 | 15 | '#============ Syncro Inserted Code ============#' 16 | foreach ($line in (Get-Content -Path $MyInvocation.MyCommand.Path -ErrorAction Stop)){ 17 | if ($line -eq '<#- Start of Script -#>') { 18 | break 19 | } else { 20 | # Mask Guid in log 21 | $line -replace '([0-9a-fA-F]{3})[0-9a-fA-F]{5}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{8}([0-9a-fA-F]{4})|^(\w{3})\w{23,}(\w{4})$', '$1$3*****-****-****-****-********$2$4' 22 | } 23 | } 24 | '#============== END Syncro Code ===============#' 25 | '' 26 | 27 | # 28 | # $AgentURI OR Required File (use to specify download link or save cybercnsagent.exe to C:\Windows\Temp) 29 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 30 | 31 | $installTypes = @('Probe','LightWeight','Scan','auto') 32 | if ($installTypes -notcontains $InstType){ 33 | Write-Warning "`$InstType must equal one of ($($installTypes -join ', '))" 34 | "Setting InstType to auto" 35 | $InstType = 'auto' 36 | } 37 | 38 | if ("$ClientID$ClientSecret" -match 'Skip'){ 39 | "Skip Install" 40 | exit 41 | } elseif ($ClientID -match '^\s*$' -or $ClientSecret -match '^\s*$'){ 42 | Write-Warning '$ClientID and $ClientSecret are both required to install the agent.' 43 | exit 2 44 | } 45 | 46 | if ($Uninstall -eq 'True'){ 47 | Get-Process cybercns* | Stop-Process -Force 48 | Get-Service cybercns* | Stop-Service -Force 49 | 50 | if ((Test-Path -Path 'C:\Program Files (x86)\CyberCNSAgentV2\uninstall.bat')){ 51 | Start-Process -FilePath 'C:\Program Files (x86)\CyberCNSAgentV2\uninstall.bat' -NoNewWindow -Wait 52 | Start-Sleep -Seconds 5 53 | } 54 | if (Test-Path 'C:\Program Files (x86)\CyberCNSAgentV2\cybercnsagentv2.exe'){ 55 | Start-Process -FilePath 'C:\Program Files (x86)\CyberCNSAgentV2\cybercnsagentv2.exe' -ArgumentList '--uninstall' -NoNewWindow -Wait 56 | Start-Sleep -Seconds 5 57 | } 58 | 59 | Get-Service CyberCNS* | ForEach-Object { sc.exe delete $_.Name } 60 | if (Test-Path -Path 'C:\Program Files (x86)\CyberCNSAgentV2'){ 61 | Remove-item -Path 'C:\Program Files (x86)\CyberCNSAgentV2\Cyber*' -Recurse -Force 62 | } 63 | } 64 | 65 | $CyberCNSService = Get-Service -Name CyberCNSAgent* -ErrorAction SilentlyContinue 66 | 67 | if ($null -ne $CyberCNSService -and $CyberCNSService.Status -ne 'Running'){ 68 | try { 69 | Start-Service -InputObject $CyberCNSService -ErrorAction Stop 70 | Start-Sleep -Seconds 3 71 | if (Get-Service -Name CyberCNSAgent* -ErrorAction SilentlyContinue -eq 'Running'){ 72 | exit 0 73 | } 74 | 75 | } 76 | catch { 77 | 'Could not start service, Proceed to install' 78 | } 79 | } elseif ($env:SyncroModule) { 80 | <# 81 | Import-Module $env:SyncroModule -WarningAction SilentlyContinue 82 | # the Issue with closing this is that "PS Monitor" is all Process monitors. 83 | Close-Rmm-Alert -Category "Ps Monitor" 84 | #> 85 | } 86 | 87 | if ($InstType -eq 'auto'){ 88 | try { 89 | if ((Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -ErrorAction SilentlyContinue).State -eq 'Enabled') { 90 | $InstType = 'Probe' 91 | } else { 92 | throw 93 | } 94 | } 95 | catch { 96 | $InstType = 'LightWeight' 97 | } 98 | } 99 | 100 | $SystemTemp = Join-Path -Path $env:SystemRoot -ChildPath 'Temp' 101 | if (!(Test-Path -Path $SystemTemp)) { 102 | $SystemTemp = $env:TEMP 103 | } 104 | $destination = Join-Path -Path $SystemTemp -ChildPath $AgentName 105 | if (!(Test-Path -Path $destination)) { 106 | Get-ChildItem -Path $SystemTemp -Filter *cybercns* | Remove-Item -Force 107 | "Downloading '$AgentName'" 108 | try { 109 | Start-BitsTransfer -Source $AgentURI -Destination $destination -Description 'Downloading CyberCNS Agent using Bits' -ErrorAction Stop 110 | } 111 | catch { 112 | Invoke-WebRequest -Uri $AgentURI -OutFile $destination -UseBasicParsing 113 | } 114 | } 115 | 116 | "Running: Start-Process $destination -ArgumentList `"-c $ClientID -a $ClientID -s `$ClientSecret -b $Url -e $environment -i $InstType`" -NoNewWindow" 117 | Start-Process $destination -ArgumentList "-c $ClientID -a $ClientID -s $ClientSecret -b $Url -e $environment -i $InstType" -NoNewWindow -Wait 118 | -------------------------------------------------------------------------------- /DisableWeatherAndNews.ps1: -------------------------------------------------------------------------------- 1 | $path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Feeds" 2 | $name = "EnableFeeds" 3 | $value = "0" 4 | #Disables Windows Weather and News 5 | write-host "Disabling Weather and News" 6 | New-Item -Path $path -Force 7 | New-ItemProperty -Path $path -Name $name -Value $value -PropertyType DWORD -Force | Out-Null 8 | -------------------------------------------------------------------------------- /FixSyncroChocoPath.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | When using chocolatey Syncro's internal Chocolatey seems broken and to have messed up the paths for strate 4 | installes of chocolatey as well 5 | 6 | .DESCRIPTION 7 | Checks for the presents of 'C:\Program Files\RepairTech\Syncro\kabuto_app_manager\choco.exe' and if its missing 8 | copies the correct executable to that path 9 | #> 10 | $ChocoPath = 'C:\Program Files\RepairTech\Syncro\kabuto_app_manager\choco.exe' 11 | $KpmPath = 'C:\Program Files\RepairTech\Syncro\kabuto_app_manager\kabuto_patch_manager.exe' 12 | if(!(Test-Path -Path $ChocoPath)){ 13 | Write-Output "choco.exe is missing" 14 | if((Test-Path -Path $KpmPath)){ 15 | Copy-Item -Path $KpmPath -Destination $ChocoPath -Force -Verbose 16 | } else { 17 | Write-Warning 'Kabuto_Patch_Manager is missing' 18 | exit 3 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Get-InstalledAV.ps1: -------------------------------------------------------------------------------- 1 | #requires -version 4.0 2 | # This Script will not work on Server OS versions 3 | # For Syncro all Vars/Fields are optional 4 | # Runtime ScriptVariable: 5 | # Name: AlertIfEnabledAV 6 | # Description: This Var will be used in a regex match aganst AV Display Name. If Match -eq $True will raise RMM Alert 7 | # 8 | # Asset Custom Fields 9 | # Name: 10 | $EnabledAV = "Enabled AV" #Type: "Text Field" 11 | # Description: Will only contain the "Display Name" of the Enabled AV(s) 12 | # Name: 13 | $AllAV = "All AV" #Type: "Text Area" 14 | # Description: Multi line output CSV for all detected AVs "DisplayName,Enabled,Date" 15 | 16 | # Ensure TLS -ge 1.2 17 | if ([Net.ServicePointManager]::SecurityProtocol -lt [Net.SecurityProtocolType]::Tls12){ 18 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 19 | } 20 | 21 | Function Get-AVStatus { 22 | 23 | <# 24 | .Synopsis 25 | Get anti-virus product information. 26 | .Description 27 | This command queries the state of installed anti-virus products via the Get-CimInstance command. 28 | The default behavior is to only display enabled products, unless you use -All. You can query by computername or existing CIMSessions. 29 | .Example 30 | PS C:\> Get-AVStatus 31 | Displayname : ESET NOD32 Antivirus 9.0.386.0 32 | ProductState : 266256 33 | Enabled : True 34 | UpToDate : True 35 | Path : C:\Program Files\ESET\ESET NOD32 Antivirus\ecmd.exe 36 | Timestamp : Thu, 21 Jul 2016 15:20:18 GMT 37 | .Notes 38 | version: 1.1 39 | Learn more about PowerShell: 40 | http://jdhitsolutions.com/blog/essential-powershell-resources/ 41 | Fork of origional https://gist.github.com/jrdnr/fb2473d6080b7f2b381dc790be679236 42 | .Inputs 43 | [string[]] 44 | [Microsoft.Management.Infrastructure.CimSession[]] 45 | .Outputs 46 | [pscustomboject] 47 | .Link 48 | Get-CimInstance 49 | #> 50 | 51 | [cmdletbinding(DefaultParameterSetName = "computer")] 52 | 53 | Param( 54 | #The name of a computer to query. 55 | [Parameter( 56 | Position = 0, 57 | ValueFromPipeline, 58 | ValueFromPipelineByPropertyName, 59 | ParameterSetName = "computer")] 60 | [ValidateNotNullorEmpty()] 61 | [string[]]$Computername = $env:COMPUTERNAME, 62 | 63 | #An existing CIMsession. 64 | [Parameter(ValueFromPipeline, ParameterSetName = "session")] 65 | [Microsoft.Management.Infrastructure.CimSession[]]$CimSession, 66 | 67 | #The default is enabled products only. 68 | [switch]$All 69 | ) 70 | 71 | Begin { 72 | Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" 73 | 74 | Function ConvertTo-Hex { 75 | Param([int]$Number) 76 | '0x{0:x}' -f $Number 77 | } 78 | 79 | If ($All) { 80 | Write-Verbose "[BEGIN ] Getting all AV products" 81 | } 82 | 83 | } #begin 84 | 85 | Process { 86 | #initialize an hashtable of paramters to splat to Get-CimInstance 87 | $cimParams = @{ 88 | Namespace = "root/SecurityCenter2" 89 | ClassName = "Antivirusproduct" 90 | ErrorAction = "Stop" 91 | } 92 | 93 | #initialize an empty array to hold results 94 | $AV = @() 95 | 96 | Write-Verbose "[PROCESS] Using parameter set: $($pscmdlet.ParameterSetName)" 97 | Write-Verbose "[PROCESS] PSBoundparameters: " 98 | Write-Verbose ($PSBoundParameters | Out-String) 99 | 100 | if ($pscmdlet.ParameterSetName -eq 'computer') { 101 | foreach ($computer in $Computername) { 102 | 103 | Write-Verbose "[PROCESS] Querying $($computer.ToUpper())" 104 | if ($computer -ne $env:COMPUTERNAME){ 105 | $cimParams.ComputerName = $computer 106 | } 107 | Try { 108 | $AV += Get-CimInstance @CimParams 109 | } 110 | Catch { 111 | Write-Warning "[$($computer.ToUpper())] $($_.Exception.Message)" 112 | $cimParams.ComputerName = $null 113 | } 114 | 115 | } #foreach computer 116 | } else { 117 | foreach ($session in $CimSession) { 118 | 119 | Write-Verbose "[PROCESS] Using session $($session.computername.toUpper())" 120 | $cimParams.CimSession = $session 121 | Try { 122 | $AV += Get-CimInstance @CimParams 123 | } 124 | Catch { 125 | Write-Warning "[$($session.computername.ToUpper())] $($_.Exception.Message)" 126 | $cimParams.cimsession = $null 127 | } 128 | 129 | } #foreach computer 130 | } 131 | 132 | foreach ($item in $AV) { 133 | Write-Verbose "[PROCESS] Found $($item.Displayname)" 134 | $hx = ConvertTo-Hex $item.ProductState 135 | $mid = $hx.Substring(3, 2) 136 | [bool]$Enabled = $mid -notmatch "00|01" 137 | 138 | $end = $hx.Substring(5) 139 | [bool]$UpToDate = $end -eq "00" 140 | 141 | if ($All -or $Enabled){ 142 | $item | Select-Object Displayname, ProductState, 143 | @{Name = "Enabled"; Expression = { $Enabled } }, 144 | @{Name = "UpToDate"; Expression = { $UptoDate } }, 145 | instanceGuid, 146 | @{Name = "Path"; Expression = { $_.pathToSignedProductExe } }, 147 | Timestamp, 148 | @{Name = "Computername"; Expression = { 149 | if($_.PSComputername -match '^\s*$'){$env:COMPUTERNAME}else{$_.PSComputername.toUpper()} 150 | } } 151 | } 152 | 153 | } #foreach 154 | 155 | } #process 156 | 157 | End { 158 | Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" 159 | } #end 160 | 161 | } #end function 162 | 163 | function Import-SyncroModule { 164 | param ( 165 | #Defaults to the UUID of local system but you can provide the UUID of Any other Syncro Asset instead. 166 | $UUID 167 | ) 168 | 169 | # Set up $env: vars for Syncro Module 170 | if($env:SyncroModule -match '^\s*$'){ 171 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 172 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 173 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 174 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 175 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 176 | $env:RepairTechUUID = if($UUID -match '^\s*$'){ $SyncroRegKey.uuid } else {$UUID} 177 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 178 | } 179 | if ((Test-Path -Path $env:SyncroModule) -and ($PSVersionTable.PSVersion -ge [system.version]'4.0')) { 180 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 181 | } elseif ($PSVersionTable.PSVersion.Major -lt 4) { 182 | Write-Warning "$($PSVersionTable.PSVersion) is not compatible with SyncroModule" 183 | [Environment]::SetEnvironmentVariable('SyncroModule',$null) 184 | $false 185 | } 186 | } 187 | 188 | function Get-InstalledApps { 189 | param ( 190 | [string]$AppName, 191 | [string]$Publisher, 192 | [switch]$or 193 | ) 194 | 195 | if ((Get-PSDrive | Where-Object {$_.Name -eq 'HKU'}).count -lt 1){ 196 | New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null 197 | } 198 | [array]$users = Get-WMIObject -class Win32_UserProfile | Sort-Object -Property LastUseTime | 199 | Where-Object { $_.LocalPath -like 'c:\user*' } 200 | $users += [PSCustomObject]@{LocalPath = 'c:\users\.DEFAULT'; SID = '.DEFAULT'} 201 | 202 | $InstLocation = @{} 203 | foreach ($u in $Users) { 204 | $hkuPath = "HKU\$($u.SID)" 205 | $ntuserdat = Join-Path -Path $u.LocalPath -ChildPath NTUSER.DAT 206 | $UserHive = "HKU:\$($u.SID)" 207 | $unload = $false 208 | 209 | if (!(Test-Path -Path $UserHive)){ 210 | reg load $hkuPath $ntuserdat 2>&1 | Out-Null 211 | $unload = $true 212 | } 213 | $UPath = Join-Path -Path $UserHive -ChildPath 'Software\Microsoft\Windows\CurrentVersion\Uninstall' 214 | if ((Test-Path -Path $UPath) -and -not $InstLocation.ContainsKey($UPath)){ 215 | $InstLocation.Add($UPath,$unload) 216 | } 217 | } 218 | 219 | $InstLocation += @{ 220 | "HKLM:\software\microsoft\windows\currentversion\uninstall" = $false 221 | "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" = $false 222 | } 223 | $AllApps = get-childitem $InstLocation.Keys.split() | ForEach-Object { Get-ItemProperty $_.PSPath } 224 | #| Select-Object DisplayVersion,InstallDate,ModifyPath,Publisher,UninstallString,Language,DisplayName 225 | 226 | foreach ($a in $AllApps){ 227 | $test = @( 228 | ($a.DisplayName -match $AppName), 229 | ($a.Publisher -match $Publisher) 230 | ) 231 | if ($true -ne $or -and $test -notcontains $false){ 232 | $a 233 | } elseif ($true -eq $or -and $test -contains $true) { 234 | $a 235 | } 236 | } 237 | 238 | foreach ($k in $InstLocation.Keys){ 239 | if($InstLocation.$k -eq $true){ 240 | reg unload $hkuPath 2>&1 | Out-Null 241 | } 242 | } 243 | } 244 | 245 | Get-AVStatus -All | Tee-Object -Variable InstalledAV 246 | 247 | if ($null -eq $InstalledAV) { 248 | $Cylance = Get-InstalledApps -AppName 'Cylance PROTECT' 249 | [array]$InstalledAV += [PSCustomObject]@{ 250 | Displayname = $Cylance.DisplayName 251 | Enabled = $true 252 | } 253 | } 254 | 255 | if ($env:SyncroModule -and $null -ne $InstalledAV){ 256 | Import-SyncroModule 257 | $AvEnabled = $InstalledAV | Where-Object {$_.Enabled -eq $true} 258 | if (($AlertIfEnabledAV -notmatch '^\s*$') -and $AvEnabled.Displayname -match $AlertIfEnabledAV){ 259 | # Remove `r from string so Syncro doesn't Barf 260 | $body = ($AvEnabled | Out-String) -replace "`r","" 261 | Rmm-Alert -Category 'Enabled_AV_Error' -Body $body 262 | } 263 | try { 264 | $enabledAVBody = $AvEnabled.Displayname -join ',' 265 | Set-Asset-Field -Name $EnabledAV -Value $enabledAVBody -ErrorAction Stop 266 | 267 | $date = if($a.Timestamp -match '^\s*$'){'Unknown'} else {([datetime]$a.Timestamp).ToString('yyyy/MM/dd')} 268 | $AllAVBody = @('Displayname,Enabled,Date') 269 | $AllAVBody += foreach ($a in $InstalledAV){'{0},{1},{2}' -f $a.Displayname, $a.Enabled, $date} 270 | $AllAVBody = ($AllAVBody | Out-String) -replace "`r","" 271 | Set-Asset-Field -Name $AllAV -Value $AllAVBody -ErrorAction Stop 272 | 273 | exit 0 274 | } 275 | catch { 276 | exit 1 277 | } 278 | 279 | } 280 | -------------------------------------------------------------------------------- /Get-MonitorInfo.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Required Syncro Field: Monitors, Type: Text Area 3 | #> 4 | 5 | $connections = try { 6 | Get-CimInstance -Namespace 'root/wmi' -ClassName 'WmiMonitorConnectionParams' -ErrorAction stop | 7 | Group-Object -AsHashTable -Property InstanceName 8 | } 9 | catch { 10 | Get-WmiObject -Namespace 'root/wmi' -ClassName 'WmiMonitorConnectionParams' | 11 | Group-Object -AsHashTable -Property InstanceName 12 | } 13 | 14 | $VideoOutput = @{ 15 | '-2' = 'UNINITIALIZED' 16 | '-1' = 'OTHER' 17 | '0' = 'VGA_HD15' 18 | '1' = 'SVIDEO' 19 | '2' = 'SCOMPOSITE_VIDEO' 20 | '3' = 'COMPONENT_VIDEO' 21 | '4' = 'DVI' 22 | '5' = 'HDMI' 23 | '6' = 'LVDS' 24 | '7' = 'UNKNOWN' 25 | '8' = 'D_JPN' 26 | '9' = 'SDI' 27 | '10' = 'DP_EXTERNAL' 28 | '11' = 'DP_EMBEDDED' 29 | '12' = 'UDI_EXTERNAL' 30 | '13' = 'UDI_EMBEDDED' 31 | '14' = 'SDTVDONGLE' 32 | '15' = 'MIRACAST' 33 | '16' = 'INDIRECT_WIRED' 34 | '2147483648' = 'BUILT_IN' 35 | } 36 | 37 | $ManufacturerHt = @{ 38 | AAC = 'AcerView'; ACI = 'Asus'; ACR = 'Acer'; ACT = 'Targa'; AMW = 'AMW'; API = 'Acer'; APP = 'Apple Computer'; ART = 'ArtMedia'; AST = 'AST Research'; AUO = 'Asus'; 39 | BNQ = 'BenQ Corp'; BOE = 'BOE Display Tech' 40 | CMO = 'Acer'; CMN = 'Chi Mei Innolux'; CPL = 'Compal / ALFA'; CPQ = 'Compaq'; 41 | DEC = 'Digital Equipment Corp'; DEL = 'Dell'; DPC = 'Delta Electronics'; DWE = 'Daewoo Telecom' 42 | ECS = 'ELITEGROUP'; EIZ = 'EIZO'; EPI = 'Envision Peripherals'; 43 | FUS = 'Fujitsu'; 44 | GSM = 'LG (Goldstar)' 45 | HEI = 'Hyundai'; HIQ = 'Hyundai'; HIT = 'Hitachi'; HPE = 'HP'; HSD = 'Hannspree'; HSL = 'Hansol'; HTC = 'Hitachi'; HWP = 'HP' 46 | IBM = 'IBM PC Company'; ICL = 'Fujitsu'; IFS = 'InFocus'; IQT = 'Hyundai'; IVM = 'Idek Iiyama' 47 | KDS = 'KDS USA'; KFC = 'KFC Computek' 48 | LEN = 'Lenovo'; LGD = 'LG Display'; LKM = 'ADLAS / AZALEA'; LNK = 'LINK Tech'; LPL = 'LG'; LTN = 'Lite-On' 49 | MAG = 'MAG InnoVision'; MEI = 'Panasonic'; MEL = 'Mitsubishi'; MTC = 'MITAC' 50 | NAN = 'NANAO'; NEC = 'NEC Tech'; NOK = 'Nokia'; NVD = 'Nvidia' 51 | OQI = 'OPTIQUEST' 52 | PBN = 'Packard Bell'; PCK = 'Daewoo'; PDC = 'Polaroid'; PHL = 'Philips' 53 | REL = 'Relisys' 54 | SAN = 'Samsung'; SAM = 'Samsung'; SEC = 'Hewlett-Packard'; SNI = 'Siemens'; SNY = 'Sony'; SPT = 'Sceptre'; STP = 'Sceptre'; SRC = 'Shamrock'; SUN = 'Sun Microsystems' 55 | TAT = 'Tatung'; TOS = 'Toshiba'; TSB = 'Toshiba' 56 | VSC = 'ViewSonic' 57 | WET = 'Westinghouse' 58 | UNK = 'Unknown' 59 | ZCM = 'Zenith Data' 60 | _YV = 'Fujitsu' 61 | } 62 | 63 | #Grabs the Monitor objects from WMI 64 | $Monitors = try { 65 | Get-CimInstance -Namespace 'root\WMI' -ClassName 'WMIMonitorID' -ErrorAction Stop 66 | } 67 | catch { 68 | Get-WmiObject -Namespace 'root\WMI' -Class 'WMIMonitorID' -ErrorAction SilentlyContinue 69 | } 70 | 71 | #Takes each monitor object found and runs the following code: 72 | [array]$Monitor_Array = ForEach ($Monitor in $Monitors) { 73 | #Grabs respective data and converts it from ASCII encoding and removes any trailing ASCII null values 74 | If ($null -ne $Monitor.UserFriendlyName) { 75 | $Mon_Model = ([System.Text.Encoding]::ASCII.GetString($Monitor.UserFriendlyName)).Replace("$([char]0x0000)","") 76 | } elseif ($null -ne $Monitor.ProductCodeID) { 77 | $Mon_Model = ([System.Text.Encoding]::ASCII.GetString($Monitor.ProductCodeID)).Replace("$([char]0x0000)","") 78 | } else { 79 | $Mon_Model = $null 80 | } 81 | $Mon_Serial_Number = ([System.Text.Encoding]::ASCII.GetString($Monitor.SerialNumberID)).Replace("$([char]0x0000)","") 82 | #$Mon_Attached_Computer = ($Monitor.PSComputerName).Replace("$([char]0x0000)","") 83 | $Mon_Manufacturer = ([System.Text.Encoding]::ASCII.GetString($Monitor.ManufacturerName)).Replace("$([char]0x0000)","") 84 | 85 | 86 | #Sets a friendly name based on the hash table above. If no entry found sets it to the original 3 character code 87 | $Mon_Manufacturer_Friendly = $ManufacturerHt.$Mon_Manufacturer 88 | If ($null -eq $Mon_Manufacturer_Friendly) { 89 | $Mon_Manufacturer_Friendly = $Mon_Manufacturer 90 | } 91 | 92 | $VideoPort = $VideoOutput[$($connections.$($Monitor.InstanceName).VideoOutputTechnology).ToString()] 93 | 94 | #Creates a custom monitor object and fills it with 4 NoteProperty members and the respective data 95 | $Monitor_Obj = [PSCustomObject]@{ 96 | Manufacturer = $Mon_Manufacturer_Friendly 97 | Model = $Mon_Model 98 | SerialNumber = $Mon_Serial_Number 99 | Year = $Monitor.YearOfManufacture 100 | ShortCode = $Mon_Manufacturer 101 | Port = $VideoPort 102 | } 103 | 104 | $Monitor_Obj 105 | } #End ForEach Monitor 106 | 107 | #Outputs the Array 108 | $Monitor_Array | Format-Table -AutoSize 109 | 110 | if ($null -ne $Monitor_Array){ 111 | $Note = ($Monitor_Array | ConvertTo-Csv -NoTypeInformation | Out-String).Replace('"','') -replace "`r","" 112 | 113 | Import-Module $env:SyncroModule 114 | Set-Asset-Field -Name 'Monitors' -Value $Note 115 | } else { 116 | 'No Monitors Detected' 117 | } 118 | -------------------------------------------------------------------------------- /Get-SyncroVars.ps1: -------------------------------------------------------------------------------- 1 | function Get-SyncroVars { 2 | [CmdletBinding()] 3 | param ( 4 | $File = $MyInvocation.MyCommand.Path, 5 | [string]$BreakString = '#- Start of Script -#', 6 | [switch]$WrapOutput 7 | ) 8 | 9 | begin { 10 | [regex]$GuidRx = '([0-9a-fA-F]{3})[0-9a-fA-F]{5}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{8}([0-9a-fA-F]{4})' 11 | } 12 | 13 | process { 14 | $SyncroVars = foreach ($line in (Get-Content -Path $File -ErrorAction SilentlyContinue)){ 15 | if ($line -like $BreakString) { 16 | break 17 | } else { 18 | # Mask Guid in log 19 | $line -replace $GuidRx, '$1$3*****-****-****-****-********$2$4' 20 | if ($l -lt $line.Length){$l = $line.Length} 21 | } 22 | } 23 | 24 | if ($SyncroVars.Count -ge 1){ 25 | $padding = { 26 | if ($l -gt $HeadTxt.Length){ 27 | ('='* [math]::Ceiling(($l - $HeadTxt.Length) / 2)) 28 | } else { 29 | '=' 30 | } 31 | } 32 | $HeadTxt = ' Start Head Content ' 33 | $HeadPad = & $padding 34 | $FootTxt = ' END Content Block =' 35 | $FootPad = & $padding 36 | 37 | '{0}{1}{0}' -f $HeadPad,$HeadTxt 38 | $SyncroVars 39 | '{0}{1}{0}' -f $FootPad,$FootTxt 40 | '' 41 | } else { 42 | $SyncroVars 43 | } 44 | } 45 | } 46 | 47 | <# Non Function Versions 48 | #region Dynamic logger 49 | $SyncroVars = foreach ($line in (Get-Content -Path $MyInvocation.MyCommand.Path -ErrorAction SilentlyContinue)){ 50 | if ($line -like '*#- Start of Script -#*') { 51 | break 52 | } else { 53 | # Mask Guid in log 54 | $line -replace '([0-9a-fA-F]{3})[0-9a-fA-F]{5}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{8}([0-9a-fA-F]{4})|^(\w{3})\w{23,}(\w{4})$', '$1$3*****-****-****-****-********$2$4' 55 | if ($l -lt $line.Length){$l = $line.Length} 56 | } 57 | } 58 | if ($SyncroVars.Count -ge 1){ 59 | $padding = { 60 | if ($l -gt $HeadTxt.Length){ 61 | ('='* [math]::Ceiling(($l - $HeadTxt.Length) / 2)) 62 | } else { 63 | '=' 64 | } 65 | } 66 | $HeadTxt = ' Start Head Content ' 67 | $HeadPad = & $padding 68 | $FootTxt = ' END Content Block =' 69 | $FootPad = & $padding 70 | 71 | '{0}{1}{0}' -f $HeadPad,$HeadTxt 72 | $SyncroVars 73 | '{0}{1}{0}' -f $FootPad,$FootTxt 74 | '' 75 | } 76 | #endregion Dynamic logger 77 | 78 | #region Simple logger 79 | '#============ Syncro Inserted Code ============#' 80 | foreach ($line in (Get-Content -Path $MyInvocation.MyCommand.Path -ErrorAction Stop)){ 81 | if ($line -like '*#- Start of Script -#*') { 82 | break 83 | } else { 84 | # Mask Guid in log 85 | $line -replace '([0-9a-fA-F]{3})[0-9a-fA-F]{5}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{8}([0-9a-fA-F]{4})|^(\w{3})\w{23,}(\w{4})$', '$1$3*****-****-****-****-********$2$4' 86 | } 87 | } 88 | '#============== END Syncro Code ===============#' 89 | '' 90 | #endregion Simple logger 91 | #> 92 | -------------------------------------------------------------------------------- /Import-SyncroModule.ps1: -------------------------------------------------------------------------------- 1 | function Import-SyncroModule { 2 | param ( 3 | #Defaults to the UUID of local system but you can provide the UUID of Any other Syncro Asset instead. 4 | $UUID 5 | ) 6 | 7 | # Ensure TLS -ge 1.2 8 | if ([Net.ServicePointManager]::SecurityProtocol -lt [Net.SecurityProtocolType]::Tls12){ 9 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 10 | } 11 | 12 | # Set up $env: vars for Syncro Module 13 | if($env:SyncroModule -match '^\s*$'){ 14 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 15 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 16 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 17 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 18 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 19 | $env:RepairTechUUID = if($UUID -match '^\s*$'){ $SyncroRegKey.uuid } else {$UUID} 20 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 21 | } 22 | if ((Test-Path -Path $env:SyncroModule) -and ($PSVersionTable.PSVersion -ge [system.version]'4.0')) { 23 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 24 | } elseif ($PSVersionTable.PSVersion.Major -lt 4) { 25 | Write-Warning "$($PSVersionTable.PSVersion) is not compatible with SyncroModule" 26 | [Environment]::SetEnvironmentVariable('SyncroModule',$null) 27 | $false 28 | } 29 | } 30 | 31 | # use "Get-Command -Module module" to list imported Cmdlets 32 | 33 | <# non Function version 34 | # Ensure TLS -ge 1.2 35 | if ([Net.ServicePointManager]::SecurityProtocol -lt [Net.SecurityProtocolType]::Tls12){ 36 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 37 | } 38 | # Set up $env: vars for Syncro Module 39 | if($env:SyncroModule -match '^\s*$'){ 40 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 41 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 42 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 43 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 44 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 45 | $env:RepairTechUUID = $SyncroRegKey.uuid 46 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 47 | } 48 | if ((Test-Path -Path $env:SyncroModule) -and ($PSVersionTable.PSVersion -ge [system.version]'4.0')) { 49 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 50 | } elseif ($PSVersionTable.PSVersion.Major -lt 4) { 51 | Write-Warning "$($PSVersionTable.PSVersion) is not compatible with SyncroModule" 52 | [Environment]::SetEnvironmentVariable('SyncroModule',$null) 53 | $false 54 | } 55 | #> 56 | 57 | $ModuleHelp = { 58 | # Syncro's full set of examples for our built in Powershell Module 59 | # Date: 2023/06/13 60 | 61 | # This creates an alert in Syncro and triggers the "New RMM Alert" in the Notification Center - automatically de-duping per asset. 62 | Rmm-Alert -Category 'sample_category' -Body 'Message Here' 63 | 64 | # This displays a popup alert on the desktop. 65 | Display-Alert -Message "Super important message here" 66 | 67 | # This logs an activity feed item on an Assets's Activity feed 68 | Log-Activity -Message "Activity description" -EventName "Event name" 69 | 70 | # This saves a screenshot of the desktop to whatever file you specify. 71 | Get-ScreenCapture -FullFileName "C:\temp\screenshot.jpg" 72 | 73 | # This will send you an email, no SMTP server required. 74 | Send-Email -To "jordanritz@eberlysystems.com" -Subject "Test Subject" -Body "This is the body" 75 | 76 | # This will upload the file to Syncro and attach it to the Asset. 77 | Upload-File -FilePath "C:\temp\screenshot.jpg" 78 | 79 | # This can write to your Asset Custom Fields. Use it to store adhoc information that isn't currently surfaced. 80 | Set-Asset-Field -Name "Field Name" -Value $someVariable 81 | 82 | # This can create a Ticket attached to the Asset & Asset Customer. 83 | # You can capture the value of this command to save the ticket_id or ticket.number like: 84 | # $value = Create-Syncro-Ticket 85 | # Write-Host $value.ticket.id 86 | Create-Syncro-Ticket -Subject "New Ticket for $problem" -IssueType "Other" -Status "New" 87 | 88 | # This just needs the ticketid or ticket number and you can add a comment. You can have it be "public" or "private", and email or not, and combine those. 89 | # For example you can make a Public comment (shows on PDF/etc) and have it NOT email the customer. 90 | Create-Syncro-Ticket-Comment -TicketIdOrNumber 123 -Subject "Contacted" -Body "This is the comment body here" -Hidden "true/false" -DoNotEmail "true/false" 91 | 92 | # This can add a timer entry to a ticket. 93 | # $StartTime needs to be formatted for a computer to read, the best format is "2018-02-14 15:30" 94 | # You can use powershell with 'Get-Date -Format o' and that will work nicely. 95 | # If you wanted to get "30 minutes ago and formatted" it works like this (Get-Date).AddMinutes(-30).toString("o") 96 | $startAt = (Get-Date).AddMinutes(-30).toString("o") 97 | Create-Syncro-Ticket-TimerEntry -TicketIdOrNumber 123 -StartTime $startAt -DurationMinutes 30 -Notes "Automated system cleaned up the disk space." -UserIdOrEmail "your.user.email@here.com" -ChargeTime "true/false" 98 | 99 | # Simply updates a ticket, only currently supports status and custom fields. 100 | Update-Syncro-Ticket -TicketIdOrNumber 123 -Status "In Progress" -CustomFieldName "Automation Results" -CustomFieldValue "Results here for example" 101 | 102 | #This closes an RMM alert in Syncro, there can only be one of each alert category per asset, so it will find the correct one. 103 | #If no alert exists it will exit gracefully. You can also choose to close a ticket generated from the alert 104 | Close-Rmm-Alert -Category "sample_category" -CloseAlertTicket "true/false" 105 | 106 | #Add the flag below to suppress and silently continue past any warnings that would normally be displayed. 107 | -WarningAction SilentlyContinue 108 | 109 | #This sends a Broadcast Message to the asset and optionally logs the activity to the asset's Recent Activity section 110 | Broadcast-Message -Title "Title Text" -Message "Super important message" -LogActivity "true/false" 111 | } 112 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 jrdnr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LogPolicy.ps1: -------------------------------------------------------------------------------- 1 | <#- Start of Script -#> 2 | # Expected Runtime Var PolicyName: set to the Value of the policy running the script 3 | # Expected Asset Custom Field: AppliedPolicies 4 | 5 | #region set Vars 6 | $workfolder = 'C:\ProgramData\MSPName' 7 | $cliX = 'policies.clixml' 8 | $date = Get-Date -Format 'yyyy.MM.dd' 9 | 10 | $FullName = Join-Path -Path $workfolder -ChildPath $cliX 11 | #endregion set Vars 12 | 13 | '#============ Syncro Inserted Code ============#' 14 | # Log all code Syncro incserts before the start of the script 15 | foreach ($line in (Get-Content -Path $MyInvocation.MyCommand.Path -ErrorAction Stop)){ 16 | if ($line -eq '<#- Start of Script -#>') {break} 17 | $line 18 | } 19 | '#============== END Syncro Code ===============#' 20 | '' 21 | #Ensure path exists for local log 22 | $path,$folders = ($workfolder.Split('\')) 23 | foreach ($f in $folders){ 24 | $p1 = Join-Path -Path $path -ChildPath $f 25 | if (-not (Test-Path -Path $p1)){ 26 | New-Item -Path $path -Name $f -ItemType Directory 27 | } 28 | $path = $p1 29 | } 30 | 31 | try { 32 | $Policies = Import-Clixml -Path $FullName -ErrorAction Stop 33 | } 34 | catch [System.IO.FileNotFoundException] { 35 | $Policies = @{} 36 | } 37 | 38 | if ($Policies.ContainsKey($date)){ 39 | $Policies.$date = (($Policies.$date -split ',') + $PolicyName | Select-Object -Unique) -join ',' 40 | } else { 41 | $Policies.Add($date,$PolicyName) 42 | } 43 | 44 | $Now = Get-Date 45 | $Keys = $Policies.Keys | Where-Object {[datetime]$_ -lt $Now.AddDays(-7)} 46 | foreach ($k in $Keys){ 47 | $Policies.Remove($k) 48 | } 49 | Export-Clixml -Path $FullName -InputObject $Policies 50 | 51 | If ($null -ne $env:SyncroModule -and $Policies[$date] -notmatch '^\s*$') { 52 | Import-Module $env:SyncroModule -WarningAction SilentlyContinue 53 | Set-Asset-Field -Name 'AppliedPolicies' -Value $Policies[$date] 54 | } 55 | -------------------------------------------------------------------------------- /Monitor Syncro env vars.ps1: -------------------------------------------------------------------------------- 1 | $UUID = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid -ErrorAction Stop).uuid 2 | $ExpectedVars = [Ordered]@{ 3 | RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 4 | RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 5 | RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 6 | RepairTechSyncroSubDomain = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name shop_subdomain).shop_subdomain 7 | RepairTechUUID = $UUID 8 | SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 9 | } 10 | 11 | 'Local $env: vars' 12 | Get-ChildItem -Path env:\ | ? name -match 'RepairTech|Syncro' -OutVariable vars 13 | '' 14 | 15 | if (($vars.name -join ',') -ne ($ExpectedVars.Keys -join ',')){ 16 | $vars.name -join ',' 17 | $ExpectedVars.Keys -join ',' 18 | '' 19 | $Alert = $true 20 | } 21 | 22 | foreach ($v in $vars){ 23 | if ($v.Value -ne $ExpectedVars[$v.name]){ 24 | "Syncro: $($v.Value)" 25 | "Expect: $($ExpectedVars[$v.name])" 26 | '' 27 | $Alert = $true 28 | } 29 | } 30 | 31 | if ($Alert){ 32 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 33 | Rmm-Alert -Category 'Env:Vars Changed' -Body 'Review and update changed Env Vars' 34 | } else { 35 | 'All Vars match' 36 | } 37 | -------------------------------------------------------------------------------- /MonitorHostFile.ps1: -------------------------------------------------------------------------------- 1 | # Set up $env: vars for Syncro Module 2 | if($env:SyncroModule -match '^\s*$'){ 3 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 4 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 5 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 6 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 7 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 8 | $env:RepairTechUUID = $SyncroRegKey.uuid 9 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 10 | } 11 | if (Test-Path -Path $env:SyncroModule) { 12 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 13 | } 14 | 15 | $hosts = Get-Content -Path "$env:SystemRoot\System32\drivers\etc\hosts" | Where-Object {$_ -notlike '#*' -and ($_ -notmatch '^\s*$')} | Out-String 16 | $diff = try { 17 | Compare-Object -ReferenceObject $HostsFile -DifferenceObject $hosts -ErrorAction SilentlyContinue 18 | } 19 | catch { 20 | $null 21 | } 22 | 23 | "Current Hosts Values" 24 | $hosts 25 | 26 | if (($HostsFile -match '^\s*$') -and ($hosts -notmatch '^\s*$')){ 27 | Set-Asset-Field -Name HostsFile -Value $hosts 28 | } elseif ($null -ne $diff) { 29 | $diff 30 | Rmm-Alert -Category 'Hosts File Diff' -Body $hosts 31 | Set-Asset-Field -Name HostsFile -Value $hosts 32 | } 33 | -------------------------------------------------------------------------------- /New-DummyFile.ps1: -------------------------------------------------------------------------------- 1 | function New-DummyFile { 2 | param( 3 | [int]$FileCount = 1, 4 | [int64]$FileBytes, 5 | [string]$Folder = $PWD, 6 | $name = 'DummyFile', 7 | $extension = 'txt' 8 | ) 9 | 10 | # Check for input 11 | if (Test-Path $folder){ 12 | #Set-Location -Path $Folder -ErrorAction Continue 13 | if ($extension -contains '.') { 14 | $extension = $extension.Substring(($extension.LastIndexOf(".") + 1), ($extension.Length - 1)) 15 | } 16 | 17 | foreach($i in (1..$FileCount)) { 18 | do { 19 | $path = $folder + '\' + $name + $r + '_' + $i + '.' + $extension 20 | $r++ 21 | } while (Test-Path -Path $path) 22 | 23 | try { 24 | $f = new-object System.IO.FileStream $path, Create, ReadWrite 25 | $f.SetLength($FileBytes) 26 | $f.Close() 27 | } 28 | catch { 29 | Get-PSDrive -Name ($Folder.split(':')[0]) 30 | return "$i files created" 31 | } 32 | 33 | Start-Sleep -Seconds 0.5 34 | } 35 | 36 | } else { 37 | Write-Warning "The folder $folder doesn't exist" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /PrintNightmare-RegFix.ps1: -------------------------------------------------------------------------------- 1 | # Set up $env: vars for Syncro Module 2 | if($env:SyncroModule -match '^\s*$'){ 3 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 4 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 5 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 6 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 7 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 8 | $env:RepairTechUUID = $SyncroRegKey.uuid 9 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 10 | } 11 | if (Test-Path -Path $env:SyncroModule) { 12 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 13 | } 14 | 15 | $path = 'hklm:' 16 | foreach ($folder in 'SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint'.split('\')) { 17 | $path = Join-Path -Path $path -ChildPath $folder 18 | if(!(Test-Path -Path $path)){ 19 | New-Item -Path $path -ItemType Directory | Out-Null 20 | } 21 | } 22 | 23 | $key = Get-ItemProperty -Path $path 24 | foreach ($prop in @('NoWarningNoElevationOnInstall','UpdatePromptSettings')) { 25 | if(($key | Get-Member | Where-Object { $_.name -eq $prop }).count -ge 1){ 26 | if($key.$prop -ne 0){ 27 | try { 28 | Set-ItemProperty -Name $key -Path $path -Value 0 -ErrorAction Stop 29 | $message = "Set $Prop to 0" 30 | Log-Activity -Message $message 31 | $message 32 | } 33 | catch { 34 | $message = "Could not set $Prop -eq $($key.$prop)" 35 | Log-Activity -Message $message 36 | Write-Warning $message 37 | } 38 | } 39 | } else { 40 | try { 41 | New-ItemProperty -Path $path -Name $prop -Value 0 -ErrorAction Stop 42 | $message = "Set $Prop to 0" 43 | Log-Activity -Message $message 44 | $message 45 | } 46 | catch { 47 | $message = "Could not create new property $Prop -eq $($key.$prop)" 48 | Log-Activity -Message $message 49 | Write-Warning $message 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SyncroMSP 2 | Unofficial Scripts repo for SyncroMSP, 3 | 4 | Pull requests welcome 5 | -------------------------------------------------------------------------------- /Re-enable WindowsUpdate Registry.ps1: -------------------------------------------------------------------------------- 1 | Get-Item HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate | 2 | Select-Object -ExpandProperty Property | 3 | Where-Object {$_ -ne 'ElevateNonAdmins'} | 4 | ForEach-Object { 5 | Remove-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate -Name $_ -ErrorAction Continue 6 | } 7 | 8 | Get-Item HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate -OutVariable p 9 | if ($p.Property -contains 'DisableWindowsUpdateAccess'){ 10 | exit 2 11 | } 12 | -------------------------------------------------------------------------------- /Remove_butil_2_3.sys.ps1: -------------------------------------------------------------------------------- 1 | $path = "C:\Users" 2 | 3 | $child_path = "AppData\Local\Temp" 4 | 5 | $files_filter = "dbutil_*_*.sys" 6 | 7 | # Set up $env: vars for Syncro Module 8 | if($env:SyncroModule -match '^\s*$'){ 9 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 10 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 11 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 12 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 13 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 14 | $env:RepairTechUUID = $SyncroRegKey.uuid 15 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 16 | } 17 | if (Test-Path -Path $env:SyncroModule) { 18 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 19 | } 20 | 21 | $paths = @("C:\Windows\Temp") 22 | [array]$paths += Get-ChildItem $path -Directory -Exclude Default*,Public | ForEach-Object { 23 | Join-Path -Path $_.FullName -ChildPath $child_path 24 | } 25 | 26 | "Paths to scan for dangerous files" 27 | $paths 28 | 29 | Get-ChildItem -Path $paths -Filter $files_filter -OutVariable f | ForEach-Object { 30 | $filePath = $_.FullName 31 | "Cleaning $filePath" 32 | try { 33 | Remove-Item $filePath -Force -Verbose -ErrorAction Stop 34 | "Removed $filePath" 35 | Log-Activity -Message "Removed $filePath" -EventName 'PowershellScript' -ErrorAction SilentlyContinue 36 | } 37 | catch { 38 | "Could not remove $filePath. Remove Manually" 39 | Rmm-Alert -Category Script_Error -Body "Could not remove $filePath. Remove Manually" 40 | exit 1 41 | } 42 | } 43 | 44 | if ($null -eq $f -or $f.count -eq 0){"Scan Successful: $files_filter, was not found on this system"} 45 | -------------------------------------------------------------------------------- /Set-PowerPlan.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Simple script to set PowerPlan 4 | 5 | .DESCRIPTION 6 | This Script uses pre-defined Microsoft Guids (https://docs.microsoft.com/en-us/windows/win32/power/power-policy-settings) 7 | to set the power plan to High performance, Balanced, or Power saver 8 | 9 | .PARAMETER PowerPlan 10 | Parameter PowerPlan should be set up as a Syncro Runtime Variable 11 | Variable Name: PowerPlan 12 | Variable Type: dropdown 13 | Values: High performance, Balanced, Power saver 14 | 15 | 16 | .EXAMPLE 17 | Set-PowerPlan -PowerPlan Balanced 18 | #> 19 | function Set-PowerPlan ($PowerPlan) { 20 | switch ($PowerPlan) { 21 | "Balanced" {$PwrGuid = '381b4222-f694-41f0-9685-ff5bb260df2e'} 22 | "Power saver" {$PwrGuid = 'a1841308-3541-4fab-bc81-f71556f20b4a'} 23 | default { 24 | # High performance 25 | $PwrGuid = '8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c' 26 | } 27 | } 28 | try { 29 | $crntPlan = $(powercfg -getactivescheme).split()[3] 30 | 31 | if ($crntPlan -ne $PwrGuid) { 32 | powercfg -setactive $PwrGuid 33 | } 34 | } catch { 35 | Write-Warning -Message "Unabled to set power plan to $PowerPlan" 36 | } 37 | 38 | Get-CimInstance -Name root\cimv2\power -Class win32_PowerPlan -Filter "IsActive = 'True'" | 39 | Select-Object -Property ElementName, Description 40 | } 41 | 42 | function New-PowerPlan { 43 | [CmdletBinding()] 44 | param ( 45 | [string]$SourcePowerPlan, 46 | [string]$PowerPlanName, 47 | [int]$LidCloseAction, 48 | [int]$MonitorTimeoutAC = 30, 49 | [int]$MonitorTimeoutDC = 30, 50 | [int]$StandbyTimeoutAC = 0, 51 | [int]$StandbyTimeoutDC = 0, 52 | [int]$HybernateTimeoutAC = 0, 53 | [int]$HybernateTimeoutDC = 0, 54 | [Switch]$EnableFastboot 55 | ) 56 | 57 | begin { 58 | # Create custom power plan: https://www.tenforums.com/tutorials/43655-create-custom-power-plan-windows-10-a.html 59 | # Change lid close action: https://www.tenforums.com/tutorials/69762-how-change-default-lid-close-action-windows-10-a.html 60 | switch ($SourcePowerPlan) { 61 | "Balanced" {$PwrGuid = '381b4222-f694-41f0-9685-ff5bb260df2e'} 62 | "Power saver" {$PwrGuid = 'a1841308-3541-4fab-bc81-f71556f20b4a'} 63 | default { 64 | # High performance 65 | $PwrGuid = '8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c' 66 | } 67 | } 68 | #$regex = '[{]?[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?' 69 | } 70 | 71 | process { 72 | $NewGuid = New-Guid 73 | POWERCFG -DUPLICATESCHEME $PwrGuid $NewGuid 74 | POWERCFG -CHANGENAME $NewGuid $PowerPlanName 75 | POWERCFG -SETACTIVE $NewGuid 76 | POWERCFG -Change -monitor-timeout-ac 30 77 | POWERCFG -CHANGE -monitor-timeout-dc 30 78 | POWERCFG -CHANGE -disk-timeout-ac 0 79 | POWERCFG -CHANGE -disk-timeout-dc 0 80 | POWERCFG -CHANGE -standby-timeout-ac 0 81 | POWERCFG -CHANGE -standby-timeout-dc 0 82 | POWERCFG -CHANGE -hibernate-timeout-ac 0 83 | POWERCFG -CHANGE -hibernate-timeout-dc 0 84 | } 85 | 86 | end { 87 | 88 | } 89 | } 90 | 91 | Set-PowerPlan -PowerPlan $PowerPlan 92 | -------------------------------------------------------------------------------- /SmartMonitoring.ps1: -------------------------------------------------------------------------------- 1 | Import-Module $env:SyncroModule -WarningAction SilentlyContinue 2 | #Requires -Version 3.0 3 | #Requires -RunAsAdministrator 4 | # Note: The threshold values used below are mostly guesses as to what might be concerning and sometimes 5 | # manufacturers even use the same attribute number for different purposes, so don't take any 6 | # one value as critical and feel free to adjust as you feel appropreiate, or even remove attributes 7 | # from monitoring entirely. It's also possible some should be monitoring Worst vs RawValue. 8 | # 9 | # Author: Nullzilla on Pastebin 10 | # Edit: Jrdn 11 | 12 | # If this is a virtual machine, we don't need to continue 13 | $Computer = Get-CimInstance -ClassName 'Win32_ComputerSystem' 14 | if ($Computer.Model -like 'Virtual*') { 15 | exit 16 | } 17 | 18 | $disks = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | 19 | Select-Object 'InstanceName') 20 | 21 | $Warnings = @() 22 | 23 | function Select-ErrorData { 24 | [CmdletBinding()] 25 | param ( 26 | [Parameter(ValueFromPipeline)] 27 | [array]$Item 28 | ) 29 | 30 | begin {} 31 | 32 | process { 33 | foreach($i in $Item){ 34 | $test = switch ($i.ID) { 35 | # Reallocated Sectors Count 36 | 5 { $i.RawValue -gt 1 } 37 | 38 | # Spin Retry Count 39 | 10 { $i.RawValue -ne 0 } 40 | 41 | # Recalibration Retries 42 | 11 { $i.RawValue -ne 0 } 43 | 44 | # Spare Blocks Available 45 | 16 { $i.RawValue -lt 100 } 46 | 47 | # Remaining Spare Blocks 48 | 17 { $i.RawValue -lt 100 } 49 | 50 | # Used Reserved Block Count Total 51 | 179 { $i.RawValue -gt 1 } 52 | 53 | # Unused Reserved Block Count (Available Spare Blocks on PCIe SSDs) (Crucial Brand) 54 | 180 { $i.RawValue -lt 100 } 55 | 56 | # Erase Failure Count 57 | 182 { $i.RawValue -ne 0 } 58 | 59 | # SATA Downshift Error Count or Runtime Bad Block 60 | 183 { $i.RawValue -ne 0 } 61 | 62 | # End-to-End error / IOEDC 63 | 184 { $i.RawValue -ne 0 } 64 | 65 | # Reported Uncorrectable Errors 66 | 187 { $i.RawValue -ne 0 } 67 | 68 | # Command Timeout 69 | 188 { $i.RawValue -gt 2 } 70 | 71 | # High Fly Writes 72 | 189 { $i.RawValue -ne 0 } 73 | 74 | # Temperature Celcius 75 | 194 { $i.RawValue -gt 50 } 76 | 77 | # Reallocation Event Count 78 | 196 { $i.RawValue -ne 0 } 79 | 80 | # Current Pending Sector Count 81 | 197 { $i.RawValue -ne 0 } 82 | 83 | # Uncorrectable Sector Count 84 | 198 { $i.RawValue -ne 0 } 85 | 86 | # UltraDMA CRC Error Count 87 | 199 { $i.RawValue -ne 0 } 88 | 89 | # Soft Read Error Rate 90 | 201 { $i.Worst -lt 95 } 91 | 92 | # RAIN Successful Recovery Page Count (Crucial Brand) 93 | 210 { $i.Worst -lt 95 } 94 | 95 | # SSD Life Left 96 | 231 { $i.Worst -lt 30 } 97 | 98 | # SSD Media Wear Out Indicator 99 | 233 { $i.Worst -lt 30 } 100 | 101 | default {$false} 102 | } 103 | if ($test) { 104 | $i 105 | } 106 | } 107 | } 108 | 109 | end {} 110 | } 111 | 112 | foreach ($disk in $disks.InstanceName) { 113 | # Retrieve SMART data 114 | $SmartData = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_ATAPISMartData' | 115 | Where-Object 'InstanceName' -eq $disk) 116 | 117 | [Byte[]]$RawSmartData = $SmartData | Select-Object -ExpandProperty 'VendorSpecific' 118 | 119 | # Starting at the third number (first two are irrelevant) 120 | # get the relevant data by iterating over every 12th number 121 | # and saving the values from an offset of the SMART attribute ID 122 | [PSCustomObject[]]$Output = for ($i = 2; $i -lt $RawSmartData.Count; $i++) { 123 | if (0 -eq ($i - 2) % 12 -and $RawSmartData[$i] -ne 0) { 124 | # Construct the raw attribute value by combining the two bytes that make it up 125 | [Decimal]$RawValue = ($RawSmartData[$i + 6] * [Math]::Pow(2, 8) + $RawSmartData[$i + 5]) 126 | 127 | $InnerOutput = [PSCustomObject]@{ 128 | DiskID = $disk 129 | ID = [int]$RawSmartData[$i] 130 | #Flags = $RawSmartData[$i + 1] 131 | #Value = $RawSmartData[$i + 3] 132 | Worst = $RawSmartData[$i + 4] 133 | RawValue = $RawValue 134 | } 135 | 136 | $InnerOutput 137 | } 138 | } 139 | $output| Sort-Object ID | Out-String 140 | 141 | $Warnings += $Output | Select-ErrorData | Format-Table 142 | } 143 | 144 | $Warnings += Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | 145 | Select-Object InstanceName, PredictFailure, Reason | 146 | Where-Object {$_.PredictFailure -ne $False} | Format-Table 147 | 148 | $Warnings += Get-CimInstance -ClassName 'Win32_DiskDrive' | 149 | Select-Object Model, SerialNumber, Name, Size, Status | 150 | Where-Object {$_.status -ne 'OK'} | Format-Table 151 | 152 | $Warnings += Get-PhysicalDisk | 153 | Select-Object FriendlyName, Size, MediaType, OperationalStatus, HealthStatus | 154 | Where-Object {$_.OperationalStatus -ne 'OK' -or $_.HealthStatus -ne 'Healthy'} | Format-Table 155 | 156 | if ($Warnings) { 157 | $Warnings = $warnings | Out-String 158 | $Warnings 159 | Rmm-Alert -Category 'Monitor - Drive SMART Values' -Body "$Warnings" 160 | Exit 1 161 | } 162 | 163 | if ($Error) { 164 | if ($Error -match "Not supported") { 165 | $notsup = "You may need to switch from AHCI to RAID/RST mode, see the link for how to do this non-destructively: https://www.top-password.com/blog/switch-from-raid-to-ahci-without-reinstalling-windows/" 166 | $notsup 167 | } 168 | Rmm-Alert -Category 'Monitor - Drive SMART Values' -Body "$Error $notsup" 169 | exit 1 170 | } 171 | 172 | Close-Rmm-Alert -Category "Monitor - Drive SMART Values" 173 | -------------------------------------------------------------------------------- /Syncro - Force Full-Large sync.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Forces the Syncro agent to perform a Full Sync. 3 | 4 | Take note that this script will restart the Syncro service. This is done on a delay so the script is reported as successful on the dashboard. 5 | 6 | The script also adds an Activity Log on the asset if the full sync was successful. 7 | 8 | USE AT YOUR OWN RISK. 9 | credit: https://pastebin.com/6SR9r9VR?fbclid=IwAR0hS06OnsJnegceWUhN9iL0HDH28tVnq0aaoouNcB-r3jHFTuw8zYW-Um4 10 | #> 11 | 12 | $UpdateTime = (Get-Date).ToUniversalTime().AddMinutes(5).ToString("yyyy-MM-ddTHH:mm:ss.0000000Z") 13 | #Update Syncro last_sync registry value 14 | Set-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro" -Name "last_sync" -Value "$UpdateTime" 15 | 16 | function Run-InNewProcess{ 17 | param([String] $code) 18 | $code = "function Run{ $code }; Run $args" 19 | $encoded = [Convert]::ToBase64String( [Text.Encoding]::Unicode.GetBytes($code)) 20 | 21 | start-process -WindowStyle hidden PowerShell.exe -argumentlist '-windowstyle','hidden','-noExit','-encodedCommand',$encoded 22 | } 23 | 24 | $script = { 25 | $CurrentDateString = (Get-Date).ToString("yyyyMMdd") 26 | $LogLocation = "C:\ProgramData\Syncro\logs\$CurrentDateString-Syncro.Service.Runner.log" 27 | 28 | Import-Module $env:SyncroModule 29 | 30 | Start-Sleep -s 10; 31 | Restart-Service -Name "Syncro" -Force 32 | 33 | Log-Activity -Message "Restarted Syncro Service for Full Sync" -EventName "SyncroRestart" 34 | 35 | # Hack to get Get-Content -wait to work properly 36 | $hackJob = Start-Job { 37 | $f=Get-Item $LogLocation 38 | while (1) { 39 | $f.LastWriteTime = Get-Date 40 | Start-Sleep -Seconds 1 41 | } 42 | } 43 | 44 | # Job that confirms if the sync happened 45 | $job = Start-Job { param($LogLocation) 46 | Import-Module $env:SyncroModule 47 | 48 | Get-Content $LogLocation -tail 0 -wait | where { $_ -match "Large sync complete" } |% { Log-Activity -Message "Full Sync Successful" -EventName "SyncroFullSync"; break } 49 | } -Arg $LogLocation 50 | 51 | # Wait for the Activity-Log job to complete or to timeout 52 | Wait-Job $job -Timeout 60 53 | 54 | # Cleanup jobs 55 | Get-Job | Stop-Job 56 | Get-Job | Remove-Job 57 | } 58 | 59 | Run-InNewProcess $script | Out-Null 60 | 61 | Exit 0 62 | -------------------------------------------------------------------------------- /Syncro API - Customer Custom field.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Update a customer custom field using the Syncro API 4 | .DESCRIPTION 5 | To use this script, you have to create a API Token that has those permissions: 6 | - Customer - Edit 7 | .NOTES 8 | Version: 1.0 9 | Author: Alexandre-Jacques St-Jacques 10 | Creation Date: 14-04-2021 11 | Purpose/Change: Initial script development 12 | #> 13 | 14 | # The API token used for the request. Create a API key with permission "Customer - Edit". It is advised to populated it with the "Script variable" feature of syncro 15 | #$ApiToken = "test" 16 | # Will usually be syncromsp.com 17 | $ApiBaseURL = $env:RepairTechApiBaseURL 18 | # Your account sub domain will magically be imported. 19 | $ApiSubDomain = $env:RepairTechApiSubDomain 20 | 21 | function Update-CustomerCustomField { 22 | param( 23 | [Parameter(Mandatory=$true)] 24 | [String] 25 | $ApiToken, 26 | [Parameter(Mandatory=$true)] 27 | [String] 28 | $CustomerId, 29 | [Parameter(Mandatory=$true)] 30 | [String] 31 | $CustomField, 32 | [Parameter(Mandatory=$true)] 33 | [String] 34 | $CustomFieldValue 35 | ) 36 | 37 | $headers = @{ 38 | Content='application/json' 39 | Authorization="Bearer $ApiToken" 40 | } 41 | 42 | $payload = @" 43 | { 44 | "properties": { 45 | "$CustomField": "$CustomFieldValue" 46 | } 47 | } 48 | "@ 49 | 50 | $ApiPath = "/api/v1/customers" 51 | 52 | $resp = try { 53 | Invoke-RestMethod -Method PUT "https://$($ApiSubDomain).$($ApiBaseURL)$($ApiPath)/$($CustomerId)" -Headers $headers -Body "$payload" -ContentType "application/json" 54 | } catch { 55 | Write-Host "ERROR!" 56 | $result = $_.Exception.Response.GetResponseStream() 57 | $reader = New-Object System.IO.StreamReader($result) 58 | $reader.BaseStream.Position = 0 59 | $reader.DiscardBufferedData() 60 | $responseBody = $reader.ReadToEnd(); 61 | Write-Host $responseBody 62 | } 63 | } 64 | 65 | # This is the function call to update the custom field of a customer. I would recommend you to populate $CustomerID using a script variable that uses the "{{customer_id}}" platform variable 66 | Update-CustomerCustomField -ApiToken $ApiToken -CustomerId $CustomerID -CustomField "Customer test" -CustomFieldValue "testing" 67 | -------------------------------------------------------------------------------- /Test-PendingReboot.ps1: -------------------------------------------------------------------------------- 1 | <#- Start of Script -#> 2 | # Addapted from https://adamtheautomator.com/pending-reboot-registry-windows/ 3 | # see origional source for running against multiple computers. 4 | <# 5 | .SYNOPSIS 6 | Tests Pending reboot 7 | 8 | .DESCRIPTION 9 | Tests multiple registry keys for anythign that would indicate a pending reboot. 10 | It can clear pending reboots and trigger a reboot or generate a syncro alert. 11 | 12 | .PARAMETER AutoReboot 13 | Optional Runtime variable to say if the script should auto reboot. 14 | default behavior without $AutoReboot set is to just trigger an alert 15 | 16 | .PARAMETER RebootLocalTime 17 | Optional Runtime variable $RebootTime to set the local time to reboot. 18 | If the string matches \d\d and is less than 60 the reboot will be scheduled for T+minutes. 19 | If the string matches a time that can be parsed by Get-Date and that Date in local time is 20 | in the future a reboot will be scheduled at that time. Otherwise Reboot time will default to 2 min 21 | 22 | .OUTPUTS 23 | Default behavior this script will self log to host, and generate a Syncro alert 24 | Alternate behavior, it will log results to activity Log and reboot. 25 | 26 | #> 27 | '#============ Syncro Inserted Code ============#' 28 | foreach ($line in (Get-Content -Path $MyInvocation.MyCommand.Path -ErrorAction SilentlyContinue)) { 29 | if ($line -eq '<#- Start of Script -#>') { break } 30 | $line 31 | } 32 | '#============== END Syncro Code ===============#' 33 | '' 34 | $RequiredModules = @( 35 | 'BurntToast', 36 | 'RunAsUser', 37 | 'PSSQLite' 38 | ) 39 | 40 | if ($RebootDelayMin0_30 -notmatch '^\s*$' -and $RebootTime -match '^\s*$') { 41 | $RebootLocalTime = $RebootDelayMin0_30 42 | } 43 | $RebootTime = switch -regex ($RebootLocalTime) { 44 | '^[6-9]\d$' { (Get-Date).AddSeconds($_) } 45 | '^[0-5]?\d$' { (Get-Date).AddMinutes($_) } 46 | '^\d?\d:\d\d' { 47 | try { 48 | $d = Get-Date -Date $_ -ErrorAction Stop 49 | if ($d -ge (Get-Date)) { 50 | $d 51 | } else { 52 | Get-Date 53 | } 54 | } catch { Get-Date } 55 | } 56 | Default { Get-Date } 57 | } 58 | switch ($AutoReboot) { 59 | 'True' { $AutoReboot = $true } 60 | Default { $AutoReboot = $false } 61 | } 62 | 63 | 64 | #Region Functions 65 | function InstallOrUpdateModule { 66 | param ( 67 | [string[]]$Name 68 | ) 69 | 70 | begin { 71 | if ((Get-PSRepository -Name PSGallery).InstallationPolicy -ne 'Trusted') { 72 | Install-PackageProvider -Name NuGet -Force 73 | Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted 74 | } 75 | } 76 | 77 | process { 78 | foreach ($n in $Name) { 79 | if (Get-InstalledModule -Name $n -ErrorAction SilentlyContinue) { 80 | Update-Module -Name $n 81 | } else { 82 | Install-Module -Name $n -Scope AllUsers -Force 83 | } 84 | } 85 | foreach ($m in $Name) { 86 | $allversions = Get-InstalledModule -Name $m -AllVersions -ErrorAction SilentlyContinue | Sort-Object Version -Descending 87 | if ($allversions.Count -gt 1) { 88 | "Uninstalling $m v$($allversions[1])" 89 | Uninstall-Module $allversions[1..$allversions.Count] -Force -ErrorAction SilentlyContinue 90 | } 91 | } 92 | } 93 | } 94 | 95 | Function New-ScheduledTaskFolder { 96 | Param ($TaskPath) 97 | 98 | $ErrorActionPreference = "stop" 99 | $scheduleObject = New-Object -ComObject schedule.service 100 | $scheduleObject.connect() 101 | 102 | $rootFolder = $scheduleObject.GetFolder("\") 103 | Try { $null = $scheduleObject.GetFolder($TaskPath) } 104 | Catch { $null = $rootFolder.CreateFolder($TaskPath) } 105 | Finally { $ErrorActionPreference = "continue" } 106 | } 107 | 108 | function Add-ScheduledReboot { 109 | [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] 110 | param ( 111 | [datetime]$RebootTime, 112 | [int]$RebootDelaySeconds = 30, 113 | [string]$RebootReason = 'Scripted Maintenance Reboot', 114 | [string]$TaskPath = 'EberlySystems', 115 | [switch]$OutObject 116 | ) 117 | 118 | begin { 119 | $WUStatus = Get-WURebootStatus -Silent -ErrorAction SilentlyContinue 120 | if ($RebootTime -lt (Get-Date).AddSeconds($RebootDelaySeconds + 10)) { 121 | $RebootTime = (Get-Date).AddSeconds($RebootDelaySeconds + 10) 122 | $SchTaskTime = (Get-Date).AddSeconds(10) 123 | } else { 124 | $SchTaskTime = $RebootTime.AddSeconds(-$RebootDelaySeconds) 125 | } 126 | 127 | $RebootComment = @' 128 | Windows Will shutdown at {1} 129 | Please Save your work and close all applications 130 | Reason: {0} 131 | '@ -f $RebootReason, $RebootTime.ToShortTimeString() 132 | 133 | $ShutdownArgs = '/r /t {0} /d p:0:0 /c "{1}"' -f $RebootDelaySeconds, $RebootComment 134 | 135 | $POSHScript = @' 136 | Get-WURebootStatus -AutoReboot -ea SilentlyContinue; Start-Sleep -Seconds {0}; shutdown.exe {1} 137 | '@ -f $RebootDelaySeconds, $ShutdownArgs 138 | 139 | $Base64encode = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($POSHScript)) 140 | $PoshArgs = "-ExecutionPolicy RemoteSigned -EncodedCommand $Base64encode" 141 | 142 | if ($true -eq $WUStatus) { 143 | $SchTaskAction = @{ 144 | Execute = 'powershell.exe' 145 | Argument = $PoshArgs 146 | } 147 | } else { 148 | $SchTaskAction = @{ 149 | Execute = 'shutdown.exe' 150 | Argument = $ShutdownArgs 151 | } 152 | } 153 | } 154 | 155 | process { 156 | New-ScheduledTaskFolder -TaskPath $TaskPath 157 | 158 | if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME)) { 159 | $TAction = New-ScheduledTaskAction @SchTaskAction 160 | $TTrigger = New-ScheduledTaskTrigger -Once -At $SchTaskTime 161 | $TSchedule = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -DontStopOnIdleEnd 162 | try { 163 | Get-ScheduledTask -TaskName 'RebootComputer' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false 164 | Register-ScheduledTask -TaskName 'RebootComputer' -TaskPath $TaskPath -Action $TAction -Trigger $TTrigger -RunLevel Highest -User System -Settings $TSchedule -ErrorAction Stop 165 | $SchTaskFailed = $false 166 | } catch { 167 | $SchTaskFailed = $true 168 | } 169 | 170 | 171 | # try { 172 | # Register-ScheduledTask -TaskName 'RebootComputer' -TaskPath $TaskPath -Action $TAction -Trigger $TTrigger -RunLevel Highest -User System -Settings $TSchedule -ErrorAction Stop 173 | # } catch [Microsoft.Management.Infrastructure.CimException] { 174 | # Set-ScheduledTask -TaskName 'RebootComputer' -TaskPath $TaskPath -Action $TAction -Trigger $TTrigger -User System -Settings $TSchedule 175 | # } catch { 176 | # (($Error[0] | Select-Object -Property Exception | Out-String).trim() -split '\r')[-1] 177 | # exit 1 178 | # } 179 | 180 | Write-Host $RebootComment 181 | } 182 | 183 | if ($PSBoundParameters.ContainsKey('OutObject')) { 184 | [PSCustomObject]@{ 185 | RebootReason = $RebootReason 186 | RebootTime = $RebootTime 187 | RebootComment = $RebootComment 188 | WinUpdateReq = $WUStatus 189 | SchTaskFailed = $SchTaskFailed 190 | } 191 | } 192 | } 193 | 194 | end {} 195 | } 196 | 197 | function New-ToastPopUp { 198 | [CmdletBinding()] 199 | param ( 200 | 201 | ) 202 | 203 | begin { 204 | New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT -erroraction silentlycontinue | out-null 205 | $ProtocolHandler = get-item 'HKCR:\ToastReboot' -erroraction 'silentlycontinue' 206 | if (!$ProtocolHandler) { 207 | #create handler for reboot 208 | New-item 'HKCR:\ToastReboot' -force 209 | set-itemproperty 'HKCR:\ToastReboot' -name '(DEFAULT)' -value 'url:ToastReboot' -force 210 | set-itemproperty 'HKCR:\ToastReboot' -name 'URL Protocol' -value '' -force 211 | new-itemproperty -path 'HKCR:\ToastReboot' -propertytype dword -name 'EditFlags' -value 2162688 212 | New-item 'HKCR:\ToastReboot\Shell\Open\command' -force 213 | set-itemproperty 'HKCR:\ToastReboot\Shell\Open\command' -name '(DEFAULT)' -value 'C:\Windows\System32\shutdown.exe -r -t 30' -force 214 | } 215 | if (-not (Test-Path C:\ProgramData\EberlySystems)) { 216 | New-Item -Path C:\ProgramData -Name EberlySystems -ItemType Directory 217 | } 218 | } 219 | 220 | process { 221 | invoke-ascurrentuser -scriptblock { 222 | $heroimage = New-BTImage -Source 'https://dlpool0dd7ff86378b.blob.core.windows.net/warning-pubic-blob/EberlyOnWhite.gif' -HeroImage 223 | $Text1 = New-BTText -Content "Eberly Systems - Reboot Required" 224 | $Text2 = New-BTText -Content "Your computer has a pending reboot. Please select if you'd like to reboot now, or snooze this message. It is important to reboot when possible for the security and performance of your system." 225 | $Button = New-BTButton -Content "Snooze" -snooze -id 'SnoozeTime' 226 | $Button2 = New-BTButton -Content "Reboot now" -Arguments "ToastReboot:" -ActivationType Protocol 227 | $5Min = New-BTSelectionBoxItem -Id 5 -Content '5 minutes' 228 | $10Min = New-BTSelectionBoxItem -Id 10 -Content '10 minutes' 229 | $1Hour = New-BTSelectionBoxItem -Id 60 -Content '1 hour' 230 | $4Hour = New-BTSelectionBoxItem -Id 240 -Content '4 hours' 231 | $1Day = New-BTSelectionBoxItem -Id 1440 -Content '1 day' 232 | $Items = $5Min, $10Min, $1Hour, $4Hour, $1Day 233 | $SelectionBox = New-BTInput -Id 'SnoozeTime' -DefaultSelectionBoxItemId 10 -Items $Items 234 | $action = New-BTAction -Buttons $Button, $Button2 -inputs $SelectionBox 235 | $Binding = New-BTBinding -Children $text1, $text2 -HeroImage $heroimage 236 | $Visual = New-BTVisual -BindingGeneric $Binding 237 | $Content = New-BTContent -Visual $Visual -Actions $action 238 | Submit-BTNotification -Content $Content -Verbose 239 | } 240 | } 241 | 242 | end { 243 | } 244 | } 245 | 246 | function New-CleanupSchTask { 247 | param ( 248 | [scriptblock]$ScriptBlock, 249 | [string]$ScriptPath = "$env:ProgramFiles\WindowsPowerShell\Scripts\Test-PendingReboot.ps1", 250 | [string]$TaskPath, 251 | [string]$TaskName = 'ClearPendingReboot' 252 | ) 253 | New-ScheduledTaskFolder -TaskPath $TaskPath 254 | 255 | $ScriptFolderPath = Split-Path -Path $ScriptPath -Parent 256 | if (! (Test-Path -Path $ScriptFolderPath)) { 257 | New-Item -Path $ScriptFolderPath -ItemType Directory 258 | } 259 | 260 | # Write $ScriptBlock block to Scripts folder 261 | if ($ScriptBlock -notmatch '^\s*$') { 262 | $ScriptBlock.ToString() | Out-File -FilePath $ScriptPath -Force 263 | } elseif (-not (Test-Path -Path $ScriptPath)) { 264 | throw 'Missing $ScriptBlock Block and script file' 265 | } 266 | 267 | $fileHash = Get-FileHash -Path $ScriptPath -Algorithm SHA256 268 | # Use ScheduledTask to cleanup after reboot 269 | $ScriptArgs = "-ClearKeys" 270 | $B64Script = "`$fp = '$ScriptPath'; if((Get-FileHash -Path `$fp -Algorithm SHA256).Hash -eq '$($fileHash.Hash)'){ & `$fp $ScriptArgs }; " 271 | $B64Script += "Remove-Item -Path `$fp -force; Get-ScheduledTask -TaskName $TaskName* | Disable-ScheduledTask" 272 | Write-Verbose "ScriptBlock" 273 | Write-Verbose "{$B64Script}" 274 | $Base64encode = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($B64Script)) 275 | $TArgs = "-ExecutionPolicy RemoteSigned -EncodedCommand $Base64encode" 276 | $TProgram = "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" 277 | $TAction = New-ScheduledTaskAction -Execute $TProgram -Argument $TArgs 278 | $TTrigger = New-ScheduledTaskTrigger -AtStartUp #-RandomDelay (New-TimeSpan -Seconds 90) 279 | $TSchedule = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -DontStopOnIdleEnd 280 | 281 | if (Get-ScheduledTask -TaskName "$TaskName*" -ErrorAction SilentlyContinue -OutVariable SchTsk) { 282 | Set-ScheduledTask -TaskName $SchTsk[0].TaskName -TaskPath $SchTsk[0].TaskPath -Action $TAction -Trigger $TTrigger -User System -Settings $TSchedule 283 | } else { 284 | Unregister-ScheduledTask -Confirm:$false -TaskName "$TaskName*" -ErrorAction SilentlyContinue 285 | Remove-Item -Path "C:\Windows\System32\Tasks\$TaskPath\$TaskName*" -ErrorAction SilentlyContinue -Force 286 | try { 287 | Register-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -Action $TAction -Trigger $TTrigger -RunLevel Highest -User System -Settings $TSchedule 288 | } catch { 289 | shutdown /r /t 30 290 | } 291 | } 292 | } 293 | 294 | function Enable-AppNotifications { 295 | [CmdletBinding()] 296 | param ( 297 | [Parameter( 298 | Position = 0, 299 | Mandatory = $true, 300 | ValueFromPipeline = $true, 301 | ValueFromPipelineByPropertyName 302 | )] 303 | [Alias('UserName')] 304 | [string[]]$Users, 305 | [string]$AppName = 'powershell.exe' 306 | ) 307 | 308 | begin { 309 | New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null 310 | [array]$CimUsers = Get-CimInstance -ClassName Win32_UserProfile | Where-Object { $_.LocalPath -like 'c:\user*' } 311 | if (($Users -eq '*' -or $Users -eq 'All') -and $Users.Count -eq 1) { 312 | $Users = $CimUsers.LocalPath | ForEach-Object { ($_ -split '\\')[-1] } 313 | } 314 | } 315 | 316 | process { 317 | foreach ($u in $Users) { 318 | $cimU = $CimUsers.where({ $_.localpath -match $u }) 319 | $hkuPath = "HKU\$($cimU.SID)" 320 | $ntuserdat = Join-Path -Path $cimU.LocalPath -ChildPath NTUSER.DAT 321 | $UserHive = "HKU:\$($cimU.SID)" 322 | $AppDataFldr = Join-Path -Path $cimU.localpath -ChildPath 'AppData\Local' 323 | $unload = $false 324 | 325 | if (!(Test-Path -Path $UserHive)) { 326 | reg load $hkuPath $ntuserdat 327 | $unload = $true 328 | } 329 | 330 | try { 331 | ##Database 332 | #Import SQLite module 333 | Import-Module PSSQLite 334 | 335 | #Set DBPath 336 | $DatabasePath = "$AppDataFldr\Microsoft\Windows\Notifications\wpndatabase.db" 337 | 338 | #Define select query 339 | $SelectQuery = " 340 | SELECT HS.HandlerId, HS.SettingKey, HS.Value 341 | FROM NotificationHandler AS NH 342 | INNER JOIN HandlerSettings AS HS ON NH.RecordId = HS.HandlerID 343 | WHERE NH.PrimaryId LIKE '%$AppName' 344 | AND HS.SettingKey = 's:toast' 345 | " 346 | #Invoke selectquery 347 | $NotificationSettings = Invoke-SqliteQuery -DataSource $DatabasePath -Query $SelectQuery 348 | 349 | #If the setting are wrong 350 | if ($NotificationSettings.Value -ne 1) { 351 | Write-Verbose 'NotificationSettings -ne 1' 352 | #Create update query 353 | $UpdateQuery = " 354 | UPDATE HandlerSettings 355 | SET Value = 1 356 | WHERE HandlerId = '$($NotificationSettings.HandlerId)' AND SettingKey = 's:toast' 357 | " 358 | #Invoke updatequery 359 | Invoke-SqliteQuery -DataSource $DatabasePath -Query $UpdateQuery 360 | } 361 | 362 | ##Registry 363 | #Get registry path for application Powershell 364 | $RegistryPath = (Get-ChildItem -Recurse -Path "$UserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings" | Where-Object -Property Name -Like "*$AppName*" | Select-Object -ExpandProperty Name) -Replace 'HKEY_USERS', 'HKU:' 365 | 366 | #Get current value for Enabled 367 | $Enabled = Get-ItemProperty -Path $RegistryPath -Name "Enabled" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Enabled 368 | 369 | #If the value are wrong 370 | if ($Enabled -ne 1) { 371 | #Update registry 372 | Set-ItemProperty -Path $RegistryPath -Name "Enabled" -Value 1 -Force 373 | } 374 | } catch { 375 | $LogPath = 'C:\ProgramData\EberlySystems\Log' 376 | $LogName = 'PowershellNotifications.log' 377 | Remove-Variable -Name p1, fTemp -ErrorAction SilentlyContinue 378 | foreach ($folder in $LogPath.split('\')) { 379 | if ($null -ne $p1) { 380 | $p1 = Join-Path -Path $fTemp -ChildPath $folder 381 | } else { 382 | $p1 = $folder 383 | } 384 | if (!(Test-Path -Path $p1)) { 385 | New-Item -Path $fTemp -Name $folder -ItemType Directory 386 | } 387 | $fTemp = $p1 388 | } 389 | "$(Get-Date) | RemediationScript | ERROR: $($_)" | Out-File "$LogPath\$LogName" -Append 390 | return $_ 391 | } 392 | 393 | if ($unload) { 394 | reg unload $hkuPath 395 | } 396 | } 397 | } 398 | 399 | end { 400 | } 401 | } 402 | #Endregion Functions 403 | 404 | #Region !!!ScriptBlock!!! 405 | # Any edit to this script block requires updating AppWhitelisting and AV alow list 406 | $TestPendingReboot = { 407 | [CmdletBinding()] 408 | param ( 409 | [Parameter()] 410 | [switch] 411 | $ClearKeys 412 | ) 413 | 414 | # Set up $env: vars for Syncro Module 415 | if ($env:SyncroModule -match '^\s*$') { 416 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 417 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 418 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 419 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 420 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 421 | $env:RepairTechUUID = $SyncroRegKey.uuid 422 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 423 | } 424 | if (Test-Path -Path $env:SyncroModule) { 425 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 426 | } 427 | 428 | 429 | $BitDefenderSvcs = @('EPIntegrationService', 'EPProtectedService', 'EPRedline', 'EPSecurityService', 'EPUpdateServer', 'EPUpdateService') 430 | 431 | #Region Functions 432 | function Get-Uptime { 433 | [datetime]$BootTime = (Get-CimInstance -ClassName win32_operatingsystem).LastBootUpTime 434 | ((Get-Date) - $BootTime) 435 | } 436 | 437 | function Test-RegistryKey { 438 | [OutputType('bool')] 439 | [CmdletBinding()] 440 | param 441 | ( 442 | [Parameter(Mandatory)] 443 | [ValidateNotNullOrEmpty()] 444 | [string]$Key, 445 | [switch]$HasChildren, 446 | [switch]$Clear 447 | ) 448 | 449 | process { 450 | switch -Regex (($PSBoundParameters.Keys) -join ' ') { 451 | 'HasChildren' { 452 | if ($Children = Get-ChildItem -Path $Key -ErrorAction Ignore) { 453 | if ($PSBoundParameters.ContainsKey('Clear')) { 454 | $Children | Remove-Item -Recurse -ErrorAction Ignore 455 | } else { 456 | $true 457 | } 458 | } 459 | 460 | } 461 | Default { 462 | if (Get-Item -Path $Key -ErrorAction Ignore) { 463 | if ($PSBoundParameters.ContainsKey('Clear')) { 464 | Remove-Item -Path $Key -Recurse -ErrorAction Ignore 465 | } else { 466 | $true 467 | } 468 | } 469 | } 470 | } 471 | } 472 | 473 | end {} 474 | } 475 | 476 | function Test-RegistryValue { 477 | [OutputType('bool')] 478 | [CmdletBinding()] 479 | param 480 | ( 481 | [Parameter(Mandatory)] 482 | [ValidateNotNullOrEmpty()] 483 | [string]$Key, 484 | 485 | [Parameter(Mandatory)] 486 | [ValidateNotNullOrEmpty()] 487 | [string]$Value, 488 | 489 | [switch]$NotNull, 490 | [string]$NotEqualValue, 491 | [switch]$Clear 492 | ) 493 | 494 | begin { 495 | $ErrorActionPreference = 'Stop' 496 | } 497 | 498 | process { 499 | switch -Regex (($PSBoundParameters.Keys) -join ' ') { 500 | 'NotNull' { 501 | if (($regVal = Get-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore) -and $regVal.($Value)) { 502 | if ($PSBoundParameters.ContainsKey('Clear')) { 503 | Remove-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore 504 | } else { 505 | $true 506 | } 507 | } 508 | } 509 | 'NotEqual' { 510 | if (($regVal = Get-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore) -and $regVal.($Value) -ne $NotEqualValue) { 511 | if ($PSBoundParameters.ContainsKey('Clear')) { 512 | Remove-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore 513 | } else { 514 | $true 515 | } 516 | } 517 | } 518 | Default { 519 | if (Get-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore) { 520 | if ($PSBoundParameters.ContainsKey('Clear')) { 521 | Remove-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore 522 | } else { 523 | $true 524 | } 525 | } 526 | } 527 | } 528 | } 529 | 530 | end {} 531 | } 532 | #Endregion Functions 533 | 534 | $tests = @( 535 | { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\ServerManager\CurrentRebootAttemps' } 536 | { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' } 537 | { Test-RegistryKey -Key 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootInProgress' } 538 | { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired' } 539 | { Test-RegistryKey -Key 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\PackagesPending' } 540 | { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\PostRebootReporting' } 541 | { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Services\Pending' -HasChildren } 542 | #{ Test-RegistryValue -Key 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Value 'PendingFileRenameOperations' -NotNull } 543 | #{ Test-RegistryValue -Key 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Value 'PendingFileRenameOperations2' -NotNull } 544 | { Test-RegistryValue -Key 'HKLM:\SOFTWARE\Microsoft\Updates' -Value 'UpdateExeVolatile' -NotEqualValue 0 } 545 | { Test-RegistryValue -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' -Value 'DVDRebootSignal' } 546 | { Test-RegistryValue -Key 'HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon' -Value 'JoinDomain' } 547 | { Test-RegistryValue -Key 'HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon' -Value 'AvoidSpnSet' } 548 | { Get-Service -Name $BitDefenderSvcs -ErrorAction SilentlyContinue | Where-Object { $_.Status -ne 'Running' } } 549 | { try { Get-WURebootStatus -Silent } catch { $false } } 550 | ) 551 | 552 | [array]$RebootRequred = foreach ($test in $tests) { 553 | if (& $test) { 554 | $test.ToString().trim() 555 | } 556 | } 557 | 558 | if (($RebootRequred.count -ge 1 -and (Get-Uptime).TotalMinutes -lt 15) -or $PSBoundParameters.ContainsKey('ClearKeys')) { 559 | foreach ($r in $RebootRequred) { 560 | if ($r -notmatch 'JoinDomain' -and $r -match 'Test-Registry') { 561 | $sb = [Scriptblock]::Create($r + " -Clear") 562 | & $sb 563 | } 564 | } 565 | if ($env:SyncroModule) { 566 | Write-Host 'No Reboot Required, Clearing Rmm-Aerts' 567 | Close-Rmm-Alert -Category 'Reboot_Required' 568 | Close-Rmm-Alert -Category 'Ps_Monitor' 569 | } 570 | } else { 571 | if ($env:SyncroModule) { 572 | Write-Host 'No Reboot Required, Clearing Rmm-Aerts' 573 | Close-Rmm-Alert -Category 'Reboot_Required' 574 | Close-Rmm-Alert -Category 'Ps_Monitor' 575 | } 576 | } 577 | } 578 | #Endregion !!!ScriptBlock!!! 579 | 580 | "Checking for Pending Reboot" 581 | .$TestPendingReboot 582 | 'LastExitCode: "{0}"' -f $LASTEXITCODE 583 | 584 | if ($RebootRequred.count -gt 0) { 585 | # Disable Hiberbootenabled (fast boot) 586 | Set-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\Power\' -Name hiberbootenabled -Value 0 587 | $lastCode = $LASTEXITCODE 588 | try { 589 | [array]$qUsers = ((query user) -split "\n").trim(' >') -replace '\s\s+', ';' | convertfrom-csv -Delimiter ';' 590 | } catch { 591 | } finally { 592 | $LASTEXITCODE = $lastCode 593 | } 594 | 595 | "Reboot Required" 596 | $RebootRequred 597 | 'LastExitCode: "{0}"' -f $LASTEXITCODE 598 | 599 | try { 600 | InstallOrUpdateModule -Name $RequiredModules -ErrorAction Stop 601 | } catch { 602 | Write-Warning "Could not update RequiredModules" 603 | Write-Host "Powershell version $($PSVersionTable.PSVersion)" 604 | } 605 | 606 | New-CleanupSchTask -ScriptBlock $TestPendingReboot -TaskPath 'EberlySystems' 607 | 608 | if ($AutoReboot -eq 'True') { 609 | $reboot = Add-ScheduledReboot -Confirm:$false -RebootTime $RebootTime -OutObject -ErrorAction Stop 610 | if ($reboot.SchTaskFailed) { 611 | $now = Get-Date 612 | switch ($now) { 613 | { $_ -lt [datetime]"2:30 am" } { [int]$seconds = ([datetime]"2:45 am" - $now).TotalSeconds } 614 | { $_ -gt [datetime]"4:00 am" } { [int]$seconds = ((Get-Date "2:45 am").AddDays(1) - $now).TotalSeconds } 615 | Default { [int]$seconds = 1 } 616 | } 617 | .$TestPendingReboot -ClearKeys 618 | shutdown /r /t $seconds /f 619 | } 620 | Log-Activity -Message "$($reboot.RebootReason) Scheduled at $($reboot.RebootTime), For WU: $($reboot.WinUpdateReq)" -EventName "RMM Automation" 621 | } elseif ($qUsers.Count -gt 0) { 622 | "Enable Notifications for: $($qusers.username)" 623 | $qUsers.username | 624 | Where-Object { Test-Path -Path "C:\Users\$_\AppData\Local\Microsoft\Windows\Notifications\wpndatabase.db" } | 625 | Enable-AppNotifications 626 | try { 627 | New-ToastPopUp -ErrorAction Stop 628 | "Sending ToastMessage" 629 | } catch { 630 | Write-Warning -Message "Unable to send ToastMessage" 631 | } 632 | } else { 633 | [string]$body = ($RebootRequred | Out-String) 634 | "" 635 | "New RMM Alert Reboot_Required" 636 | Rmm-Alert -Category 'Reboot_Required' -Body $body 637 | } 638 | if ($LASTEXITCODE -gt 0) { 639 | exit $LASTEXITCODE 640 | } else { 641 | exit 0 642 | } 643 | } 644 | -------------------------------------------------------------------------------- /Uninstall Threatlocker.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | IF EXIST "%PROGRAMFILES(X86)%" (GOTO 64BIT) ELSE (GOTO 32BIT) 4 | :64BIT 5 | %@Try% 6 | curl "https://api.threatlocker.com/updates/installers/threatlockerstubx64.exe" -o "C:\ThreatLockerStub.exe" 7 | %@EndTry% 8 | :@Catch 9 | bitsadmin /transfer mydownloadjob /download /priority normal "https://api.threatlocker.com/updates/installers/threatlockerstubx64.exe" "c:\ThreatLockerStub.exe" 10 | :@EndCatch 11 | GOTO UNINSTALL 12 | 13 | :32BIT 14 | %@Try% 15 | curl "https://api.threatlocker.com/updates/installers/threatlockerstubx86.exe" -o "C:\ThreatLockerStub.exe" 16 | %@EndTry% 17 | :@Catch 18 | bitsadmin /transfer mydownloadjob /download /priority normal "https://api.threatlocker.com/updates/installers/threatlockerstubx86.exe" "c:\ThreatLockerStub.exe" 19 | :@EndCatch 20 | GOTO UNINSTALL 21 | 22 | :UNINSTALL 23 | C:\ThreatLockerStub.exe uninstall 24 | GOTO VERIFYINSTALL 25 | 26 | :VERIFYINSTALL 27 | FOR /F "tokens=3 delims=: " %%F IN ('sc query "ThreatLockerService" ^| findstr " STATE"') DO ( 28 | IF /I "%%F" neq "RUNNING" ( 29 | GOTO SUCCESS 30 | ) ELSE ( 31 | GOTO FAILED 32 | ) 33 | ) 34 | 35 | :SUCCESS 36 | echo "ThreatLocker uninstalled successfully" 37 | IF EXIST "C:\ThreatLockerStub.exe" (DEL "C:\ThreatLockerStub.exe") 38 | EXIT /b 0 39 | 40 | :FAILED 41 | echo "ThreatLocker failed to uninstall" 42 | IF EXIST "C:\ThreatLockerStub.exe" (DEL "C:\ThreatLockerStub.exe") 43 | EXIT /b 1 44 | -------------------------------------------------------------------------------- /Uninstall-CyberCNS.ps1: -------------------------------------------------------------------------------- 1 | <#- Start of Script -#> 2 | '============ Syncro Inserted Code ============' 3 | foreach ($line in (Get-Content -Path $MyInvocation.MyCommand.Path -ErrorAction Stop)) { 4 | if ($line -eq '<#- Start of Script -#>') { break } 5 | $line 6 | } 7 | '============== END Syncro Code ===============' 8 | '' 9 | $paths = @('C:\Program Files (x86)\CyberCNSAgent', 'C:\Program Files (x86)\CyberCNSAgentV2') 10 | $SyncroTxtField = 'CyberCNS' 11 | $i = 0 12 | 13 | while ( 14 | $Uninstall -eq 'True' ` 15 | -and (Test-Path -Path 'C:\Program Files (x86)\CyberCNSAgent*\uninstall.bat') ` 16 | -and (Test-Path -Path 'C:\Program Files (x86)\CyberCNSAgent*\cybercnsagent.exe') ` 17 | -and $i -lt 6) { 18 | Get-Process -Name cybercns* | Stop-Process -Force 19 | net stop CyberCNSAgentMonitor 20 | Start-Process -FilePath sc -ArgumentList 'delete CyberCNSAgentMonitor' -Wait 21 | foreach ($p in $paths) { 22 | $batPath = Join-Path -Path $p -ChildPath "uninstall.bat" 23 | $agentPath = Join-Path -Path $p -ChildPath "cybercnsagent.exe" 24 | if (Test-Path -Path $agentPath) { 25 | Write-Host "Running: '$agentPath'" 26 | Start-Process -FilePath $agentPath -ArgumentList '-r' -NoNewWindow -Wait -Verbose 27 | } 28 | if (Test-Path -Path $batPath) { 29 | Write-Host "Running: '$batPath'" 30 | Start-Process -FilePath $batPath -NoNewWindow -Wait -Verbose 31 | } 32 | } 33 | Start-Sleep -Seconds 30 34 | $i++ 35 | } 36 | 37 | Get-Process -Name cybercns* | Stop-Process -Force -ErrorAction SilentlyContinue 38 | 39 | $InstLocation = @( 40 | "HKLM:\software\microsoft\windows\currentversion\uninstall", 41 | "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" 42 | ) 43 | $CcnsInstalls = get-childitem $InstLocation | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_.Publisher -match 'CyberCNS' } 44 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 45 | Import-Module $env:SyncroModule 46 | if ($CcnsInstalls.Count -ge 1) { 47 | Set-Asset-Field -Name $SyncroTxtField -Value 'True' 48 | $CcnsInstalls 49 | } else { 50 | Set-Asset-Field -Name $SyncroTxtField -Value 'False' 51 | foreach ($p in $paths) { 52 | if (Test-Path -Path $p) { 53 | try { 54 | Remove-Item -Path $p -Recurse -Force -ErrorAction Stop -Verbose 55 | } catch { 56 | } 57 | } else { 58 | Write-Host "'$p' Does not exist" 59 | } 60 | } 61 | } 62 | 63 | if ($lastexitcode -ge 1 -and !(Test-Path -Path $paths)) { 64 | exit 1 65 | } else { 66 | exit 0 67 | } 68 | -------------------------------------------------------------------------------- /Uninstall-Webroot.ps1: -------------------------------------------------------------------------------- 1 | # Removes Webroot SecureAnywhere by force 2 | # Run the script once, reboot, then run again 3 | 4 | # Webroot SecureAnywhere registry keys 5 | $RegKeys = @( 6 | "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\WRUNINST", 7 | "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WRUNINST", 8 | "HKLM:\SOFTWARE\WOW6432Node\WRData", 9 | "HKLM:\SOFTWARE\WOW6432Node\WRCore", 10 | "HKLM:\SOFTWARE\WOW6432Node\WRMIDData", 11 | "HKLM:\SOFTWARE\WOW6432Node\webroot", 12 | "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WRUNINST", 13 | "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WRUNINST", 14 | "HKLM:\SOFTWARE\WRData", 15 | "HKLM:\SOFTWARE\WRMIDData", 16 | "HKLM:\SOFTWARE\WRCore", 17 | "HKLM:\SOFTWARE\webroot", 18 | "HKLM:\SYSTEM\ControlSet001\services\WRSVC", 19 | "HKLM:\SYSTEM\ControlSet001\services\WRkrn", 20 | "HKLM:\SYSTEM\ControlSet001\services\WRBoot", 21 | "HKLM:\SYSTEM\ControlSet001\services\WRCore", 22 | "HKLM:\SYSTEM\ControlSet001\services\WRCoreService", 23 | "HKLM:\SYSTEM\ControlSet001\services\wrUrlFlt", 24 | "HKLM:\SYSTEM\ControlSet002\services\WRSVC", 25 | "HKLM:\SYSTEM\ControlSet002\services\WRkrn", 26 | "HKLM:\SYSTEM\ControlSet002\services\WRBoot", 27 | "HKLM:\SYSTEM\ControlSet002\services\WRCore", 28 | "HKLM:\SYSTEM\ControlSet002\services\WRCoreService", 29 | "HKLM:\SYSTEM\ControlSet002\services\wrUrlFlt", 30 | "HKLM:\SYSTEM\CurrentControlSet\services\WRSVC", 31 | "HKLM:\SYSTEM\CurrentControlSet\services\WRkrn", 32 | "HKLM:\SYSTEM\CurrentControlSet\services\WRBoot", 33 | "HKLM:\SYSTEM\CurrentControlSet\services\WRCore", 34 | "HKLM:\SYSTEM\CurrentControlSet\services\WRCoreService", 35 | "HKLM:\SYSTEM\CurrentControlSet\services\wrUrlFlt" 36 | ) 37 | 38 | # Webroot SecureAnywhere startup registry item paths 39 | $RegStartupPaths = @( 40 | "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run", 41 | "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" 42 | ) 43 | 44 | # Webroot SecureAnywhere folders 45 | $Folders = @( 46 | "%ProgramData%\WRData", 47 | "%ProgramData%\WRCore", 48 | "%ProgramFiles%\Webroot", 49 | "%ProgramFiles(x86)%\Webroot", 50 | "%ProgramData%\Microsoft\Windows\Start Menu\Programs\Webroot SecureAnywhere" 51 | ) 52 | 53 | # Try to Uninstall - https://community.webroot.com/webroot-secureanywhere-antivirus-12/pc-uninstallation-option-missing-from-control-panel-34688 54 | Start-Process -FilePath "${Env:ProgramFiles(x86)}\Webroot\WRSA.exe" -ArgumentList "-uninstall" -Wait -ErrorAction SilentlyContinue 55 | Start-Process -FilePath "${Env:ProgramFiles}\Webroot\WRSA.exe" -ArgumentList "-uninstall" -Wait -ErrorAction SilentlyContinue 56 | 57 | # Stop & Delete Webroot SecureAnywhere service 58 | sc.exe stop WRSVC 59 | sc.exe stop WRCoreService 60 | sc.exe stop WRSkyClient 61 | sc.exe delete WRSVC 62 | sc.exe delete WRCoreService 63 | sc.exe delete WRSkyClient 64 | 65 | # Stop Webroot SecureAnywhere process 66 | Stop-Process -Name "WRSA" -Force -ErrorAction SilentlyContinue 67 | 68 | # Remove Webroot SecureAnywhere registry keys 69 | ForEach ($RegKey in $RegKeys) { 70 | Write-Host "Removing $RegKey" 71 | Remove-Item -Path $RegKey -Force -Recurse -ErrorAction SilentlyContinue 72 | } 73 | 74 | # Remove Webroot SecureAnywhere registry startup items 75 | ForEach ($RegStartupPath in $RegStartupPaths) { 76 | Write-Host "Removing WRSVC from $RegStartupPath" 77 | Remove-ItemProperty -Path $RegStartupPath -Name "WRSVC" 78 | } 79 | 80 | # Remove Webroot SecureAnywhere folders 81 | ForEach ($Folder in $Folders) { 82 | Write-Host "Removing $Folder" 83 | Remove-Item -Path "$Folder" -Force -Recurse -ErrorAction SilentlyContinue 84 | } 85 | -------------------------------------------------------------------------------- /UninstallExample.ps1: -------------------------------------------------------------------------------- 1 | <#- Start of Script -#> 2 | '#============ Syncro Inserted Code ============#' 3 | foreach ($line in (Get-Content -Path $MyInvocation.MyCommand.Path -ErrorAction Stop)){ 4 | if ($line -eq '<#- Start of Script -#>') {break} 5 | $line 6 | } 7 | '#============== END Syncro Code ===============#' 8 | '' 9 | 10 | #Example application uninstall, will attempt to find apps installed in system locations as well as User hives. 11 | # Not all apps record uninstall info in these locations so may not work for all apps. 12 | 13 | # version 1.0 14 | # changes: update Var names, improve blank bypass for listing installed apps. 15 | 16 | # $RegexAppName = 'Wave Browser' 17 | # $RegexPublisher = 'Piriform' 18 | # $MaxNumberApps 19 | $SilentUninstallFlag = '/SILENT' 20 | $exit = 0 21 | $log = "$env:TEMP\installedApps.csv" 22 | 23 | function Get-InstalledApps { 24 | param ( 25 | [string]$AppName, 26 | [string]$Publisher, 27 | [switch]$or 28 | ) 29 | 30 | if ((Get-PSDrive | Where-Object {$_.Name -eq 'HKU'}).count -lt 1){ 31 | New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null 32 | } 33 | [array]$users = Get-WMIObject -class Win32_UserProfile | Sort-Object -Property LastUseTime | 34 | Where-Object { $_.LocalPath -like 'c:\user*' } 35 | $users += [PSCustomObject]@{LocalPath = 'c:\users\.DEFAULT'; SID = '.DEFAULT'} 36 | 37 | $InstLocation = @{} 38 | foreach ($u in $Users) { 39 | $hkuPath = "HKU\$($u.SID)" 40 | $ntuserdat = Join-Path -Path $u.LocalPath -ChildPath NTUSER.DAT 41 | $UserHive = "HKU:\$($u.SID)" 42 | $unload = $false 43 | 44 | if (!(Test-Path -Path $UserHive)){ 45 | reg load $hkuPath $ntuserdat 2>&1 | Out-Null 46 | $unload = $true 47 | } 48 | $UPath = Join-Path -Path $UserHive -ChildPath 'Software\Microsoft\Windows\CurrentVersion\Uninstall' 49 | if ((Test-Path -Path $UPath) -and -not $InstLocation.ContainsKey($UPath)){ 50 | $InstLocation.Add($UPath,$unload) 51 | } 52 | } 53 | 54 | $InstLocation += @{ 55 | "HKLM:\software\microsoft\windows\currentversion\uninstall" = $false 56 | "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" = $false 57 | } 58 | $AllApps = get-childitem $InstLocation.Keys.split() | ForEach-Object { Get-ItemProperty $_.PSPath } 59 | #| Select-Object DisplayVersion,InstallDate,ModifyPath,Publisher,UninstallString,Language,DisplayName 60 | 61 | foreach ($a in $AllApps){ 62 | $test = @( 63 | ($a.DisplayName -match $AppName), 64 | ($a.Publisher -match $Publisher) 65 | ) 66 | if ($true -ne $or -and $test -notcontains $false){ 67 | $a 68 | } elseif ($true -eq $or -and $test -contains $true) { 69 | $a 70 | } 71 | } 72 | 73 | foreach ($k in $InstLocation.Keys){ 74 | if($InstLocation.$k -eq $true){ 75 | reg unload $hkuPath 2>&1 | Out-Null 76 | } 77 | } 78 | } 79 | 80 | $splat = @{} 81 | if ($RegexAppName -notmatch '^\s*$'){ 82 | $splat.Add('AppName',$RegexAppName) 83 | } 84 | if ($RegexPublisher -notmatch '^\s*$'){ 85 | $splat.Add('Publisher',$RegexPublisher) 86 | } 87 | if ($or -eq 'True'){ 88 | $splat.Add('or',$true) 89 | } 90 | 91 | $ht = @{} 92 | [array]$Applist = Get-InstalledApps @splat | Sort-Object -Property DisplayName 93 | $Applist | Where-Object {$_.DisplayName -notmatch '^[\.\s\*\+]*$' -and -not $ht.ContainsKey($_.DisplayName) } | 94 | ForEach-Object {$ht.Add($_.DisplayName,$_.Publisher), $_} | 95 | Select-Object -Property InstallDate, DisplayName, Publisher, DisplayVersion, UninstallString, QuietUninstallString -OutVariable report | 96 | Export-Csv -NoTypeInformation -Path $log 97 | $report | Format-Table -AutoSize 98 | 99 | $totalApps = $Applist.count 100 | Write-Host "INFO: `$Applist.count is $totalApps" 101 | 102 | try { 103 | [int]$MaxNumberApps = [int]$MaxNumberApps 104 | if ($MaxNumberApps -lt 1){$MaxNumberApps = 5} 105 | } 106 | catch { 107 | $MaxNumberApps = 5 108 | } 109 | 110 | if (($RegexAppName + $RegexPublisher) -notmatch '^[\.\s\*\+]*$' -and $Applist.count -le $MaxNumberApps){ 111 | foreach ($a in $Applist){ 112 | 'Uninstalling "{0}" by "{1}"' -f $a.DisplayName, $a.Publisher 113 | if($a.QuietUninstallString -match '"(.*)"\s(/.*)'){ 114 | Start-Process -FilePath $Matches[1] -ArgumentList $Matches[2] -Wait 115 | } elseif ($a.UninstallString -like 'C:\Program Files*'){ 116 | Start-Process -FilePath $a.UninstallString -ArgumentList $SilentUninstallFlag -Wait 117 | } elseif ($a.UninstallString -like 'MsiExec.exe*'){ 118 | $ArgList = (($a.UninstallString -split 'MsiExec.exe')[1].trim() -replace '/I{','/X{').ToString() 119 | $ArgList = '{0} /quiet /norestart' -f $ArgList 120 | Start-Process -FilePath MsiExec.exe -ArgumentList $ArgList -Wait 121 | } else { 122 | try { 123 | $ErrorActionPreference = 'Stop' 124 | Get-Package -Name $a.DisplayName -IncludeWindowsInstaller | Uninstall-Package 125 | } 126 | catch { 127 | "Could not auto uninstall $($a.DisplayName)" 128 | "Uninstall String: '$($a.UninstallString)'" 129 | $exit = 2 130 | } 131 | finally { 132 | $ErrorActionPreference = 'Continue' 133 | } 134 | } 135 | } 136 | Start-Sleep -Seconds 10 -Verbose 137 | Get-InstalledApps @splat | Sort-Object -Property DisplayName | 138 | Where-Object {$_.DisplayName -notmatch '^[\.\s\*\+]*$'} | 139 | Select-Object -Property InstallDate, DisplayName, Publisher, DisplayVersion, UninstallString, QuietUninstallString | 140 | Format-Table -AutoSize 141 | } elseif (($RegexAppName + $RegexPublisher) -notmatch '^[\.\s\*\+]*$' -and $Applist.count -gt 5){ 142 | Write-Warning "Search terms to broad to auto uninstall" 143 | $exit = 3 144 | } 145 | 146 | if ($report.count -ge 83){ 147 | Write-Host "Log Path: $log" 148 | if ($env:SyncroModule){ 149 | Import-Module -Name $env:SyncroModule -WarningAction silentlycontinue 150 | Upload-File -FilePath $log 151 | } 152 | } 153 | 154 | Remove-Item -Path $log 155 | 156 | exit $exit 157 | -------------------------------------------------------------------------------- /Upgrade Windows 10 with Enablement Pac.ps1: -------------------------------------------------------------------------------- 1 | # Upgrade Windows 10 with Enablement Package 2 | Import-Module $env:SyncroModule -DisableNameChecking 3 | 4 | # Target release version registry settings portion needs testing to confirm functionality 5 | 6 | # Todo: 7 | # - Add support for upgrading Windows 11 with UA 8 | # - Add support for older packages/specific builds 9 | # Windows 10 21H2 x64 http://b1.download.windowsupdate.com/c/upgr/2021/08/windows10.0-kb5003791-x64_b401cba483b03e20b2331064dd51329af5c72708.cab 10 | # Windows 10 21H2 x86 http://b1.download.windowsupdate.com/c/upgr/2021/08/windows10.0-kb5003791-x86_1bf1a29db06015e9deaefba26cf1f300e8ac18b8.cab 11 | # Windows 10 21H2 arm64 http://b1.download.windowsupdate.com/c/upgr/2021/08/windows10.0-kb5003791-arm64_05c00a882a8cb93b8dc1b94ef8133f909f3cd937.cab 12 | 13 | # These will need updating with each new enablement package 14 | $Win10CabURL = "https://catalog.s.download.windowsupdate.com/c/upgr/2022/07/windows10.0-kb5015684-x64_d2721bd1ef215f013063c416233e2343b93ab8c1.cab" 15 | $Win10TargetVersion = "22H2" 16 | 17 | # Other variables 18 | $Reboot = $true # If changing this to false you will also want to disable AttemptUpgradeAssistant 19 | # Attempt Upgrade Assistant method if enablement fails/not possible 20 | $AttemptUpgradeAssistant = $true # True can cause a reboot regardless of reboot setting above as UA always restarts 21 | # Ignore Windows Update Target Release Version registry settings 22 | $IgnoreTargetReleaseVersion = $false 23 | # Location to download files 24 | $TargetFolder = "$env:Temp" 25 | # Name for Syncro alerts 26 | $SyncroAlertCategory = "Upgrade Windows 10" 27 | 28 | # Get version/build info 29 | $MajorVersion = ([System.Environment]::OSVersion.Version).Major 30 | # 19041 and older do not have DisplayVersion key, if so we grab ReleaseID instead (no longer updated in new versions) 31 | if ((Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion) { 32 | $DisplayVersion = ((Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion) 33 | } else { 34 | $DisplayVersion = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ReleaseId 35 | } 36 | # Convert versions to numerical form so comparison operators can be used 37 | $DisplayVersionNumerical = ($DisplayVersion).replace('H1', '05').replace('H2', '10') 38 | $Win10TargetVersionNumerical = ($Win10TargetVersion).replace('H1', '05').replace('H2', '10') 39 | # Compile build number, it's also useful to have separate as UBR can be 3 or 4 digits which confuses comparison operators in combined form 40 | $Build = ([System.Environment]::OSVersion.Version).Build 41 | $UBR = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name UBR).UBR 42 | $BuildUBR = $Build + ".$UBR" 43 | # Correct Microsoft's version number for Windows 11 44 | if ($Build -ge 22000) { $MajorVersion = '11' } 45 | Write-Host "Windows $MajorVersion $DisplayVersion build $BuildUBR detected." 46 | 47 | # Exit if not eligible 48 | if ($MajorVersion -lt '10') { 49 | Write-Host "Windows versions prior to 10 cannot be updated with this script." 50 | exit 0 51 | } 52 | if ($Build -ge '22000') { 53 | Write-Host "Windows 11 cannot be updated with this script." 54 | exit 0 55 | } 56 | if ($DisplayVersionNumerical -ge $Win10TargetVersionNumerical) { 57 | Write-Host "Already running $DisplayVersion which is the same or newer than target release $Win10TargetVersion, no update required." 58 | Close-Rmm-Alert -Category $SyncroAlertCategory 59 | exit 0 60 | } 61 | if ($AttemptUpgradeAssistant -eq $false -and $MajorVersion -eq '10' -and $Build -le '19041' -and $UBR -lt '1247') { 62 | $notification = "Windows 10 builds older than 19041.1247 (September 14, 2021 patch for 2004/20H1) cannot be upgraded with enablement package and Upgrade Assistant method is disabled." 63 | Write-Host $notification 64 | Rmm-Alert -Category $SyncroAlertCategory -Body $notification 65 | exit 1 66 | } 67 | if ($IgnoreTargetReleaseVersion -eq $false -and (Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate") -eq $true) { 68 | $WindowsUpdateKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -ErrorAction SilentlyContinue 69 | if ($WindowsUpdateKey.TargetReleaseVersion -eq 1 -and $WindowsUpdateKey.TargetReleaseVersionInfo) { 70 | $WindowsUpdateTargetReleaseNumerical = ($WindowsUpdateKey.TargetReleaseVersionInfo).replace('H1', '05').replace('H2', '10') 71 | if ($WindowsUpdateTargetReleaseNumerical -lt $win10TargetVersionNumerical) { 72 | $notification = "Windows Update TargetReleaseVersion registry settings are in place limiting upgrade to $($WindowsUpdateKey.TargetReleaseVersionInfo). To ignore these settings, change the script variable or target version and run again." 73 | Rmm-Alert -Category $SyncroAlertCategory -Body $notification 74 | exit 1 75 | } 76 | } 77 | } 78 | 79 | function Invoke-UpgradeAssistant { 80 | $URL = 'https://go.microsoft.com/fwlink/?LinkID=799445' 81 | $Arg = "/QuietInstall /SetPriorityLow /SkipEULA /ShowOOBE none" 82 | $DiskSpaceRequired = '11' # in GBs 83 | $DiskSpace = [Math]::Round((Get-CimInstance -Class Win32_Volume | Where-Object { $_.DriveLetter -eq $env:SystemDrive } | Select-Object -ExpandProperty FreeSpace) / 1GB) 84 | if ($DiskSpace -lt $DiskSpaceRequired) { 85 | $notification = "Only $DiskSpace GB free, $DiskSpaceRequired GB required." 86 | Rmm-Alert -Category $SyncroAlertCategory -Body $notification 87 | exit 1 88 | } 89 | # Retrieve headers to make sure we have the final destination redirected file URL 90 | $DLURL = (Invoke-WebRequest -UseBasicParsing -Uri $URL -MaximumRedirection 0 -ErrorAction Ignore).headers.location 91 | $DLFileName = [io.path]::GetFileName("$DLURL") 92 | Invoke-WebRequest -Uri "$dlurl" -OutFile "$TargetFolder\$DLFileName" 93 | Start-Process "$TargetFolder\$DLFileName" -ArgumentList "$Arg" 94 | Start-Sleep -s 120 95 | Remove-Item "$TargetFolder\$DLFileName" -Force 96 | Close-Rmm-Alert -Category $SyncroAlertCategory 97 | } 98 | 99 | # Attempt upgrade 100 | if ($MajorVersion -eq '10' -and $Build -ge '19041' -and $UBR -ge '1247' -and $Build -lt '22000') { 101 | Write-Host "Attempting enablement upgrade." 102 | # Download the cab file for install 103 | $TargetFile = "$TargetFolder\$(([uri]$Win10CabURL).Segments[-1])" 104 | Invoke-WebRequest -Uri $Win10CabURL -OutFile $TargetFile 105 | # Add the Enablement Package to the image 106 | try { 107 | dism /Online /Add-Package /PackagePath:$TargetFile /Quiet /NoRestart 108 | Remove-Item $TargetFile 109 | } catch { 110 | if ($AttemptUpgradeAssistant) { 111 | Write-Host "Enablement failed, attempting Upgrade Assistant method instead." 112 | Invoke-UpgradeAssistant 113 | } else { 114 | Rmm-Alert -Category $SyncroAlertCategory -Body $_ 115 | exit 1 116 | } 117 | } finally { 118 | if (-not $Error) { 119 | Write-Host "Package added successfully." 120 | Close-Rmm-Alert -Category $SyncroAlertCategory 121 | } 122 | } 123 | # Reboot if desired 124 | if ($Reboot -and -not $Error) { 125 | "Reboot variable enabled, initiating reboot." 126 | # If Automatic Restart Sign-On is enabled, /g allows the device to automatically sign in and lock 127 | # based on the last interactive user. After sign in, it restarts any registered applications. 128 | shutdown /g /f 129 | } 130 | } elseif ($AttemptUpgradeAssistant -eq $true -and $MajorVersion -eq '10' -and $Build -le '19041' -and $UBR -lt '1247') { 131 | Write-Host "Build is not compatible with enablement upgrade, attempting Upgrade Assistant method instead." 132 | Invoke-UpgradeAssistant 133 | } else { 134 | $notification = "System detection logic failed, check script for issues." 135 | Rmm-Alert -Category $SyncroAlertCategory -Body $notification 136 | exit 1 137 | } 138 | -------------------------------------------------------------------------------- /Windows11CompatibilityCheck.ps1: -------------------------------------------------------------------------------- 1 | # https://www.cyberdrain.com/monitoring-with-powershell-checking-if-your-device-is-compatible-with-windows-11/ 2 | # Updated for Syncro 3 | # Required: Create an asset Custom filed Windows 11 Compatible [checkbox] 4 | 5 | # Set up $env: vars for Syncro Module 6 | if($env:SyncroModule -match '^\s*$'){ 7 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 8 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 9 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 10 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 11 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 12 | $env:RepairTechUUID = $SyncroRegKey.uuid 13 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 14 | } 15 | if (Test-Path -Path $env:SyncroModule) { 16 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 17 | } 18 | 19 | $Models = @" 20 | AMD,AMD,3015e 21 | AMD,AMD,3020e 22 | AMD,Athlon™,Gold 3150C 23 | AMD,Athlon™,Gold 3150U 24 | AMD,Athlon™,Silver 3050C 25 | AMD,Athlon™,Silver 3050e 26 | AMD,Athlon™,Silver 3050U 27 | AMD,Athlon™,3000G 28 | AMD,Athlon™,300GE 29 | AMD,Athlon™,300U 30 | AMD,Athlon™,320GE 31 | AMD,Athlon™,Gold 3150G 32 | AMD,Athlon™,Gold 3150GE 33 | AMD,Athlon™,Silver 3050GE 34 | AMD,EPYC™,7232P 35 | AMD,EPYC™,7252 36 | AMD,EPYC™,7262 37 | AMD,EPYC™,7272 38 | AMD,EPYC™,7282 39 | AMD,EPYC™,7302 40 | AMD,EPYC™,7302P 41 | AMD,EPYC™,7352 42 | AMD,EPYC™,7402 43 | AMD,EPYC™,7402P 44 | AMD,EPYC™,7452 45 | AMD,EPYC™,7502 46 | AMD,EPYC™,7502P 47 | AMD,EPYC™,7532 48 | AMD,EPYC™,7542 49 | AMD,EPYC™,7552 50 | AMD,EPYC™,7642 51 | AMD,EPYC™,7662 52 | AMD,EPYC™,7702 53 | AMD,EPYC™,7702P 54 | AMD,EPYC™,7742 55 | AMD,EPYC™,7F32 56 | AMD,EPYC™,7F52 57 | AMD,EPYC™,7F72 58 | AMD,EPYC™,7H12 59 | AMD,EPYC™,72F3 60 | AMD,EPYC™,7313 61 | AMD,EPYC™,7313P 62 | AMD,EPYC™,7343 63 | AMD,EPYC™,73F3 64 | AMD,EPYC™,7413 65 | AMD,EPYC™,7443 66 | AMD,EPYC™,7443P 67 | AMD,EPYC™,7453 68 | AMD,EPYC™,74F3 69 | AMD,EPYC™,7513 70 | AMD,EPYC™,7543 71 | AMD,EPYC™,7543P 72 | AMD,EPYC™,75F3 73 | AMD,EPYC™,7643 74 | AMD,EPYC™,7663 75 | AMD,EPYC™,7713 76 | AMD,EPYC™,7713P 77 | AMD,EPYC™,7763 78 | AMD,Ryzen™ 3,3250C 79 | AMD,Ryzen™ 3,3250U 80 | AMD,Ryzen™ 3,3200G with Radeon™ Vega 8 Graphics 81 | AMD,Ryzen™ 3,3200GE 82 | AMD,Ryzen™ 3,3200U 83 | AMD,Ryzen™ 3,3350U 84 | AMD,Ryzen™ 3,2300X 85 | AMD,Ryzen™ 3,5300U 86 | AMD,Ryzen™ 3,3100 87 | AMD,Ryzen™ 3,3300U 88 | AMD,Ryzen™ 3,4300G 89 | AMD,Ryzen™ 3,4300GE 90 | AMD,Ryzen™ 3,4300U 91 | AMD,Ryzen™ 3,5400U 92 | AMD,Ryzen™ 3 PRO,3200G 93 | AMD,Ryzen™ 3 PRO,3200GE 94 | AMD,Ryzen™ 3 PRO,3300U 95 | AMD,Ryzen™ 3 PRO,4350G 96 | AMD,Ryzen™ 3 PRO,4350GE 97 | AMD,Ryzen™ 3 PRO,4450U 98 | AMD,Ryzen™ 3 PRO,5450U 99 | AMD,Ryzen™ 5,3400G with Radeon™ RX Vega 11 Graphics 100 | AMD,Ryzen™ 5,3400GE 101 | AMD,Ryzen™ 5,3450U 102 | AMD,Ryzen™ 5,3500C 103 | AMD,Ryzen™ 5,3500U 104 | AMD,Ryzen™ 5,3550H 105 | AMD,Ryzen™ 5,3580U Microsoft Surface® Edition 106 | AMD,Ryzen™ 5,2500X 107 | AMD,Ryzen™ 5,2600 108 | AMD,Ryzen™ 5,2600E 109 | AMD,Ryzen™ 5,2600X 110 | AMD,Ryzen™ 5,5500U 111 | AMD,Ryzen™ 5,3500 Processor 112 | AMD,Ryzen™ 5,3600 113 | AMD,Ryzen™ 5,3600X 114 | AMD,Ryzen™ 5,3600XT 115 | AMD,Ryzen™ 5,4600G 116 | AMD,Ryzen™ 5,4500U 117 | AMD,Ryzen™ 5,4600GE 118 | AMD,Ryzen™ 5,4600H 119 | AMD,Ryzen™ 5,4600U 120 | AMD,Ryzen™ 5,5600H 121 | AMD,Ryzen™ 5,5600HS 122 | AMD,Ryzen™ 5,5600U 123 | AMD,Ryzen™ 5,5600X 124 | AMD,Ryzen™ 5 PRO,3400G 125 | AMD,Ryzen™ 5 PRO,3400GE 126 | AMD,Ryzen™ 5 PRO,3500U 127 | AMD,Ryzen™ 5 PRO,2600 128 | AMD,Ryzen™ 5 PRO,3600 129 | AMD,Ryzen™ 5 PRO,4650G 130 | AMD,Ryzen™ 5 PRO,4650GE 131 | AMD,Ryzen™ 5 PRO,4650U 132 | AMD,Ryzen™ 5 PRO,5650U 133 | AMD,Ryzen™ 7,3700C 134 | AMD,Ryzen™ 7,3700U 135 | AMD,Ryzen™ 7,3750H 136 | AMD,Ryzen™ 7,3780U Microsoft Surface® Edition 137 | AMD,Ryzen™ 7,2700 138 | AMD,Ryzen™ 7,2700E Processor 139 | AMD,Ryzen™ 7,2700X 140 | AMD,Ryzen™ 7,5700U 141 | AMD,Ryzen™ 7,3700X 142 | AMD,Ryzen™ 7,3800X 143 | AMD,Ryzen™ 7,3800XT 144 | AMD,Ryzen™ 7,4700G 145 | AMD,Ryzen™ 7,4700GE 146 | AMD,Ryzen™ 7,4700U 147 | AMD,Ryzen™ 7,4800H 148 | AMD,Ryzen™ 7,4800HS 149 | AMD,Ryzen™ 7,4800U 150 | AMD,Ryzen™ 7,5800H 151 | AMD,Ryzen™ 7,5800HS 152 | AMD,Ryzen™ 7,5800U 153 | AMD,Ryzen™ 7,5800 154 | AMD,Ryzen™ 7,5800X 155 | AMD,Ryzen™ 7 PRO,3700U 156 | AMD,Ryzen™ 7 PRO,2700 157 | AMD,Ryzen™ 7 PRO,2700X 158 | AMD,Ryzen™ 7 PRO,4750G 159 | AMD,Ryzen™ 7 PRO,4750GE 160 | AMD,Ryzen™ 7 PRO,4750U 161 | AMD,Ryzen™ 7 PRO,5850U 162 | AMD,Ryzen™ 9,3900 Processor 163 | AMD,Ryzen™ 9,3900X 164 | AMD,Ryzen™ 9,3900XT 165 | AMD,Ryzen™ 9,3950X 166 | AMD,Ryzen™ 9,4900H 167 | AMD,Ryzen™ 9,4900HS 168 | AMD,Ryzen™ 9,5900HS 169 | AMD,Ryzen™ 9,5900HX 170 | AMD,Ryzen™ 9,5980HS 171 | AMD,Ryzen™ 9,5980HX 172 | AMD,Ryzen™ 9,5900 173 | AMD,Ryzen™ 9,5900X 174 | AMD,Ryzen™ 9,5950X 175 | AMD,Ryzen™ 9 PRO,3900 176 | AMD,Ryzen™ Threadripper™,2920X 177 | AMD,Ryzen™ Threadripper™,2950X 178 | AMD,Ryzen™ Threadripper™,2970WX 179 | AMD,Ryzen™ Threadripper™,2990WX 180 | AMD,Ryzen™ Threadripper™,3960X 181 | AMD,Ryzen™ Threadripper™,3970X 182 | AMD,Ryzen™ Threadripper™,3990X 183 | AMD,Ryzen™ Threadripper™ PRO,3945WX 184 | AMD,Ryzen™ Threadripper™ PRO,3955WX 185 | AMD,Ryzen™ Threadripper™ PRO,3975WX 186 | AMD,Ryzen™ Threadripper™ PRO,3995WX 187 | Intel®,Atom®,x6200FE 188 | Intel®,Atom®,x6211E 189 | Intel®,Atom®,x6212RE 190 | Intel®,Atom®,x6413E 191 | Intel®,Atom®,x6414RE 192 | Intel®,Atom®,x6425E 193 | Intel®,Atom®,x6425RE 194 | Intel®,Atom®,x6427FE 195 | Intel®,Celeron®,G4900 196 | Intel®,Celeron®,G4900T 197 | Intel®,Celeron®,G4920 198 | Intel®,Celeron®,G4930 199 | Intel®,Celeron®,G4930E 200 | Intel®,Celeron®,G4930T 201 | Intel®,Celeron®,G4932E 202 | Intel®,Celeron®,G4950 203 | Intel®,Celeron®,J4005 204 | Intel®,Celeron®,J4105 205 | Intel®,Celeron®,J4115 206 | Intel®,Celeron®,N4000 207 | Intel®,Celeron®,N4100 208 | Intel®,Celeron®,3867U 209 | Intel®,Celeron®,4205U 210 | Intel®,Celeron®,4305U 211 | Intel®,Celeron®,4305UE 212 | Intel®,Celeron®,J4025 213 | Intel®,Celeron®,J4125 214 | Intel®,Celeron®,N4020 215 | Intel®,Celeron®,N4120 216 | Intel®,Celeron®,5205U 217 | Intel®,Celeron®,5305U 218 | Intel®,Celeron®,G5900 219 | Intel®,Celeron®,G5900E 220 | Intel®,Celeron®,G5900T 221 | Intel®,Celeron®,G5900TE 222 | Intel®,Celeron®,G5905 223 | Intel®,Celeron®,G5905T 224 | Intel®,Celeron®,G5920 225 | Intel®,Celeron®,G5925 226 | Intel®,Celeron®,J6412 227 | Intel®,Celeron®,J6413 228 | Intel®,Celeron®,N6210 229 | Intel®,Celeron®,N6211 230 | Intel®,Celeron®,N4500 231 | Intel®,Celeron®,N4505 232 | Intel®,Celeron®,N5100 233 | Intel®,Celeron®,N5105 234 | Intel®,Celeron®,6305 235 | Intel®,Celeron®,6305E 236 | Intel®,Core™,i5-10210Y 237 | Intel®,Core™,i5-10310Y 238 | Intel®,Core™,i5-8200Y 239 | Intel®,Core™,i5-8210Y 240 | Intel®,Core™,i5-8310Y 241 | Intel®,Core™,i7-10510Y 242 | Intel®,Core™,i7-8500Y 243 | Intel®,Core™,m3-8100Y 244 | Intel®,Core™,i3-8100 245 | Intel®,Core™,i3-8100B 246 | Intel®,Core™,i3-8100H 247 | Intel®,Core™,i3-8100T 248 | Intel®,Core™,i3-8109U 249 | Intel®,Core™,i3-8140U 250 | Intel®,Core™,i3-8300 251 | Intel®,Core™,i3-8300T 252 | Intel®,Core™,i3-8350K 253 | Intel®,Core™,i5+8400 254 | Intel®,Core™,i5+8500 255 | Intel®,Core™,i5-8257U 256 | Intel®,Core™,i5-8259U 257 | Intel®,Core™,i5-8260U 258 | Intel®,Core™,i5-8269U 259 | Intel®,Core™,i5-8279U 260 | Intel®,Core™,i5-8300H 261 | Intel®,Core™,i5-8400 262 | Intel®,Core™,i5-8400B 263 | Intel®,Core™,i5-8400H 264 | Intel®,Core™,i5-8400T 265 | Intel®,Core™,i5-8500 266 | Intel®,Core™,i5-8500B 267 | Intel®,Core™,i5-8500T 268 | Intel®,Core™,i5-8600 269 | Intel®,Core™,i5-8600K 270 | Intel®,Core™,i5-8600T 271 | Intel®,Core™,i7-8086K 272 | Intel®,Core™,i7-8557U 273 | Intel®,Core™,i7-8559U 274 | Intel®,Core™,i7-8569U 275 | Intel®,Core™,i7-8700 276 | Intel®,Core™,i7-8700B 277 | Intel®,Core™,i7-8700K 278 | Intel®,Core™,i7-8700T 279 | Intel®,Core™,i7-8750H 280 | Intel®,Core™,i7-8850H 281 | Intel®,Core™,i3-8130U 282 | Intel®,Core™,i5-8250U 283 | Intel®,Core™,i5-8350U 284 | Intel®,Core™,i7-8550U 285 | Intel®,Core™,i7-8650U 286 | Intel®,Core™,i3-8145U 287 | Intel®,Core™,i3-8145UE 288 | Intel®,Core™,i5-8265U 289 | Intel®,Core™,i5-8365U 290 | Intel®,Core™,i5-8365UE 291 | Intel®,Core™,i7-8565U 292 | Intel®,Core™,i7-8665U 293 | Intel®,Core™,i7-8665UE 294 | Intel®,Core™,i3-9100 295 | Intel®,Core™,i3-9100E 296 | Intel®,Core™,i3-9100F 297 | Intel®,Core™,i3-9100HL 298 | Intel®,Core™,i3-9100T 299 | Intel®,Core™,i3-9100TE 300 | Intel®,Core™,i3-9300 301 | Intel®,Core™,i3-9300T 302 | Intel®,Core™,i3-9320 303 | Intel®,Core™,i3-9350K 304 | Intel®,Core™,i3-9350KF 305 | Intel®,Core™,i5-9300H 306 | Intel®,Core™,i5-9300HF 307 | Intel®,Core™,i5-9400 308 | Intel®,Core™,i5-9400F 309 | Intel®,Core™,i5-9400H 310 | Intel®,Core™,i5-9400T 311 | Intel®,Core™,i5-9500 312 | Intel®,Core™,i5-9500E 313 | Intel®,Core™,i5-9500F 314 | Intel®,Core™,i5-9500T 315 | Intel®,Core™,i5-9500TE 316 | Intel®,Core™,i5-9600 317 | Intel®,Core™,i5-9600K 318 | Intel®,Core™,i5-9600KF 319 | Intel®,Core™,i5-9600T 320 | Intel®,Core™,i7-9700 321 | Intel®,Core™,i7-9700E 322 | Intel®,Core™,i7-9700F 323 | Intel®,Core™,i7-9700K 324 | Intel®,Core™,i7-9700KF 325 | Intel®,Core™,i7-9700T 326 | Intel®,Core™,i7-9700TE 327 | Intel®,Core™,i7-9750H 328 | Intel®,Core™,i7-9750HF 329 | Intel®,Core™,i7-9850H 330 | Intel®,Core™,i7-9850HE 331 | Intel®,Core™,i7-9850HL 332 | Intel®,Core™,i9-8950HK 333 | Intel®,Core™,i9-9880H 334 | Intel®,Core™,i9-9900 335 | Intel®,Core™,i9-9900K 336 | Intel®,Core™,i9-9900KF 337 | Intel®,Core™,i9-9900KS 338 | Intel®,Core™,i9-9900T 339 | Intel®,Core™,i9-9980HK 340 | Intel®,Core™,i3-10100Y 341 | Intel®,Core™,i3-10110Y 342 | Intel®,Core™,i9-10900X 343 | Intel®,Core™,i9-10920X 344 | Intel®,Core™,i9-10940X 345 | Intel®,Core™,i9-10980XE 346 | Intel®,Core™,i3-10100 347 | Intel®,Core™,i3-10100E 348 | Intel®,Core™,i3-10100F 349 | Intel®,Core™,i3-10100T 350 | Intel®,Core™,i3-10100TE 351 | Intel®,Core™,i3-10105 352 | Intel®,Core™,i3-10105F 353 | Intel®,Core™,i3-10105T 354 | Intel®,Core™,i3-10110U 355 | Intel®,Core™,i3-10300 356 | Intel®,Core™,i3-10300T 357 | Intel®,Core™,i3-10305 358 | Intel®,Core™,i3-10305T 359 | Intel®,Core™,i3-10320 360 | Intel®,Core™,i3-10325 361 | Intel®,Core™,i5-10200H 362 | Intel®,Core™,i5-10210U 363 | Intel®,Core™,i5-10300H 364 | Intel®,Core™,i5-10310U 365 | Intel®,Core™,i5-10400 366 | Intel®,Core™,i5-10400F 367 | Intel®,Core™,i5-10400H 368 | Intel®,Core™,i5-10400T 369 | Intel®,Core™,i5-10500 370 | Intel®,Core™,i5-10500E 371 | Intel®,Core™,i5-10500H 372 | Intel®,Core™,i5-10500T 373 | Intel®,Core™,i5-10500TE 374 | Intel®,Core™,i5-10600 375 | Intel®,Core™,i5-10600K 376 | Intel®,Core™,i5-10600KF 377 | Intel®,Core™,i5-10600T 378 | Intel®,Core™,i7-10510U 379 | Intel®,Core™,i7-10610U 380 | Intel®,Core™,i7-10700 381 | Intel®,Core™,i7-10700E 382 | Intel®,Core™,i7-10700F 383 | Intel®,Core™,i7-10700K 384 | Intel®,Core™,i7-10700KF 385 | Intel®,Core™,i7-10700T 386 | Intel®,Core™,i7-10700TE 387 | Intel®,Core™,i7-10710U 388 | Intel®,Core™,i7-10750H 389 | Intel®,Core™,i7-10810U 390 | Intel®,Core™,i7-10850H 391 | Intel®,Core™,i7-10870H 392 | Intel®,Core™,i7-10875H 393 | Intel®,Core™,i9-10850K 394 | Intel®,Core™,i9-10885H 395 | Intel®,Core™,i9-10900 396 | Intel®,Core™,i9-10900E 397 | Intel®,Core™,i9-10900F 398 | Intel®,Core™,i9-10900K 399 | Intel®,Core™,i9-10900KF 400 | Intel®,Core™,i9-10900T 401 | Intel®,Core™,i9-10900TE 402 | Intel®,Core™,i9-10980HK 403 | Intel®,Core™,i3-1000G1 404 | Intel®,Core™,i3-1000G4 405 | Intel®,Core™,i3-1005G1 406 | Intel®,Core™,i5-1030G4 407 | Intel®,Core™,i5-1030G7 408 | Intel®,Core™,i5-1035G1 409 | Intel®,Core™,i5-1035G4 410 | Intel®,Core™,i5-1035G7 411 | Intel®,Core™,i5-1038NG7 412 | Intel®,Core™,i7-1060G7 413 | Intel®,Core™,i7-1065G7 414 | Intel®,Core™,i7-1068NG7 415 | Intel®,Core™,i3-L13G4 416 | Intel®,Core™,i5-L16G7 417 | Intel®,Core™,i5-11400 418 | Intel®,Core™,i5-11400F 419 | Intel®,Core™,i5-11400T 420 | Intel®,Core™,i5-11500 421 | Intel®,Core™,i5-11500T 422 | Intel®,Core™,i5-11600 423 | Intel®,Core™,i5-11600K 424 | Intel®,Core™,i5-11600KF 425 | Intel®,Core™,i5-11600T 426 | Intel®,Core™,i7-11700 427 | Intel®,Core™,i7-11700F 428 | Intel®,Core™,i7-11700K 429 | Intel®,Core™,i7-11700KF 430 | Intel®,Core™,i7-11700T 431 | Intel®,Core™,i9-11900 432 | Intel®,Core™,i9-11900F 433 | Intel®,Core™,i9-11900K 434 | Intel®,Core™,i9-11900KF 435 | Intel®,Core™,i9-11900T 436 | Intel®,Core™,i3-1110G4 437 | Intel®,Core™,i3-1115G4 438 | Intel®,Core™,i3-1115G4E 439 | Intel®,Core™,i3-1115GRE 440 | Intel®,Core™,i3-1120G4 441 | Intel®,Core™,i3-1125G4 442 | Intel®,Core™,i5-11300H 443 | Intel®,Core™,i5-1130G7 444 | Intel®,Core™,i5-1135G7 445 | Intel®,Core™,i5-1135G7 446 | Intel®,Core™,i5-1140G7 447 | Intel®,Core™,i5-1145G7 448 | Intel®,Core™,i5-1145G7E 449 | Intel®,Core™,i5-1145GRE 450 | Intel®,Core™,i7-11370H 451 | Intel®,Core™,i7-11375H 452 | Intel®,Core™,i7-1160G7 453 | Intel®,Core™,i7-1165G7 454 | Intel®,Core™,i7-1165G7 455 | Intel®,Core™,i7-1180G7 456 | Intel®,Core™,i7-1185G7 457 | Intel®,Core™,i7-1185G7E 458 | Intel®,Core™,i7-1185GRE 459 | Intel®,Pentium®,Gold 4425Y 460 | Intel®,Pentium®,Gold 6500Y 461 | Intel®,Pentium®,Gold G5400 462 | Intel®,Pentium®,Gold G5400T 463 | Intel®,Pentium®,Gold G5420 464 | Intel®,Pentium®,Gold G5420T 465 | Intel®,Pentium®,Gold G5500 466 | Intel®,Pentium®,Gold G5500T 467 | Intel®,Pentium®,Gold G5600 468 | Intel®,Pentium®,Gold G5600T 469 | Intel®,Pentium®,Gold G5620 470 | Intel®,Pentium®,Silver J5005 471 | Intel®,Pentium®,Silver N5000 472 | Intel®,Pentium®,Gold 4417U 473 | Intel®,Pentium®,Gold 5405U 474 | Intel®,Pentium®,Silver J5040 475 | Intel®,Pentium®,Silver N5030 476 | Intel®,Pentium®,Gold 6405U 477 | Intel®,Pentium®,Gold G6400 478 | Intel®,Pentium®,Gold G6400E 479 | Intel®,Pentium®,Gold G6400T 480 | Intel®,Pentium®,Gold G6400TE 481 | Intel®,Pentium®,Gold G6405 482 | Intel®,Pentium®,Gold G6405T 483 | Intel®,Pentium®,Gold G6500 484 | Intel®,Pentium®,Gold G6500T 485 | Intel®,Pentium®,Gold G6505 486 | Intel®,Pentium®,Gold G6505T 487 | Intel®,Pentium®,Gold G6600 488 | Intel®,Pentium®,Gold G6605 489 | Intel®,Pentium®,6805 490 | Intel®,Pentium®,J6426 491 | Intel®,Pentium®,N6415 492 | Intel®,Pentium®,Silver N6000 493 | Intel®,Pentium®,Silver N6005 494 | Intel®,Pentium®,Gold 7505 495 | Intel®,Xeon®,Bronze 3104 496 | Intel®,Xeon®,Bronze 3106 497 | Intel®,Xeon®,Gold 5115 498 | Intel®,Xeon®,Gold 5118 499 | Intel®,Xeon®,Gold 5119T 500 | Intel®,Xeon®,Gold 5120 501 | Intel®,Xeon®,Gold 5120T 502 | Intel®,Xeon®,Gold 5122 503 | Intel®,Xeon®,Gold 6126 504 | Intel®,Xeon®,Gold 6126F 505 | Intel®,Xeon®,Gold 6126T 506 | Intel®,Xeon®,Gold 6128 507 | Intel®,Xeon®,Gold 6130 508 | Intel®,Xeon®,Gold 6130F 509 | Intel®,Xeon®,Gold 6130T 510 | Intel®,Xeon®,Gold 6132 511 | Intel®,Xeon®,Gold 6134 512 | Intel®,Xeon®,Gold 6136 513 | Intel®,Xeon®,Gold 6138 514 | Intel®,Xeon®,Gold 6138F 515 | Intel®,Xeon®,Gold 6138P 516 | Intel®,Xeon®,Gold 6138T 517 | Intel®,Xeon®,Gold 6140 518 | Intel®,Xeon®,Gold 6142 519 | Intel®,Xeon®,Gold 6142F 520 | Intel®,Xeon®,Gold 6144 521 | Intel®,Xeon®,Gold 6146 522 | Intel®,Xeon®,Gold 6148 523 | Intel®,Xeon®,Gold 6148F 524 | Intel®,Xeon®,Gold 6150 525 | Intel®,Xeon®,Gold 6152 526 | Intel®,Xeon®,Gold 6154 527 | Intel®,Xeon®,Platinum 8153 528 | Intel®,Xeon®,Platinum 8156 529 | Intel®,Xeon®,Platinum 8158 530 | Intel®,Xeon®,Platinum 8160 531 | Intel®,Xeon®,Platinum 8160F 532 | Intel®,Xeon®,Platinum 8160T 533 | Intel®,Xeon®,Platinum 8164 534 | Intel®,Xeon®,Platinum 8168 535 | Intel®,Xeon®,Platinum 8170 536 | Intel®,Xeon®,Platinum 8176 537 | Intel®,Xeon®,Platinum 8176F 538 | Intel®,Xeon®,Platinum 8180 539 | Intel®,Xeon®,Silver 4108 540 | Intel®,Xeon®,Silver 4109T 541 | Intel®,Xeon®,Silver 4110 542 | Intel®,Xeon®,Silver 4112 543 | Intel®,Xeon®,Silver 4114 544 | Intel®,Xeon®,Silver 4114T 545 | Intel®,Xeon®,Silver 4116 546 | Intel®,Xeon®,Silver 4116T 547 | Intel®,Xeon®,E-2124 548 | Intel®,Xeon®,E-2124G 549 | Intel®,Xeon®,E-2126G 550 | Intel®,Xeon®,E-2134 551 | Intel®,Xeon®,E-2136 552 | Intel®,Xeon®,E-2144G 553 | Intel®,Xeon®,E-2146G 554 | Intel®,Xeon®,E-2174G 555 | Intel®,Xeon®,E-2176G 556 | Intel®,Xeon®,E-2176M 557 | Intel®,Xeon®,E-2186G 558 | Intel®,Xeon®,E-2186M 559 | Intel®,Xeon®,E-2224 560 | Intel®,Xeon®,E-2224G 561 | Intel®,Xeon®,E-2226G 562 | Intel®,Xeon®,E-2226GE 563 | Intel®,Xeon®,E-2234 564 | Intel®,Xeon®,E-2236 565 | Intel®,Xeon®,E-2244G 566 | Intel®,Xeon®,E-2246G 567 | Intel®,Xeon®,E-2254ME 568 | Intel®,Xeon®,E-2254ML 569 | Intel®,Xeon®,E-2274G 570 | Intel®,Xeon®,E-2276G 571 | Intel®,Xeon®,E-2276M 572 | Intel®,Xeon®,E-2276ME 573 | Intel®,Xeon®,E-2276ML 574 | Intel®,Xeon®,E-2278G 575 | Intel®,Xeon®,E-2278GE 576 | Intel®,Xeon®,E-2278GEL 577 | Intel®,Xeon®,E-2286G 578 | Intel®,Xeon®,E-2286M 579 | Intel®,Xeon®,E-2288G 580 | Intel®,Xeon®,Bronze 3204 581 | Intel®,Xeon®,Bronze 3206R 582 | Intel®,Xeon®,Gold 5215 583 | Intel®,Xeon®,Gold 5215L 584 | Intel®,Xeon®,Gold 5217 585 | Intel®,Xeon®,Gold 5218B 586 | Intel®,Xeon®,Gold 5218N 587 | Intel®,Xeon®,Gold 5218R 588 | Intel®,Xeon®,Gold 5218T 589 | Intel®,Xeon®,Gold 5220 590 | Intel®,Xeon®,Gold 5220R 591 | Intel®,Xeon®,Gold 5220S 592 | Intel®,Xeon®,Gold 5220T 593 | Intel®,Xeon®,Gold 5222 594 | Intel®,Xeon®,Gold 6208U 595 | Intel®,Xeon®,Gold 6209U 596 | Intel®,Xeon®,Gold 6210U 597 | Intel®,Xeon®,Gold 6212U 598 | Intel®,Xeon®,Gold 6222V 599 | Intel®,Xeon®,Gold 6226 600 | Intel®,Xeon®,Gold 6226R 601 | Intel®,Xeon®,Gold 6230 602 | Intel®,Xeon®,Gold 6230N 603 | Intel®,Xeon®,Gold 6230R 604 | Intel®,Xeon®,Gold 6230T 605 | Intel®,Xeon®,Gold 6238 606 | Intel®,Xeon®,Gold 6238L 607 | Intel®,Xeon®,Gold 6238T 608 | Intel®,Xeon®,Gold 6240 609 | Intel®,Xeon®,Gold 6240L 610 | Intel®,Xeon®,Gold 6240R 611 | Intel®,Xeon®,Gold 6240Y 612 | Intel®,Xeon®,Gold 6242 613 | Intel®,Xeon®,Gold 6242R 614 | Intel®,Xeon®,Gold 6244 615 | Intel®,Xeon®,Gold 6246R 616 | Intel®,Xeon®,Gold 6248 617 | Intel®,Xeon®,Gold 6248R 618 | Intel®,Xeon®,Gold 6250 619 | Intel®,Xeon®,Gold 6250L 620 | Intel®,Xeon®,Gold 6252 621 | Intel®,Xeon®,Gold 6252N 622 | Intel®,Xeon®,Gold 6254 623 | Intel®,Xeon®,Gold 6256 624 | Intel®,Xeon®,Gold 6258R 625 | Intel®,Xeon®,Gold 6262V 626 | Intel®,Xeon®,Gold Gold 5218 627 | Intel®,Xeon®,Gold Gold 6238R 628 | Intel®,Xeon®,Gold6246 629 | Intel®,Xeon®,Goldv 6234 630 | Intel®,Xeon®,Platinum 8253 631 | Intel®,Xeon®,Platinum 8256 632 | Intel®,Xeon®,Platinum 8260 633 | Intel®,Xeon®,Platinum 8260L 634 | Intel®,Xeon®,Platinum 8260Y 635 | Intel®,Xeon®,Platinum 8268 636 | Intel®,Xeon®,Platinum 8270 637 | Intel®,Xeon®,Platinum 8276 638 | Intel®,Xeon®,Platinum 8276L 639 | Intel®,Xeon®,Platinum 8280 640 | Intel®,Xeon®,Platinum 8280L 641 | Intel®,Xeon®,Platinum 9221 642 | Intel®,Xeon®,Platinum 9222 643 | Intel®,Xeon®,Platinum 9242 644 | Intel®,Xeon®,Platinum 9282 645 | Intel®,Xeon®,Silver 4208 646 | Intel®,Xeon®,Silver 4209T 647 | Intel®,Xeon®,Silver 4210 648 | Intel®,Xeon®,Silver 4210R 649 | Intel®,Xeon®,Silver 4210T 650 | Intel®,Xeon®,Silver 4214 651 | Intel®,Xeon®,Silver 4214R 652 | Intel®,Xeon®,Silver 4214Y 653 | Intel®,Xeon®,Silver 4215 654 | Intel®,Xeon®,Silver 4215R 655 | Intel®,Xeon®,Silver 4216 656 | Intel®,Xeon®,W-2223 657 | Intel®,Xeon®,W-2225 658 | Intel®,Xeon®,W-2235 659 | Intel®,Xeon®,W-2245 660 | Intel®,Xeon®,W-2255 661 | Intel®,Xeon®,W-2265 662 | Intel®,Xeon®,W-2275 663 | Intel®,Xeon®,W-2295 664 | Intel®,Xeon®,W-3223 665 | Intel®,Xeon®,W-3225 666 | Intel®,Xeon®,W-3235 667 | Intel®,Xeon®,W-3245 668 | Intel®,Xeon®,W-3245M 669 | Intel®,Xeon®,W-3265 670 | Intel®,Xeon®,W-3265M 671 | Intel®,Xeon®,W-3275 672 | Intel®,Xeon®,W-3275M 673 | Intel®,Xeon®,W-10855M 674 | Intel®,Xeon®,W-10885M 675 | Intel®,Xeon®,W-1250 676 | Intel®,Xeon®,W-1250E 677 | Intel®,Xeon®,W-1250P 678 | Intel®,Xeon®,W-1250TE 679 | Intel®,Xeon®,W-1270 680 | Intel®,Xeon®,W-1270E 681 | Intel®,Xeon®,W-1270P 682 | Intel®,Xeon®,W-1270TE 683 | Intel®,Xeon®,W-1290 684 | Intel®,Xeon®,W-1290E 685 | Intel®,Xeon®,W-1290P 686 | Intel®,Xeon®,W-1290T 687 | Intel®,Xeon®,W-1290TE 688 | Intel®,Xeon®,Gold 5315Y 689 | Intel®,Xeon®,Gold 5317 690 | Intel®,Xeon®,Gold 5318N 691 | Intel®,Xeon®,Gold 5318S 692 | Intel®,Xeon®,Gold 5320 693 | Intel®,Xeon®,Gold 5320T 694 | Intel®,Xeon®,Gold 6312U 695 | Intel®,Xeon®,Gold 6314U 696 | Intel®,Xeon®,Gold 6326 697 | Intel®,Xeon®,Gold 6330 698 | Intel®,Xeon®,Gold 6330N 699 | Intel®,Xeon®,Gold 6334 700 | Intel®,Xeon®,Gold 6336Y 701 | Intel®,Xeon®,Gold 6338 702 | Intel®,Xeon®,Gold 6338N 703 | Intel®,Xeon®,Gold 6338T 704 | Intel®,Xeon®,Gold 6342 705 | Intel®,Xeon®,Gold 6346 706 | Intel®,Xeon®,Gold 6348 707 | Intel®,Xeon®,Gold 6354 708 | Intel®,Xeon®,Gold Gold 5318Y 709 | Intel®,Xeon®,Platinum 8351N 710 | Intel®,Xeon®,Platinum 8352S 711 | Intel®,Xeon®,Platinum 8352V 712 | Intel®,Xeon®,Platinum 8352Y 713 | Intel®,Xeon®,Platinum 8358 714 | Intel®,Xeon®,Platinum 8358P 715 | Intel®,Xeon®,Platinum 8360Y 716 | Intel®,Xeon®,Platinum 8368 717 | Intel®,Xeon®,Platinum 8368Q 718 | Intel®,Xeon®,Platinum 8380 719 | Intel®,Xeon®,Silver 4309Y 720 | Intel®,Xeon®,Silver 4310 721 | Intel®,Xeon®,Silver 4310T 722 | Intel®,Xeon®,Silver 4314 723 | Intel®,Xeon®,Silver 4316 724 | Qualcomm®,Snapdragon™,Snapdragon 850 725 | Qualcomm®,Snapdragon™,Snapdragon 7c 726 | Qualcomm®,Snapdragon™,Snapdragon 8c 727 | Qualcomm®,Snapdragon™,Snapdragon 8cx 728 | Qualcomm®,Snapdragon™,Snapdragon 8cx (Gen2) 729 | Qualcomm®,Snapdragon™,Microsoft SQ1 730 | Qualcomm®,Snapdragon™,Microsoft SQ2 731 | "@ | convertfrom-csv -Header Manafacturer, series, model 732 | 733 | $Proc = (Get-CimInstance -ClassName Win32_Processor).name -split ' ' | ForEach-Object { $models | Where-Object -Property model -eq $_ } 734 | 735 | $Results = [PSCustomObject]@{ 736 | "TPM Compatible" = (Get-Tpm).tpmpresent 737 | "Processor Compatible" = [bool]$Proc 738 | "64 Bit OS" = [Environment]::Is64BitOperatingSystem 739 | } 740 | 741 | if ($results.psobject.properties.value -contains $false) { 742 | write-host "This device is not compatible with Windows 11. See the detailed results for more information" 743 | $Results | Format-List 744 | Log-Activity -Message "$env:computername is not Win 11 Compatatable" -EventName "This device is not compatible with Windows 11. See the detailed results for more information" 745 | Set-Asset-Field -Name 'Windows 11 Compatible' -Value $false 746 | } 747 | else { 748 | write-host "This device is compatible with Windows 11. See the detailed results for more information" 749 | $Results | format-list 750 | 751 | Log-Activity -Message "$env:computername is Win 11 Compatatable" -EventName "This device is compatible with Windows 11. See the detailed results for more information" 752 | Set-Asset-Field -Name 'Windows 11 Compatible' -Value $true 753 | } 754 | -------------------------------------------------------------------------------- /Write-AVTestFile.ps1: -------------------------------------------------------------------------------- 1 | # Writes an EICAR string to faile specified by $OutPath 2 | 3 | #$Base64 = [Convert]::ToBase64String([char[]]$String) 4 | #$bytes = [Convert]::FromBase64String($Base64) 5 | #$String = [System.Text.Encoding]::UTF8.GetString($bytes) 6 | 7 | $OutPath = 'C:\ProgramData\eicar.com' 8 | 9 | # EICAR string represented as a byte array to avoid av detection w/in this script. 10 | $bytes = [Byte[]]@( 11 | 88, 53, 79, 33, 80, 37, 64, 65, 80, 91, 52, 92, 80, 90, 88, 53, 52, 40, 80, 94, 41, 55, 67, 67, 41, 55, 125, 12 | 36, 69, 73, 67, 65, 82, 45, 83, 84, 65, 78, 68, 65, 82, 68, 45, 65, 78, 84, 73, 86, 73, 82, 85, 83, 45, 84, 13 | 69, 83, 84, 45, 70, 73, 76, 69, 33, 36, 72, 43, 72, 42 14 | ) 15 | 16 | Out-File -FilePath $OutPath -InputObject [System.Text.Encoding]::UTF8.GetString($bytes) 17 | 18 | & $OutPath | Out-Null 19 | -------------------------------------------------------------------------------- /alert or set custom field.ps1: -------------------------------------------------------------------------------- 1 | # this script expects 2 runtime variables 2 | # 3 | # $PolicyName is required and will be used in the alert massage or as the value 4 | # of the the asset custom field 5 | # 6 | # $AssetCustomField is optional if specified the script will set the field 7 | # inserted of raising an alert 8 | 9 | Import-Module $env:SyncroModule -DisableNameChecking 10 | 11 | if ([string]::IsNullOrEmpty($PolicyName)){ 12 | Rmm-Alert -Category 'Policy_Assigned' -Body 'Error: $PolicyName is missing or blank' 13 | } elseif ([string]::IsNullOrEmpty($AssetCustomField)){ 14 | Rmm-Alert -Category 'Policy_Assigned' -Body "$env:computername is assigned $PolicyName" 15 | } else { 16 | Set-Asset-Field -Name $AssetCustomField -Value $PolicyName 17 | } 18 | -------------------------------------------------------------------------------- /disableActiveX_CVE-2021-40444.cmd: -------------------------------------------------------------------------------- 1 | GOTO startCMD 2 | :: Disable ActiveX controls per MSRC gidance 3 | :: This script is intended to mitigate MITRE CVE-2021-40444 4 | :: Reference: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444 5 | 6 | :: Version: 1.0 7 | :: Author: jrdnr 8 | :: Creation Date: 08/09/2021 9 | :: Purpose/Change: Initial script development 10 | :startCMD 11 | 12 | REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0" /v 1001 /t REG_DWORD /d 00000003 /f 13 | REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0" /v 1004 /t REG_DWORD /d 00000003 /f 14 | 15 | REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v 1001 /t REG_DWORD /d 00000003 /f 16 | REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v 1004 /t REG_DWORD /d 00000003 /f 17 | 18 | REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\2" /v 1001 /t REG_DWORD /d 00000003 /f 19 | REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\2" /v 1004 /t REG_DWORD /d 00000003 /f 20 | 21 | REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3" /v 1001 /t REG_DWORD /d 00000003 /f 22 | REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3" /v 1004 /t REG_DWORD /d 00000003 /f 23 | -------------------------------------------------------------------------------- /disableActiveX_CVE-2021-40444.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Disable ActiveX controls per MSRC gidance 4 | .DESCRIPTION 5 | This script is intended to mitigate MITRE CVE-2021-40444 6 | Reference: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444 7 | 8 | Required Script Variable: 9 | Name: BlockActiveX 10 | Type: Dropdown 11 | Values: False (Default) 12 | True 13 | .NOTES 14 | Version: 1.2 15 | Author: jrdnr 16 | Creation Date: 08/09/2021 17 | Purpose/Change: Resolve error with missing path, improved output 18 | #> 19 | 20 | $regRoot = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones" 21 | foreach ($i in 0..3) { 22 | $regKey = Join-Path -Path $regRoot -ChildPath $i 23 | if('False' -eq $BlockActiveX){ 24 | Remove-Item -Path $regKey -Verbose 25 | } elseif (Test-Path -Path $regKey){ 26 | Set-ItemProperty -Path $regKey -Name 1001 -Value 3 | Out-Null 27 | Set-ItemProperty -Path $regKey -Name 1004 -Value 3 | Out-Null 28 | } else { 29 | Write-Warning "$regKey Not Found" 30 | foreach ($child in $regKey.Split('\')) { 31 | $root = "$root\$child" 32 | if ($child -match ':') { 33 | $root = $child 34 | } elseif (!(Test-Path -Path "$root")) { 35 | New-Item -Path $root 36 | } 37 | } 38 | New-ItemProperty -Path $regKey -Name 1001 -Value 3 | Out-Null 39 | New-ItemProperty -Path $regKey -Name 1004 -Value 3 | Out-Null 40 | } 41 | [array]$return += Get-ItemProperty -Path $regKey -ErrorAction SilentlyContinue | Select-Object -Property @{n='ZoneKey';e={$i}},'1001','1004' 42 | } 43 | 44 | $return | Out-Host 45 | -------------------------------------------------------------------------------- /enableActiveX_CVE-2021-40444.cmd: -------------------------------------------------------------------------------- 1 | GOTO startCMD 2 | :: Re-Enables ActiveX controls per MSRC gidance 3 | :: This script is intended to revert the mitigation for MITRE CVE-2021-40444 4 | :: Reference: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444 5 | 6 | :: Version: 1.0 7 | :: Author: jrdnr 8 | :: Creation Date: 08/09/2021 9 | :: Purpose/Change: Initial script development 10 | :startCMD 11 | 12 | REG DELETE "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0" /f 13 | 14 | REG DELETE "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /f 15 | 16 | REG DELETE "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\2" /f 17 | 18 | REG DELETE "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3" /f 19 | -------------------------------------------------------------------------------- /nable_Cleanup.ps1: -------------------------------------------------------------------------------- 1 | $Publisher = 'MspPlatform|N-able|SolarWinds' 2 | $SilentUninstallFlag = '/SILENT' 3 | $exit = 0 4 | 5 | $FileLocation = @( 6 | 'C:\Program Files\' 7 | 'C:\Program Files (x86)\' 8 | 'C:\ProgramData\' 9 | ) 10 | 11 | $folderList = @( 12 | 'BeAnywhere' 13 | 'MspPlatform' 14 | 'N-able' 15 | '^Package Cache$' 16 | 'SolarWinds' 17 | ) 18 | $SvcPath = @( 19 | 'HKLM:\SYSTEM\CurrentControlSet\Services', 20 | 'HKLM:\SYSTEM\CurrentControlSet001\Services', 21 | 'HKLM:\SYSTEM\CurrentControlSet002\Services', 22 | 'HKLM:\SYSTEM\CurrentControlSet003\Services' 23 | ) 24 | $SvcSubKey = @( 25 | 'AssetDiscovery', 26 | 'InterfaceDiscovery', 27 | 'N-ablesyslog', 28 | 'N-ableTechnologies Windows Software Probe', 29 | 'N-ableTechnologies Windows Software Probe Maintenance' 30 | ) 31 | 32 | $RegPath = @( 33 | 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\N-ableTechnologies Inc. Windows Agent', 34 | 'HKLM:\SOFTWARE\N-ableTechnologies\Windows Agent', 35 | 'HKLM:\SYSTEM\CurrentControlSet\Services\N-ableTechnologies Windows Agent', 36 | 'HKLM:\SYSTEM\CurrentControlSet\Services\N-ableTechnologies Windows Agent Maintenance', 37 | 'HKLM:\SOFTWARE\N-ableTechnologies\Windows Software Probe', 38 | 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\N-ableTechnologies Inc. Windows Probe' 39 | ) 40 | 41 | function Import-SyncroModule { 42 | param ( 43 | #Defaults to the UUID of local system but you can provide the UUID of Any other Syncro Asset instead. 44 | $UUID 45 | ) 46 | 47 | # Set up $env: vars for Syncro Module 48 | if($env:SyncroModule -match '^\s*$'){ 49 | $SyncroRegKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\RepairTech\Syncro' -Name uuid, shop_subdomain 50 | $env:RepairTechFilePusherPath = 'C:\ProgramData\Syncro\bin\FilePusher.exe' 51 | $env:RepairTechKabutoApiUrl = 'https://rmm.syncromsp.com' 52 | $env:RepairTechSyncroApiUrl = 'https://{subdomain}.syncromsp.com' 53 | $env:RepairTechSyncroSubDomain = $SyncroRegKey.shop_subdomain 54 | $env:RepairTechUUID = if($UUID -match '^\s*$'){ $SyncroRegKey.uuid } else {$UUID} 55 | $env:SyncroModule = "$env:ProgramData\Syncro\bin\module.psm1" 56 | } 57 | if ((Test-Path -Path $env:SyncroModule) -and ($PSVersionTable.PSVersion -ge [system.version]'4.0')) { 58 | Import-Module -Name $env:SyncroModule -WarningAction SilentlyContinue 59 | } elseif ($PSVersionTable.PSVersion.Major -lt 4) { 60 | Write-Warning "$($PSVersionTable.PSVersion) is not compatible with SyncroModule" 61 | [Environment]::SetEnvironmentVariable('SyncroModule',$null) 62 | $false 63 | } 64 | } 65 | 66 | function Get-InstalledApps { 67 | param ( 68 | [string]$App, 69 | [string]$Publisher 70 | ) 71 | $installLocation = @( 72 | "HKLM:\software\microsoft\windows\currentversion\uninstall" 73 | "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" 74 | ) 75 | $AllApps = get-childitem $installLocation | ForEach-Object { Get-ItemProperty $_.PSPath } 76 | 77 | foreach ($a in $AllApps){ 78 | if ($a.DisplayName -match $App -and $a.Publisher -match $Publisher){ 79 | $a 80 | } 81 | } 82 | } 83 | 84 | $Applist = Get-InstalledApps -Publisher $Publisher 85 | if($null -ne $Applist){ 86 | foreach ($a in $Applist){ 87 | 'Uninstalling "{0}" by "{1}"' -f $a.DisplayName, $a.Publisher 88 | if($a.QuietUninstallString -match '"(.*)"\s(/.*)'){ 89 | Start-Process -FilePath $Matches[1] -ArgumentList $Matches[2] -Wait 90 | } elseif ($a.UninstallString -like 'C:\Program Files*'){ 91 | Start-Process -FilePath $a.UninstallString -ArgumentList $SilentUninstallFlag -Wait 92 | } elseif ($a.UninstallString -like 'MsiExec.exe*'){ 93 | $ArgList = (($a.UninstallString -split 'MsiExec.exe')[1].trim() -replace '/I{','/X{').ToString() 94 | $ArgList = '{0} /quiet /norestart' -f $ArgList 95 | Start-Process -FilePath MsiExec.exe -ArgumentList $ArgList -Wait 96 | } else { 97 | "Could not auto uninstall $($a.DisplayName)" 98 | "Uninstall String: '$($a.UninstallString)'" 99 | $exit = 2 100 | } 101 | } 102 | } 103 | 104 | Get-ChildItem -Path $FileLocation -ErrorAction SilentlyContinue | Where-Object {$_.name -match ($folderList -join '|')} | Remove-Item -Recurse -Force -ErrorAction Continue -Verbose 105 | Get-ChildItem -Path $SvcPath -ErrorAction SilentlyContinue | Where-Object {$_.name -match ($SvcSubKey -join '|')} | Remove-Item -Recurse -Force -ErrorAction Continue -Verbose 106 | Get-ChildItem -Path $RegPath -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction Continue -Verbose 107 | try { 108 | $CredPovider = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\' 109 | $dll = 'MSPACredentialProvider_.+_N-Central' 110 | 111 | Get-ChildItem $CredPovider | Where-Object { 112 | (Get-ItemProperty (Join-Path -Path $CredPovider -ChildPath $_.PSChildName) | 113 | Select-Object -ExpandProperty '(default)') -match $dll} | 114 | Remove-Item -Force -ErrorAction Stop -Verbose 115 | Get-ChildItem -Path "$env:SystemRoot\system32\MSPACredentialProvider*" | 116 | Where-Object {$_.name -match $dll } -OutVariable MSPACredentialProvider | 117 | Remove-Item -Force -ErrorAction Stop -Verbose 118 | } 119 | catch { 120 | if ($MSPACredentialProvider.Count -lt 1){ 121 | Write-Warning "Error Cleaning up registry keys" 122 | } else { 123 | Write-Warning "Could not Delete MSPACredentialProvider dll" 124 | $HKLMPath = 'HKLM:' 125 | foreach ($p in ('SOFTWARE\Microsoft\ServerManager').Split('\')){ 126 | $NewPath = Join-Path -Path $HKLMPath -ChildPath $p 127 | if (!(Test-Path -Path $NewPath)){ 128 | New-Item -Path $HKLMPath -Name $p 129 | } 130 | $HKLMPath = $NewPath 131 | } 132 | if (!(Test-Path -Path (Join-Path -Path $HKLMPath -ChildPath CurrentRebootAttemps))) { 133 | New-Item -Path $HKLMPath -Name CurrentRebootAttemps -Value 'Reboot required after Registry Update' 134 | } 135 | } 136 | $exit = 1 137 | } 138 | 139 | Import-SyncroModule 140 | if (Test-Path -Path $env:SyncroModule) {Close-Rmm-Alert -Category 'Ncentral_DLL' } 141 | 142 | exit $exit 143 | -------------------------------------------------------------------------------- /winget-as-system.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | A basic script to demonstrate Winget 4 | Origional source https://forums.lawrencesystems.com/t/running-winget-from-another-admin-account-than-the-one-actually-logged-in/12816/2 5 | 6 | .DESCRIPTION 7 | A basic script to demonstrate Winget running as either a logged on user or as the 'System' user. 8 | 9 | Use with PSExec https://docs.microsoft.com/en-gb/sysinternals/downloads/psexec to see it running as the 'System' user 10 | 11 | .INPUTS 12 | None. 13 | 14 | .OUTPUTS 15 | When run with '-debug', a debug log file will be created under the current users 'temp' folder, as well as details being output to the console. The log file is useful if running the script as 'system' on a scheduled task etc. as obviously you can not see the console output. 16 | 17 | .EXAMPLE 18 | PS> .\wingetExample.ps1 19 | 20 | .EXAMPLE 21 | PS> .\wingetExample.ps1 -debug 22 | #> 23 | 24 | [CmdletBinding()] 25 | param() 26 | 27 | #Editable Variables 28 | $excludedPackages = @("Microsoft.Office", "Microsoft.dotnet", "7zip.7zip") #Skip these packages as they cause issues when upgrading 29 | $logFile = $env:TEMP + "\Winget_log.txt" 30 | 31 | #Variables 32 | $Head = 0 33 | $packageCount = 0 34 | $runningUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name 35 | 36 | #Function to write debug information to a log file 37 | function Write-DebugLog($message) { 38 | if ($DebugPreference -eq 'Continue') { 39 | add-content -Encoding ASCII $logFile ("$(get-date -f dd-MM-yyyy_hh:mm:ss) $message") 40 | } 41 | Write-Debug ("$message") 42 | } 43 | 44 | #Wipe previous log file if it exists 45 | if (Test-Path -Path $logFile -PathType Leaf) { 46 | Remove-Item $logFile 47 | } 48 | 49 | Write-DebugLog -message "Running as $runningUser" 50 | 51 | #Get a list of packages to upgrade 52 | if ($runningUser -eq "NT Authority\system") { 53 | $AppPath = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe" 54 | set-location -path $AppPath 55 | ((.\AppInstallerCLI.exe upgrade --accept-source-agreements | Format-Table -AutoSize) | Out-String).Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries) > $null #Run this to accept agreements, doesn't work as one command for 'upgrade' 56 | $Winget_Upgrade_Search = ((.\AppInstallerCLI.exe upgrade | Format-Table -AutoSize) | Out-String).Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries) 57 | } 58 | else { 59 | ((winget upgrade --accept-source-agreements | Format-Table -AutoSize) | Out-String).Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries) > $null 60 | $Winget_Upgrade_Search = ((winget upgrade | Format-Table -AutoSize) | Out-String).Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries) 61 | } 62 | 63 | #If we have packages to upgrade convert the list to a PowerShell object so we can work with items more easliy 64 | If ($Winget_Upgrade_Search[$Winget_Upgrade_Search.Count - 1] -like "*upgrades available*") { 65 | 66 | #Get the header details 67 | $Winget_Upgrade_Search | ForEach-Object { 68 | 69 | If ($_ -like "------------------------------*") { 70 | $Head = ($Winget_Upgrade_Search.IndexOf($_)) 71 | } 72 | } 73 | $Winget_Header = $Winget_Upgrade_Search[($Head) - 1] -split "\s{2,}" 74 | 75 | $Winget_Upgrade_App_List = @() 76 | $Winget_Upgrade_Search[($Head + 1)..($Winget_Upgrade_Search.Count + 1)] | ForEach-Object { 77 | 78 | If ($_ -notlike "*upgrades available*") { 79 | 80 | $results = $_ | Select-String "([^\s]+)" -AllMatches 81 | 82 | $Splits = @('', '', '', '') 83 | $Splits[3] = $results.Matches[$results.Matches.Length - 2] 84 | $Splits[2] = $results.Matches[$results.Matches.Length - 3] 85 | $Splits[1] = $results.Matches[$results.Matches.Length - 4] 86 | 87 | for ($i = 0; $i -lt ($results.Matches.Length - 4); $i++) { 88 | if ($i -ne ($results.Matches.Length - 5)) { 89 | $Splits[0] += $results.Matches[$i].Value + " " 90 | } 91 | else { 92 | $Splits[0] += $results.Matches[$i].Value 93 | } 94 | } 95 | 96 | $Stack = new-object psobject 97 | $Stack | Add-Member -membertype noteproperty -name "$($Winget_Header[0])" -Value $($Splits[0]) 98 | $Stack | Add-Member -membertype noteproperty -name "$($Winget_Header[1])" -Value $($Splits[1]) 99 | $Stack | Add-Member -membertype noteproperty -name "$($Winget_Header[2])" -Value $($Splits[2]) 100 | $Stack | Add-Member -membertype noteproperty -name "$($Winget_Header[3])" -Value $($Splits[3]) 101 | $Winget_Upgrade_App_List += $Stack 102 | } 103 | } 104 | } 105 | 106 | foreach ($item in $Winget_Upgrade_App_List) { 107 | 108 | if (!$excludedPackages.Contains($item.Id.Value)) { 109 | Write-DebugLog -message "Upgrade available for $($item.Name), from $($item.Version.Value), to $($item.Available.Value)" 110 | $packageCount ++ 111 | } 112 | else { 113 | Write-DebugLog -message "Skipping $($item.Name) as it is on an exclusion list" 114 | } 115 | } 116 | 117 | Write-DebugLog -message "$packageCount with upgrades available" 118 | --------------------------------------------------------------------------------