├── VERSION ├── src ├── bin │ ├── ecc │ │ ├── EntClient.dll │ │ └── EntClientGenuine.dll │ └── eds │ │ └── 230513 │ │ └── EDS11.ecml ├── res │ ├── img │ │ ├── pos_switches.png │ │ └── qb_unexpected_error.png │ ├── qbactivator-icon.ico │ ├── logit_api_intuit.key │ └── doc │ │ └── instructions.txt ├── functions │ ├── init │ │ ├── Init.ps1 │ │ ├── Header.ps1 │ │ ├── InstallerObjectClass.ps1 │ │ ├── InstallerVariables.ps1 │ │ ├── PosInstallerObjects.ps1 │ │ ├── ScriptVariables.ps1 │ │ └── ScriptBlocks.ps1 │ ├── setup │ │ ├── PosActivation.ps1 │ │ ├── PosInstallation.ps1 │ │ ├── PosClientModule.ps1 │ │ ├── PosDownload.ps1 │ │ └── PosLicensing.ps1 │ ├── misc │ │ ├── BandwidthTest.ps1 │ │ ├── StopQuickBooksProcesses.ps1 │ │ └── ClearIntuitData.ps1 │ ├── display │ │ ├── DisplayLieScreen.ps1 │ │ ├── DisplayComponents.ps1 │ │ ├── DisplayError.ps1 │ │ └── DisplayMenu.ps1 │ ├── utility │ │ ├── Compare-IsValidHash.ps1 │ │ ├── New-ToastNotification.ps1 │ │ ├── Invoke-URLInDefaultBrowser.ps1 │ │ ├── Show-WebRequestDownloadJobState.ps1 │ │ ├── Format-Text.ps1 │ │ └── Measure-UserBandwidth.ps1 │ └── repair │ │ └── ClientModuleRepairs.ps1 ├── Main.ps1 └── main.cmd ├── tests ├── shortcuts │ ├── TEMP.lnk │ ├── APPDATA.lnk │ ├── Log Files.lnk │ ├── Intuit Public.lnk │ ├── EntClient Folder.lnk │ ├── Intuit Program Files.lnk │ ├── Intuit V8 Program Data.lnk │ └── Intuit Program Data (License).lnk ├── Screenshots │ ├── bitstransfererror.png │ ├── invalidofferingcode.png │ ├── failedtoverifyinstaller.png │ ├── quickbooksposrunintoaproblem.png │ └── elseisnotinternalexternalcommand.png ├── web_header_test.ps1 ├── installer_size_data.txt └── silent.txt ├── assets ├── icon │ ├── qbactivator-icon.ico │ └── qbactivator-icon.png ├── images │ ├── qbactivator_splash.png │ ├── qbactivator_github_thumb.png │ ├── change-currency │ │ ├── changecurrency1.png │ │ ├── changecurrency10.png │ │ ├── changecurrency11.png │ │ ├── changecurrency12.png │ │ ├── changecurrency13.png │ │ ├── changecurrency2.png │ │ ├── changecurrency3.png │ │ ├── changecurrency4.png │ │ ├── changecurrency5.png │ │ ├── changecurrency6.png │ │ ├── changecurrency7.png │ │ ├── changecurrency8.png │ │ └── changecurrency9.png │ └── download_btn.svg ├── youtube │ ├── qbactivator_yt_thumb.png │ └── qbactivator_yt_fullscreen.png ├── artwork.design │ └── qbactivator.afdesign └── logo │ ├── qbactivator_logo.svg │ └── qbactivator_logo_white.svg ├── .gitignore ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ └── bug_report.md ├── LICENSE ├── CHANGELOG.md ├── PowerCMD.sh └── README.md /VERSION: -------------------------------------------------------------------------------- 1 | 0.24.0 -------------------------------------------------------------------------------- /src/bin/ecc/EntClient.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/src/bin/ecc/EntClient.dll -------------------------------------------------------------------------------- /tests/shortcuts/TEMP.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/shortcuts/TEMP.lnk -------------------------------------------------------------------------------- /tests/shortcuts/APPDATA.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/shortcuts/APPDATA.lnk -------------------------------------------------------------------------------- /src/bin/eds/230513/EDS11.ecml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/src/bin/eds/230513/EDS11.ecml -------------------------------------------------------------------------------- /src/res/img/pos_switches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/src/res/img/pos_switches.png -------------------------------------------------------------------------------- /src/res/qbactivator-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/src/res/qbactivator-icon.ico -------------------------------------------------------------------------------- /tests/shortcuts/Log Files.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/shortcuts/Log Files.lnk -------------------------------------------------------------------------------- /assets/icon/qbactivator-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/icon/qbactivator-icon.ico -------------------------------------------------------------------------------- /assets/icon/qbactivator-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/icon/qbactivator-icon.png -------------------------------------------------------------------------------- /src/bin/ecc/EntClientGenuine.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/src/bin/ecc/EntClientGenuine.dll -------------------------------------------------------------------------------- /src/res/img/qb_unexpected_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/src/res/img/qb_unexpected_error.png -------------------------------------------------------------------------------- /tests/shortcuts/Intuit Public.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/shortcuts/Intuit Public.lnk -------------------------------------------------------------------------------- /assets/images/qbactivator_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/qbactivator_splash.png -------------------------------------------------------------------------------- /tests/shortcuts/EntClient Folder.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/shortcuts/EntClient Folder.lnk -------------------------------------------------------------------------------- /assets/youtube/qbactivator_yt_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/youtube/qbactivator_yt_thumb.png -------------------------------------------------------------------------------- /tests/Screenshots/bitstransfererror.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/Screenshots/bitstransfererror.png -------------------------------------------------------------------------------- /tests/shortcuts/Intuit Program Files.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/shortcuts/Intuit Program Files.lnk -------------------------------------------------------------------------------- /assets/artwork.design/qbactivator.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/artwork.design/qbactivator.afdesign -------------------------------------------------------------------------------- /assets/images/qbactivator_github_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/qbactivator_github_thumb.png -------------------------------------------------------------------------------- /tests/Screenshots/invalidofferingcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/Screenshots/invalidofferingcode.png -------------------------------------------------------------------------------- /tests/shortcuts/Intuit V8 Program Data.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/shortcuts/Intuit V8 Program Data.lnk -------------------------------------------------------------------------------- /assets/youtube/qbactivator_yt_fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/youtube/qbactivator_yt_fullscreen.png -------------------------------------------------------------------------------- /tests/Screenshots/failedtoverifyinstaller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/Screenshots/failedtoverifyinstaller.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency1.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency10.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency11.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency12.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency13.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency2.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency3.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency4.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency5.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency6.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency7.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency8.png -------------------------------------------------------------------------------- /assets/images/change-currency/changecurrency9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/assets/images/change-currency/changecurrency9.png -------------------------------------------------------------------------------- /tests/Screenshots/quickbooksposrunintoaproblem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/Screenshots/quickbooksposrunintoaproblem.png -------------------------------------------------------------------------------- /tests/shortcuts/Intuit Program Data (License).lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/shortcuts/Intuit Program Data (License).lnk -------------------------------------------------------------------------------- /tests/Screenshots/elseisnotinternalexternalcommand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuralpain/qbactivator/HEAD/tests/Screenshots/elseisnotinternalexternalcommand.png -------------------------------------------------------------------------------- /src/res/logit_api_intuit.key: -------------------------------------------------------------------------------- 1 | URL = https://logit.api.intuit.com/v1/ 2 | URL = https://logit.api.intuit.com/v1/Logger 3 | 4 | APIKey = intuit_apikey=GzvGCK/Hrr6YDPHYVnahrkcbC6S36YWltAdIK+fYHgVs2jpM5ffbFXHRGC5kbz6t -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # testing 2 | *.exe 3 | *.zip 4 | *.log 5 | 6 | # build files 7 | build/ 8 | dist/ 9 | cache/ 10 | 11 | # qb 12 | intuit 13 | QuickBooks Tool Hub 14 | 15 | # misc 16 | .backup/ 17 | .DS_Store 18 | .history/ 19 | target/ 20 | earlier_releases/ -------------------------------------------------------------------------------- /tests/web_header_test.ps1: -------------------------------------------------------------------------------- 1 | $ReleaseYear = 2013 2 | $Version = 11 3 | 4 | $URL = "https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/${ReleaseYear}/Latest/QuickBooksPOSV${Version}.exe" 5 | 6 | Write-Host ((Invoke-WebRequest $URL -UseBasicParsing -Method Head).Headers.'Content-Length') -------------------------------------------------------------------------------- /src/functions/init/Init.ps1: -------------------------------------------------------------------------------- 1 | function Clear-Terminal { Clear-Host; Write-Host } 2 | function Set-Version($v) { $Script:QB_VERSION = $v } 3 | function Get-Version { return $Script:QB_VERSION } 4 | function Set-License($l) { $Script:LICENSE_KEY = $l } 5 | function Get-License { return $Script:LICENSE_KEY } 6 | -------------------------------------------------------------------------------- /src/functions/init/Header.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | qbactivator, PowerShell Core 3 | Copyright (c) 2023, neuralpain 4 | Module for activation of QuickBooks Point of Sale 5 | #> 6 | 7 | <# 8 | [ ] check is quickbooks is installed 9 | [ ] during activation, reset header screen to show "installing" status 10 | #> 11 | -------------------------------------------------------------------------------- /src/functions/setup/PosActivation.ps1: -------------------------------------------------------------------------------- 1 | function Start-PosActivation { 2 | Clear-Terminal 3 | 4 | if ($Script:QUICKBOOKS_IS_INSTALLED) { 5 | Stop-QuickBooksProcesses 6 | # check for any errors with the client module 7 | Repair-LevelOne_GenuineClientModule 8 | } 9 | else { 10 | Write-Error_QuickBooksNotInstalled 11 | Invoke-NextProcess $PROC_RETURN_MAIN 12 | } 13 | 14 | Install-ClientModule # inject modified client module 15 | Write-Host "Proceeding with activation..." 16 | Start-Sleep -Milliseconds $TIME_SLOW 17 | } 18 | -------------------------------------------------------------------------------- /tests/installer_size_data.txt: -------------------------------------------------------------------------------- 1 | b2B -> bits x 0.125 OR bits / 8 = bytes 2 | b2MB -> bits / 1048576 = MB 3 | B2b2MB -> (bytes / 0.125 OR bytes * 8) / 1048576 = MB 4 | b2Mb -> bits x 0.000001 = Mb 5 | 6 | 7 | # -- POS v19 -- # 8 | bits | - - - - | 1017415680 9 | bytes | 0.125/8 | 127176960 10 | MB | 1048576 | 970.28 11 | 12 | 13 | # -- POS v18 -- # 14 | bits | - - - - | 637981160 15 | bytes | 0.125/8 | 79747645 16 | MB | 1048576 | 608.42 17 | 18 | 19 | # -- POS v12 -- # 20 | bits | - - - - | 461077328 21 | bytes | 0.125/8 | 57634666 22 | MB | 1048576 | 439.71 23 | 24 | 25 | # -- POS v11 -- # 26 | bits | - - - - | 164665944 27 | bytes | 0.125/8 | 20583243 28 | MB | 1048576 | 157.03 29 | -------------------------------------------------------------------------------- /src/functions/misc/BandwidthTest.ps1: -------------------------------------------------------------------------------- 1 | function Get-BandwidthTestResults { 2 | $Script:BANDWIDTH_BITS = (Measure-UserBandwidth -Type Download -Unit Bits) 3 | # $Script:BANDWIDTH_BITS = 0 # Debug 4 | if ($Script:BANDWIDTH_BITS -eq 0) { 5 | Write-Host "Proceeding without an estimated time..." 6 | # Write-Host "[DEBUG] Proceeding without an estimated time..." # Debug 7 | $Script:BANDWIDTH_UNKNOWN = $true 8 | return 9 | } 10 | else { 11 | if ($Script:BANDWIDTH -lt 80000) { 12 | # 0.01 MB 13 | $Script:BANDWIDTH_UNKNOWN = $true 14 | } 15 | else { 16 | $Script:BANDWIDTH = (Convert-UserBandwidth -InputUnit Bits -Value $Script:BANDWIDTH_BITS -OutputUnit Megabytes) 17 | } 18 | Write-Host " Done." 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: neuralpain 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /src/functions/init/InstallerObjectClass.ps1: -------------------------------------------------------------------------------- 1 | class Installer { 2 | [string] $WindowTitle # installer window data 3 | [System.Object] $Object # POS Installer Object 4 | [string] $Url # download url 5 | [string] $Name # name of installer 6 | [string] $VerNum # POS version number, e.g. 11 7 | [string] $Year # POS release year, e.g. 2013 8 | [string] $Hash # installer hash value 9 | [string] $Path # insatllation path 10 | [string] $LNum1 # license number #1 11 | [string] $LNum2 # license number #2 12 | [string] $PNum # product number 13 | [string] $Validation # validation string 14 | [int] $XBits # installer bit size 15 | [int] $XByte # installer byte size 16 | [string] $Size # installer megabyte size 17 | } 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "Short description..." 5 | labels: bug 6 | assignees: neuralpain 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - Windows edition: [e.g. 10, 11] 28 | - Version [e.g. 21H2, 22H2] 29 | - QuickBooks Product [e.g. POS v18, POS v19] 30 | - qbactivator version [e.g. qba-19, v0.21.1, qba-22-beta] 31 | 32 | **Additional context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /src/functions/setup/PosInstallation.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-QuickBooksInstaller { 2 | if ($Script:INSTALLER_AVAILABLE) { 3 | Start-Installer .\$Script:INSTALLER_OBJECT 4 | } 5 | else { 6 | Write-Host "A QuickBooks POS installer was not found." -ForegroundColor Yellow 7 | New-ToastNotification -ToastText "A QuickBooks POS installer was not found." -ToastTitle "Installer not found" 8 | Start-Sleep -Milliseconds $TIME_SLOW 9 | $Script:RUN_NEXT_PROCEDURE = $null 10 | return 11 | } 12 | } 13 | 14 | function Start-Installer { 15 | param ($Installer) 16 | # clear temporary installation files from previous 17 | # installer launch and start a new installation process 18 | Remove-Item $intuit_temp -Recurse -Force >$null 2>&1 19 | Write-WaitingScreen 20 | 21 | try { 22 | New-ToastNotification -ToastText "Installing QuickBooks POS..." -ToastTitle "qbactivator" 23 | Start-Process -FilePath $Installer -Wait 24 | } 25 | catch { Write-Error_CannotStartInstaller } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/functions/display/DisplayLieScreen.ps1: -------------------------------------------------------------------------------- 1 | function Write-LieScolding { 2 | # from `Write-LieResponse` 3 | param($Mssg, [Switch]$ReadAKey) 4 | 5 | Clear-Terminal 6 | Write-Host "$Mssg" -ForegroundColor White -BackgroundColor DarkRed 7 | Write-InfoLink -NoExit 8 | 9 | if ($ReadAKey) { Read-Host } 10 | else { Start-Sleep -Milliseconds $TIME_SLOW } 11 | 12 | Write-Menu_Main 13 | } 14 | 15 | function Write-LieResponse { 16 | # from `Write-Menu_Main` 17 | Write-HeaderLabel 18 | Write-Host "Do you really have one?`n" 19 | Write-Host "1. No, I lied." 20 | Write-Host "2. I have a cat." 21 | Write-Host "3. I can't remeber it." 22 | Write-Host "4. My dog ate my license." 23 | Write-Host "5. Yes, I do." 24 | Write-Host "6. I just wanted to see what would happen." 25 | $query = Read-Host "`n#" 26 | 27 | switch ($query) { 28 | 0 { break } 29 | 1 { Write-LieScolding "Lying is bad." } 30 | 2 { Write-LieScolding "Having a cat does not make you a good person." } 31 | 3 { Write-LieScolding "It's likely you never will." } 32 | 4 { Write-LieScolding "Ha ha... nice try." } 33 | 5 { Get-UserOwnLicense } 34 | 6 { Write-LieScolding "And now you've wasted both our time." -ReadAKey } 35 | default { Write-LieResponse } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/functions/utility/Compare-IsValidHash.ps1: -------------------------------------------------------------------------------- 1 | function Compare-IsValidHash { 2 | <# 3 | .SYNOPSIS 4 | Compares the file hash (MD5) of the specified file against the provided hash. 5 | 6 | .DESCRIPTION 7 | This function uses PowerShell's Get-FileHash cmdlet to retrieve the hash of the specified file. 8 | It then compares the retrieved hash against the provided hash. If the two hashes match, the function returns $true, 9 | otherwise it returns $false. 10 | 11 | .PARAMETER Hash 12 | A string containing the expected MD5 hash value 13 | 14 | .PARAMETER File 15 | A string containing the path to the file to be compared 16 | 17 | .EXAMPLE 18 | Compare-IsValidHash -Hash "1234567890ABCDEF" -File "C:\path\to\file.txt" 19 | 20 | If the MD5 hash of "C:\path\to\file.txt" is "1234567890ABCDEF", this function will return $true. Otherwise it will return $false. 21 | 22 | .OUTPUTS 23 | Boolean 24 | #> 25 | [CmdletBinding()] 26 | param ($Hash, $File) 27 | 28 | # retrieve the hash of the specified file 29 | $_hash = ((Get-FileHash $File -Algorithm MD5 | 30 | Select-Object Hash) -split " ").Trim("@{Hash=}") 31 | 32 | # compare the retrieved hash against the provided hash 33 | if ($_hash -ne $Hash) { return $false } 34 | else { return $true } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2023, neuralpain 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /src/functions/misc/StopQuickBooksProcesses.ps1: -------------------------------------------------------------------------------- 1 | function Stop-QuickBooksProcesses { 2 | Write-Host "Terminating QuickBooks processes... " 3 | try { 4 | taskkill.exe /fi "imagename eq qb*" /f /t >$null 2>&1 5 | taskkill.exe /fi "imagename eq intuit*" /f /t >$null 2>&1 6 | taskkill.exe /f /im qbw.exe >$null 2>&1 7 | taskkill.exe /f /im qbw32.exe >$null 2>&1 8 | taskkill.exe /f /im qbupdate.exe >$null 2>&1 9 | taskkill.exe /f /im qbhelp.exe >$null 2>&1 10 | taskkill.exe /f /im QBCFMonitorService.exe >$null 2>&1 11 | taskkill.exe /f /im QBUpdateService.exe >$null 2>&1 12 | taskkill.exe /f /im IBuEngHost.exe >$null 2>&1 13 | taskkill.exe /f /im msiexec.exe >$null 2>&1 14 | taskkill.exe /f /im mscorsvw.exe >$null 2>&1 15 | taskkill.exe /f /im QBWebConnector.exe >$null 2>&1 16 | taskkill.exe /f /im QBDBMgr9.exe >$null 2>&1 17 | taskkill.exe /f /im QBDBMgr.exe >$null 2>&1 18 | taskkill.exe /f /im QBDBMgrN.exe >$null 2>&1 19 | taskkill.exe /f /im QuickBooksMessaging.exe >$null 2>&1 20 | Write-Host "QuickBooks processes terminated." 21 | New-ToastNotification -ToastText "QuickBooks processes terminated" -ToastTitle "qbactivator" 22 | } 23 | catch { 24 | Write-Host "Error terminating QuickBooks processes. Error: $_" 25 | New-ToastNotification -ToastText "Error terminating QuickBooks processes" -ToastTitle "qbactivator" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/functions/misc/ClearIntuitData.ps1: -------------------------------------------------------------------------------- 1 | function Clear-IntuitData { 2 | # Delete Intuit POS installation debris 3 | Write-Host "Removing previous installation files... " 4 | 5 | foreach ($path in $qbPathList) { 6 | # remove quickbooks pos program data folder 7 | if (Test-Path "$env:ProgramData\$path") { 8 | Remove-Item "$env:ProgramData\$path" -Recurse -Force >$null 2>&1 9 | Write-Host "Removed $(Format-Text "$env:ProgramData\$path" -Foreground Yellow -Formatting Underline)" 10 | } 11 | # remove folder of the last quickbooks pos version installed 12 | if (Test-Path "${env:ProgramFiles(x86)}\$path") { 13 | Remove-Item "${env:ProgramFiles(x86)}\$path" -Recurse -Force >$null 2>&1 14 | Write-Host "Removed $(Format-Text "${env:ProgramFiles(x86)}\$path" -Foreground Yellow -Formatting Underline)" 15 | } 16 | # remove previous copy of sample practice company 17 | if (Test-Path "$env:PUBLIC\Documents\$path\Data\Sample Practice") { 18 | Remove-Item "$env:PUBLIC\Documents\$path\Data\Sample Practice" -Recurse -Force >$null 2>&1 19 | Write-Host "Removed sample practice data at`n$(Format-Text "$env:PUBLIC\Documents\$path" -Foreground Yellow -Formatting Underline)" 20 | } 21 | } 22 | 23 | # Remove entitlement data store 24 | if (Test-Path "$env:PUBLIC\Documents\$path\Data\Sample Practice") { 25 | Remove-Item -Path $CLIENT_MODULE_DATA_PATH -Recurse -Force >$null 2>&1 26 | Write-Host "Removed activation data at`n$(Format-Text "$CLIENT_MODULE_DATA_PATH" -Foreground Yellow -Formatting Underline)" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/functions/setup/PosClientModule.ps1: -------------------------------------------------------------------------------- 1 | 2 | # verify that the patch was successful 3 | $VerifyClientModulePatch = { 4 | if (Compare-IsValidHash -File "$CLIENT_MODULE_FULL_PATH" -Hash $PATCH_HASH) { 5 | Write-Host "Patch successful." 6 | } 7 | else { 8 | Write-Host "Unable to patch POS."; Pause 9 | Invoke-NextProcess $PROC_RETURN_MAIN 10 | } 11 | } 12 | 13 | function Get-ClientModule { 14 | param ($Local, $FromHostUrl) 15 | # check if the local file exists 16 | if ($Local) { 17 | if (Test-Path $Local -PathType Leaf) { 18 | Copy-Item $Local $CLIENT_MODULE_FULL_PATH 19 | return 20 | } 21 | } 22 | 23 | Write-Host "Local file not found." 24 | # if its a host request only 25 | &$TestInternetAvailable 26 | Write-Host "Downloading, please wait..." 27 | Start-BitsTransfer $FromHostUrl $CLIENT_MODULE_FULL_PATH 28 | New-ToastNotification -ToastText "Client module downloaded." -ToastTitle "Download complete" 29 | return 30 | } 31 | 32 | function Install-ClientModule { 33 | Write-Host "Patching client module... " 34 | Rename-Item $CLIENT_MODULE_FULL_PATH "${CLIENT_MODULE_FULL_PATH}.bak" >$null 2>&1 35 | # attempt to patch with the local patch file first 36 | if (Test-Path "$LOCAL_PATCH_FILE" -PathType Leaf) { 37 | $isValid = Compare-IsValidHash -Hash $PATCH_HASH -File $LOCAL_PATCH_FILE 38 | if ($isValid) { Copy-Item $LOCAL_PATCH_FILE $CLIENT_MODULE_FULL_PATH } 39 | else { 40 | Write-Host "`nPatch file may be corrupted." 41 | Get-ClientModule -FromHostUrl $CLIENT_FILE_ON_HOST 42 | &$VerifyClientModulePatch # call back and verify that the patch was successful 43 | } 44 | } 45 | else { 46 | Get-ClientModule -FromHostUrl $CLIENT_FILE_ON_HOST 47 | &$VerifyClientModulePatch # call back and verify that the patch was successful 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/functions/utility/New-ToastNotification.ps1: -------------------------------------------------------------------------------- 1 | function New-ToastNotification { 2 | <# 3 | .SYNOPSIS 4 | Creates and displays a Windows Toast notification 5 | 6 | .DESCRIPTION 7 | Creates a Windows Toast notification and displays it to the user. 8 | 9 | .PARAMETER ToastTitle 10 | The title of the Toast notification 11 | 12 | .PARAMETER ToastText 13 | The text of the Toast notification 14 | 15 | .EXAMPLE 16 | New-ToastNotification "Hello World" "This is a Toast notification" 17 | 18 | Creates and displays a Toast notification with the title "Hello World" and the text "This is a Toast notification" 19 | 20 | .NOTES 21 | The function requires Windows 10 build 10586 (Anniversary Update) or higher 22 | #> 23 | [CmdletBinding()] 24 | param( 25 | [String] 26 | $ToastTitle, 27 | [String] 28 | [parameter(ValueFromPipeline)] 29 | $ToastText 30 | ) 31 | 32 | # don't allow toast notifications on operating systems below Windows 10 33 | if (((Get-WmiObject -Class Win32_OperatingSystem).Version.Split('.')[0]) -lt 10) { return } 34 | 35 | [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null 36 | $Template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02) 37 | 38 | $RawXml = [xml] $Template.GetXml() 39 | ($RawXml.toast.visual.binding.text | Where-Object { $_.id -eq "1" }).AppendChild($RawXml.CreateTextNode($ToastTitle)) > $null 40 | ($RawXml.toast.visual.binding.text | Where-Object { $_.id -eq "2" }).AppendChild($RawXml.CreateTextNode($ToastText)) > $null 41 | 42 | $SerializedXml = New-Object Windows.Data.Xml.Dom.XmlDocument 43 | $SerializedXml.LoadXml($RawXml.OuterXml) 44 | 45 | $Toast = [Windows.UI.Notifications.ToastNotification]::new($SerializedXml) 46 | $Toast.Tag = "PowerShell" 47 | $Toast.Group = "PowerShell" 48 | $Toast.ExpirationTime = [DateTimeOffset]::Now.AddMinutes(1) 49 | 50 | $Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("PowerShell") 51 | $Notifier.Show($Toast); 52 | } 53 | -------------------------------------------------------------------------------- /src/Main.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-NextProcess { 2 | param ([Parameter(Mandatory = $true)]$NextProcess) 3 | 4 | $Script:RUN_NEXT_PROCEDURE = $NextProcess 5 | 6 | switch ($NextProcess) { 7 | $PROC_DOWNLOAD { 8 | Select-QuickBooksVersion 9 | Get-QuickBooksObject 10 | if ($null -eq $Script:RUN_NEXT_PROCEDURE) { break } 11 | elseif ($Script:INSTALLER_DOWNLOAD_ONLY) { 12 | &$TestInternetAvailable 13 | Start-InstallerDownload 14 | break 15 | } 16 | else { 17 | &$TestInternetAvailable 18 | Start-InstallerDownload 19 | Invoke-NextProcess $PROC_LICENSE 20 | } 21 | } 22 | $PROC_LICENSE { 23 | &$LocateQuickBooksInstaller 24 | if ($Script:INSTALLER_AVAILABLE) { &$ValidateQuickBooksInstaller } 25 | else { Invoke-NextProcess $PROC_DOWNLOAD } # get an installer 26 | Get-IntuitLicense $Script:INSTALLER_HASH 27 | Install-IntuitLicense 28 | Invoke-NextProcess $PROC_INSTALL 29 | break 30 | } 31 | $PROC_INSTALL { 32 | if ($Script:INSTALLER_IS_VALID) { 33 | Invoke-QuickBooksInstaller 34 | &$VerifyIfQuickBooksIsInstalled 35 | if ($Script:QUICKBOOKS_INSTALL_ONLY) { break } 36 | else { Invoke-NextProcess $PROC_ACTIVATE } 37 | } 38 | else { break } 39 | } 40 | $PROC_ACTIVATE { 41 | Start-PosActivation 42 | if ($null -eq $Script:RUN_NEXT_PROCEDURE) { break } 43 | else { Invoke-NextProcess $PROC_NEXT_STAGE } 44 | } 45 | $PROC_TROUBLESHOOT { Write-Menu_Troubleshooting } 46 | $PROC_EXIT { 47 | Write-Action_ExitActivator 48 | exit $EXIT_QBA 49 | } 50 | $PROC_NEXT_STAGE { exit $OK } 51 | $PROC_RETURN_MAIN { Write-Menu_Main } 52 | default { Invoke-NextProcess $PROC_RETURN_MAIN } 53 | } 54 | 55 | Invoke-NextProcess $PROC_RETURN_MAIN 56 | } 57 | 58 | # -------- start PowerShell execution -------- # 59 | 60 | Start-Transcript $LOG 61 | Clear-Terminal 62 | 63 | if ("C:\Windows\system32" -eq $pwd) { 64 | Write-Error_IsManualAdministrator 65 | exit $EXIT_QBA 66 | } 67 | else { 68 | &$VerifyIfQuickBooksIsInstalled 69 | Write-Menu_Main 70 | } 71 | 72 | # -------- end PowerShell execution -------- # 73 | 74 | exit 75 | -------------------------------------------------------------------------------- /src/functions/utility/Invoke-URLInDefaultBrowser.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-URLInDefaultBrowser { 2 | <# 3 | .SYNOPSIS 4 | Cmdlet to open a URL in the User's default browser. 5 | 6 | .DESCRIPTION 7 | Cmdlet to open a URL in the User's default browser. 8 | 9 | .PARAMETER URL 10 | Specify the URL to be Opened. 11 | 12 | .EXAMPLE 13 | PS> Invoke-URLInDefaultBrowser -URL 'http://jkdba.com' 14 | 15 | This will open the website "jkdba.com" in the user's default browser. 16 | 17 | .NOTES 18 | This cmdlet has only been test on Windows 10, using edge, chrome, and firefox as default browsers. 19 | #> 20 | [CmdletBinding()] 21 | param ( 22 | [Parameter(Position = 0, Mandatory = $true)] 23 | [ValidateNotNullOrEmpty()] 24 | [String] $URL 25 | ) 26 | # Verify Format. Do not want to assume http or https so throw warning. 27 | if ( $URL -notmatch "http://*" -and $URL -notmatch "https://*") { 28 | Write-Warning -Message "The URL Specified is formatted incorrectly: ($URL)" 29 | Write-Warning -Message "Please make sure to include the URL Protocol (http:// or https://)" 30 | break; 31 | } 32 | # Replace spaces with encoded space 33 | $URL = $URL -replace ' ', '%20' 34 | 35 | # Get Default browser 36 | $DefaultSettingPath = 'HKCU:\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice' 37 | $DefaultBrowserName = (Get-Item $DefaultSettingPath | Get-ItemProperty).ProgId 38 | 39 | # Handle for Edge 40 | # edge will no open with the specified shell open command in the HKCR. 41 | if ($DefaultBrowserName -eq 'AppXq0fevzme2pys62n3e0fbqa7peapykr8v') { 42 | # Open url in edge 43 | start Microsoft-edge:$URL 44 | } 45 | else { 46 | try { 47 | # Create PSDrive to HKEY_CLASSES_ROOT 48 | $null = New-PSDrive -PSProvider registry -Root 'HKEY_CLASSES_ROOT' -Name 'HKCR' 49 | # Get the default browser executable command/path 50 | $DefaultBrowserOpenCommand = (Get-Item "HKCR:\$DefaultBrowserName\shell\open\command" | Get-ItemProperty).'(default)' 51 | $DefaultBrowserPath = [regex]::Match($DefaultBrowserOpenCommand, '\".+?\"') 52 | # Open URL in browser 53 | Start-Process -FilePath $DefaultBrowserPath -ArgumentList $URL 54 | } 55 | catch { 56 | Throw $_.Exception 57 | } 58 | finally { 59 | # Clean up PSDrive for 'HKEY_CLASSES_ROOT 60 | Remove-PSDrive -Name 'HKCR' 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/res/doc/instructions.txt: -------------------------------------------------------------------------------- 1 | 2 | █▀█ █▄▄ ▄▀█ █▀▀ ▀█▀ █ █░█ ▄▀█ ▀█▀ █▀█ █▀█ 3 | ▀▀█ █▄█ █▀█ █▄▄ ░█░ █ ▀▄▀ █▀█ ░█░ █▄█ █▀▄ 4 | 5 | Simplified README v2.7 6 | 7 | Activation script for QuickBooks Point Of Sale Software on Windows. 8 | 9 | For more information on this activation script, visit 10 | 11 | 12 | Take a moment to read the FAQs for any issues you may encounter: 13 | 14 | 15 | !!! An internet connection is required. 16 | 17 | [ --- Instructions for activation --- ] 18 | 19 | 1. Run "qbactivator.cmd", select the store you need to install and 20 | activate (Store 1 or Store 2) and allow the QuickBooks software to 21 | install completely before you continue the activation. 22 | 23 | If you are installing on Client, exit the activator after the 24 | software is installed. The Client will be activated automatically 25 | with the license from the Server workstation. 26 | 27 | 2. Uncheck the "Launch QuickBooks" box. 28 | 3. Click Finish and continue with the script. QuickBooks will open 29 | automatically. 30 | 4. You will be asked for Administrative privileges. Click Next. 31 | 5. Select "Open Practice Mode" 32 | 6. Click Next 33 | 7. Select "Use Sample Data..." 34 | 8. Click Next 35 | 9. Click OK 36 | 10. Click "Register by phone now" 37 | 11. Enter the code `999999` 38 | 12. Click Next 39 | 13. Click Finish 40 | 41 | The software might seem frozen but it just takes a few seconds 42 | for the UI to load. It will greet you with a dialog informing you 43 | that "You are in Practice Mode" when it is ready for interaction 44 | along with a yellow indicator in the top-right. 45 | 46 | You can end the activation here or continue to add more users if 47 | that is something you need. 48 | 49 | [ --- OPTIONAL --- Steps 18-23 are for adding more users --- ] 50 | [ ---------------- on the Server workstation --------------- ] 51 | 52 | 14. Click the "Help" option in the menu bar 53 | 15. Click "Manage My License" 54 | 16. Click "Buy Additional User License" 55 | 17. Enter the code for the number of users you want 56 | 57 | For 5 users use "9999995". For 30 users use "99999930", etc. 58 | 59 | 18. Click Next 60 | 19. Click Finish 61 | 20. Exit the software 62 | 21. Continue the script 63 | 64 | @neuralpain // 'cause why not? 65 | With help from @Navish360 66 | -- 67 | Original patch by Beast_iND 68 | -------------------------------------------------------------------------------- /tests/silent.txt: -------------------------------------------------------------------------------- 1 | QuickBooksPremier2019.exe -s -a QBMIGRATOR=1 MSICOMMAND=/s QB_PRODUCTNUM=XXX-XXX QB_LICENSENUM=XXXX-XXXX-XXXX-XXX 2 | 3 | .\QuickBooksPOSV11.exe QB_PRODUCTNUM=023-147 QB_LICENSENUM=1063-0575-1585-222 4 | 5 | .\QuickBooksPOSV19.exe /S /v /qn QB_PRODUCTNUM=595-828 QB_LICENSENUM=0106-3903-4389-908 6 | 7 | 8 | 9 | QuickBooksPremier2022.exe -s -a QBMIGRATOR=1 MSICOMMAND=/s QB_PRODUCTNUM=747060 QB_LICENSENUM=XXXXXX 10 | 11 | QuickBooksEnterprise22.exe -s -a QBMIGRATOR=1 MSICOMMAND=/s QB_PRODUCTNUM=884649 QB_LICENSENUM=XXXXXX 12 | 13 | 14 | Now deploy Quickbooks 2014 or 2015 using a custom command line: 15 | msiexec.exe /i "QuickBooks.msi" NSTALLMANAGER=1 ALLUSERS=1 /qn /norestart /log output.log CKBOX_GDS=0 AgreeToLicense=Yes INSTALLDESKTOPICONS=0 MULTIUSERINSTALL=1 QB_LICENSENUM=XXXX-XXXX-XXXX-XXX QB_PRODUCTNUM=XXX-XXX PARENTAPP=INSTALLMANAGER 16 | 17 | 18 | ====================================== 19 | 20 | 21 | Examples of silent installation commands 22 | Last Updated: 2021-03-06 23 | 24 | To perform a silent installation, run the setup program with the appropriate command line options. This section provides some examples. 25 | 26 | These examples use standard Microsoft command line parameters with the InstallShield setup command. Only the CMDVISUAL property is specific to the zSecure™ Visual client application. 27 | 28 | Specify command-line options that require a parameter with no space between the option and its parameter. For example, this command is valid: 29 | 30 | zSecureVisualSetup.exe /v"INSTALLDIR=c:\MyDirectory" 31 | 32 | This command is not valid: 33 | 34 | zSecureVisualSetup.exe /v "INSTALLDIR=c:\MyDirectory" 35 | 36 | Put quotation marks around the parameters of an option only if the parameter contains spaces. 37 | 38 | If a path in a parameter contains spaces, you might need to use quotation marks in quotation marks, as in this example: 39 | zSecureVisualSetup.exe /v"INSTALLDIR=\"c:\My Directory\"" 40 | 41 | Silent installation with default settings 42 | zSecureVisualSetup.exe /s /v"/qn” 43 | 44 | Silent installation with a different target directory 45 | zSecureVisualSetup.exe /s /v"/qn INSTALLDIR=" 46 | 47 | Silent installation with a different target directory and a configuration file 48 | zSecureVisualSetup.exe /s /v"/qn CMDVISUAL=C:\temp\setup1.cfg 49 | INSTALLDIR=" 50 | 51 | Silent installation with a different target directory and a log file 52 | zSecureVisualSetup.exe /s /v"/l*v c:\test.log 53 | "INSTALLDIR= /qb" 54 | 55 | Silent installation with default settings and no reboot 56 | zSecureVisualSetup.exe /s /v"/qn /norestart ” -------------------------------------------------------------------------------- /src/functions/init/InstallerVariables.ps1: -------------------------------------------------------------------------------- 1 | # start list from most recent version first 2 | $qbVersionList = 11, 12, 18, 19 3 | $qbExeList = $POS11InstObj.Name, $POS12InstObj.Name, $POS18InstObj.Name, $POS19InstObj.Name 4 | $qbHashList = $POS11InstObj.Hash, $POS12InstObj.Hash, $POS18InstObj.Hash, $POS19InstObj.Hash 5 | $qbPathList = $POS11InstObj.Path, $POS12InstObj.Path, $POS18InstObj.Path, $POS19InstObj.Path 6 | 7 | # extra licenses 8 | $pos19_licenses = @("4569-3302-3865-178", "7881-1645-9971-269", "4938-5814-0940-038", "4808-1135-2336-049", "2851-9930-2558-997", "6120-5395-3507-303", "9987-3884-2589-215", "2708-9947-4862-202", "5009-9403-1002-207", "8409-4961-4037-794", "3053-7747-9128-534", "7786-9879-2771-754", "7487-0743-3346-368", "9280-8996-7677-618", "5956-5105-0683-052", "7767-9250-5701-417") 9 | $pos18_licenses = @("4798-4713-5577-215", "6108-6944-0442-313", "9877-7080-8166-654", "9324-1610-3399-773", "0332-2949-2962-553", "9795-2504-8646-275", "6793-3031-4084-521", "9122-6269-9978-972", "7318-8184-8823-424", "3616-4890-7410-775", "5417-1662-5253-895", "4942-3840-9153-387", "3477-1552-0630-590", "3815-2087-1596-845", "4279-4883-7575-102", "2046-1663-3706-369") 10 | $pos12_licenses = @("0023-8629-2358-007", "2289-2505-2376-712", "2069-3001-1276-177", "1596-0116-8423-156", "9884-4020-2536-935", "0454-9731-8461-756", "6632-9109-5515-608", "5460-5353-7861-933", "3390-0307-6528-013", "5581-2740-9316-682", "1627-7594-2197-477", "6603-6131-8677-496", "4416-4005-9128-286", "8664-0924-4097-580", "4041-6901-8695-956", "6643-0061-1816-223") 11 | $pos11_licenses = @("4152-7820-7508-121", "4710-8115-1842-661", "6666-1981-1862-788", "3006-9510-2311-039", "7943-2223-9879-816", "0097-1334-7945-038", "6111-6942-7154-813", "6711-1593-7271-896", "1886-6113-4556-755", "6212-2023-0526-681", "8040-0005-4774-245", "6925-4558-7435-923", "0417-2770-7838-353", "1690-6238-0164-884", "4557-9535-0444-555", "7718-8079-1215-532") 12 | 13 | # client patch and repair 14 | $PATCH_HASH = "1A1816C78925E734FCA16974BDBAA4AA" 15 | $LOCAL_PATCH_FILE = ".\EntClient.dll" 16 | $LOCAL_GENUINE_FILE = ".\EntClientGenuine.dll" 17 | $CLIENT_FILE_ON_HOST = "https://raw.githubusercontent.com/neuralpain/qbactivator/main/src/bin/ecc/EntClient.dll" 18 | $GENUINE_CLIENT_FILE_ON_HOST = "https://raw.githubusercontent.com/neuralpain/qbactivator/main/src/bin/ecc/EntClientGenuine.dll" 19 | 20 | $CLIENT_MODULE_DATA = "EntitlementDataStore.ecml" 21 | $CLIENT_MODULE_DATA_PATH = "$env:ProgramData\Intuit\Entitlement Client\v8" 22 | $CLIENT_MODULE_DATA_FULL_PATH = "$CLIENT_MODULE_DATA_PATH\$CLIENT_MODULE_DATA" 23 | 24 | $CLIENT_MODULE = "Intuit.Spc.Map.EntitlementClient.Common.dll" 25 | $CLIENT_MODULE_PATH = "$env:SystemRoot\Microsoft.NET\assembly\GAC_MSIL\Intuit.Spc.Map.EntitlementClient.Common\v4.0_8.0.0.0__5dc4fe72edbcacf5" 26 | $CLIENT_MODULE_FULL_PATH = "$CLIENT_MODULE_PATH\$CLIENT_MODULE" 27 | -------------------------------------------------------------------------------- /src/functions/init/PosInstallerObjects.ps1: -------------------------------------------------------------------------------- 1 | $POS11InstObj = [Installer]@{ 2 | WindowTitle = 'QuickBooks Point of Sale 2013' 3 | Url = 'https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2013/Latest/QuickBooksPOSV11.exe' 4 | Name = 'QuickBooksPOSV11.exe' 5 | VerNum = '11' 6 | Year = '2013' 7 | Hash = 'A1AF552A49ADFF40E6462A968DD552A4' 8 | Path = 'Intuit\QuickBooks Point of Sale 11.0' 9 | LNum1 = '1063-0575-1585-222' 10 | LNum2 = '8432-0480-0178-029' 11 | PNum = '023-147' 12 | XBits = 164665944 13 | XByte = 20583243 14 | Size = '157.03' 15 | } 16 | 17 | $POS12InstObj = [Installer]@{ 18 | WindowTitle = 'QuickBooks Desktop Point of Sale 12.0' 19 | Url = 'https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2015/Latest/QuickBooksPOSV12.exe' 20 | Name = 'QuickBooksPOSV12.exe' 21 | VerNum = '12' 22 | Year = '2015' 23 | Hash = '30FB99C5E98DF6874D438C478314EF9D' 24 | Path = 'Intuit\QuickBooks Point of Sale 12.0' 25 | LNum1 = '6740-7656-8840-594' 26 | LNum2 = '0877-0442-6111-615' 27 | PNum = '448-229' 28 | XBits = 461077328 29 | XByte = 57634666 30 | Size = '439.71' 31 | } 32 | 33 | $POS18InstObj = [Installer]@{ 34 | WindowTitle = 'QuickBooks Desktop Point of Sale 18.0' 35 | Url = 'https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2018/Latest/QuickBooksPOSV18.exe' 36 | Name = 'QuickBooksPOSV18.exe' 37 | VerNum = '18' 38 | Year = '2018' 39 | Hash = 'DD45AA4EC0DF431243C9836816E2305A' 40 | Path = 'Intuit\QuickBooks Desktop Point of Sale 18.0' 41 | LNum1 = '2421-4122-2213-596' 42 | LNum2 = '3130-3560-7860-900' 43 | PNum = '818-769' 44 | XBits = 637981160 45 | XByte = 79747645 46 | Size = '608.42' 47 | } 48 | 49 | $POS19InstObj = [Installer]@{ 50 | WindowTitle = 'QuickBooks Desktop Point of Sale 19.0' 51 | Url = 'https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2019/Latest/QuickBooksPOSV19.exe' 52 | Name = 'QuickBooksPOSV19.exe' 53 | VerNum = '19' 54 | Year = '2019' 55 | Hash = 'F5C434677270319F9A515210CA916187' 56 | Path = 'Intuit\QuickBooks Desktop Point of Sale 19.0' 57 | LNum1 = '0106-3903-4389-908' 58 | LNum2 = '7447-0864-8898-657' 59 | PNum = '595-828' 60 | XBits = 1017415680 61 | XByte = 127176960 62 | Size = '970.28' 63 | } 64 | 65 | <# 66 | $PosInstalerExe = [Installer]@{ 67 | Object = $null 68 | Name = $null 69 | VerNum = $null 70 | Year = $null 71 | Hash = $null 72 | Path = $null 73 | LNum1 = $null 74 | LNum2 = $null 75 | PNum = $null 76 | XBits = 0 77 | XByte = 0 78 | Size = 0 79 | } 80 | #> 81 | -------------------------------------------------------------------------------- /src/functions/display/DisplayComponents.ps1: -------------------------------------------------------------------------------- 1 | function Write-HeaderLabel { 2 | Clear-Terminal 3 | Format-Text " qbactivator `n" -Foreground White -Background DarkGreen -Formatting Bold 4 | 5 | # store selection information 6 | if ($Script:SECOND_STORE) { 7 | Write-Host "Workstation: $(Format-Text "Secondary Server" -Foreground DarkYellow)" 8 | } elseif ($Script:ADDITIONAL_CLIENTS) { 9 | Write-Host "Workstation: $(Format-Text "Additional Clients and Other" -Foreground DarkYellow)" 10 | } else { 11 | Write-Host "Workstation: $(Format-Text "Primary Server (Default)" -Foreground DarkYellow)" 12 | } 13 | 14 | # quickbooks installation status 15 | if ($Script:QUICKBOOKS_IS_INSTALLED) { 16 | Write-Host "QuickBooks POS: $(Format-Text "Installed" -Foreground Green)" 17 | Write-Host "Path: $(Format-Text "$($Script:QUICKBOOKS_INSTALLED_PATH)" -Foreground Green)" 18 | } else { 19 | Write-Host "QuickBooks POS: $(Format-Text "Not installed" -Foreground DarkYellow)" 20 | Write-Host "Path: $(Format-Text "Unavailable" -Foreground DarkYellow)" 21 | } 22 | 23 | # pos version 24 | if (Get-Version -ne $null) { 25 | Write-Host "POS Version: $(Format-Text "POS v$(Get-Version)" -Foreground DarkYellow)" 26 | } elseif (-not($Script:QUICKBOOKS_IS_INSTALLED)) { 27 | Write-Host "POS Version: $(Format-Text "Unknown" -Foreground DarkYellow)" 28 | } 29 | 30 | Write-Host # break line 31 | } 32 | 33 | function Write-InfoLink { 34 | param([Switch]$WithFAQs, [Switch]$ReturnToMenu) 35 | Write-Host "`nFor more information, visit:" -ForegroundColor White 36 | Write-Host "https://github.com/neuralpain/qbactivator" -ForegroundColor Green 37 | if ($WithFAQs) { Write-Host "https://github.com/neuralpain/qbactivator/wiki/FAQs" -ForegroundColor Green } 38 | if ($ReturnToMenu) { $Script:RUN_NEXT_PROCEDURE = $null } 39 | } 40 | 41 | function Write-WaitingScreen { 42 | Write-HeaderLabel 43 | Write-Host "QuickBooks software installation in progress..." -ForegroundColor White 44 | Write-Host "`nPlease ensure that the QuickBooks software is completely`ninstalled on your system. Activation will proceed after`nthe installation is completed." 45 | Write-Host "`nIf you need to cancel the installation for any reason, `nplease close this window afterwards." -ForegroundColor Cyan 46 | Write-InfoLink 47 | } 48 | 49 | function Write-Action_ExitActivator { 50 | Write-Host "---" 51 | Write-Host "Exiting qbactivator..." -ForegroundColor Yellow 52 | Start-Sleep -Milliseconds $TIME_BLINK 53 | } 54 | 55 | function Write-Action_OperationCancelled { 56 | Write-Host "---" 57 | Write-Host "Operation cancelled by user." -ForegroundColor Yellow 58 | Start-Sleep -Milliseconds $TIME_BLINK 59 | } 60 | 61 | function Write-Action_OptionUnavailable { 62 | Write-Host "---" 63 | Write-Host "This option is disabled." -ForegroundColor Yellow 64 | Start-Sleep -Milliseconds $TIME_NORMAL 65 | } 66 | -------------------------------------------------------------------------------- /src/functions/display/DisplayError.ps1: -------------------------------------------------------------------------------- 1 | function Write-Error_IsManualAdministrator { 2 | Clear-Terminal 3 | New-ToastNotification -ToastText "User started as Administrator." -ToastTitle "qbactivator Error" 4 | Write-Host "User started as Administrator" -ForegroundColor White -BackgroundColor DarkRed 5 | Write-Host "`nDo not manually (right-click) run qbactivator as`nadministrator. This will result in errors during`ninstallation. Please start the script normally." -ForegroundColor White 6 | Write-InfoLink -ReturnToMenu 7 | Pause 8 | } 9 | 10 | function Write-Error_CannotStartInstaller { 11 | Clear-Terminal 12 | New-ToastNotification -ToastText "Failed to start the installer." -ToastTitle "Installer Error" 13 | Write-Host "Unable to execute the installer" -ForegroundColor White -BackgroundColor DarkRed 14 | Write-Host "`nPlease ensure that you are using a genuine installer`ndownloaded from Intuit." -ForegroundColor White 15 | Write-InfoLink -ReturnToMenu 16 | Pause 17 | } 18 | 19 | function Write-Error_NoInternetConnectivity { 20 | Clear-Terminal 21 | New-ToastNotification -ToastText "No internet connectivity." -ToastTitle "Connection Error" 22 | Write-Host "Unable to start the download" -ForegroundColor White -BackgroundColor DarkRed 23 | Write-Host "`nThere is no internet connectivity at this time.`nPlease check the connection and try again." -ForegroundColor White 24 | Write-InfoLink -ReturnToMenu 25 | Pause 26 | } 27 | 28 | function Write-Error_QuickBooksIsInstalled { 29 | Clear-Terminal 30 | New-ToastNotification -ToastText "QuickBooks is already installed." -ToastTitle "Unable to Install" 31 | Write-Host "A version of QuickBooks is already installed" -ForegroundColor White -BackgroundColor DarkRed 32 | Write-Host "`nAll previous versions must be removed before installation." -ForegroundColor Yellow 33 | Write-Host "`nIf you are requesting activation-only, remove the installer`nfrom this location and restart the activator. The activator`nimmediately checks for a QuickBooks installation executable`nand runs it if one is available." -ForegroundColor White 34 | Write-InfoLink -ReturnToMenu 35 | Pause 36 | } 37 | 38 | function Write-Error_QuickBooksNotInstalled { 39 | Clear-Terminal 40 | New-ToastNotification -ToastText "QuickBooks is not installed." -ToastTitle "Unable to Activate" 41 | Write-Host "QuickBooks is not installed on the system" -ForegroundColor White -BackgroundColor DarkRed 42 | Write-Host "`nThe activation cannot be completed." -ForegroundColor Yellow 43 | Write-Host "`nPlease ensure that a QuickBooks product is correctly and`ncompletely installed before requesting activation." -ForegroundColor White 44 | Write-InfoLink -ReturnToMenu 45 | Pause 46 | } 47 | 48 | function Write-Error_FileNotFound($File) { 49 | Clear-Terminal 50 | New-ToastNotification -ToastText "File `"$File`" not found." -ToastTitle "Download Error" 51 | Write-Host "The requested file could not be downloaded" -ForegroundColor White -BackgroundColor DarkRed 52 | Write-Host "`nThe file was not found on the server at `"$File`"" -ForegroundColor White 53 | Write-Host "Please submit this issue to @neuralpain. Thank you." -ForegroundColor White 54 | Write-InfoLink -ReturnToMenu 55 | Pause 56 | } 57 | 58 | function Write-Error_UnableToVerifyInstaller { 59 | Clear-Terminal 60 | New-ToastNotification -ToastText "Unable to verify `"$Script:INSTALLER_OBJECT`"." -ToastTitle "Installer Error" 61 | Write-Host "Failed to verify the installer." -ForegroundColor White -BackgroundColor DarkRed 62 | Write-Host "`nThe installer `"$Script:INSTALLER_OBJECT`" may be corrupted." -ForegroundColor Yellow 63 | Write-InfoLink -ReturnToMenu 64 | Pause 65 | } 66 | 67 | function Write-Error_UninstallUnsupported { 68 | Write-Host "---" 69 | Write-Host "Uninstall currently unsupported." -ForegroundColor Yellow 70 | Start-Sleep -Milliseconds $TIME_NORMAL 71 | } 72 | -------------------------------------------------------------------------------- /src/functions/utility/Show-WebRequestDownloadJobState.ps1: -------------------------------------------------------------------------------- 1 | function Show-WebRequestDownloadJobState { 2 | <# 3 | .SYNOPSIS 4 | Display a simple animation while waiting for a download job to complete. 5 | 6 | .DESCRIPTION 7 | Waits for a download job to complete, displaying a 8 | progress bar while it is running. When the download is complete, the 9 | function will write a completion message to the console. 10 | 11 | .PARAMETER DownloadJob 12 | The download job to wait for 13 | 14 | .PARAMETER Message 15 | The message to display while the download is in progress 16 | 17 | .EXAMPLE 18 | Show-WebRequestDownloadJobState -DownloadJob $DownloadJob -Message "Downloading from host" 19 | 20 | Waits for the download job to complete 21 | 22 | .EXAMPLE 23 | $Job = Start-Job -ScriptBlock { Invoke-WebRequest -Uri "https://www.gutenberg.org/cache/epub/1184/pg1184.txt" -OutFile "TheRoadNotTaken.txt" } 24 | Show-WebRequestDownloadJobState -DownloadJob $Job -Message "Downloading from host" 25 | 26 | Waits for the download job to complete 27 | 28 | .EXAMPLE 29 | Start-Job -ScriptBlock { 30 | Invoke-WebRequest -Uri "https://www.gutenberg.org/cache/epub/1184/pg1184.txt" -OutFile "TheRoadNotTaken.txt" 31 | } | Show-WebRequestDownloadJobState -Message "Downloading from host" 32 | 33 | Waits for the download job to complete 34 | 35 | .NOTES 36 | Filename: Show-WebRequestDownloadJobState.ps1 37 | Version 1.2 38 | Author: neuralpain 39 | Created: 2024-03-16 40 | Updated: 2024-03-19 41 | 42 | Version history: 43 | 44 | 1.0 - Initial release with basic functionality 45 | 46 | 1.1 - Bug fixes 47 | 48 | 1.2 - Change text color 49 | #> 50 | [CmdletBinding()] 51 | param( 52 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)] 53 | $DownloadJob, 54 | [Parameter(Mandatory = $true)] 55 | [String]$Message, 56 | [scriptblock]$CompleteScript, 57 | [scriptblock]$FailedScript, 58 | [scriptblock]$StoppedScript 59 | ) 60 | 61 | $Padding = " " * ($Message.Length + 12) 62 | 63 | while ($DownloadJob.State -eq 'Running') { 64 | Write-Host -NoNewLine "`r[*....] $($Message)..." -ForegroundColor White 65 | Start-Sleep -Milliseconds 100 66 | Write-Host -NoNewLine "`r[.*...] $($Message)..." -ForegroundColor White 67 | Start-Sleep -Milliseconds 100 68 | Write-Host -NoNewLine "`r[..*..] $($Message)..." -ForegroundColor White 69 | Start-Sleep -Milliseconds 100 70 | Write-Host -NoNewLine "`r[...*.] $($Message)..." -ForegroundColor White 71 | Start-Sleep -Milliseconds 100 72 | Write-Host -NoNewLine "`r[....*] $($Message)..." -ForegroundColor White 73 | Start-Sleep -Milliseconds 100 74 | Write-Host -NoNewLine "`r[.....] $($Message)..." -ForegroundColor White 75 | Start-Sleep -Milliseconds 100 76 | } 77 | 78 | # Clear the progress bar 79 | Write-Host -NoNewLine "`r${Padding}`r" 80 | 81 | # if the variable contains a script block, execute it 82 | switch ($DownloadJob.State) { 83 | 'Completed' { 84 | if ($CompleteScript -eq $null) { Write-Host ":: Download completed successfully.${Padding}" -ForegroundColor Green; break } 85 | # if not, write a success message 86 | else { &$CompleteScript } 87 | } 88 | 'Failed' { 89 | if ($FailedScript -eq $null) { Write-Host ":: Failed to download from host.${Padding}" -ForegroundColor Red; break } 90 | # if not, write a failure message 91 | else { &$FailedScript } 92 | } 93 | 'Stopped' { 94 | if ($StoppedScript -eq $null) { Write-Host ":: Download was manually stopped.${Padding}" -ForegroundColor Red; break } 95 | # if not, write a failure message 96 | else { &$StoppedScript } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/functions/init/ScriptVariables.ps1: -------------------------------------------------------------------------------- 1 | $OK = 0x0000 2 | $ERR = 0x0001 3 | $EXIT_QBA = 0x0002 # no action; complete exit 4 | $PAUSE = 0x0003 5 | 6 | $TIME_BLINK = 500 7 | $TIME_SHORT = 800 8 | $TIME_NORMAL = 1000 9 | $TIME_SLOW = 2000 10 | 11 | # THIS! ...because Enums in PowerShell don't work how I want them to 12 | $PROC_INSTALL = 0x208a 13 | $PROC_ACTIVATE = 0x208b 14 | $PROC_WRITE_LIES = 0x208c 15 | $PROC_LICENSE = 0x208d 16 | $PROC_TROUBLESHOOT = 0x208e 17 | $PROC_EXIT = 0x208f 18 | $PROC_EMPTY = 0x2090 19 | $PROC_COMPLETE_EXIT = 0x2091 20 | $PROC_NEXT_STAGE = 0x2092 21 | $PROC_DOWNLOAD = 0x2093 22 | $PROC_RETURN_MAIN = 0x2094 23 | 24 | # MISCELLANEOUS 25 | $Script:LICENSE_KEY = "" # quickbooks license key 26 | $Script:QB_VERSION = $null # version of quickbooks (to be) installed 27 | $Script:SELECTED_QB_OBJECT = $null # quickbooks object selected to be installed 28 | $Script:TARGET_LOCATION = "$pwd" # directory where files will be downloaded 29 | $Script:RUN_NEXT_PROCEDURE = $null # WAS UNUSED, FOUND A USE FOR IT; contains the next step to be run 30 | $Script:ACTIVATION_ONLY = $false # indicate whether or not the script should only activate quickbooks 31 | 32 | # IF QUICKBOOKS IS INSTALLED 33 | [bool]$Script:QUICKBOOKS_IS_INSTALLED = $false # indicate whether or not quickbooks is installed 34 | $Script:QUICKBOOKS_INSTALLED_PATH = $null # path where quickbooks is installed 35 | $Script:QUICKBOOKS_INSTALLED_VERSION = $null # version of quickbooks installed 36 | $Script:QUICKBOOKS_INSTALL_ONLY = $false # indicate whether or not the script should only install quickbooks 37 | 38 | # INSTALLER RELATED 39 | $Script:INSTALLER_SIZE = 0 # size of installer 40 | [int]$Script:INSTALLER_BITS = 0 # bit size of installer 41 | [int]$Script:INSTALLER_BYTES = 0 # byte size of installer 42 | $Script:INSTALLER_OBJECT = $null # the installer, the `.exe` object 43 | $Script:INSTALLER_PATH = $null # path to the installer 44 | $Script:INSTALLER_HASH = $null # hash of the installer 45 | $Script:INSTALLER_IS_VALID = $false # indicate whether or not the installer is valid for use 46 | [bool]$Script:INSTALLER_AVAILABLE = $false # indicate whether or not the installer is available on the user's system 47 | [bool]$Script:INSTALLER_DOWNLOAD_ONLY = $false # indicate whether or not the script should only download the installer 48 | 49 | # BANDWIDTH RELATED 50 | [int]$Script:BANDWIDTH_BITS = 0 # bit size of bandwidth 51 | [int]$Script:RAW_DOWNLOAD_TIME = 0 # raw download time 52 | [int]$Script:BANDWIDTH_BYTES = 0 # byte size of bandwidth 53 | # [bool]$Script:DOWNLOAD_PATCH = $false # UNUSED 54 | [bool]$Script:BANDWIDTH_UNKNOWN = $true # indicate whether or not bandwidth is unknown; bandwidth text successful or failed 55 | [double]$Script:BANDWIDTH = 0 # bandwidth size 56 | 57 | # STORE RELATED 58 | [bool]$Script:SECOND_STORE = $false # indicate whether or not there is a second store 59 | [bool]$Script:CUSTOM_LICENSING = $false # indicate whether or not the user added a custom license 60 | [bool]$Script:ADDITIONAL_CLIENTS = $false # indicate whether or not the user wants to activate additional clients 61 | 62 | # CONFIG 63 | # $Script:ALLOW_ONLINE = 1 # UNUSED 64 | # $Script:TOAST_NOTIFICATIONS = 1 # enable toast notifications, UNUSED 65 | 66 | # download and security level preferences 67 | $Script:ProgressPreference = "SilentlyContinue" 68 | # securely enable TLS 1.2 to download files 69 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12 70 | 71 | # log file 72 | $LOG = "C:\Windows\Logs\qbactivator\qbactivator_$(Get-Date -Format "yyyyMMdd_HHmmss").log" 73 | 74 | # temp folder for Intuit (is this folder still being used?) 75 | $intuit_temp = "$env:TEMP\Intuit" 76 | -------------------------------------------------------------------------------- /src/functions/init/ScriptBlocks.ps1: -------------------------------------------------------------------------------- 1 | $InitializeMain = { 2 | $Script:QB_VERSION = $null 3 | $Script:ACTIVATION_ONLY = $false 4 | $Script:INSTALLER_SIZE = 0 5 | $Script:INSTALLER_BITS = 0 6 | $Script:INSTALLER_BYTES = 0 7 | $Script:INSTALLER_OBJECT = $null 8 | $Script:INSTALLER_PATH = $null 9 | $Script:INSTALLER_HASH = $null 10 | $Script:INSTALLER_IS_VALID = $false 11 | $Script:INSTALLER_AVAILABLE = $false 12 | # $Script:BANDWIDTH = 0 13 | # $Script:BANDWIDTH_BITS = 0 14 | # $Script:BANDWIDTH_BYTES = 0 15 | # $Script:BANDWIDTH_UNKNOWN = $false 16 | $Script:RAW_DOWNLOAD_TIME = 0 17 | $Script:SECOND_STORE = $false 18 | $Script:CUSTOM_LICENSING = $false 19 | $Script:QUICKBOOKS_IS_INSTALLED = $false 20 | $Script:ADDITIONAL_CLIENTS = $false 21 | } 22 | 23 | $OpenLogs = { 24 | New-ToastNotification -ToastText "Locating qbactivator logs..." -ToastTitle "qbactivator" 25 | explorer.exe "C:\Windows\Logs\qbactivator" 26 | } 27 | 28 | $InvokeGeneralActivation = { 29 | Clear-Terminal 30 | Stop-QuickBooksProcesses 31 | New-ToastNotification -ToastText "Forced General Activation initiated" -ToastTitle "qbactivator" 32 | Invoke-NextProcess $PROC_NEXT_STAGE 33 | } 34 | 35 | $ExitQbactivator = { 36 | New-ToastNotification -ToastText "Exiting qbactivator..." -ToastTitle "qbactivator" 37 | Invoke-NextProcess $PROC_EXIT 38 | } 39 | 40 | $OpenWiki = { 41 | New-ToastNotification -ToastText "Opening qbactivator Wiki..." -ToastTitle "qbactivator" 42 | Invoke-URLInDefaultBrowser -URL "https://github.com/neuralpain/qbactivator/wiki" 43 | } 44 | 45 | $TestInternetAvailable = { 46 | Write-Host -NoNewline "Testing connectivity... " 47 | if (-not(Test-Connection www.google.com -Quiet)) { 48 | Write-Error_NoInternetConnectivity 49 | Invoke-NextProcess $PROC_RETURN_MAIN 50 | } 51 | else { Write-Host "OK" } 52 | } 53 | 54 | $VerifyIfQuickBooksIsInstalled = { 55 | foreach ($path in $qbPathList) { 56 | if (Test-Path "${env:ProgramFiles(x86)}\$path\QBPOSShell.exe" -PathType Leaf) { 57 | Write-Host "Found `"$path`"" 58 | $Script:QUICKBOOKS_IS_INSTALLED = $true 59 | $Script:QUICKBOOKS_INSTALLED_PATH = $path 60 | $Script:INSTALLER_DOWNLOAD_ONLY = $true 61 | break 62 | } 63 | } 64 | } 65 | 66 | $CheckQuickBooksIsNotInstalled_ReturnToMainMenu = { 67 | if (-not($Script:QUICKBOOKS_IS_INSTALLED)) { 68 | Write-Host "Disabled when QuickBooks is not installed." -ForegroundColor Yellow 69 | $Script:SECOND_STORE = $false 70 | $Script:ADDITIONAL_CLIENTS = $false 71 | Start-Sleep -Milliseconds $TIME_NORMAL 72 | Invoke-NextProcess $PROC_RETURN_MAIN 73 | } 74 | } 75 | 76 | $CheckQuickBooksIsInstalled_ReturnToMainMenu = { 77 | if ($Script:QUICKBOOKS_IS_INSTALLED) { 78 | Write-Host "Disabled when QuickBooks is installed." -ForegroundColor Yellow 79 | $Script:SECOND_STORE = $false 80 | $Script:ADDITIONAL_CLIENTS = $false 81 | Start-Sleep -Milliseconds $TIME_NORMAL 82 | Invoke-NextProcess $PROC_RETURN_MAIN 83 | } 84 | } 85 | 86 | $ValidateQuickBooksInstaller = { 87 | Write-Host -NoNewLine "Verifying `"$($Script:INSTALLER_OBJECT)`"... " 88 | foreach ($hash in $qbHashList) { 89 | if (Compare-IsValidHash -Hash $hash -File $Script:INSTALLER_OBJECT) { 90 | Write-Host "$($Script:INSTALLER_OBJECT) is valid." 91 | $Script:INSTALLER_IS_VALID = $true 92 | $Script:INSTALLER_HASH = $hash 93 | return 94 | } 95 | } 96 | # mark installer as invalid 97 | Write-Host "Invalid." 98 | $Script:INSTALLER_IS_VALID = $false 99 | Write-Error_UnableToVerifyInstaller 100 | } 101 | 102 | $LocateQuickBooksInstaller = { 103 | Write-Host "`nLocating QuickBooks POS installer..." 104 | # Find which installer version is available and compare 105 | # known hashes against the installer for verification 106 | foreach ($exe in $qbExeList) { 107 | if (Test-Path ".\$exe" -PathType Leaf) { 108 | Write-Host "Found `"$exe`"" 109 | $Script:INSTALLER_AVAILABLE = $true 110 | $Script:INSTALLER_OBJECT = $exe 111 | Set-Version ($exe.Trim("QuickBooksPOSV.exe")) 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/functions/repair/ClientModuleRepairs.ps1: -------------------------------------------------------------------------------- 1 | function Repair-LevelOne_GenuineClientModule { 2 | <# 3 | .SYNOPSIS 4 | Check if the .bak file exists 5 | #> 6 | if (Test-Path "${CLIENT_MODULE_FULL_PATH}.bak" -PathType Leaf) { 7 | Write-Host "Lv1: Fixing error on client module... " 8 | Remove-Item $CLIENT_MODULE_FULL_PATH -Force >$null 2>&1 9 | Rename-Item "${CLIENT_MODULE_FULL_PATH}.bak" $CLIENT_MODULE_FULL_PATH >$null 2>&1 10 | # check if the `.bak` file was successfully removed, else escalate to Lv2 11 | if (Test-Path "${CLIENT_MODULE_FULL_PATH}.bak" -PathType Leaf) { 12 | Write-Host "Lv1: Unable to resolve error." 13 | Write-Host "Lv1: Escalating to Lv2..." 14 | Start-Sleep -Milliseconds $TIME_SLOW 15 | Repair-LevelTwo_GenuineClientModule_SanityCheck 16 | } else { 17 | # notify the user that the client module was successfully repaired 18 | New-ToastNotification -ToastText "Lv1: Client module restored." -ToastTitle "Client Module Repair" 19 | } 20 | } 21 | else { 22 | Write-Host "Lv1: Modified client module was not found." 23 | Start-Sleep -Milliseconds $TIME_SLOW 24 | } 25 | } 26 | 27 | function Repair-LevelTwo_GenuineClientModule_SanityCheck { 28 | <# 29 | .SYNOPSIS 30 | Check if the client file is the genuine one and make any additional repairs. Will only run if this is requested. 31 | #> 32 | param([switch]$SanityCheck) 33 | # if a client module is found on the system then, do a comparison with the PATCH_HASH for genuineity 34 | if ($SanityCheck) { Write-Host "Lv2: Performing a sanity check..." } 35 | 36 | if (Test-Path $CLIENT_MODULE_FULL_PATH -PathType Leaf) { 37 | Write-Host "Lv2: Found a client module." 38 | # if the comparison returns true, then this client module was modified 39 | if ((Compare-IsValidHash -File $CLIENT_MODULE_FULL_PATH -Hash $PATCH_HASH)) { 40 | Write-Host "Lv2: Client module is modified. Repairing..." 41 | # remove client files 42 | Remove-Item "$CLIENT_MODULE_PATH\*" -Force >$null 2>&1 43 | # fix this error by using the LOCAL_GENUINE_FILE on user system to repair, if this is available 44 | # if a LOCAL_GENUINE_FILE is not found, then download it from the host 45 | Get-ClientModule -Local $LOCAL_GENUINE_FILE -FromHostUrl $GENUINE_CLIENT_FILE_ON_HOST 46 | } 47 | else { 48 | # if the comparison with PATCH_HASH returns false, then there is no issue 49 | Write-Host "Lv2: No issues found. Nothing to repair." 50 | Start-Sleep -Milliseconds $TIME_SLOW 51 | return 52 | } 53 | } 54 | else { 55 | # if no client module is found on the system, then download it from the host 56 | Write-Host "Lv2: No client module found. Retrieving..." 57 | Get-ClientModule -Local $LOCAL_GENUINE_FILE -FromHostUrl $GENUINE_CLIENT_FILE_ON_HOST 58 | # remove the `.bak` file, if it exists 59 | if (Test-Path "${CLIENT_MODULE_FULL_PATH}.bak" -PathType Leaf) { 60 | Remove-Item "${CLIENT_MODULE_FULL_PATH}.bak" -Force >$null 2>&1 61 | Write-Host "Lv2: Removed unusable client module backup." 62 | } 63 | } 64 | # ---------------------------------------------------- 65 | # check if the client module was repaired successfully 66 | if ((Compare-IsValidHash -File $CLIENT_MODULE_FULL_PATH -Hash $PATCH_HASH)) { 67 | Write-Host "Lv2: Unable to repair the client module." # create fullscreen prompt for this 68 | # notify the user that the client module was not repaired 69 | New-ToastNotification -ToastText "Lv2: Unable to repair the client module." -ToastTitle "Client Module Repair" 70 | } 71 | else { 72 | Write-Host "Lv2: Client module repaired successfully." 73 | # notify the user that the client module was successfully repaired 74 | New-ToastNotification -ToastText "Lv2: Client module repaired successfully." -ToastTitle "Client Module Repair" 75 | Start-Sleep -Milliseconds $TIME_SLOW 76 | } 77 | } 78 | 79 | function Repair-LevelThree_Reactivation { 80 | # ensure the the quickbooks entitlement client is available for reactivation 81 | if (-not($Script:QUICKBOOKS_IS_INSTALLED)) { 82 | Write-Error_QuickBooksNotInstalled 83 | return 84 | } 85 | 86 | # 如 entitlement client 不在, 没问题,就创建新的 87 | if (-not(Test-Path $CLIENT_MODULE_DATA_PATH -PathType Container)) { 88 | Write-Host "Lv3: Data folder not found." 89 | New-Item $CLIENT_MODULE_DATA_PATH -ItemType Directory >$null 2>&1 90 | Write-Host "Lv3: Created new data folder." 91 | return 92 | } 93 | 94 | Write-Host -NoNewline "Lv3: Removing old activation data... " 95 | Remove-Item "$CLIENT_MODULE_DATA_PATH\*" -Force >$null 2>&1 96 | Write-Host "Done" 97 | 98 | New-ToastNotification -ToastText "Activation data has been cleared." -ToastTitle "Client Module Repair" 99 | } 100 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.24.0 4 | 5 | - Fix critical bug affecting additional Client licenses 6 | - Add Toast notifications 7 | - TLS security improvements 8 | - Bug fixes and improvements 9 | 10 | #### v0.23.0 11 | 12 | - Add manual refresh option to update menu head information 13 | - Fix issue [#43](https://github.com/neuralpain/qbactivator/issues/43) where `qba-22` ignored local available POS installers 14 | - Minor improvements 15 | 16 | #### v0.22.0 17 | 18 | - Add new Troubleshooting menu 19 | - Add option `Lv3` in troubleshooting to potentially fix "Invalid Product Code" error 20 | - Add 16 more licenses for each version of POS, a total of 64 new licenses; available for client activation 21 | - Add links to qbactivator wiki, etc. in Troubleshooting Menu 22 | - Add indicators for installation & activation status 23 | - Fix instructions not being exported before activation 24 | - Fix edge-case loop error scenario when refusing to proceed to download an installer 25 | - Enabled transcript log to trace errors encountered during the runtime of the activator 26 | - Disabled bandwidth calculation 27 | 28 | - Code refactoring, minor bug fixes and improvements 29 | 30 | #### v0.21.2 31 | 32 | - Fix validation bug on local patch files 33 | - Fix bug preventing launch of QuickBooks POS application after installation 34 | - Minor bug fixes 35 | 36 | #### v0.21.1 37 | 38 | - Fix licensing issues for POS v19 ([#30](https://github.com/neuralpain/qbactivator/issues/30)) and custom licenses ([#31](https://github.com/neuralpain/qbactivator/issues/31)) 39 | - Code refactoring 40 | 41 | #### v0.21.0 42 | 43 | - Add progress bar for Point of Sale installer while downloading ✨ 44 | - Add option to install custom licenses from the user 45 | - Add preventative measure for users who manually run qbactivator as administrator 46 | - Temporarily drop support for activation of other QuickBooks Desktop products 47 | - Code refactoring 48 | - Minor bug fixes 49 | 50 | #### v0.20.3 51 | 52 | - Minor bug fix in deleting items from `C:\ProgramData\Intuit` 53 | 54 | #### v0.20.2 55 | 56 | - Fix error requesting network information 57 | - Add support for multi-store licensing with help from @Navish360 (removed split store-client licenses) 58 | - Other bug fixes and improvements 59 | 60 | #### v0.20.1 61 | 62 | - Add licenses for server and client workstations 63 | - Bug fixes and improvements 64 | 65 | #### v0.20.0 66 | 67 | - Fix error fetching headers from the web on certain Windows installations 68 | - Now deletes specific Point of Sale installation folder instead of entire Intuit directory 69 | - Bug fixes and improvements 70 | 71 | #### v0.19.0 72 | 73 | - Previous client errors are fixed during activation request 74 | - Add menu to download POS software if unavailable locally 75 | - Add bypass for installer verification if user trusts their own installer 76 | - Add automatic download of patch if unavailable or an error occurred with local copy 77 | - Removed 4 steps from instructions 78 | - Code optimization and error handling improvements 79 | 80 | #### v0.18.1 81 | 82 | - Fix POS v19 installer being recognized as corrupted when downloaded from official server ([#6](https://github.com/neuralpain/qbactivator/issues/6)) 83 | - Update build script with archive functionality (requires zip to be installed) 84 | 85 | #### v0.18.0 86 | 87 | - Fix non-verification of installed QuickBooks software for activation-only requests ([#4](https://github.com/neuralpain/qbactivator/issues/4)) 88 | - Improved error screens to provide helpful information 89 | - Update hash values from SHA1 to MD5 for faster verification 90 | - Add function `Clear-IntuitData` for clean up of leftover files from previous installation of QuickBooks after uninstall 91 | - Add function `Install-IntuitLicense` for proper licensing and improved error checking 92 | - Add function `Invoke-QuickBooksInstaller` to perform file integrity check and run the available installer while also checking for conflicts before installation 93 | - Add function `Find-PatchFile` to contain patch file verification 94 | - Modified `Compare-Hash` function to work with new changes 95 | - Code optimization and improvements 96 | 97 | #### v0.17.1 98 | 99 | - Update license keys for POS v11 and v12 100 | 101 | #### v0.17.0 102 | 103 | - Implement a more robust method of activation ([#1](https://github.com/neuralpain/qbactivator/issues/1)) 104 | - Add automatic run of qb installer 105 | - Minor bug fixes and improvements 106 | 107 | #### v0.16.1 108 | 109 | - Minor bug fixes and improvements 110 | 111 | #### v0.16.0 112 | 113 | - Add UAC prompt before script is run 114 | - Embed instructions and keys into script 115 | - Add integrity check for patch file 116 | - Code optimization and improvements 117 | -------------------------------------------------------------------------------- /src/main.cmd: -------------------------------------------------------------------------------- 1 | if %ERRORLEVEL% EQU 0 ( 2 | echo Starting services... 3 | net start "Intuit Entitlement Service v8" >nul 2>&1 4 | goto :pos_activation 5 | ) else if %ERRORLEVEL% EQU 3 ( 6 | @REM pause screen before exiting 7 | echo. & pause 8 | goto exitQBA 9 | ) else if %ERRORLEVEL% EQU 5 ( 10 | echo Starting services... 11 | net start "Intuit Entitlement Service v8" >nul 2>&1 12 | goto :standard_activation 13 | ) else goto exitQBA 14 | 15 | :pos_activation 16 | net start "QBPOSDBServiceV11" >nul 2>&1 17 | set "QBPOSDIR11=C:\Program Files (x86)\Intuit\QuickBooks Point of Sale 11.0\QBPOSShell.exe" 18 | set "QBPOSDIR12=C:\Program Files (x86)\Intuit\QuickBooks Point of Sale 12.0\QBPOSShell.exe" 19 | set "QBPOSDIR18=C:\Program Files (x86)\Intuit\QuickBooks Desktop Point of Sale 18.0\QBPOSShell.exe" 20 | set "QBPOSDIR19=C:\Program Files (x86)\Intuit\QuickBooks Desktop Point of Sale 19.0\QBPOSShell.exe" 21 | set "CLIENT_MODULE=%SystemRoot%\Microsoft.NET\assembly\GAC_MSIL\Intuit.Spc.Map.EntitlementClient.Common\v4.0_8.0.0.0__5dc4fe72edbcacf5\Intuit.Spc.Map.EntitlementClient.Common.dll" 22 | 23 | :: start quickbooks 24 | echo Starting QuickBooks... 25 | if exist "%QBPOSDIR19%" ( 26 | %pwsh% "Start-Process -FilePath '%QBPOSDIR19%'" 27 | ) else if exist "%QBPOSDIR18%" ( 28 | %pwsh% "Start-Process -FilePath '%QBPOSDIR18%'" 29 | ) else if exist "%QBPOSDIR12%" ( 30 | %pwsh% "Start-Process -FilePath '%QBPOSDIR12%'" 31 | ) else if exist "%QBPOSDIR11%" ( 32 | %pwsh% "Start-Process -FilePath '%QBPOSDIR11%'" 33 | ) 34 | 35 | :: export and open minified readme 36 | pushd "%wdir%" 37 | set "0=%~f0" 38 | %pwsh% "$f=[IO.File]::ReadAllText($env:0) -split ':qbreadme\:.*'; [IO.File]::WriteAllText('README.txt',$f[1].Trim(),[System.Text.Encoding]::UTF8)" 39 | popd & start notepad.exe "README.txt" 40 | 41 | @mode 60,18 42 | cls & echo. 43 | %pwsh% "Write-Host ' qbactivator ' -ForegroundColor White -BackgroundColor DarkGreen" 44 | echo. 45 | echo Follow the steps below to activate QuickBooks software. 46 | echo. 47 | echo 1. QuickBooks should open automatically 48 | echo -- DO NOT check for updates 49 | echo 2. Select "Open Practice Mode" 50 | echo 3. Select "Use Sample Data..." 51 | echo 4. Click "Register by phone now" 52 | echo 5. Enter the code 999999 53 | echo 6. Click Next 54 | echo 7. Click Finish 55 | echo. 56 | echo -- Continue when finished. 57 | echo. & pause 58 | goto end_activation 59 | 60 | :standard_activation 61 | @mode 60,17 62 | cls & echo. 63 | %pwsh% "Write-Host ' qbactivator ' -ForegroundColor White -BackgroundColor DarkGreen" 64 | echo. 65 | echo Follow the steps below to activate QuickBooks software. 66 | echo. 67 | echo 1. Open the QuickBooks software 68 | echo 2. Click "Help" then "About..." 69 | echo 3. Press CTRL+R+P 70 | echo 4. Enter the code 99999930 71 | echo 5. Click Next 72 | echo 6. Click Finish 73 | echo 7. Close QuickBooks 74 | echo. 75 | echo -- Continue when finished. 76 | echo. & pause 77 | goto end_activation 78 | 79 | :end_activation 80 | :: end activation and end all QuickBooks processes 81 | cls & echo. 82 | echo Terminating QuickBooks processes... 83 | taskkill /fi "imagename eq qb*" /f /t >nul 2>&1 84 | taskkill /fi "imagename eq intuit*" /f /t >nul 2>&1 85 | taskkill /f /im qbw.exe >nul 2>&1 86 | taskkill /f /im qbw32.exe >nul 2>&1 87 | taskkill /f /im qbupdate.exe >nul 2>&1 88 | taskkill /f /im qbhelp.exe >nul 2>&1 89 | taskkill /f /im QBCFMonitorService.exe >nul 2>&1 90 | taskkill /f /im QBUpdateService.exe >nul 2>&1 91 | taskkill /f /im IBuEngHost.exe >nul 2>&1 92 | taskkill /f /im msiexec.exe >nul 2>&1 93 | taskkill /f /im mscorsvw.exe >nul 2>&1 94 | taskkill /f /im QBWebConnector.exe >nul 2>&1 95 | taskkill /f /im QBDBMgr9.exe >nul 2>&1 96 | taskkill /f /im QBDBMgr.exe >nul 2>&1 97 | taskkill /f /im QBDBMgrN.exe >nul 2>&1 98 | taskkill /f /im QuickBooksMessaging.exe >nul 2>&1 99 | :: restore files to original state 100 | echo Attempting to restore client module... 101 | copy /v /y /z "%CLIENT_MODULE%.bak" "%CLIENT_MODULE%" >nul 102 | fc "%CLIENT_MODULE%" "%CLIENT_MODULE%.bak" > nul 103 | :: error handling if files have not been restored 104 | if %ERRORLEVEL% EQU 1 ( 105 | cls & echo. 106 | echo qbactivator ran into a problem while attempting to restore 107 | echo the client. 108 | echo. 109 | echo Restart qbactivator and go through the troubleshooting 110 | echo "Lv1: Restore" to resolve the error. You may choose to 111 | echo exit the script afterwards. 112 | echo. & pause 113 | goto :exitQBA 114 | ) else ( 115 | del /q /f /a "%CLIENT_MODULE%.bak" 116 | echo Restoration successful. 117 | ping -n 1 127.0.0.1 >nul 118 | echo Patch completed without errors. 119 | ping -n 1 127.0.0.1 >nul 120 | goto :exitQBA 121 | ) 122 | 123 | :exitQBA 124 | :: clean up files and exit script 125 | taskkill /f /fi "WindowTitle eq README*" >nul 2>&1 126 | del "%wdir%README.txt" >nul 2>&1 127 | cls & echo. 128 | echo qbactivator will now terminate. 129 | ping -n 1 127.0.0.1 >nul 130 | goto :eof 131 | -------------------------------------------------------------------------------- /src/functions/setup/PosDownload.ps1: -------------------------------------------------------------------------------- 1 | function Get-TimeToComplete { 2 | param ([int]$DownloadSize, [int]$Bandwidth) 3 | 4 | [double]$time = ($DownloadSize / $Bandwidth) 5 | [int]$time = [math]::Round($time) 6 | 7 | $Script:RAW_DOWNLOAD_TIME = $time 8 | 9 | if ($time -gt 60) { 10 | [int]$time_m = $time / 60 11 | [int]$time_s = $time % 60 12 | return "${time_m}m${time_s}s" 13 | } 14 | 15 | return "$time seconds" 16 | } 17 | 18 | function Compare-InstallerDownloadSize { 19 | # clean up uncompleted donwnload 20 | if (-not(Compare-IsValidHash -File $Script:SELECTED_QB_OBJECT.Name -Hash $Script:SELECTED_QB_OBJECT.Hash)) { 21 | # Write-Host $Script:SELECTED_QB_OBJECT.Name # Debug 22 | Remove-Item $Script:SELECTED_QB_OBJECT.Name 23 | } 24 | } 25 | 26 | function Select-QuickBooksVersion { 27 | <# 28 | .NOTES 29 | Triggered by `Write-Menu_VersionSelection` 30 | #> 31 | if ($null -ne $Script:QB_VERSION) { 32 | Write-Host "Already selected version: $(Get-Version)" 33 | Write-Host "Clear selection?" 34 | $query = Read-Host "Y/n" 35 | switch ($query) { 36 | "Y" { Set-Version $null } 37 | default { break } # do nothing and return to menu 38 | } 39 | } 40 | 41 | while ($null -eq $Script:QB_VERSION) { 42 | Write-Menu_VersionSelection 43 | switch (Get-Version) { 44 | "" { break } 45 | 0 { 46 | Write-Action_OperationCancelled 47 | Set-Version $null 48 | return 49 | } 50 | default { 51 | if ($qbVersionList -notcontains $Script:QB_VERSION) { 52 | Write-Host "Invalid option `"${version}`"" -ForegroundColor Red 53 | Set-Version $null 54 | Start-Sleep -Milliseconds $TIME_BLINK 55 | break 56 | } 57 | else { return } 58 | } 59 | } 60 | } 61 | } 62 | 63 | function Get-QuickBooksObject { 64 | <# 65 | .SYNOPSIS 66 | Downloads the QuickBooks POS installer from the internet. 67 | 68 | .DESCRIPTION 69 | This function is the first function called by the Install-QuickBooksPOS function. 70 | It gets the QuickBooks POS installer from the internet. 71 | 72 | .NOTES 73 | Linked to Install-QuickBooksPOS 74 | #> 75 | if ($null -eq $Script:QB_VERSION) { Write-Menu_SubMenu } 76 | else { 77 | switch (Get-Version) { 78 | $POS19InstObj.VerNum { $Script:SELECTED_QB_OBJECT = $POS19InstObj } 79 | $POS18InstObj.VerNum { $Script:SELECTED_QB_OBJECT = $POS18InstObj } 80 | $POS12InstObj.VerNum { $Script:SELECTED_QB_OBJECT = $POS12InstObj } 81 | $POS11InstObj.VerNum { $Script:SELECTED_QB_OBJECT = $POS11InstObj } 82 | } 83 | 84 | $Script:INSTALLER_SIZE = $Script:SELECTED_QB_OBJECT.Size 85 | $Script:INSTALLER_BYTES = $Script:SELECTED_QB_OBJECT.XByte 86 | $Script:INSTALLER_BITS = $Script:SELECTED_QB_OBJECT.XBits 87 | } 88 | } 89 | 90 | function Start-InstallerDownload { 91 | <# 92 | .SYNOPSIS 93 | Downloads the QuickBooks POS installer from the internet. 94 | 95 | .DESCRIPTION 96 | This function starts the download of the QuickBooks POS installer 97 | from the internet. The download progress is displayed in the console 98 | and estimated time of completion is calculated based on the user's 99 | internet speed. 100 | #> 101 | Clear-Terminal 102 | Write-Host " Downloading POS v$($Script:SELECTED_QB_OBJECT.VerNum), $($Script:INSTALLER_SIZE)MB... " -ForegroundColor White -BackgroundColor DarkCyan 103 | New-ToastNotification -ToastText "Downloading POS v$($Script:SELECTED_QB_OBJECT.Name), $($Script:INSTALLER_SIZE)MB..." -ToastTitle "Download started" 104 | 105 | if (-not($Script:BANDWIDTH_UNKNOWN)) { 106 | $estimated_download_time = Get-TimeToComplete $Script:INSTALLER_BITS $Script:BANDWIDTH_BITS 107 | Write-Host "`nDST: $($Script:TARGET_LOCATION)`nETC: $estimated_download_time @ $($Script:BANDWIDTH) Mbps" -ForegroundColor White 108 | } 109 | else { 110 | Write-Host "`nDST: $($Script:TARGET_LOCATION)`nETC: UNKNOWN_DURATION @ >0.01 Mbps" -ForegroundColor White 111 | } 112 | 113 | Write-Host "`nEstimated time is calculated from the point that your`ninternet speed was tested. This is just an estimation and`nmay not reflect the actual time that it would take for the`ndownload to complete on your system. This is subject to`nchange as your internet speed fluctuates." 114 | Write-Host "`nPlease wait while the installer is being downloaded.`nThe installer will be started automatically after the`ndownload is complete.`n" -ForegroundColor Yellow 115 | 116 | $installer_download_path = "$($Script:TARGET_LOCATION)\$($Script:SELECTED_QB_OBJECT.Name)" 117 | $installer_download_url = "$($Script:SELECTED_QB_OBJECT.Url)" 118 | 119 | $installer_download_job = Start-Job -ScriptBlock { 120 | param($url, $Destination) 121 | try { 122 | Invoke-WebRequest -Uri $url -OutFile $Destination 123 | New-ToastNotification -ToastText "Successfully downloaded $($Script:SELECTED_QB_OBJECT.Name)." -ToastTitle "Download complete" 124 | } 125 | catch { Write-Host "Error: $_" -ForegroundColor Red } 126 | finally { Compare-InstallerDownloadSize } 127 | } -ArgumentList $installer_download_url, $installer_download_path 128 | 129 | Show-WebRequestDownloadJobState -DownloadJob $installer_download_job -Message "Downloading installer" 130 | 131 | # Write-Host $installer_download_path # Debug 132 | Wait-Job $installer_download_job >$null 2>&1 133 | Remove-Job $installer_download_job 134 | # Pause # Debug 135 | } 136 | -------------------------------------------------------------------------------- /src/functions/setup/PosLicensing.ps1: -------------------------------------------------------------------------------- 1 | function Write-License { 2 | param([String]$LNumber, [String]$PNumber) 3 | return '' -join '' 4 | } 5 | 6 | function Get-UserOwnLicense { 7 | <# 8 | .NOTES 9 | Triggered by `Write-LieResponse` 10 | #> 11 | Clear-Terminal 12 | Write-Host "Enter a valid license below`n" -ForegroundColor White -BackgroundColor DarkCyan 13 | Write-Host "A valid license pattern: 0000-0000-0000-000" -ForegroundColor White 14 | Write-Host "A valid product key pattern: 000-000`n" -ForegroundColor White 15 | 16 | $custom_license_number = Read-Host "License" 17 | $custom_product_number = Read-Host "Product Key" 18 | 19 | Write-Host "`nIs this license information correct? (Y/n): " -ForegroundColor Yellow -NoNewline 20 | $query = Read-Host 21 | 22 | switch ($query) { 23 | "n" { Get-UserOwnLicense } 24 | default { break } 25 | } 26 | 27 | if ($custom_license_number.Length -lt 18 -or $custom_license_number.Length -gt 18 -or $custom_product_number.Length -lt 7 -or $custom_product_number.Length -gt 7) { 28 | Clear-Terminal 29 | Write-Host "`nLicense is invalid" -ForegroundColor White -BackgroundColor DarkRed 30 | Write-Host "`nCheck your license and try again." -ForegroundColor White 31 | $query = Read-Host "`nTry again? (y/N)" 32 | Write-Host -NoNewLine "Selected: $query"; Write-Host -NoNewLine "`r `r" # To transcript # Debug 33 | switch ($query) { 34 | "y" { Get-UserOwnLicense; break } 35 | default { $Script:RUN_NEXT_PROCEDURE = $null; break } 36 | } 37 | } 38 | 39 | Set-License (Write-License $custom_license_number $custom_product_number) 40 | $Script:CUSTOM_LICENSING = $true 41 | } 42 | 43 | function Install-IntuitLicense { 44 | Clear-IntuitData 45 | Write-Host -NoNewLine "Installing registration keys... " 46 | 47 | switch (Get-Version) { 48 | $POS19InstObj.VerNum { 49 | $path = $POS19InstObj.Path 50 | mkdir $env:ProgramData\$path >$null 2>&1 51 | Out-File -FilePath $env:ProgramData\$path\qbregistration.dat ` 52 | -InputObject (Get-License) ` 53 | -Encoding UTF8 ` 54 | -NoNewline 55 | } 56 | 57 | $POS18InstObj.VerNum { 58 | $path = $POS18InstObj.Path 59 | mkdir $env:ProgramData\$path >$null 2>&1 60 | Out-File -FilePath $env:ProgramData\$path\qbregistration.dat ` 61 | -InputObject (Get-License) ` 62 | -Encoding UTF8 ` 63 | -NoNewline 64 | } 65 | 66 | $POS12InstObj.VerNum { 67 | $path = $POS12InstObj.Path 68 | mkdir $env:ProgramData\$path >$null 2>&1 69 | Out-File -FilePath $env:ProgramData\$path\qbregistration.dat ` 70 | -InputObject (Get-License) ` 71 | -Encoding UTF8 ` 72 | -NoNewline 73 | } 74 | 75 | $POS11InstObj.VerNum { 76 | $path = $POS11InstObj.Path 77 | mkdir $env:ProgramData\$path >$null 2>&1 78 | Out-File -FilePath $env:ProgramData\$path\qbregistration.dat ` 79 | -InputObject (Get-License) ` 80 | -Encoding UTF8 ` 81 | -NoNewline 82 | } 83 | } 84 | 85 | # Pause # Debug 86 | Write-Host "Done" 87 | } 88 | 89 | function Get-IntuitLicense { 90 | param ($Hash) 91 | 92 | switch ($Hash) { 93 | $POS19InstObj.Hash { 94 | Set-Version $POS19InstObj.VerNum 95 | $Script:INSTALLER_SIZE = $POS19InstObj.Size 96 | $Script:INSTALLER_BYTES = $POS19InstObj.XByte 97 | 98 | if ($Script:CUSTOM_LICENSING) { 99 | return 100 | } elseif ($Script:SECOND_STORE) { 101 | Set-License (Write-License -LNumber $POS19InstObj.LNum2 -PNumber $POS19InstObj.PNum) 102 | } elseif ($Script:ADDITIONAL_CLIENTS) { 103 | $_license = ($pos19_licenses | Get-Random) 104 | Set-License (Write-License -LNumber $_license -PNumber $POS19InstObj.PNum) 105 | } else { 106 | Set-License (Write-License -LNumber $POS19InstObj.LNum1 -PNumber $POS19InstObj.PNum) 107 | } 108 | } 109 | 110 | $POS18InstObj.Hash { 111 | Set-Version $POS18InstObj.VerNum 112 | $Script:INSTALLER_SIZE = $POS18InstObj.Size 113 | $Script:INSTALLER_BYTES = $POS18InstObj.XByte 114 | 115 | if ($Script:CUSTOM_LICENSING) { 116 | return 117 | } elseif ($Script:SECOND_STORE) { 118 | Set-License (Write-License -LNumber $POS18InstObj.LNum2 -PNumber $POS18InstObj.PNum) 119 | } elseif ($Script:ADDITIONAL_CLIENTS) { 120 | $_license = ($pos18_licenses | Get-Random) 121 | Set-License (Write-License -LNumber $_license -PNumber $POS18InstObj.PNum) 122 | } else { 123 | Set-License (Write-License -LNumber $POS18InstObj.LNum1 -PNumber $POS18InstObj.PNum) 124 | } 125 | } 126 | 127 | $POS12InstObj.Hash { 128 | Set-Version $POS12InstObj.VerNum 129 | $Script:INSTALLER_SIZE = $POS12InstObj.Size 130 | $Script:INSTALLER_BYTES = $POS12InstObj.XByte 131 | 132 | if ($Script:CUSTOM_LICENSING) { 133 | return 134 | } elseif ($Script:SECOND_STORE) { 135 | Set-License (Write-License -LNumber $POS12InstObj.LNum2 -PNumber $POS12InstObj.PNum) 136 | } elseif ($Script:ADDITIONAL_CLIENTS) { 137 | $_license = ($pos12_licenses | Get-Random) 138 | Set-License (Write-License -LNumber $_license -PNumber $POS12InstObj.PNum) 139 | } else { 140 | Set-License (Write-License -LNumber $POS12InstObj.LNum1 -PNumber $POS12InstObj.PNum) 141 | } 142 | } 143 | 144 | $POS11InstObj.Hash { 145 | Set-Version $POS11InstObj.VerNum 146 | $Script:INSTALLER_SIZE = $POS11InstObj.Size 147 | $Script:INSTALLER_BYTES = $POS11InstObj.XByte 148 | 149 | if ($Script:CUSTOM_LICENSING) { 150 | return 151 | } elseif ($Script:SECOND_STORE) { 152 | Set-License (Write-License -LNumber $POS11InstObj.LNum2 -PNumber $POS11InstObj.PNum) 153 | } elseif ($Script:ADDITIONAL_CLIENTS) { 154 | $_license = ($pos11_licenses | Get-Random) 155 | Set-License (Write-License -LNumber $_license -PNumber $POS11InstObj.PNum) 156 | } else { 157 | Set-License (Write-License -LNumber $POS11InstObj.LNum1 -PNumber $POS11InstObj.PNum) 158 | } 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/functions/display/DisplayMenu.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Menu Shortcuts / HotKeys 3 | 100: Exit Qbactivator 4 | 200: Open Troubleshooting Menu 5 | 300: Open wiki 6 | 500: Open logs 7 | #> 8 | 9 | function Write-Menu_Main { 10 | &$InitializeMain 11 | &$VerifyIfQuickBooksIsInstalled 12 | Write-HeaderLabel 13 | Write-Host "$(Format-Text "Select activation option" -Foreground Gray -Formatting Bold, Underline)`n" 14 | Write-Host "1 - POS Primary Server/Workstation" 15 | Write-Host "2 - POS Secondary Server/Workstation" 16 | Write-Host "3 - POS Client Workstations" 17 | Write-Host "4 - I have my own license :p" 18 | Write-Host "5 - Troubleshooting" 19 | Write-Host "6 - Refresh qbactivator" 20 | Write-Host "0 - Exit" 21 | $query = Read-Host "`n#" 22 | 23 | switch ($query) { 24 | 0 { &$ExitQbactivator } 25 | 10 { &$InvokeGeneralActivation } 26 | 100 { &$ExitQbactivator } 27 | 200 { Invoke-NextProcess $PROC_TROUBLESHOOT } 28 | 300 { &$OpenWiki; Write-Menu_Main } 29 | 500 { &$OpenLogs; Write-Menu_Main } 30 | 1 { 31 | $Script:SECOND_STORE = $false 32 | $Script:ADDITIONAL_CLIENTS = $false 33 | Write-Menu_SubMenu 34 | } 35 | 2 { 36 | $Script:SECOND_STORE = $true 37 | $Script:ADDITIONAL_CLIENTS = $false 38 | Write-Menu_SubMenu 39 | } 40 | 3 { 41 | $Script:SECOND_STORE = $false 42 | $Script:ADDITIONAL_CLIENTS = $true 43 | Write-Menu_SubMenu 44 | } 45 | 4 { 46 | &$CheckQuickBooksIsInstalled_ReturnToMainMenu 47 | Write-LieResponse 48 | if ($null -eq $Script:RUN_NEXT_PROCEDURE) { 49 | Write-Menu_SubMenu 50 | } 51 | } 52 | 5 { 53 | &$CheckQuickBooksIsNotInstalled_ReturnToMainMenu 54 | Invoke-NextProcess $PROC_TROUBLESHOOT 55 | } 56 | 6 { 57 | &$InitializeMain 58 | &$VerifyIfQuickBooksIsInstalled 59 | Invoke-NextProcess $PROC_RETURN_MAIN 60 | } 61 | default { Invoke-NextProcess $PROC_RETURN_MAIN } 62 | } 63 | } 64 | 65 | function Write-Menu_SubMenu { 66 | Write-HeaderLabel 67 | Write-Host "$(Format-Text "Select next operation" -Foreground Gray -Formatting Bold, Underline)`n" 68 | Write-Host "1 - Install & Activate" 69 | Write-Host "2 - Activate Only" 70 | Write-Host "3 - Install Only" 71 | Write-Host "4 - Download a POS installer" 72 | 73 | Write-Host "0 - Cancel" 74 | $query = Read-Host "`n#" 75 | Write-Host -NoNewLine "Selected: $query"; Write-Host -NoNewLine "`r `r" # To transcript # Debug 76 | switch ($query) { 77 | 0 { 78 | $Script:SECOND_STORE = $false 79 | $Script:ADDITIONAL_CLIENTS = $false 80 | Write-Menu_Main 81 | break 82 | } 83 | 10 { &$InvokeGeneralActivation } 84 | 100 { &$ExitQbactivator } 85 | 200 { Invoke-NextProcess $PROC_TROUBLESHOOT } 86 | 300 { &$OpenWiki; Write-Menu_SubMenu } 87 | 500 { &$OpenLogs; Write-Menu_SubMenu } 88 | 1 { 89 | &$CheckQuickBooksIsInstalled_ReturnToMainMenu 90 | Invoke-NextProcess $PROC_LICENSE 91 | break 92 | } 93 | 2 { 94 | &$CheckQuickBooksIsNotInstalled_ReturnToMainMenu 95 | Invoke-NextProcess $PROC_ACTIVATE 96 | break 97 | } 98 | 3 { 99 | $Script:QUICKBOOKS_INSTALL_ONLY = $true 100 | &$CheckQuickBooksIsInstalled_ReturnToMainMenu 101 | Invoke-NextProcess $PROC_LICENSE 102 | break 103 | } 104 | 4 { 105 | $Script:INSTALLER_DOWNLOAD_ONLY = $true 106 | Invoke-NextProcess $PROC_DOWNLOAD 107 | break 108 | } 109 | default { Write-Menu_SubMenu; break } 110 | } 111 | } 112 | 113 | function Write-Menu_VersionSelection { 114 | Write-HeaderLabel 115 | Write-Host "$(Format-Text "Select QuickBooks POS verison" -Foreground Gray -Formatting Bold, Underline)`n" 116 | Write-Host "11 - QuickBooks POS 2013" 117 | Write-Host "12 - QuickBooks POS 2015" 118 | Write-Host "18 - QuickBooks POS 2018" 119 | Write-Host "19 - QuickBooks POS 2019" 120 | Write-Host "0 --- Cancel" 121 | $query = Read-Host "`nVersion" 122 | Set-Version $query 123 | 124 | # allow exit at any point in time 125 | switch ($query) { 126 | 10 { &$InvokeGeneralActivation } 127 | 100 { &$ExitQbactivator } 128 | 200 { Invoke-NextProcess $PROC_TROUBLESHOOT } 129 | 300 { &$OpenWiki; Write-Menu_VersionSelection } 130 | 500 { &$OpenLogs; Write-Menu_VersionSelection } 131 | } 132 | } 133 | 134 | function Write-Menu_Troubleshooting { 135 | Write-HeaderLabel 136 | Write-Host "$(Format-Text "Select troubleshooting option" -Foreground Gray -Formatting Bold, Underline)`n" 137 | Write-Host "1 - Lv1 Client module: Restore" 138 | Write-Host "2 - Lv2 Client module: Repair" 139 | Write-Host "3 - Lv3 Client module: Re-activation" 140 | Write-Host "4 - Lv4 Re-install QuickBooks" 141 | Write-Host "5 - QuickBooks Patch Test" 142 | Write-Host "6 - View links to stuff" 143 | Write-Host "0 - Back" 144 | $query = Read-Host "`n#" 145 | Write-Host -NoNewLine "Selected: $query"; Write-Host -NoNewLine "`r `r" # To transcript # Debug 146 | switch ($query) { 147 | 0 { Write-Menu_Main; break } 148 | 10 { &$InvokeGeneralActivation } 149 | 100 { &$ExitQbactivator } 150 | 200 { Invoke-NextProcess $PROC_TROUBLESHOOT } 151 | 300 { &$OpenWiki; Write-Menu_Troubleshooting } 152 | 500 { &$OpenLogs; Write-Menu_Troubleshooting } 153 | 1 { 154 | Stop-QuickBooksProcesses 155 | Repair-LevelOne_GenuineClientModule 156 | Write-Menu_Troubleshooting 157 | break 158 | } 159 | 2 { 160 | Stop-QuickBooksProcesses 161 | Repair-LevelTwo_GenuineClientModule_SanityCheck 162 | Write-Menu_Troubleshooting 163 | break 164 | } 165 | 3 { 166 | Repair-LevelThree_Reactivation 167 | Write-Host "Starting reactivation process..." 168 | Invoke-NextProcess $PROC_ACTIVATE 169 | break 170 | } 171 | 4 { 172 | Write-Error_UninstallUnsupported 173 | Write-Menu_Troubleshooting 174 | break 175 | } 176 | 5 { 177 | Stop-QuickBooksProcesses 178 | Install-ClientModule 179 | Write-Menu_Troubleshooting 180 | break 181 | } 182 | 6 { Write-Menu_LinkOptions; break } 183 | default { Write-Menu_Troubleshooting; break } 184 | } 185 | } 186 | 187 | function Write-Menu_LinkOptions { 188 | Write-HeaderLabel 189 | Write-Host "$(Format-Text "Select a link to jump to" -Foreground Gray -Formatting Bold, Underline)`n" 190 | Write-Host "1 - View the qbactivator Wiki" 191 | Write-Host "2 - Terminate QuickBooks processes" 192 | Write-Host "3 - View qbactivator logs" 193 | Write-Host "0 - Back" 194 | $query = Read-Host "`n#" 195 | Write-Host -NoNewLine "Selected: $query"; Write-Host -NoNewLine "`r `r" # To transcript # Debug 196 | switch ($query) { 197 | 0 { Write-Menu_Troubleshooting; break } 198 | 10 { &$InvokeGeneralActivation } 199 | 100 { &$ExitQbactivator } 200 | 200 { Invoke-NextProcess $PROC_TROUBLESHOOT } 201 | 300 { &$OpenWiki; Write-Menu_LinkOptions } 202 | 500 { &$OpenLogs; Write-Menu_LinkOptions } 203 | 1 { 204 | Write-Host "Opening qbactivator Wiki..." 205 | &$OpenWiki 206 | Write-Menu_LinkOptions 207 | break 208 | } 209 | 2 { 210 | Stop-QuickBooksProcesses 211 | Write-Menu_LinkOptions 212 | break 213 | } 214 | 3 { 215 | &$OpenLogs 216 | Write-Menu_LinkOptions 217 | break 218 | } 219 | default { Write-Menu_LinkOptions; break } 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/functions/utility/Format-Text.ps1: -------------------------------------------------------------------------------- 1 | function Format-Text { 2 | <# 3 | .SYNOPSIS 4 | Writes text with color and formatting 5 | 6 | .DESCRIPTION 7 | Writes text with color, formatting and RGB support 8 | 9 | .INPUTS 10 | This function accepts pipeline input. 11 | 12 | .PARAMETER Text 13 | The text to be written 14 | 15 | .PARAMETER Foreground 16 | The foreground color of the text to be written. 17 | Accepts a valid color name, 8-bit 0-255 integer value, 24-bit RGB 0,0,0 format. 18 | 19 | .PARAMETER Background 20 | The background color of the text to be written. 21 | Accepts a valid color name, 8-bit 0-255 integer value, 24-bit RGB 0,0,0 format. 22 | 23 | .PARAMETER Formatting 24 | The text formatting options to be applied to the text. 25 | Accepts a list of valid formatting options: 26 | - Bold 27 | - Dim 28 | - Underline 29 | - Blink 30 | - Reverse 31 | - Hidden 32 | 33 | .PARAMETER BitDepth 34 | The bit depth of the text to be written. 35 | Accepts values: 8 or 24 36 | 37 | .EXAMPLE 38 | Format-Text -Text "This is some red text on a black background" -Foreground Red -Background Black 39 | 40 | .EXAMPLE 41 | Write-Host "This text: $(Format-Text -Text "is green and underlined" -Foreground Green -Formatting Bold, Underline). Cool right?" 42 | 43 | 44 | .EXAMPLE 45 | Format-Text -Console -Foreground Blue -Background White 46 | 47 | This example shows how to change the color of the console. 48 | 49 | .EXAMPLE 50 | "Lorem ipsum dolor sit amet" | Format-Text -BitDepth 8 -Foreground 166 -Formatting Bold 51 | 52 | "Lorem ipsum dolor sit amet" | Format-Text -BitDepth 24 -Foreground 12,66,34 -Formatting Underline 53 | 54 | This example shows how to pipe text to the function with color in 8 and 24 bit depth. 55 | 56 | .NOTES 57 | 8-bit color format: 58 | 59 | ESC[38;5;⟨n⟩m Select foreground color, where `n` is a number from the table below 60 | ESC[48;5;⟨n⟩m Select background color, where `n` is a number from the table below 61 | 62 | 0-7: standard colors (as in ESC [ 30-37 m) 63 | 8-15: high intensity colors (as in ESC [ 90-97 m) 64 | 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5) 65 | 232-255: grayscale from dark to light in 24 steps 66 | 67 | 68 | RGB color format: 69 | 70 | ESC[38;2;⟨r⟩;⟨g⟩;⟨b⟩ m Select RGB foreground color 71 | ESC[48;2;⟨r⟩;⟨g⟩;⟨b⟩ m Select RGB background color 72 | 73 | .NOTES 74 | Filename: Format-Text.ps1 75 | Version: 1.3 76 | Author: neuralpain 77 | Created: 2024-03-17 78 | Updated: 2024-04-20 79 | 80 | Version history: 81 | 82 | 1.0 - Initial release 83 | 84 | 1.1 - Add complete color set for both foreground and background 85 | 86 | 1.2 - Add support for 8-bit and 24-bit colors 87 | 88 | 1.3 - Add proper support for Light and Dark colors on Forground and Background; and fixed bug on text formatting 89 | #> 90 | [CmdletBinding()] 91 | param( 92 | [switch]$Console, 93 | [switch]$ConsoleReset, # unavailable on for now 94 | [Parameter(Position = 0, Mandatory = $false, HelpMessage = "The text to be written", ValueFromPipeline = $true)] 95 | [String]$Text, 96 | [Parameter(Mandatory = $false, HelpMessage = "The bit depth of the text to be written")] 97 | [ValidateSet(8, 24)] 98 | [Int]$BitDepth, 99 | [Parameter(Mandatory = $false, HelpMessage = "The foreground color of the text to be written")] 100 | [ValidateCount(1, 3)] 101 | [String[]]$Foreground, 102 | [Parameter(Mandatory = $false, HelpMessage = "The background color of the text to be written")] 103 | [ValidateCount(1, 3)] 104 | [String[]]$Background, 105 | [Parameter(Mandatory = $false, HelpMessage = "The text formatting options to be applied to the text")] 106 | [String[]]$Formatting 107 | ) 108 | 109 | $Esc = [char]27 110 | $Reset = "${Esc}[0m" 111 | 112 | if ($Console) { 113 | # Set the foreground color 114 | $Host.UI.RawUI.ForegroundColor = $Foreground 115 | # Set the background color 116 | $Host.UI.RawUI.BackgroundColor = $Background 117 | # Clear the screen to apply the changes 118 | Clear-Host 119 | return 120 | } 121 | 122 | switch ($BitDepth) { 123 | 8 { 124 | # if the value is less than 0, set it to 0 125 | if ($null -eq $Foreground -or $Foreground -lt 0) { $Foreground = 0 } 126 | if ($null -eq $Background -or $Background -lt 0) { $Background = 0 } 127 | 128 | # if the value is greater than 255, set it to 255 129 | if ($Foreground -gt 255) { $Foreground = 255 } 130 | if ($Background -gt 255) { $Background = 255 } 131 | 132 | $Foreground = "${Esc}[38;5;${Foreground}m" 133 | $Background = "${Esc}[48;5;${Background}m" 134 | break 135 | } 136 | 24 { 137 | foreach ($color in $Foreground) { 138 | if ($null -eq $color -or $color -lt 0) { $color = 0 } 139 | if ($color -gt 255) { $color = 255 } 140 | $_foreground += ";${color}" 141 | } 142 | 143 | foreach ($color in $Background) { 144 | if ($null -eq $color -or $color -lt 0) { $color = 0 } 145 | if ($color -gt 255) { $color = 255 } 146 | $_background += ";${color}" 147 | } 148 | 149 | $Foreground = "${Esc}[38;2${_foreground}m" 150 | $Background = "${Esc}[48;2${_background}m" 151 | break 152 | } 153 | default { 154 | # Text Color: 155 | switch ($Foreground) { 156 | 'Black' { $Foreground = "${Esc}[30m" } 157 | 'DarkRed' { $Foreground = "${Esc}[31m" } 158 | 'DarkGreen' { $Foreground = "${Esc}[32m" } 159 | 'DarkYellow' { $Foreground = "${Esc}[33m" } 160 | 'DarkBlue' { $Foreground = "${Esc}[34m" } 161 | 'DarkMagenta' { $Foreground = "${Esc}[35m" } 162 | 'DarkCyan' { $Foreground = "${Esc}[36m" } 163 | 'Gray' { $Foreground = "${Esc}[37m" } 164 | 'DarkGray' { $Foreground = "${Esc}[90m" } 165 | 'Red' { $Foreground = "${Esc}[91m" } 166 | 'Green' { $Foreground = "${Esc}[92m" } 167 | 'Yellow' { $Foreground = "${Esc}[93m" } 168 | 'Blue' { $Foreground = "${Esc}[94m" } 169 | 'Magenta' { $Foreground = "${Esc}[95m" } 170 | 'Cyan' { $Foreground = "${Esc}[96m" } 171 | 'White' { $Foreground = "${Esc}[97m" } 172 | default { $Foreground = "" } 173 | } 174 | # Background Color: 175 | switch ($Background) { 176 | 'Black' { $Background = "${Esc}[40m" } 177 | 'DarkRed' { $Background = "${Esc}[41m" } 178 | 'DarkGreen' { $Background = "${Esc}[42m" } 179 | 'DarkYellow' { $Background = "${Esc}[43m" } 180 | 'DarkBlue' { $Background = "${Esc}[44m" } 181 | 'DarkMagenta' { $Background = "${Esc}[45m" } 182 | 'DarkCyan' { $Background = "${Esc}[46m" } 183 | 'Gray' { $Background = "${Esc}[47m" } 184 | 'DarkGray' { $Background = "${Esc}[100m" } 185 | 'Red' { $Background = "${Esc}[101m" } 186 | 'Green' { $Background = "${Esc}[102m" } 187 | 'Yellow' { $Background = "${Esc}[103m" } 188 | 'Blue' { $Background = "${Esc}[104m" } 189 | 'Magenta' { $Background = "${Esc}[105m" } 190 | 'Cyan' { $Background = "${Esc}[106m" } 191 | 'White' { $Background = "${Esc}[107m" } 192 | default { $Background = "" } 193 | } 194 | break 195 | } 196 | } 197 | 198 | # Text Formatting: 199 | if ($Formatting.Length -eq 0) { 200 | $Format = "" 201 | } 202 | else { 203 | $i = 0 204 | $Format = "${Esc}[" 205 | foreach ($type in $Formatting) { 206 | switch ($type) { 207 | 'Bold' { $Format += "1" } 208 | 'Dim' { $Format += "2" } 209 | 'Underline' { $Format += "4" } 210 | 'Blink' { $Format += "5" } 211 | 'Reverse' { $Format += "7" } 212 | 'Hidden' { $Format += "8" } 213 | default { $Format += "" } 214 | } 215 | $i++ 216 | if ($i -lt ($Formatting.Length)) { $Format += ";" } 217 | else { $Format += "m"; break } 218 | } 219 | } 220 | 221 | $OutString = "${Foreground}${Background}${Format}${Text}${Reset}" 222 | Write-Output $OutString 223 | } 224 | -------------------------------------------------------------------------------- /src/functions/utility/Measure-UserBandwidth.ps1: -------------------------------------------------------------------------------- 1 | function Measure-UserBandwidth { 2 | <# 3 | .SYNOPSIS 4 | Measures the user's Internet bandwidth. 5 | 6 | .DESCRIPTION 7 | Measures internet bandwidth using the Ookla Speedtest CLI, which is a command-line interface to the Speedtest.net website. 8 | The function will download the CLI from the internet if necessary. 9 | 10 | .PARAMETER Type 11 | Specifies the type of bandwidth to measure (Download or Upload). 12 | 13 | .PARAMETER Unit 14 | Specifies the unit of measurement for the bandwidth (Bytes or Bits). 15 | 16 | .EXAMPLE 17 | Measure-UserBandwidth -Type Download -Unit Bytes 18 | 19 | Measures the user's download bandwidth in Bytes. 20 | 21 | .EXAMPLE 22 | Measure-UserBandwidth -Type Upload -Unit Bits 23 | 24 | Measures the user's upload bandwidth in Bits. 25 | 26 | .NOTES 27 | The function will write to the console when running the speed test. 28 | 29 | .NOTES 30 | Unit Bytes is not accurate at the moment. 31 | 32 | .NOTES 33 | Version: 1.0 34 | Author: neuralpain 35 | Date: 2024-03-16 36 | #> 37 | [CmdletBinding()] 38 | param ( 39 | [Parameter(Mandatory = $true)] 40 | [ValidateSet("Download", "Upload")] 41 | [String]$Type, 42 | [Parameter(Mandatory = $true)] 43 | [ValidateSet("Bits", "Bytes")] 44 | [String]$Unit 45 | ) 46 | 47 | $SPEEDTEST_FOLDER = "$env:APPDATA\Ookla\Speedtest CLI" 48 | $SPEEDTEST_LICENSE = "$SPEEDTEST_FOLDER\speedtest-cli.ini" 49 | $SPEEDTEST_LICENSE_TEXT = "[Settings]`r`nLicenseAccepted=604ec27f828456331ebf441826292c49276bd3c1bee1a2f65a6452f505c4061c`r`nGDPRTimeStamp=1704516852" # utf8, noBOM 50 | $SPEEDTEST_CLI_URL = "https://install.speedtest.net/app/cli/ookla-speedtest-1.2.0-win64.zip" 51 | 52 | if ($Type -eq "Upload") { 53 | Write-Host "Upload speed test unavailable." 54 | return 0 55 | } 56 | 57 | if (-not(Test-Path "$SPEEDTEST_LICENSE" -PathType Leaf)) { 58 | New-Item $SPEEDTEST_FOLDER -Type Directory >$null 2>&1 59 | [IO.File]::WriteAllLines($SPEEDTEST_LICENSE, $SPEEDTEST_LICENSE_TEXT) 60 | } 61 | 62 | if (-not(Test-Path "$env:TEMP\speedtest.exe")) { 63 | if (-not(Test-Path "$env:TEMP\speedtest.zip")) { 64 | Start-BitsTransfer $SPEEDTEST_CLI_URL "$env:TEMP\speedtest.zip" 65 | } 66 | 67 | Add-Type -Assembly System.IO.Compression.FileSystem 68 | 69 | $_zip = [IO.Compression.ZipFile]::OpenRead("$env:TEMP\speedtest.zip") 70 | 71 | [System.IO.Compression.ZipFileExtensions]::ExtractToFile(( 72 | $_zip.Entries | Where-Object { $_.Name -eq "speedtest.exe" } 73 | ), "$env:TEMP\speedtest.exe", $true) 74 | 75 | $_zip.Dispose() 76 | } 77 | 78 | try { 79 | Write-Host "Testing internet speed... " -NoNewline 80 | 81 | # accept CLI usage license and General Data Protection Regulation (EU) before use 82 | Invoke-Expression "$env:TEMP\speedtest.exe --accept-gdpr --accept-license" >$null 2>&1 83 | 84 | switch ($Unit) { 85 | 'Bits' { [int]$result = ((Invoke-Expression "$env:TEMP\speedtest.exe --accept-gdpr --accept-license --format json") -replace '.*"bandwidth":(\d+).*', '$1') } 86 | 'Bytes' { [int]$result = ((Invoke-Expression "$env:TEMP\speedtest.exe --accept-gdpr --accept-license --format json") -replace '.*"bytes":(\d+).*', '$1') } 87 | } 88 | 89 | Write-Host "Done." 90 | } 91 | catch { 92 | Write-Host "`nSpeed test failed." 93 | return $null 94 | } 95 | 96 | return $result 97 | } 98 | 99 | function Convert-UserBandwidth { 100 | <# 101 | .SYNOPSIS 102 | Converts user bandwidth from one unit to another. 103 | 104 | .DESCRIPTION 105 | This function converts the specified input unit of user bandwidth to the specified output unit. 106 | Supported input and output units are: 107 | - Bytes to Mbps 108 | - Bits to Mbps 109 | 110 | .PARAMETER InputUnit 111 | The unit of input user bandwidth. 112 | Must be one of: "Bits", "Bytes" 113 | 114 | .PARAMETER Value 115 | The value of the input user bandwidth. 116 | 117 | .PARAMETER OutputUnit 118 | The unit of output user bandwidth. 119 | Optional. If not specified, the output unit is determined by the input unit. 120 | Must be one of: "Kilobits", "Kilobytes", "Megabits", "Megabytes", "Gigabits", "Gigabytes" 121 | 122 | .EXAMPLE 123 | Convert-UserBandwidth -InputUnit Bytes -Value 1000000 124 | 125 | Converts 1000000 Bytes to Mbps (1000 Mbps). 126 | 127 | .EXAMPLE 128 | Convert-UserBandwidth -InputUnit Bits -Value 8000000000 -OutputUnit Megabits 129 | 130 | Converts 8000000000 Bits to Megabits (8000 Mbps). 131 | 132 | .OUTPUTS 133 | The result of the conversion, in the specified output unit. 134 | 135 | .NOTES 136 | Version: 1.0 137 | Author: neuralpain 138 | Date: 2024-03-16 139 | #> 140 | [CmdletBinding()] 141 | [OutputType([int], [double])] 142 | param( 143 | [Parameter(Position = 0, Mandatory = $true)] 144 | [ValidateSet("Bits", "Bytes")] 145 | [String]$InputUnit, 146 | [Parameter(Mandatory = $true)] 147 | [int]$Value, 148 | [Parameter(Mandatory = $false)] 149 | [ValidateSet("Bits", "Bytes", "Kilobits", "Kilobytes", "Megabits", "Megabytes", 150 | "Gigabits", "Gigabytes", "Terabits", "Terabytes", "Petabits", "Petabytes", 151 | "Exabits", "Exabytes", "Zetabits", "Zetabytes", "Yottabits", "Yottabytes")] 152 | [String]$OutputUnit 153 | ) 154 | 155 | switch ($InputUnit) { 156 | 'Bits' { 157 | # Convert Bits to Bytes 158 | $bytes = [math]::Round(($Value / 8), 2) 159 | # Convert Bits to Mbps 160 | if (-not $PSBoundParameters.ContainsKey('OutputUnit')) { 161 | $OutputUnit = 'Megabits' 162 | } 163 | switch ($OutputUnit) { 164 | 'Bytes' { $result = $bytes } 165 | 'Kilobits' { $result = [math]::Round(($Value / [math]::Pow(10, 3)), 2) } 166 | 'Kilobytes' { $result = [math]::Round(($Value / (8 * [math]::Pow(10, 3))), 2) } 167 | 'Megabits' { $result = [math]::Round(($Value / [math]::Pow(10, 6)), 2) } 168 | 'Megabytes' { $result = [math]::Round(($Value / (8 * [math]::Pow(10, 6))), 2) } 169 | 'Gigabits' { $result = [math]::Round(($Value / [math]::Pow(10, 9)), 2) } 170 | 'Gigabytes' { $result = [math]::Round(($Value / (8 * [math]::Pow(10, 9))), 2) } 171 | # Just in case someone needs something just a bit higher than the average peasant user 172 | 'Terabits' { $result = [math]::Round(($Value / [math]::Pow(10, 12)), 2) } 173 | 'Terabytes' { $result = [math]::Round(($Value / (8 * [math]::Pow(10, 12))), 2) } 174 | 'Petabits' { $result = [math]::Round(($Value / [math]::Pow(10, 15)), 2) } 175 | 'Petabytes' { $result = [math]::Round(($Value / (8 * [math]::Pow(10, 15))), 2) } 176 | # And for the rare edge case of an enthusiast somewhere who drank a bit too much coffee in the morning 177 | 'Exabits' { $result = [math]::Round(($Value / [math]::Pow(10, 18)), 2) } 178 | 'Exabytes' { $result = [math]::Round(($Value / (8 * [math]::Pow(10, 18))), 2) } 179 | 'Zetabits' { $result = [math]::Round(($Value / [math]::Pow(10, 21)), 2) } 180 | 'Zetabytes' { $result = [math]::Round(($Value / (8 * [math]::Pow(10, 21))), 2) } 181 | 'Yottabits' { $result = [math]::Round(($Value / [math]::Pow(10, 24)), 2) } 182 | 'Yottabytes' { $result = [math]::Round(($Value / (8 * [math]::Pow(10, 24))), 2) } 183 | } 184 | } 185 | 'Bytes' { 186 | # Convert Bytes to Bits 187 | # Bytes need to be converted to bits and then converted to the output units of Kilobits, Megabits, Gigabits, etc. 188 | $bits = $Value * 8 189 | # Convert Bytes to Mbps 190 | if (-not $PSBoundParameters.ContainsKey('OutputUnit')) { 191 | $OutputUnit = 'Megabits' 192 | } 193 | switch ($OutputUnit) { 194 | 'Bits' { $result = $bits } 195 | 'Kilobits' { $result = [math]::Round(($bits / [math]::Pow(10, 3)), 2) } 196 | 'Kilobytes' { $result = [math]::Round(($Value / 1024), 2) } 197 | 'Megabits' { $result = [math]::Round(($bits / [math]::Pow(10, 6)), 2) } 198 | 'Megabytes' { $result = [math]::Round(($Value / [math]::Pow(1024, 2)), 2) } 199 | 'Gigabits' { $result = [math]::Round(($bits / [math]::Pow(10, 9)), 2) } 200 | 'Gigabytes' { $result = [math]::Round(($Value / [math]::Pow(1024, 3)), 2) } 201 | # Just in case someone needs something just a bit higher than the average peasant user 202 | 'Terabits' { $result = [math]::Round(($bits / [math]::Pow(10, 12)), 2) } 203 | 'Terabytes' { $result = [math]::Round(($Value / [math]::Pow(1024, 4)), 2) } 204 | 'Petabits' { $result = [math]::Round(($bits / [math]::Pow(10, 15)), 2) } 205 | 'Petabytes' { $result = [math]::Round(($Value / [math]::Pow(1024, 5)), 2) } 206 | # And for the rare edge case of an enthusiast somewhere who drank a bit too much coffee in the morning 207 | 'Exabits' { $result = [math]::Round(($bits / [math]::Pow(10, 18)), 2) } 208 | 'Exabytes' { $result = [math]::Round(($Value / [math]::Pow(1024, 6)), 2) } 209 | 'Zetabits' { $result = [math]::Round(($bits / [math]::Pow(10, 21)), 2) } 210 | 'Zetabytes' { $result = [math]::Round(($Value / [math]::Pow(1024, 7)), 2) } 211 | 'Yottabits' { $result = [math]::Round(($bits / [math]::Pow(10, 24)), 2) } 212 | 'Yottabytes' { $result = [math]::Round(($Value / [math]::Pow(1024, 8)), 2) } 213 | } 214 | } 215 | } 216 | 217 | return $result 218 | } 219 | -------------------------------------------------------------------------------- /PowerCMD.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # PowerCMD.sh, Version 0.3.0 4 | # Copyright (c) 2024, neuralpain 5 | # https://github.com/neuralpain/PowerCMD 6 | # A bundler to integrate PowerShell with CMD 7 | 8 | v="0.3.0" 9 | return="PowerCMD:" 10 | 11 | # --- START CONFIGURATION --- # 12 | 13 | # [ TERMINAL WINDOW CONFIG ] 14 | window_width=60 15 | window_height=22 16 | 17 | # [ SCRIPT INFO ] 18 | # edit script version in ./VERSION 19 | version=$(> $cmd_cache # your working directory in batch 115 | echo "set \"pwsh=PowerShell -NoP -C\"" >> $cmd_cache 116 | echo "setlocal EnableExtensions DisableDelayedExpansion" >> $cmd_cache 117 | echo "set ARGS=%*" >> $cmd_cache 118 | echo "if defined ARGS set ARGS=%ARGS:\"=\\\"%" >> $cmd_cache 119 | echo "if defined ARGS set ARGS=%ARGS:'=''%" >> $cmd_cache 120 | echo >> $cmd_cache 121 | 122 | # uses neuralpain/cmdUAC.cmd 123 | if [[ $with_admin == true ]]; then 124 | echo ":: check admin permissions" >> $cmd_cache 125 | echo "fsutil dirty query %systemdrive% >nul" >> $cmd_cache 126 | echo ":: if error, we do not have admin." >> $cmd_cache 127 | echo "if %ERRORLEVEL% NEQ 0 (" >> $cmd_cache 128 | echo " cls & echo." >> $cmd_cache 129 | echo " echo This script requires administrative privileges." >> $cmd_cache 130 | echo " echo Attempting to elevate..." >> $cmd_cache 131 | echo " goto UAC_Prompt" >> $cmd_cache 132 | echo ") else ( goto :init )" >> $cmd_cache 133 | echo >> $cmd_cache 134 | echo ":UAC_Prompt" >> $cmd_cache 135 | echo "set n=%0 %*" >> $cmd_cache 136 | echo "set n=%n:\"=\" ^& Chr(34) ^& \"%" >> $cmd_cache 137 | echo "echo Set objShell = CreateObject(\"Shell.Application\")>\"%tmp%\cmdUAC.vbs\"" >> $cmd_cache 138 | echo "echo objShell.ShellExecute \"cmd.exe\", \"/c start \" ^& Chr(34) ^& \".\" ^& Chr(34) ^& \" /d \" ^& Chr(34) ^& \"%CD%\" ^& Chr(34) ^& \" cmd /c %n%\", \"\", \"runas\", ^1>>\"%tmp%\cmdUAC.vbs\"" >> $cmd_cache 139 | echo "cscript \"%tmp%\cmdUAC.vbs\" //Nologo" >> $cmd_cache 140 | echo "del \"%tmp%\cmdUAC.vbs\"" >> $cmd_cache 141 | echo "goto :eof" >> $cmd_cache 142 | echo >> $cmd_cache 143 | fi 144 | 145 | echo ":init" >> $cmd_cache 146 | echo "cls & echo." >> $cmd_cache 147 | echo "echo Initializing. Please wait..." >> $cmd_cache 148 | echo "%pwsh% ^\"Invoke-Expression ('^& {' + (Get-Content -Raw '%~f0') + '} %ARGS%')\"" >> $cmd_cache 149 | } 150 | 151 | bundle() { 152 | [[ ! -d "./cache" ]] && mkdir cache || rm -r ./cache/*; 153 | # uses neuralpain/PwshBatch.cmd 154 | echo "<# :# DO NOT REMOVE THIS LINE" > $cmd_cache 155 | echo >> $cmd_cache 156 | echo :: █▀█ █▄▄ ▄▀█ █▀▀ ▀█▀ █ █░█ ▄▀█ ▀█▀ █▀█ █▀█ >> $cmd_cache 157 | echo :: ▀▀█ █▄█ █▀█ █▄▄ ░█░ █ ▀▄▀ █▀█ ░█░ █▄█ █▀▄ >> $cmd_cache 158 | echo >> $cmd_cache 159 | echo ":: $name.cmd, Version $version" >> $cmd_cache 160 | # add the copyright information, link to your project repository and 161 | # description of the script, or remove it entirely, whichever you choose 162 | echo ":: Copyright (c) $license_year, $license_owner" >> $cmd_cache 163 | echo ":: $project_url" >> $cmd_cache 164 | echo ":: $script_description" >> $cmd_cache 165 | echo >> $cmd_cache 166 | echo "@echo off" >> $cmd_cache 167 | echo "@mode $window_width,$window_height" >> $cmd_cache 168 | echo "@title $script_title v$version" >> $cmd_cache 169 | add_pwsh 170 | echo >> $cmd_cache 171 | 172 | # -- add batch code -- # 173 | if [[ -f "$src/main.cmd" ]]; then 174 | cat $src/main.cmd >> $cmd_cache 175 | echo >> $cmd_cache 176 | echo ":qbreadme:" >> $cmd_cache 177 | cat $res/doc/instructions.txt >> $cmd_cache 178 | echo ":qbreadme:" >> $cmd_cache 179 | echo >> $cmd_cache 180 | fi 181 | # -- end batch code -- # 182 | 183 | echo "# ---------- PowerShell Script ---------- #>" >> $cmd_cache 184 | 185 | # Loop through the powershell_functions 186 | for function in "${powershell_functions[@]}"; do 187 | # add a break between files: 188 | # 142: end of one file 189 | echo >> $pwsh_cache # [break] 190 | # 1: start of next file 191 | cat $function >> $pwsh_cache 192 | done 193 | 194 | # final bundle 195 | cat $cmd_cache > $buildfile.cmd 196 | cat $pwsh_cache >> $buildfile.cmd 197 | echo "$return Bundling complete." 198 | 199 | # archive for stable release 200 | [[ $1 == "-a" || $1 == "--archive" ]] && compress 201 | } 202 | 203 | bundle_test() { 204 | build="$(date "+%y%m%d.%H%M%S")$1" 205 | # this one to become the file name 206 | buildfile="$buildfile-$version-beta-Build.$build" 207 | # this one for the script's head comment 208 | version="$version-beta [Build $build]" 209 | [[ ! -d "./build" ]] && mkdir build 210 | bundle 211 | } 212 | 213 | compress() { 214 | # add files to include in the release package 215 | cp ./LICENSE ./VERSION dist 216 | for file in "${additional_files[@]}"; do 217 | cp $file dist 218 | done 219 | 220 | cd dist 221 | 222 | # ensure that the 'zip' package should be installed 223 | zip -q $complete_release * || (echo -e "$return error: Failed to create archive." && return) 224 | # files to exclude in lightweight release 225 | # `*.zip` is mandatory, else it will include the normal release as well 226 | zip -q $lightweight_release * -x ${exclude_files[@]} *.zip || (echo -e "$return error: Failed to create archive." && return) 227 | 228 | # cleanup temporary files copied to /dist 229 | rm ./LICENSE ./VERSION 230 | for file in "${remove_files[@]}"; do 231 | rm $file 232 | done 233 | 234 | [[ -f $complete_release ]] && echo -e "$return Archived to '/dist'" 235 | } 236 | 237 | printusage() { 238 | echo "Usage: PowerCMD [OPTION...]" 239 | echo -e "A bundler to integrate PowerShell with CMD\n" 240 | echo " -s, --release Build for stable release" 241 | echo " -a, --archive Archive stable release package" 242 | echo " -t, --test [note] Build unit tests" 243 | echo " -C, --clear-all Delete temporary files and folders" 244 | echo " -c, --clear Clear all unit test builds" 245 | echo " -v, --version Display version number and exit" 246 | echo " -h, --help Display this help message and exit" 247 | echo -e "\nFor more information, visit\033[0m" 248 | echo -e "\033[0;32mhttps://github.com/neuralpain/PowerCMD\033[0m" 249 | } 250 | 251 | printversion() { 252 | echo -e "Version $v" 253 | } 254 | 255 | case "$1" in 256 | -h|--help) 257 | printusage && exit;; 258 | -v|--verison) 259 | printversion && exit;; 260 | -c|--clear) 261 | rm -r ./build/* &>/dev/null && exit;; 262 | -C|--clear-all) 263 | rm -r ./build ./dist ./cache &>/dev/null && exit;; 264 | -s|--release) 265 | buildfile=./dist/$name-$version 266 | [[ ! -d "./dist" ]] && mkdir dist || rm -r ./dist/*; 267 | bundle $2;; 268 | -t|--test) 269 | # add a specific note in the file for the current iteration of the script test 270 | [[ $# -gt 1 ]] && note=$@ && note=${note/"-t "} && note=${note/"--test "} && note=${note//" "/-} && note="-$note" 271 | bundle_test $note;; 272 | *) 273 | if [[ $@ == "" ]]; then echo "$return Missing argument." 274 | else echo -e "$return Invalid option '$1'"; fi 275 | exit 276 | esac 277 | exit 278 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | qbactivator logo dark 5 |
6 | 7 | 8 |

9 |

Activation script for QuickBooks Point of Sale Software on Windows

10 |

11 | 12 | > [!CAUTION] 13 | > **Do not** clone or download this *repository* or the *source code* to run qbactivator. The compiled script **is not** contained within the source (ref. [#10][issue_10]). Use the download button **above** to get the latest version of the script and [read the Wiki][getstarted] to get started using qbactivator. 14 | 15 | ### Features 16 | 17 | - Permanent activation 18 | - Automatic licensing 19 | - Multi-Store support 20 | - Optional downloader for installer packages 21 | - Protection against compromised packages 22 | 23 | > [!NOTE] 24 | > Protection involves comparing hashes of verified installer packages against the hash of the installer that the user has downloaded or transferred from another location. If an installer package has been flagged as compromised but the user trusts the installer (or is too lazy to download an official installer), the user can decide to ignore the warning and use their current installer package. 25 | 26 | ### Supported Operating Systems 27 | - Windows 11 28 | - Windows 10 29 | - Windows 8.1 30 | - Windows 7 SP1 (requires [Windows Management Framework 4.0][wikiwmf4]) 31 | - Windows Server 2012-2022 (ref. [#44][issue_44]) 32 | 33 | > [!IMPORTANT] 34 | > `qbactivator` **requires** at least PowerShell 4.0 [or later][updatepowershell] to be installed on your Windows machine in order to function as intended. If you are using Windows 10 or above, it is likely that PowerShell 5.1 or a later version is already installed on your machine. You can check your PowerShell version by using the `$PSVersionTable` command in PowerShell if you are unsure. 35 | 36 | ### A few things before you start 37 | 38 | - An internet connection **is not** required for activation or adding users, i.e., you are able to activate offline; but you can let it have that one free phone call to let Intuit know that it's safe. 39 | - QuickBooks POS should be installed before other QuickBooks Desktop products. 40 | - Manually running the QuickBooks POS installer or entering any keys into the installer **is not required** as the script will handle these tasks. You only need to navigate through the buttons and options. 41 | - Remember that you **should not** launch QuickBooks Point of Sale after installation. Ensure that you uncheck the "Launch QuickBooks Point Of Sale" option before clicking on "Finish" and proceeding with the activation process. 42 | - It is recommended to **avoid** installing updates through the application due to some of the features being blocked (ref. [#27][issue_27]), but they are available [here](https://github.com/neuralpain/qbactivator/wiki#optional-updates-for-quickbooks-pos-software-from-intuit) if you want to download them yourself. 43 | - All versions of QuickBooks Desktop Point of Sale, including v12, v18, and v19, are licensed as `Pro Multistore Level`. The only exception is POS v11, which is licensed as `Pro Level`. 44 | - [Read the instructions][instructions] to run `qbactivator` and activate QuickBooks. 45 | - [Read the FAQs](#faqs) for further information and guidance for any concerns you may have. 46 | 47 | > [!WARNING] 48 | > `qbactivator` is intended to operate with only one version of QuickBooks POS installed. In the event of multiple installations, the activator may encounter errors. Therefore, before executing qbactivator, it is crucial to remove all other versions of QuickBooks POS. 49 | 50 | ## Downloads & Updates 51 | 52 | > [!NOTE] 53 | > ### Latest Release [⧉][release] 54 | > 55 | > **v0.24.0** 56 | > - Fix critical bug affecting additional Client licenses 57 | > - Add Toast notifications 58 | > - TLS security improvements 59 | > - Bug fixes and improvements 60 | > 61 | > *v0.23.0* 62 | > - Add manual refresh option to update menu head information 63 | > - Fix issue [#43](https://github.com/neuralpain/qbactivator/issues/43) where `qba-22` ignored local available POS installers 64 | > - Minor improvements 65 | > 66 | > *v0.22.0* 67 | > - Add new Troubleshooting menu 68 | > - Add option `Lv3` in troubleshooting to potentially fix "Invalid Product Code" error 69 | > - Add 16 more licenses for each version of POS, a total of 64 new licenses; available for client activation 70 | > - Add links to qbactivator wiki, etc. in Troubleshooting Menu 71 | > - Add indicators for installation & activation status 72 | > - Fix instructions not being exported before activation 73 | > - Fix edge-case loop error scenario when refusing to proceed to download an installer 74 | > - Enabled transcript log to trace errors encountered during the runtime of the activator 75 | > - Disabled bandwidth calculation 76 | > - Code refactoring, minor bug fixes and improvements 77 | 78 | ### Release Breakdown 79 | 80 | Each release of qbactivator comes with 3 packages: 81 | 82 | - **qbactivator-[version].zip**: the complete release which contains all the files necessary to activate the QuickBooks POS software **offline**. It also includes the LICENSE and README. 83 | - **qbactivator-[version].min.zip**: a lightweight release ZIP package (take note of the `.min` in the name) which excludes larger files that can be downloaded online, such as the patch file. It also includes the LICENSE and README. 84 | - **qbactivator-[version].cmd**: just the script file with no other files. 85 | 86 | All packages perform the same function as they are derived from a single script, merely packaged in different formats. The regular package is ideal for users who either lack internet access at a specific workstation or prefer to activate the software offline. 87 | 88 | On the other hand, the `.min.zip` package and the single `.cmd` file are smaller and more portable. These formats are perfect for users with fast internet connections who can quickly download the files, or for those who need a swift, on-the-go solution. 89 | 90 | > [!TIP] 91 | > If you encouner an issue where the QuickBooks installer performs a rollback during setup, this may be a driver issue. Download this [Visual C++ redistributable repack](https://github.com/abbodi1406/vcredist/releases/download/v0.82.0/VisualCppRedist_AIO_x86_x64.exe) and run it to install the Microsoft Visual C++ Redistributable packages for 2005-2022. 92 | > 93 | >Check for any updates to this repack [here](https://github.com/abbodi1406/vcredist/releases). 94 | 95 | ### Available QuickBooks POS Software from Intuit 96 | 97 | - [QuickBooks Point Of Sale V19 (2019) ⧉](https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2019/Latest/QuickBooksPOSV19.exe) 98 | - [QuickBooks Point Of Sale V18 (2018) ⧉](https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2018/Latest/QuickBooksPOSV18.exe) 99 | - [QuickBooks Point Of Sale V12 (2015) ⧉](https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2015/Latest/QuickBooksPOSV12.exe) 100 | - [QuickBooks Point Of Sale V11 (2013) ⧉](https://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2013/Latest/QuickBooksPOSV11.exe) 101 | 102 | > [!TIP] 103 | > Browse the QuickBooks [product download page](https://downloads.quickbooks.com/app/qbdt/products) for additional QuickBooks Desktop software that is not included here in this documentation. 104 | 105 | ## FAQs 106 | 107 | ### Is this activator safe? 108 | 109 | Yes, it is. 110 | 111 | ### Why should I use this? 112 | 113 | You don't have to, but it's the only activator that fully supports [all versions](#available-quickbooks-pos-software-from-intuit) of QuickBooks Point Of Sale. 114 | 115 | ### Where are the license keys? 116 | 117 | License keys are not provided to the user beforehand. `qbactivator` will automatically install the appropriate license keys for the version of QuickBooks Point of Sale being installed on the system. This is to ensure stability during activation and avoid any potential issues that may arise from using invalid or incorrect license keys. However, if you have your own license keys, you are able to use them with `qbactivator` through the "I have my own license" menu option. 118 | 119 | License keys are reviewed regularly to keep `qbactivator` functioning as intended. 120 | 121 | [Click to view more frequently asked questions][faqs] 122 | 123 | ## License 124 | 125 | ``` 126 | BSD 2-Clause License 127 | 128 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 129 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 130 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 131 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 132 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 133 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 134 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 135 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 136 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 137 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 138 | 139 | See LICENSE for details. 140 | ``` 141 | 142 | 143 | [wiki]: https://github.com/neuralpain/qbactivator/wiki 144 | [faqs]: https://github.com/neuralpain/qbactivator/wiki/FAQs 145 | [getstarted]: https://github.com/neuralpain/qbactivator/wiki#getting-started 146 | [update]: https://github.com/neuralpain/qbactivator/wiki#downloads--updates 147 | [instructions]: https://github.com/neuralpain/qbactivator/wiki/How-to-Use 148 | [download_cmd]: https://github.com/neuralpain/qbactivator/releases/latest/download/qbactivator-0.24.0.cmd 149 | [download_min]: https://github.com/neuralpain/qbactivator/releases/latest/download/qbactivator-0.24.0.min.zip 150 | [download]: https://github.com/neuralpain/qbactivator/releases/latest/download/qbactivator-0.24.0.zip 151 | [release]: https://github.com/neuralpain/qbactivator/releases/latest 152 | [powershell]: https://github.com/PowerShell/PowerShell/releases/latest 153 | [updatepowershell]: https://github.com/neuralpain/qbactivator/wiki/Updating-PowerShell 154 | [wikiwmf4]: https://github.com/neuralpain/qbactivator/wiki/Updating-PowerShell#3-windows-management-framework-40 155 | 156 | [issue_10]: https://github.com/neuralpain/qbactivator/issues/10#issuecomment-1416758671 157 | [issue_12]: https://github.com/neuralpain/qbactivator/issues/12#issuecomment-1478727716 158 | [issue_27]: https://github.com/neuralpain/qbactivator/issues/27#issuecomment-1913171241 159 | [issue_44]: https://github.com/neuralpain/qbactivator/issues/44 160 | 161 | -------------------------------------------------------------------------------- /assets/images/download_btn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /assets/logo/qbactivator_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /assets/logo/qbactivator_logo_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | --------------------------------------------------------------------------------