diff --git a/.github/actions/spelling/excludes.txt b/.github/actions/spelling/excludes.txt index 9962711a29..d09c921276 100644 --- a/.github/actions/spelling/excludes.txt +++ b/.github/actions/spelling/excludes.txt @@ -18,3 +18,6 @@ ^src/Valijson/ ^src/YamlCppLib/ ^\.github/ +^src/AppInstallerCLITests/TestData/InputNames.txt$ +^src/AppInstallerCLITests/TestData/InputPublishers.txt$ +^src/AppInstallerCLITests/TestData/NormalizationInitialIds.txt$ diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 9e0f0c7c38..537c02caf7 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -27,11 +27,14 @@ bitmask bkup blargle blogs +bomgar BOMs brk Buf +casemap casemappings cch +CDEF centralus certmgr certs @@ -54,6 +57,7 @@ cstdint ctc Ctx curated +CYRL deigh deleteifnotneeded dirs @@ -71,13 +75,18 @@ EXEHASH experimentalfeatures fd fintimes +Fixfor flargle foldc foldcase FOLDERID +ftp FULLWIDTH fuzzer gcpi +GES +GESMBH +GHS gity Globals google @@ -93,6 +102,7 @@ IHost IID IInstalled incosistencies +IName INET inor IPackage @@ -113,6 +123,7 @@ KF KNOWNFOLDERID ktf Langs +LATN ldcase lhs libyaml @@ -123,6 +134,8 @@ localhost LPBYTE LPWSTR LSTATUS +LTDA +MBH megamorf memcpy MMmmbbbb @@ -134,6 +147,7 @@ MSIHASH MSIXHASH msstore multimap +mx mycustom myinstalldir mylog @@ -142,6 +156,7 @@ mysilentwithprogress mytool Newtonsoft NOEXPAND +normer nuffing nullopt objbase @@ -166,14 +181,17 @@ pz qb qword readonly +regexes REGSAM REINSTALLMODE rhs +roblox rosoft rowids RRF rrr rzkzqaqjwj +SARL schematab sddl seof @@ -187,13 +205,16 @@ sortof spamming SPAPI Srinivasan +SRL srs Standalone startswith strtoull subdir subkey +superstring suppy +swervy sysrefcomp Tagit temppath @@ -204,6 +225,8 @@ tombstoned transitioning UCase ucasemap +UChars +uec uild uintptr Uninitialize @@ -213,7 +236,9 @@ uninstallprevious uninstalls unparsable UNSCOPED +UParse UPSERT +URIs URLZONE userfilesetting usersettingstest @@ -221,11 +246,15 @@ USHORT Utils UWP vamus +VERSI +VERSIE vns +vy wcslen webpages Webserver website +WERSJA wesome windir windowsdeveloper @@ -233,7 +262,10 @@ winerror wingetdev winreg withstarts +wn +wsv Workflows wto Wunused WZDNCRFJ +zy diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt index 3653b13b33..bc16ffa049 100644 --- a/.github/actions/spelling/patterns.txt +++ b/.github/actions/spelling/patterns.txt @@ -18,3 +18,5 @@ data:[a-zA-Z=;,/0-9+-]+ El proyecto .* diferentes # Package family names \b[-.A-Za-z0-9]+_[a-z0-9]{13}\b +# Locales for name normalization +\b\p{Lu}{2,3}(?:-(?:CANS|CYRL|LATN|MONG))?-\p{Lu}{2}(?![A-Z])(?:-VALENCIA)?\b diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj index fc733cf476..251385568a 100644 --- a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj +++ b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj @@ -185,8 +185,10 @@ + + @@ -432,6 +434,15 @@ true + + true + + + true + + + true + diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters index 64bc5e2ff0..858f4f4700 100644 --- a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters +++ b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters @@ -110,6 +110,12 @@ Source Files + + Source Files + + + Source Files + @@ -333,5 +339,14 @@ TestData + + TestData + + + TestData + + + TestData + \ No newline at end of file diff --git a/src/AppInstallerCLITests/NameNormalization.cpp b/src/AppInstallerCLITests/NameNormalization.cpp new file mode 100644 index 0000000000..5e77185003 --- /dev/null +++ b/src/AppInstallerCLITests/NameNormalization.cpp @@ -0,0 +1,133 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "TestCommon.h" +#include + +using namespace std::string_view_literals; +using namespace AppInstaller::Utility; + + +// This skipped test case can be used to update the test file. +// It writes back to the output content location, so you must manually +// copy the file(s) back to the git managed location to update. +TEST_CASE("NameNorm_Update_Database_Initial", "[.]") +{ + std::ifstream namesStream(TestCommon::TestDataFile("InputNames.txt")); + REQUIRE(namesStream); + std::ifstream publishersStream(TestCommon::TestDataFile("InputPublishers.txt")); + REQUIRE(publishersStream); + std::ofstream resultsStream(TestCommon::TestDataFile("NormalizationInitialIdsUpdate.txt"), std::ofstream::out | std::ofstream::trunc | std::ofstream::binary); + REQUIRE(resultsStream); + + // Far larger than any one value; hopefully + char name[4096]{}; + char publisher[4096]{}; + + NameNormalizer normer(NormalizationVersion::Initial); + + for (;;) + { + namesStream.getline(name, ARRAYSIZE(name)); + publishersStream.getline(publisher, ARRAYSIZE(publisher)); + + if (namesStream || publishersStream) + { + REQUIRE(namesStream); + REQUIRE(publishersStream); + + INFO("Name[" << name << "], Publisher[" << publisher << "]"); + + auto normalized = normer.Normalize(name, publisher); + + std::string normalizedId = normalized.Publisher(); + normalizedId += '.'; + normalizedId += normalized.Name(); + + resultsStream << normalizedId << std::endl; + REQUIRE(resultsStream); + } + else + { + break; + } + } +} + +// If this test is failing, either changes to winget code or the ICU binaries have caused it. +// This will impact the functionality of the PreIndexedPackageSource, as it is the primary +// mechanism used to cross reference packages installed outside of winget with those in the +// source. +TEST_CASE("NameNorm_Database_Initial", "[name_norm]") +{ + std::ifstream namesStream(TestCommon::TestDataFile("InputNames.txt")); + REQUIRE(namesStream); + std::ifstream publishersStream(TestCommon::TestDataFile("InputPublishers.txt")); + REQUIRE(publishersStream); + std::ifstream resultsStream(TestCommon::TestDataFile("NormalizationInitialIds.txt")); + REQUIRE(resultsStream); + + // Far larger than any one value; hopefully + char name[4096]{}; + char publisher[4096]{}; + char expectedId[4096]{}; + + NameNormalizer normer(NormalizationVersion::Initial); + + for (;;) + { + namesStream.getline(name, ARRAYSIZE(name)); + publishersStream.getline(publisher, ARRAYSIZE(publisher)); + resultsStream.getline(expectedId, ARRAYSIZE(expectedId)); + + if (namesStream || publishersStream || resultsStream) + { + REQUIRE(namesStream); + REQUIRE(publishersStream); + REQUIRE(resultsStream); + + INFO("Name[" << name << "], Publisher[" << publisher << "]"); + + auto normalized = normer.Normalize(name, publisher); + + std::string normalizedId = normalized.Publisher(); + normalizedId += '.'; + normalizedId += normalized.Name(); + + REQUIRE(expectedId == normalizedId); + } + else + { + break; + } + } +} + +TEST_CASE("NameNorm_Architecture", "[name_norm]") +{ + NameNormalizer normer(NormalizationVersion::Initial); + + REQUIRE(normer.Normalize("Name", {}).Architecture() == Architecture::Unknown); + REQUIRE(normer.Normalize("Name x86", {}).Architecture() == Architecture::X86); + REQUIRE(normer.Normalize("Name x86_64", {}).Architecture() == Architecture::X64); + REQUIRE(normer.Normalize("Name (64 bit)", {}).Architecture() == Architecture::X64); + REQUIRE(normer.Normalize("Name 32/64 bit", {}).Architecture() == Architecture::Unknown); + REQUIRE(normer.Normalize("Fox86", {}).Architecture() == Architecture::Unknown); +} + +TEST_CASE("NameNorm_Locale", "[name_norm]") +{ + NameNormalizer normer(NormalizationVersion::Initial); + + REQUIRE(normer.Normalize("Name", {}).Locale() == ""); + REQUIRE(normer.Normalize("Name en-US", {}).Locale() == "en-us"); + REQUIRE(normer.Normalize("Name (es-mx)", {}).Locale() == "es-mx"); + REQUIRE(normer.Normalize("Names-mx", {}).Locale() == ""); +} + +TEST_CASE("NameNorm_KBNumbers", "[name_norm]") +{ + NameNormalizer normer(NormalizationVersion::Initial); + + REQUIRE(normer.Normalize("Fix for (KB42)", {}).Name() == "FixforKB42"); +} diff --git a/src/AppInstallerCLITests/Regex.cpp b/src/AppInstallerCLITests/Regex.cpp new file mode 100644 index 0000000000..974c800682 --- /dev/null +++ b/src/AppInstallerCLITests/Regex.cpp @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "TestCommon.h" +#include +#include + +using namespace std::string_view_literals; +using namespace AppInstaller::Regex; + + +TEST_CASE("Regex_Construction", "[regex]") +{ + Expression empty; + REQUIRE(!empty); + + Expression lowerVowels("(a|e|i|o|u)"); + REQUIRE(lowerVowels); + + // Ensure functionality to later verify against copy + REQUIRE(lowerVowels.IsMatch(L"a")); + REQUIRE(!lowerVowels.IsMatch(L"b")); + + Expression copy = lowerVowels; + REQUIRE(copy); + + // Ensure that the copy can also work + REQUIRE(lowerVowels.IsMatch(L"a")); + REQUIRE(copy.IsMatch(L"a")); + + REQUIRE(!lowerVowels.IsMatch(L"b")); + REQUIRE(!copy.IsMatch(L"b")); + + Expression moved = std::move(copy); + REQUIRE(moved); + + REQUIRE(moved.IsMatch(L"a")); + REQUIRE(!moved.IsMatch(L"b")); +} + +TEST_CASE("Regex_IsMatch", "[regex]") +{ + Expression ArchitectureX32{ R"((X32|X86)(?=\P{Nd}|$)(?:\sEDITION)?)", Options::CaseInsensitive }; + + REQUIRE(ArchitectureX32.IsMatch(L"X32")); + REQUIRE(ArchitectureX32.IsMatch(L"X86 edition")); + + REQUIRE(!ArchitectureX32.IsMatch(L"Not a match")); + REQUIRE(!ArchitectureX32.IsMatch(L"X86 editions")); +} + +TEST_CASE("Regex_Replace", "[regex]") +{ + Expression test{ R"((b|d\s|vy))" }; + REQUIRE(test.Replace(L"The bright and swervy", {}) == std::wstring{ L"The right answer" }); + + Expression vowels{ "(a|e|i|o|u)", Options::CaseInsensitive }; + REQUIRE(vowels.Replace(L"The QUICK brown fox jumped over the lazy dog.", L"[$0]") == std::wstring{ L"Th[e] Q[U][I]CK br[o]wn f[o]x j[u]mp[e]d [o]v[e]r th[e] l[a]zy d[o]g." }); +} + +TEST_CASE("Regex_ForEach", "[regex]") +{ + std::wstring input = L"The words in the Sentence but no more"; + std::vector expected = { L"The", L"words", L"in", L"the", L"Sentence" }; + + Expression test{ R"(\S+)" }; + + size_t i = 0; + test.ForEach(input, + [&](bool isMatch, std::wstring_view text) + { + if (!isMatch) + { + REQUIRE(text == L" "); + return true; + } + else + { + REQUIRE(i < expected.size()); + REQUIRE(text == expected[i]); + ++i; + + return i < expected.size(); + } + }); +} diff --git a/src/AppInstallerCLITests/TestData/InputNames.txt b/src/AppInstallerCLITests/TestData/InputNames.txt new file mode 100644 index 0000000000..3d33d50fef --- /dev/null +++ b/src/AppInstallerCLITests/TestData/InputNames.txt @@ -0,0 +1,1137 @@ +0 A.D. +010 Editor 11.0 (64-bit) +360安全卫士 +360杀毒 +4K Slideshow Maker 1.8 +4K Stogram +4K Video Downloader +4K Video Downloader 4.12 +4K Video to MP3 +4K YouTube to MP3 3.12 +7-Zip 16.04 (x64 edition) +7-Zip 19.00 (x64 edition) +7-Zip 20.02 alpha (x64) +7-Zip ZS 19.00 ZS v1.4.5 R2 (x64) +AWS Command Line Interface +AWS Command Line Interface v2 +AWS SAM Command Line Interface +AXIS Camera Station 5.33 +AbaClient +Accessibility Insights For Windows v1.1 +Active Directory Authentication Library for SQL Server +Adobe Acrobat Reader DC - Czech +Adobe Acrobat Reader DC +Adobe Acrobat Reader DC MUI +AdoptOpenJDK JDK with Hotspot 11.0.7.10 (x64) +AdoptOpenJDK JDK with Hotspot 11.0.8.10 (x64) +AdoptOpenJDK JDK with Hotspot 14.0.1.7 (x64) +AdoptOpenJDK JDK with Hotspot 14.0.2.12 (x64) +AdoptOpenJDK JDK with Hotspot 15.0.0.36 (x64) +AdoptOpenJDK JDK with Hotspot 8.0.252.09 (x64) +AdoptOpenJDK JDK with Hotspot 8.0.265.01 (x64) +Advanced IP Scanner 2.5 +Advanced Log Viewer 8.1.0 +Advanced Port Scanner 2.5 +AdvancedRestClient 15.0.5 +Aegisub 8975-master-8d77da3 +Aegisub r8942 +AeroZoom 4.0 beta 2 +Alacritty +Alchemy Beta x64 +Algodoo v2.1.0 +AltDrag +Amazon Chime +Amazon Corretto (x64) +Amazon Corretto 8 (x64) +Amazon WorkSpaces +Anaconda3 2020.07 (Python 3.8.3 64-bit) +Angry IP Scanner +AntiMicro +AppGet +Appium 1.15.1 +Appium 1.18.3 +Arduino +Armagetron Advanced 0.2.8.3.5 +Artha 1.0.3.0 +AssaultCube 1.2.0.2 +Audacity 2.4.2 +AuthPass version 1.7.9_1605 +Auto Dark Mode +AutoHotkey 1.1.32.00 +AutoHotkey 1.1.33.02 +Autopsy +AviSynth 2.6 +Avro Keyboard 5.6.0 +Aya +Azure Cosmos DB Emulator +Azure Data Studio (User) +Azure Functions Core Tools - 3.0.2534 (x64) +Azure IoT Explorer (preview) +Azure IoT explorer +BCUninstaller +BITS Manager +BKChem-0.13.0 +BOINC +BPBible 0.5.3.1 +Backup and Sync from Google +Barrier 2.3.2-snapshot +Barrier 2.3.3-release +Beaker Browser 0.8.10 +Beats winlogbeat 7.7.0 (x86_64) +Beats winlogbeat 7.9.2 (x86_64) +BeeBEEP 5.8.2 +Beeftext +Betaflight Configurator +Beyond Compare 4 +Beyond Compare 4.3.6 +Beyond Compare 4.3.7 +BiglyBT +BitPay version 4.8.1 +Bitwarden +BleachBit 4.0.0.1628 (current user) +Blender +BlueJeans +Bob the Hamster VGA 2008-01-23 +Bonjour +Borderless Gaming +Bot Framework Composer 1.0.0 +Bot Framework Composer 1.0.1 +Bot Framework Composer 1.0.2 +Bot Framework Composer 1.1.1 +Bot Framework Emulator 4.10.0 +Bot Framework Emulator 4.8.1 +Bot Framework Emulator 4.9.0 +Brackets +Brave +Brave Nightly +Bulk Rename Utility 3.3.1.0 (64-bit) +Buttercup 1.19.0 +Buttercup 1.20.0 +C-Dogs SDL +CCEnhancer version 4.5.6 +CCleaner +CDBurnerXP (64 bit) +CMake +CORSAIR iCUE Software +CPUID CPU-Z 1.92 +CPUID CPU-Z 1.93 +CPUID CPU-Z 1.94 +CPUID HWMonitor 1.41 +CPUID HWMonitor 1.42 +Cacher +CaesiumPH 0.9.5 +Camtasia 2019 +Camtasia 2020 +Caprine 2.47.0 +Caprine 2.48.0 +Caption 2.0.1 (only current user) +Captura v8.0.0 +CemUI 2.3.3 (only current user) +Cerebro 0.3.2 +CertAid for Windows +CertDump +Certify The Web version 5.1.5 +ChMac 2.0 +ChefDK v4.11.0 +ChemAxon ChemCurator +ChemAxon Markush Editor +ChemAxon Marvin Suite 20.13.0 +ChemAxon Marvin Suite 20.19.0 +Chromium +Circuit Diagram version 3.0 +Circuit Diagram version 3.1 +Cisco Webex Meetings +Citycraft Launcher 1.9.9 +ClamWin Free Antivirus 0.99.4 +Clash for Windows 0.11.1 +Clash for Windows 0.11.6 +Clash for Windows 0.11.8 +Clash for Windows 0.9.11 +ClassIn +Clementine +Clink v0.4.9 +Cloudflare WARP +CodeBlocks +CodeLite +Coffee +Colobot: Gold Edition alpha-0.1.12 +Color Cop 5.4.3 +Colorpicker 2.0.3 +ConEmu 201011.x64 +Concept2 Utility +ConfigMgr 2012 Toolkit R2 +Contasimple Desktop 3.1.0 +Core Temp 1.16 +Couchbase Server 6.5.1-6299 Community Edition +Couchbase Server 6.5.1-6299 Enterprise Edition +Cozy Drive 3.20.0 +Cppcheck x64 2.0 +Crypter 4.0.0 +Cryptomator +CrystalDiskInfo 8.6.1 +CrystalDiskInfo 8.6.2 +CrystalDiskInfo 8.6.2 Kurei Kei Edition +CrystalDiskInfo 8.6.2 Shizuku Edition +CrystalDiskInfo 8.7.0 +CrystalDiskInfo 8.8.1 +CrystalDiskInfo 8.8.1 Kurei Kei Edition +CrystalDiskInfo 8.8.1 Shizuku Edition +CrystalDiskInfo 8.8.5 +CrystalDiskInfo 8.8.9 +CrystalDiskInfo 8.8.9 Kurei Kei Edition +CrystalDiskInfo 8.8.9 Shizuku Edition +CrystalDiskInfo 8_8_2 +CrystalDiskInfo 8_8_2 Kurei Kei Edition +CrystalDiskInfo 8_8_2 Shizuku Edition +CrystalDiskMark 7.0.0h +CrystalDiskMark 7.0.0h Shizuku Edition +CubicSDR 0.2.5 Installer +CutePDF Writer +Cyberduck +DB Browser for SQLite +DBeaver 7.0.5 (current user) +DBeaver 7.1.0 (current user) +DBeaver 7.1.2 (current user) +DBeaver 7.1.3 (current user) +DBeaver 7.1.4 (current user) +DBeaver 7.2.0 (current user) +DBeaver 7.2.1 (current user) +DBeaver 7.2.2 (current user) +DBeaver 7.2.3 (current user) +DJI Assistant 2 (DJI FPV series) version V2.0.2.11 +DJI Assistant 2 For Aeroscope version V2.0.1.3 +DJI Assistant 2 For Autopilot version V2.0.3.7 +DJI Assistant 2 For Battery Station version V2.0.1.9 +DJI Assistant 2 For MG version V2.0.18.1 +DJI Assistant 2 For Matrice version V2.0.13.2 +DJI Assistant 2 For Mavic version V2.0.14.1 +DJI Assistant 2 For Phantom version V2.0.10.4 +Dave Gnukem +DeepVocalToolBox_beta_1.1.6 version beta_1.1.6 +DeepVocal_beta_1.1.6 version beta_1.1.6 +Deezer 4.19.20 +DefaultAudio +Defraggler +Dell Command | Update +Dell Update +Dev-C++ +Dimension 4 v5.31 +Discord Media Loader version 1.3.0.0 +Discord Media Loader version 1.4.0.0 +Ditto +Dixa +DjVuLibre DjView 3.5.27+4.11 +DockStation 1.5.1 +Docker Desktop +Dokan Library 1.3.0.1000 (x64) +Dokan Library 1.4.0.1000 (x64) +Dolphin +Doomsday 2.2.2.3313 +Dopamine +Doxie 2.12.2 +Dropbox +EGR-SafenetActivation +EGR-ShellExtension +EagleGet version 2.1.5.10 +EagleGet version 2.1.6.70 +EasyConnect +EditPlus (64 bit) +EduMIPS64 +Elasticsearch 7.9.2 +Elgato Stream Deck +Empoche 0.4.0 +Empoche 0.4.3 +Encrypto version 1.0.1 +EnglishizeCmd 2.0 +Enpass +Eraser 6.2.0.2986 +Eraser 6.2.0.2988 +Eraser 6.2.0.2989 +Eraser 6.2.0.2990 +Esteem 2.2.7 +Ethereum - Geth - Official Go implementation of the Ethereum protocol +Evernote v. 6.21.2 +Evernote v. 6.24.2 +Everything 1.4.1.969 (x64) +Everything 1.4.1.986 (x64) +Everything 1.4.1.988 (x64) +Everything 1.4.1.988 Lite (x64) +Everything 1.4.1.992 (x64) +ExpressVPN +Expresso +Extreme TuxRacer 0.8 (x64) +Far Manager 3 x64 +FastCopy +FastStone Capture 9.3 +FastStone Image Viewer 7.5 +Fedora Media Writer +Ferdi 5.5.0 +Fiddler Everywhere 1.0.2 +Fiddler Everywhere 1.1.0 +Fiddler Everywhere 1.1.0-insiders +Fiddler Everywhere 1.1.0-internal +Fiddler Everywhere 1.1.1 +Fiddler Everywhere 1.1.1-insiders +Fiddler Everywhere 1.1.1-internal +File Converter (64 bit) +FileSeek 6.4 +FileZilla Client 3.47.0 +FileZilla Client 3.48.1 +FileZilla Client 3.49.1 +FileZilla Client 3.50.0 +FileZilla Client 3.51.0 +Firefox Developer Edition 77.0 (x64 en-US) +Firefox Developer Edition 78.0 (x64 en-US) +Firefox Developer Edition 80.0 (x64 en-US) +Firefox Developer Edition 82.0 (x64 en-US) +FlashFXP 5 +FlightGear v2018.3.5 +FontBase 2.11.3 +FontForge version 14-03-2020 +FormatFactory 5.3.0.1 +FormatFactory 5.4.5.0 +Foxit PhantomPDF +Foxit Reader +Franz 5.5.0 +FreeCommander XE +FreeMat +GIMP 2.10.0 +GIMP 2.10.10 +GIMP 2.10.14 +GIMP 2.10.16 +GIMP 2.10.18 +GIMP 2.10.20 +GIMP 2.10.6 +GIMP 2.10.8 +GNU Arm Embedded Toolchain 9-2020-q2-update 9 2020 (remove only) +GNU Midnight Commander version 4.8.24 (build: 20200521-217) +GNU Privacy Guard +GNURadio-3.7 +GOG GALAXY +GPL Ghostscript +GSview 5.0 +Garmin Express +Gauge 1.0.6 +Gauge 1.1.1 +Geany 1.36 +Geekbench 5 +Gephi 0.9.2 +GetDiz +Git Extensions 3.3.1.7897 +Git Extensions 3.4.1.9675 +Git Extensions 3.4.3.9999 +Git LFS version 2.11.0 +Git version 2.24.1.2 +Git version 2.25.1 +Git version 2.26.2 +Git version 2.27.0 +Git version 2.28.0 +Git version 2.29.0 +GitHub CLI +GitHub Desktop Machine-Wide Installer +GitHubReleaseNotes +Gitter +Glimpse 0.1.2 +Glimpse 0.2.0 (64-bit) +Glimpse 0.2.0 +GnuCash 3.9 +GnuCash 4.1 +GnuWin32: Grep-2.5.4 +GnuWin32: Make-3.81 +GnuWin32: Wget-1.11.4-1 +GnuWin32: Zip-3.0 +Go Programming Language amd64 go1.13.12 +Go Programming Language amd64 go1.13.13 +Go Programming Language amd64 go1.13.14 +Go Programming Language amd64 go1.13.15 +Go Programming Language amd64 go1.14.10 +Go Programming Language amd64 go1.14.3 +Go Programming Language amd64 go1.14.4 +Go Programming Language amd64 go1.14.5 +Go Programming Language amd64 go1.14.6 +Go Programming Language amd64 go1.14.7 +Go Programming Language amd64 go1.14.8 +Go Programming Language amd64 go1.14.9 +Go Programming Language amd64 go1.15 +Go Programming Language amd64 go1.15.1 +Go Programming Language amd64 go1.15.2 +Go Programming Language amd64 go1.15.3 +Go Programming Language amd64 go1.15beta1 +GoldWave v6.52 +Google Chrome +Google Cloud SDK +Google Earth Pro +Gpg4win (3.1.11) +Gpg4win (3.1.13) +GrafanaEnterprise +GrafanaOSS +Grammarly for Microsoft® Office Suite +GrampsAIO64 +GraphQL Playground 1.8.10 +GraphiQL 0.7.2 +Graphviz +Greenshot 1.2.10.6 +Grid 1.6.2 +Grindstone 4 +HHD Software Free Hex Editor Neo 6.44 +HM NIS Edit 2.0.3 +HP Cloud Recovery Tool +HUAWEI Cloud +HWiNFO64 Version 6.26 +HWiNFO64 Version 6.28 +HWiNFO64 Version 6.30 +HWiNFO64 Version 6.32 +HandyWinGet +Harmony 0.9.1 (only current user) +HashTab 5.2.0.14 +HashTab 6.0.0.34 +HeavyLoad V3.6 (64 bit) +Hedgewars +HeidiSQL 11.0.0.5919 +HeidiSQL 11.0.0.5995 +HeidiSQL 11.0.0.5997 +HeidiSQL 11.0.0.6000 +HeidiSQL 11.0.0.6057 +Helix Core Apps +HelpNDoc 6.9.0.577 Personal Edition +HexChat +Hosts File Editor +Hover +HttpMaster Express Edition 4.7.0 +HttpMaster Express Edition 4.7.1 +HttpMaster Express Edition 4.7.2 +HttpMaster Express Edition 4.7.3 +HttpMaster Professional Edition 4.7.1 +HttpMaster Professional Edition 4.7.2 +HttpMaster Professional Edition 4.7.3 +Huawei QuickApp IDE +Hyne Timber Design 7.5.14.0 +Hyperspace Desktop 1.1.3 +IAP Desktop +IDA Freeware 7.0 +IO Ninja 3 +IPFilter 3.0.2.9-beta +IRCCloud 0.15.0 +IZArc 4.4 +ImageGlass +Inkscape +Inno Setup version 6.0.4 +Inno Setup version 6.0.5 +InternetOff 3.0, 32\64 bit edition +Intuiter 0.5.0 +IrfanView 4.54 (64-bit) +IronPython 2.7.10 +IronPython 2.7.9 +IsWiX +IsoBuster 4.6 +JChem .NET API 20.19.0.482 +JabRef +Jackett +Jami +Java 8 Update 251 (64-bit) +Java 8 Update 261 (64-bit) +JetBrains Toolbox +Jitsi Meet 2.3.1 +Jitsi Meet 2.4.1 +Joplin 1.0.201 +Joplin 1.0.216 +Joplin 1.0.233 +Julia 1.4.1 +Julia 1.4.2 +Julia 1.5.1 +K-Lite Codec Pack 15.7.0 Standard +K-Lite Mega Codec Pack 15.7.0 +KKBOX +Kaku 2.0.2 +KeePass Password Safe 2.44 +KeePass Password Safe 2.45 +KeePass Password Safe 2.46 +KeePassXC +KeeWeb +Keybase +KiCad 5.1.5_1 +KiCad 5.1.6_1 +KiCad 5.1.7_1 +Krisp +Krita (x64) 4.3.0 +L'Math version r1.6 +LBRY 0.45.1 +LBRY 0.45.2 +LBRY 0.46.2 +LBRY 0.47.0 +LBRY 0.47.1 +LINE +LINQPad 6 +LLVM +LMMS 1.2.1 +LMMS 1.2.2 +LOVE 11.3 +Laragon 4.0.15 +LastPass (uninstall only) +Lazarus 2.0.8 +League of Legends +Lenovo Migration Assistant +Lenovo System Update +Lens 3.5.1 +Leonflix 0.7.0 +Liberica JDK 11 (64-bit) +Liberica JDK 11 Full (64-bit) +Liberica JDK 14 (64-bit) +Liberica JDK 14 Full (64-bit) +Liberica JDK 15 (64-bit) +Liberica JDK 15 Full (64-bit) +Liberica JDK 8 (64-bit) +Liberica JDK 8 Full (64-bit) +LibreCAD +LibreOffice 7.0.1.2 +LibreOffice 7.0.2.2 +Lidarr version 0.7.1 +LightBulb 2.0 +LightBulb 2.2 +Lightscreen version 2.4 +Linrad-04.14a version 04.14a +Lisk Hub 1.22.0 +Listen1 2.13.0 +Listen1 2.5.2 +Local 5.5.3 +LockHunter 3.3, 32/64 bit +LogFusion 6.4 +LogFusion 6.4.1 +Logitech Gaming Software 9.02 +Loom 0.37.2 +LyX 2.3.4.4 +LyX 2.3.5.2 +MCX Studio version nightlybuild +MCX Studio version v2020 +MKVToolNix 46.0.0 (64-bit) +MKVToolNix 47.0.0 (64-bit) +MKVToolNix 48.0.0 (64-bit) +MKVToolNix 49.0.0 (64-bit) +MKVToolNix 50.0.0 (64-bit) +MPC-HC 1.7.13 (64-bit) +MPC-HC 1.9.5 (64-bit) +MPC-HC 1.9.6 (64-bit) +MQTT Explorer 0.3.5 +MSIX Core +MX5 +MY.GAMES GameCenter +MacType +MailWasher +MailWasherPro +Majsoul Plus 2.0.0 +MakeMKV v1.15.3 +Malwarebytes version 4.2.1.89 +Marble version 2.2.0 +MariaDB 10.5 (x64) +Mark Text 0.16.2 +Markdown Monster 1.22.8.0 +Markdown Monster 1.23.0.0 +Markdown Monster 1.23.12.0 +Markdown Monster 1.23.14.0 +Markdown Monster 1.24.12.0 +Markdown Outlook +Master Packager +Mattermost +MediaInfo 20.09 +MediaInfo-CLI 20.09 +MediaMonkey 4.1 +Meld +Memurai Developer +Microsoft .NET Core SDK 3.1.202 (x64) +Microsoft .NET Core SDK 3.1.300 (x64) +Microsoft .NET Core SDK 3.1.301 (x64) +Microsoft .NET Core SDK 3.1.302 (x64) +Microsoft .NET Core SDK 3.1.401 (x64) +Microsoft .NET Core SDK 3.1.402 (x64) +Microsoft .NET Framework 4.5 Multi-Targeting Pack +Microsoft .NET Framework 4.5.1 Multi-Targeting Pack (ENU) +Microsoft .NET Framework 4.5.1 Multi-Targeting Pack +Microsoft .NET Framework 4.5.1 SDK +Microsoft .NET Framework 4.5.2 Multi-Targeting Pack (ENU) +Microsoft .NET Framework 4.5.2 Multi-Targeting Pack +Microsoft .NET Framework 4.7.2 SDK +Microsoft .NET Framework 4.7.2 Targeting Pack +Microsoft .NET Framework 4.8 SDK +Microsoft .NET Framework 4.8 Targeting Pack +Microsoft .NET SDK 5.0.100-preview.5.20279.10 (x64) +Microsoft .NET SDK 5.0.100-preview.8.20417.9 (x64) +Microsoft .NET SDK 5.0.100-rc.1.20452.10 (x64) +Microsoft .NET SDK 5.0.100-rc.2.20479.15 (x64) +Microsoft Azure CLI +Microsoft Azure Storage Emulator - v5.10 +Microsoft Azure Storage Explorer version 1.14.0 +Microsoft Azure Storage Explorer version 1.15.1 +Microsoft Deployment Toolkit (6.3.8456.1000) +Microsoft Edge +Microsoft Edge Beta +Microsoft Edge Dev +Microsoft Garage Mouse without Borders +Microsoft Help Viewer 2.2 +Microsoft Help Viewer 2.3 +Microsoft MPI (10.1.12498.16) +Microsoft MPI (10.1.12498.18) +Microsoft MPI SDK (10.1.12498.18) +Microsoft ODBC Driver 13 for SQL Server +Microsoft ODBC Driver 17 for SQL Server +Microsoft OLE DB Driver for SQL Server +Microsoft R Open 3.5.3 +Microsoft R Open 4.0.2 +Microsoft SQL Server 2012 Native Client +Microsoft SQL Server 2014 Management Objects +Microsoft SQL Server 2016 +Microsoft SQL Server 2016 Policies +Microsoft SQL Server 2016 T-SQL Language Service +Microsoft SQL Server 2016 T-SQL ScriptDom +Microsoft SQL Server 2017 +Microsoft SQL Server 2017 Policies +Microsoft SQL Server 2017 T-SQL Language Service +Microsoft SQL Server Data-Tier Application Framework (x86) +Microsoft SQL Server Management Studio - 16.5.3 +Microsoft SQL Server Management Studio - 17.9.1 +Microsoft SQL Server Management Studio - 18.5 +Microsoft SQL Server Management Studio - 18.5.1 +Microsoft SQL Server Management Studio - 18.6 +Microsoft Small Basic v1.2 +Microsoft System CLR Types for SQL Server 2014 +Microsoft System CLR Types for SQL Server 2016 +Microsoft System CLR Types for SQL Server 2017 +Microsoft Visio Viewer 2016 +Microsoft Visual Studio 2010 Tools for Office Runtime (x64) +Microsoft Visual Studio 2015 Shell (Isolated) +Microsoft Visual Studio Code (User) +Microsoft Visual Studio Code Insiders (User) +Microsoft Visual Studio Tools for Applications 2015 +Microsoft Visual Studio Tools for Applications 2015 Language Support +Microsoft Visual Studio Tools for Applications 2017 +Microsoft Web Platform Installer 5.1 +Miniconda3 4.7.12 (Python 3.7.4 64-bit) +Miniconda3 py37_4.8.3 (Python 3.7.7 64-bit) +MongoDB 4.2.8 2008R2Plus SSL (64 bit) +Mono for Windows (x64) +MonoGame SDK +Moonlight Game Streaming Client +Motrix 1.5.10 +Motrix 1.5.15 +Mozilla Firefox 68.8.0 ESR (x64 en-US) +Mozilla Firefox 68.9.0 ESR (x64 en-US) +Mozilla Firefox 76.0.1 (x86 en-US) +Mozilla Firefox 77.0 (x64 en-US) +Mozilla Firefox 77.0.1 (x64 en-US) +Mozilla Firefox 78.0 ESR (x64 en-US) +Mozilla Firefox 78.0.1 (x64 en-US) +Mozilla Firefox 78.0.2 (x64 cs) +Mozilla Firefox 78.0.2 (x64 en-US) +Mozilla Firefox 78.1.0 ESR (x64 en-US) +Mozilla Firefox 78.4.0 ESR (x64 en-US) +Mozilla Firefox 79.0 (x64 en-US) +Mozilla Firefox 80.0 (x64 en-US) +Mozilla Firefox 80.0.1 (x64 en-US) +Mozilla Firefox 81.0 (x64 en-US) +Mozilla Firefox 81.0.1 (x64 en-US) +Mozilla Firefox 81.0.2 (x64 en-US) +Mozilla Firefox 82.0 (x64 en-US) +Mozilla Firefox 82.0.1 (x64 en-US) +Mozilla Firefox 82.0.1 (x64 es-MX) +Mozilla Firefox 82.0.2 (x64 en-US) +Mozilla Maintenance Service +Mozilla Thunderbird 68.10.0 (x64 en-US) +Mozilla Thunderbird 68.8.0 (x86 en-US) +Mozilla Thunderbird 68.9.0 (x64 en-US) +Mozilla Thunderbird 77.0 (x64 en-US) +Mozilla Thunderbird 78.0 (x64 cs) +Mozilla Thunderbird 78.0 (x64 en-US) +Mozilla Thunderbird 78.0.1 (x64 en-US) +Mozilla Thunderbird 78.1.0 (x64 en-US) +Mozilla Thunderbird 78.1.1 (x64 en-US) +Mozilla Thunderbird 78.3.2 (x64 en-US) +Mu +Mullvad VPN 2020.5.0 +Mullvad VPN 2020.6.0 +Multilingual App Toolkit 4.0 +Multipass +Mumble 1.3.1 +Mumble 1.3.2 +Mumble 1.3.3 +MuseScore 3 +Muta 2.1.02 +MyHarmony +MyPaint +MySQL Installer - Community +Mypal 28.14.2 (x64 en-US) +NBTExplorer +NSwagStudio +NVDA +NVIDIA NVIDIA RTX Voice Driver 1.0.0.2 +NVIDIA RTX Voice Application +NZXT CAM 4.10.1 +NZXT CAM 4.11.0 +NZXT CAM 4.12.0 +NZXT CAM 4.13.0 +NZXT CAM 4.8.0 +NZXT CAM 4.9.2 +Nelson-0.4.8.2662 (64 bits) +NeoLoad 7.3.0 +Netron 4.5.9 +Nitro Pro +Nmap 7.80 +NoSQLBooster for MongoDB 4.7.5 (only current user) +NoSQLBooster for MongoDB 5.2.12 +NoSQLBooster for MongoDB 6.1.8 +Node.js +Nodist +NordVPN +NordVPN +NordVPN network TAP +NordVPN network TUN +NoteHighlight2016 +Notepad2-mod 4.2.25.998 +Notion 2.0.8 +Notion 2.0.9 +Npcap 0.9982 +NullpoMino version 7.5 +Nullsoft Install System +OBS Studio +OHRRPGCE gorgonzola 20200502 +ONLYOFFICE Desktop Editors 5.6 (x64) +Octave 5.2.0 +OneNote Tagging Kit +Open Shop Channel Downloader version 1.2.9 +Open-Shell +OpenHashTab version 2.2.0 +OpenHashTab version 2.3.0 +OpenJDK 1.8.0_252-2-ojdkbuild +OpenJDK 11.0.7-1-ojdkbuild +OpenJDK 13.0.3-1-ojdkbuild +OpenJDK 14.0.1-1-ojdkbuild +OpenMPT 1.29 (64-Bit) +OpenOffice 4.1.7 +OpenRA +OpenSCAD (remove only) +OpenSSL (64-bit) +OpenShot Video Editor version 2.5.1 +OpenTTD 1.10.1 +OpenTTD 1.10.3 +OpenVPN 2.4.9-I601-Win10 +OpenVPN Configuration Generator x64 +OpenVPN Connect +Opera GX Stable 68.0.3618.142 +Opera GX Stable 68.0.3618.197 +Opera Stable 68.0.3618.63 +Opera Stable 69.0.3686.36 +Opera Stable 69.0.3686.77 +Opera Stable 70.0.3728.144 +Opera Stable 70.0.3728.95 +Opera Stable 71.0.3770.198 +Oracle VM VirtualBox 6.1.10 +Oracle VM VirtualBox 6.1.12 +Oracle VM VirtualBox 6.1.14 +Oracle VM VirtualBox 6.1.16 +OutSystems Development Environment 11 +PDF reDirect (remove only) +PDFsam Basic +PKU_Gateway 0.9.8 +PSPad editor +Packet Sender x64 +Pale Moon 28.10.0 (x64 en-US) +Pale Moon 28.9.3 (x64 en-US) +Pandoc 2.10.1 +Pandoc 2.11.0.2 +Pandoc 2.9.2.1 +Paradox Launcher +Paragon Backup & Recoveryâ„¢ 17 CE +Parsec +PasteIntoFile version 2.0 +PeaZip 7.2.1 (WIN64) +PeaZip 7.3.1 (WIN64) +Persepolis Download Manager version 3.2.0.0 +PhonerLite 2.84 +PhotoSync +PicPick +PicoTorrent +Planet Blupi +PlayStationâ„¢Now +Playnite +Plex +Plex Media Player +Plex Media Server +Plexamp 3.0.3 +Plexamp 3.1.0 +Plexamp 3.1.1 +PokerTH +Postbox 7.0.18 (x86 en-US) +PostgreSQL 12 +PostgreSQL 13 +PowerShell 7-preview-x64 +PowerShell 7-x64 +PowerShell Universal +PowerToys (Preview) +Primesieve version 7.5 +Private Internet Access +Progress Telerik Fiddler +Project My Screen App +ProtonVPN +ProtonVPNTap +PuTTY release 0.74 (64-bit) +Puppet +Puppet Agent (64-bit) +Puppet Bolt +Puppet Development Kit +Pure Data (64-bit) 0.50-2 +PyMODA version 1.1.0 +Python 2.7.18 +Python 3.7 PyAudio-0.2.11 +Python 3.7.7 (64-bit) +Python 3.8.1 (64-bit) +Python 3.8.3 (64-bit) +Python 3.8.4 (64-bit) +Python 3.8.5 (64-bit) +Python 3.8.6 (64-bit) +Python 3.9.0 (64-bit) +Python Launcher +QGIS 3.10.6 'A Coru +QGIS 3.12.3 'Bucuresti' +QGIS 3.14.0 'Pi' +QTextPad version 1.4 +Qalculate! +QtSpim +Quick Picture Viewer +QuickLook +Quicken +R for Windows 4.0.0 +R for Windows 4.0.2 +R for Windows 4.0.3 +RStudio +Rambox 0.7.5 +Rapid Environment Editor version 9.2.0.937 +Raspberry Pi Imager +RawTherapee version 5.8 +Reddit Wallpaper Changer +Reko decompiler for x86-64 +Remote Desktop Manager +Remote Desktop Manager Free +Remote Mouse version 3.015 +RenderDoc +Renode +ResponsivelyApp 0.1.5 +RetroShare +Revo Uninstaller 2.1.7 +Revo Uninstaller Pro 4.3.3 +Robo 3T 1.3.1 +Robo 3T 1.4.1 +Robo 3T 1.4.2 +Rocket.Chat 2.17.9 +RocketDock 1.3.5 +Rocks'n'Diamonds 4.1.4.1 +Rosi +Royal TS 5.02.60420.0 +Royal TS 5.03.60925.0 +Rtools 4.0 (4.0.0.28) +Ruby 2.7.1-1-x64 +Ruby 2.7.1-1-x64 with MSYS2 +Ruby 2.7.2-1-x64 +RunJS 1.10.1 +RunJS 1.11.0 +Rust 1.43 (MSVC 64-bit) +Rust 1.44 (GNU 64-bit) +Rust 1.44 (GNU) +Rust 1.44 (MSVC 64-bit) +Rust 1.44 (MSVC) +Rust 1.45 (GNU 64-bit) +Rust 1.45 (GNU) +Rust 1.45 (MSVC 64-bit) +Rust 1.45 (MSVC) +SIW 2020 v10.6.0915a Trial +SMPlayer 20.4.2 (x64) +SSHFS-Win 2020 (x64) +SVG Explorer Extension 0.1.1 +Samsung DeX +Satisfactory Mod Launcher 1.0.17 +Scratch Desktop 3.11.1 +ScreenToGif +Scribus 1.4.8 (64bit) +ScummVM 2.2.0 +Search Deflector +Sejda PDF Desktop +Seq +SharePoint Online Management Shell +ShareX +SharpKeys +Shotcut +Sigil 1.3.0 +Signal 1.34.1 +Signal 1.34.3 +Signal 1.34.4 +Signal 1.34.5 +Signal 1.36.1 +Signal 1.36.3 +Signal 1.37.2 +Simply Fortran 3 +SitdownMW +Skype version 8.60 +Skype version 8.64 +Skype version 8.65 +Slack Machine-Wide +Snagit 2020 +SnakeTail 64-bit v1.9.6.0 +Snoop +SoapUI 5.5.0 +Sonic Pi +Sonos +Sonos Controller +SoundSwitch 5.0.4.31153 +Sourcetree +SpeedCrunch +Spek +Standard Notes 3.4.1 +Steam +Steel Bank Common Lisp 2.0.0 (X86-64) +SteelSeries Engine 3.17.9 +Stellarium 0.20.1 +Stellarium 0.20.2 +Stellarium 0.20.3 +Strawberry Perl +Streamlabs OBS +Streamlabs OBS 0.23.2 +Streamlabs OBS 0.24.0 +Streamlink +Streamlink Twitch GUI +Stretchly 1.0.0 +Stretchly 1.1.0 +Stretchly 1.2.0 +Stride +Studio 2.0 version 2.0 +Sublime Merge +Sublime Text 3 +SumatraPDF +SuperCollider Version 3.11.0 +SuperTuxKart 1.1.0 - 3D open-source arcade racer with a variety characters, tracks, and modes to play +Surface Duo Emulator version 2020.806.2 +SyncTrayzor (x64) version 1.1.24.0 +System Explorer 7.0.0 +TAP-Windows 9.24.2 +Taiga +Tailscale +Tailscale IPN +Taisei Project +Taskade 3.1.1 +Taskade 3.2.0 +Td-agent v3.8.0 +Td-agent v4.0.1 +TeXstudio - TeXstudio is a fully featured LaTeX editor. +TeXworks 0.6.5 +TeamSpeak 3 Client +TechPowerUp GPU-Z +Telegram Desktop version 2.1.13 +Telegram Desktop version 2.1.20 +Telegram Desktop version 2.1.6 +Telegram Desktop version 2.2 +Telegram Desktop version 2.3 +Telegram Desktop version 2.3.1 +Telegram Desktop version 2.4.1 +Telegram Desktop version 2.4.3 +Telegram Desktop version 2.4.4 +Tera Term 4.105 +Terminus 1.0.117 +Terminus 1.0.119 +Terminus 1.0.120 +Termite +Tesseract-OCR - open source OCR engine +Texmaker 5.0.4 (64-bit) +Texnomic SecureDNS Terminal +Textify v1.8.2 +TickTick version 3.7.1.1 +TightVNC +TikzEdt 0.2.3 +Tiled +TmNationsForever +Toggl Desktop +Toggl Track +TortoiseGit 2.10.0.2 (64 bit) +TortoiseSVN 1.13.1.28686 (64 bit) +TortoiseSVN 1.14.0.28885 (64 bit) +TranslucentTB +Transmission 3.00 (bb6b5a062e) (x64) +Transmission Remote GUI 5.18 +TrayStatus 4.3 +TrayStatus 4.4 +TreeSize Free V4.4.2 +TreeSize V8.0.2 (64 bit) +Trelby +Trillian +TunnelBear +Tux Paint 0.9.23 +Tweeten +Twinkle Tray 1.12.2 +Twitch +TypeRefHasher +USB Safely Remove 6.3 +UXL Launcher Version 3.3.1.0 +UXL Launcher Version 4.0.0.0 +Ultimaker Cura +Ultimaker Cura 4.5 +Ultimaker Cura 4.6 +UltraVnc +Unchecky v1.2 +Unified Remote +Unity Hub 2.4.2 +Update for (KB2504637) +Update for Microsoft Visual Studio 2015 (KB3095681) +Uplay +Ut Video Codec Suite +VCV Rack +VLC media player 3.0.10 (64-bit) +VLC media player 3.0.11 (64-bit) +VLC media player 4.0.0 (64-bit) +VMware Horizon Client +VMware Player +VMware Workstation +VNC Server 6.0.0 +VNC Viewer 6.0.0 +VSCodium (User) +VSCodium +VcXsrv +Vim 8.2 (x64) +VirtViewer 9.0-256 (64-bit) +Vivaldi +Vortex +Vrew 0.4.18 +VulkanSDK 1.2.135.0 +Warzone 2100-3.4.0 +Waterfox Current 2020.05 (x64 en-US) +Waterfox Current 2020.09 (x64 en-US) +Waterfox Current 2020.10 (x64 en-US) +Wayk Now +WeakAuras Companion 3.0.1 +WeakAuras Companion 3.0.2 +WeakAuras Companion 3.0.3 +WeakAuras Companion 3.0.6 +Weka 3.8.4 +Win32DiskImager version 1.0.0 +WinCompose version 0.9.4 +WinDynamicDesktop version 3.4.1.0 +WinDynamicDesktop version 4.2.0.0 +WinDynamicDesktop version 4.3.1.0 +WinFsp 2020 +WinHTTrack Website Copier 3.49-2 (x64) +WinMerge 2.16.6.0 +WinRAR 5.90 (64-bit) +WinRAR 5.91 (64-bit) +WinSCP 5.17.7 +WinZip 24.0 +Winamp +Windows 10 Update Assistant +Windows Admin Center +Windows Assessment and Deployment Kit - Windows 10 +Windows Assessment and Deployment Kit Windows Preinstallation Environment Add-ons - Windows 10 +Windows Driver Kit - Windows 10.0.19041.1 +Windows Driver Package - Dynastream Innovations, Inc. ANT LibUSB Drivers (04/11/2012 1.2.40.201) +Windows Driver Package - Silicon Labs Software (DSI_SiUSBXp_3_1) USB (02/06/2007 3.1) +Windows SDK AddOn +Windows Software Development Kit - Windows 10.0.17763.132 +Windows Software Development Kit - Windows 10.0.18362.1 +Windows Software Development Kit - Windows 10.0.19041.1 +WireGuard +Wireshark 3.2.2 32-bit +Wireshark 3.2.4 64-bit +Wireshark 3.2.5 64-bit +Wireshark 3.2.7 64-bit +WizFile v2.06 +WizKey v1.5.0.8 +WizMouse v1.7.0.3 +WizTree v3.33 +WizTree v3.35 +WordPress.com 5.2.0 +WordPress.com 6.0.0 +WordPress.com 6.0.1 +WordPress.com 6.0.2 +Workrave 1.10.44 +Writage +X2Go Client for Windows +XAMPP +XCA +XMake build utility +XMind 10.2.1 +XnView 2.49.4 +XnViewMP 0.97.1 +Yarn +Yinxiang Biji v. 6.20.16 +Yinxiang Biji v. 6.21.10 +Yinxiang Biji v. 6.21.3 +Yinxiang Biji v. 6.21.4 +Yinxiang Biji v. 6.21.9 +YouTube Music Desktop App 1.11.0 +YubiKey Manager +Zentimo PRO 2.3 +ZeroTier One +Zettlr +Zint +Zoom +Zoom Outlook Plugin +Zotero +Zulip +Zulu 3.5.1 +Zygor Client Uninstaller +balenaEtcher 1.5.100 +balenaEtcher 1.5.101 +balenaEtcher 1.5.102 +balenaEtcher 1.5.106 +balenaEtcher 1.5.107 +balenaEtcher 1.5.109 +balenaEtcher 1.5.88 +balenaEtcher 1.5.95 +beatdrop 2.6.2 +bottom +butterflow-ui +calibre 64bit +copytranslator 9.1.0 +darktable +dnGREP 2.9.270 (x64) +draw.io 13.0.3 +dupeGuru 4.0.4 +eM Client +ebbflow +f.lux +ffftp +ghostwriter version 1.7.1 +gnuplot 5.2 patchlevel 8 +grepWin x64 +guinget version 0.1.0.1 +guinget version 0.1.1 +guinget version 0.1.2 +hide.me VPN 3.4.0 +hide.me VPN 3.4.1 +i2pd +iSEEK AnswerWorks English Runtime +iTunes +kdenlive +kdiff3 +mRemoteNG +maxima-5.43.2 +mpv.net version 5.4.8.0 +ndm 1.2.0 (only current user) +nexusfont 2.6 (ver 2.6.2.1870) +ownCloud +pCon.planner PRO +pandoc-plot 0.7.1.0 +pgAdmin 4 version 4.22 +pgAdmin 4 version 4.23 +pgAdmin 4 version 4.26 +pgAdmin 4 version 4.27 +qBittorrent 4.2.5 +qBittorrent 4.3.0 +qBittorrent 4.3.0.1 +remoteit 2.5.32 +remoteit 2.6.2 +sbt 1.3.8 +scilab-6.1.0 (64-bit) +sqlectron 1.31.0 +stretchly 0.21.1 +ueli 8.7.0 +ueli 8.8.1 +ueli 8.9.0 +xmoto 0.6.0 +xmoto 0.6.1 +微软设备健康助手 +支付宝安全控件 5.3.0.3807 +百度网盘 +腾讯QQ diff --git a/src/AppInstallerCLITests/TestData/InputPublishers.txt b/src/AppInstallerCLITests/TestData/InputPublishers.txt new file mode 100644 index 0000000000..8086c5f7bc --- /dev/null +++ b/src/AppInstallerCLITests/TestData/InputPublishers.txt @@ -0,0 +1,1137 @@ +Wildfire Games +SweetScape Software +360安全中心 +360安全中心 +Open Media LLC +Open Media LLC +Open Media LLC +Open Media LLC +Open Media LLC +Open Media LLC +Igor Pavlov +Igor Pavlov +Igor Pavlov +Igor Pavlov, Tino Reichardt +Amazon Web Services Developer Relations +Amazon Web Services +AWS Serverless Applications +Axis Communications AB +Abacus Research AG +Microsoft +Microsoft Corporation +Adobe Systems Incorporated +Adobe Systems Incorporated +Adobe Systems Incorporated +AdoptOpenJDK +AdoptOpenJDK +AdoptOpenJDK +AdoptOpenJDK +AdoptOpenJDK +AdoptOpenJDK +AdoptOpenJDK +Famatech +Ondrej Salplachta +Famatech +Pawel Psztyc +Aegisub Team +Aegisub Team +a wandersick +Alacritty +Alchemy Development Group +Algoryx +Stefan Sundin +Amazon.com, Inc. +Amazon +Amazon +Amazon Web Services, Inc +Anaconda, Inc. +Angry IP Scanner +AntiMicro +AppGet +Appium Developers +Appium Developers +Arduino LLC +Armagetron Advanced Team +Sundaram Ramaswamy +Rabid Viper Productions +Audacity Team +CodeUX.design e.U. +Armin Osaj +Lexikos +Lexikos +The Sleuth Kit +GPL Public release. +OmicronLab +7room +Microsoft® Corporation +Microsoft Corporation +Microsoft +Microsoft +Microsoft +Marcin Szeniak +Contoso.com +Beda Kosata +Space Sciences Laboratory, U.C. Berkeley +BPBible Development Team +Google, Inc. +Debauchee Open Source Group +Debauchee Open Source Group +Paul Frazee +Elastic +Elastic +Marco Mastroddi Software +beeftext.org +The Betaflight open source project. +Scooter Software, Inc. +Scooter Software +Scooter Software +Bigly Software +BitPay +Bitwarden Inc. +BleachBit +Blender Foundation +BlueJeans Network, Inc. +Hamster Republic Productions +Apple Inc. +Andrew Sampson +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +brackets.io +Brave Software Inc +Brave Software Inc +TGRMN Software +Buttercup +Buttercup +C-Dogs SDL Team +SingularLabs +Piriform +Canneverbe Limited +Kitware +Corsair +CPUID, Inc. +CPUID, Inc. +CPUID, Inc. +CPUID, Inc. +CPUID, Inc. +Penguin Labs, LLC +SaeraSoft +TechSmith Corporation +TechSmith Corporation +Sindre Sorhus +Sindre Sorhus +Giel Cobben +Mathew Sachin +RedDucks +Alexandr Subbotin +MIT IS&T +secana +Webprofusion Pty Ltd +a wandersick +Chef Software, Inc. +ChemAxon +ChemAxon +ChemAxon +ChemAxon +The Chromium Authors +Circuit Diagram +Circuit Diagram +Cisco Webex LLC +Daniel Scalzi +alch +Fndroid +Fndroid +Fndroid +Fndroid +Beijing EEO Education Technology Co., Ltd. +Clementine +Martin Ridgers +Cloudflare, Inc. +The Code::Blocks Team +Eran Ifrah +Steven Cole +TerranovaTeam +Jay Prall +Toinane +ConEmu-Maximus5 +Concept2 Inc. +Microsoft Corporation +Contasimple S.L. +ALCPU +Couchbase Inc. +Couchbase Inc. +Cozy Cloud +The Cppcheck team +Habib Rehman +cryptomator.org +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +Crystal Dew World +cubicsdr.com +Acro Software Inc. +iterate GmbH +DB Browser for SQLite Team +DBeaver Corp +DBeaver Corp +DBeaver Corp +DBeaver Corp +DBeaver Corp +DBeaver Corp +DBeaver Corp +DBeaver Corp +DBeaver Corp +DJI +DJI +DJI +DJI +DJI +DJI +DJI +DJI +TshwaneDJe +Boxstar +Boxstar +Deezer +Ashley Stone +Piriform +Dell, Inc. +Dell Inc. +Bloodshed Software +Thinking Man Software +Serraniel +Serraniel +Scott Brogden +Dixa +DjVuZone +DockStation +Docker Inc. +Dokany Project +Dokany Project +Dolphin Team +dengine.net +Digimezzo +Doxie & Co. LLC +Dropbox, Inc. +EasternGraphics +EasternGraphics +EagleGet +EagleGet +Luke Stratman +ES-Computing +EduMIPS64 Development Team +Elastic +Elgato Systems GmbH +Empoche.com +Empoche.com +MacPaw, Inc. +a wandersick +Sinew Software Systems Private Limited +The Eraser Project +The Eraser Project +The Eraser Project +The Eraser Project +Esteem +Ethereum +Evernote Corp. +Evernote Corp. +David Carpenter +David Carpenter +David Carpenter +David Carpenter +voidtools +ExpressVPN +Ultrapico +The ExtremeTuxRacer team +Eugene Roshal & Far Group +H.Shirouzu +FastStone Soft +FastStone Soft +Fedora Project +Amine Mouafik +Progress Software Corporation +Progress Software Corporation +Progress Software Corporation +Progress Software Corporation +Progress Software Corporation +Progress Software Corporation +Progress Software Corporation +Adrien Allard +Binary Fortress Software +Tim Kosse +Tim Kosse +Tim Kosse +Tim Kosse +Tim Kosse +Mozilla +Mozilla +Mozilla +Mozilla +OpenSight Software LLC +The FlightGear Team +Dominik Levitsky Studio, LLC +FontForgeBuilds +Free Time +Free Time +Foxit Software Inc. +Foxit Software Inc. +Stefan Malzner +Marek Jasinski - www.FreeCommander.com +Humanity +The GIMP Team +The GIMP Team +The GIMP Team +The GIMP Team +The GIMP Team +The GIMP Team +The GIMP Team +The GIMP Team +ARM Holdings +The Free Software Foundation, Inc. +The GnuPG Project +GCN Development +GOG.com +Artifex Software Inc. +Ghostgum Software Pty Ltd +Garmin Ltd or its subsidiaries +ThoughtWorks Inc. +ThoughtWorks Inc. +The Geany developer team +Primate Labs Inc. +Gephi +Outertech +Git Extensions Team +Git Extensions Team +Git Extensions Team +GitHub, Inc. +The Git Development Community +The Git Development Community +The Git Development Community +The Git Development Community +The Git Development Community +The Git Development Community +GitHub, Inc. +GitHub, Inc. +Stef Heyenrath +Troupe Technology Limited +Glimpse Project +Glimpse Project +Glimpse Project +GnuCash Development Team +GnuCash Development Team +GnuWin32 +GnuWin32 +GnuWin32 +GnuWin32 +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +https://golang.org +GoldWave Inc. +Google LLC +Google Inc. +Google +The Gpg4win Project +The Gpg4win Project +Grafana Labs +Grafana Labs +Grammarly +The Gramps project +Graphcool +Adam Miskiewicz +AT&T Research Labs. +Greenshot +Grid Team +Epiforge Software, LLC +HHD Software, Ltd. +Hector Maurcio Rodriguez Segura +HP Inc. +Huawei Software Technologies Co., Ltd. +Martin Malik - REALiX +Martin Malik - REALiX +Martin Malik - REALiX +Martin Malik - REALiX +HandyOrg +Vincent L +Implbits Software +Implbits Software +JAM Software +Hedgewars Project +Ansgar Becker +Ansgar Becker +Ansgar Becker +Ansgar Becker +Ansgar Becker +Perforce Software, Inc. +IBE Software +HexChat +Scott Lerch +Caphyon +Borvid +Borvid +Borvid +Borvid +Borvid +Borvid +Borvid +Huawei Corporation +Hyne & Son Pty Ltd +Marquis Kurt +Google Inc +Hex-Rays SA +Tibbo Technology Inc +David Moore +IRCCloud Ltd. +Ivan Zahariev +Duong Dieu Phap +Inkscape +jrsoftware.org +jrsoftware.org +Crystal Rich, Ltd +seonglae +Irfan Skiljan +IronPython Team +IronPython Team +ISWIX LLC +Smart Projects +ChemAxon +JabRef +Jackett +Savoir-Faire Linux +Oracle Corporation +Oracle Corporation +JetBrains +Jitsi Team +Jitsi Team +Laurent Cozic +Laurent Cozic +Laurent Cozic +Julia Language +Julia Language +Julia Language +KLCP +KLCP +KKBOX Taiwan Co., Ltd. +Chia-Lung, Chen +Dominik Reichl +Dominik Reichl +Dominik Reichl +KeePassXC Team +KeeWeb +Keybase, Inc. +KiCad +KiCad +KiCad +Krisp Technologies, Inc +Krita Foundation +Roni Lehto +LBRY Inc. +LBRY Inc. +LBRY Inc. +LBRY Inc. +LBRY Inc. +LINE Corporation +Joseph Albahari +LLVM +LMMS Developers +LMMS Developers +love2d.org +leokhoa +LastPass +Lazarus Team +Riot Games, Inc +Lenovo +Lenovo +Lakend Labs, Inc. +Leonflix +BellSoft +BellSoft +BellSoft +BellSoft +BellSoft +BellSoft +BellSoft +BellSoft +LibreCAD Team +The Document Foundation +The Document Foundation +Team Lidarr +Alexey 'Tyrrrz' Golub +Alexey 'Tyrrrz' Golub +Christian Kaiser +Leif Asbrink SM5BSZ +Lisk Foundation +Listen 1 +Listen 1 +Flywheel +Crystal Rich Ltd +Binary Fortress Software +Binary Fortress Software +Logitech Inc. +Loom, Inc. +LyX Team +LyX Team +COTILab +COTILab +Moritz Bunkus +Moritz Bunkus +Moritz Bunkus +Moritz Bunkus +Moritz Bunkus +MPC-HC Team +MPC-HC Team +MPC-HC Team +Thomas Nordquist +Microsoft +Maxthon International Limited +MY.COM B.V. +FlyingSnow, Samantha Glocker +Firetrust +Firetrust +Majsoul Plus Team +GuinpinSoft inc +Malwarebytes +KDE +MariaDB Corporation Ab +Jocs +West Wind Technologies +West Wind Technologies +West Wind Technologies +West Wind Technologies +West Wind Technologies +Markdown Outlook +Master Packager Ltd. +Mattermost, Inc. +MediaArea.net +MediaArea.net +Ventis Media Inc. +The Meld project +Janea Systems +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Garage +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft +Microsoft +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Anaconda, Inc. +Anaconda, Inc. +MongoDB Inc. +Xamarin, Inc. +The MonoGame Team +Moonlight Game Streaming Project +AGALWOOD +AGALWOOD +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Mozilla +Nicholas H.Tollervey +Mullvad VPN +Mullvad VPN +Microsoft Corporation +canonical +The Mumble Developers +The Mumble Developers +The Mumble Developers +Werner Schweer and Others +Youta Tec +Logitech +Martin Renold and the MyPaint Development Team +Oracle Corporation +Feodor2 +Justin Aquadro +Rico Suter +NV Access +NVIDIA Corporation +NVIDIA Corporation +NZXT, Inc. +NZXT, Inc. +NZXT, Inc. +NZXT, Inc. +NZXT, Inc. +NZXT, Inc. +Allan CORNET +Neotys +Lutz Roeder +Nitro +Nmap Project +qinghai +qinghai +qinghai +Node.js Foundation +Nodist +NordVPN +TEFINCOM S.A. +NordVPN +NordVPN +CodingRoad +XhmikosR +Notion Labs, Incorporated +Notion Labs, Incorporated +Nmap Project +NullNoname +Nullsoft and Contributors +OBS Project +Hamster Republic Productions +Ascensio System SIA +GNU Octave +WetHat Lab +Open Shop Channel +The Open-Shell Team +namazso +namazso +ojdkbuild open-source project +ojdkbuild open-source project +ojdkbuild open-source project +ojdkbuild open-source project +OpenMPT Devs +Apache Software Foundation +OpenRA developers +The OpenSCAD Developers +Shining Light Productions +OpenShot Studios, LLC +OpenTTD +OpenTTD +OpenVPN Technologies, Inc. +SparkLabs Pty Ltd +OpenVPN Technologies +Opera Software +Opera Software +Opera Software +Opera Software +Opera Software +Opera Software +Opera Software +Opera Software +Oracle Corporation +Oracle Corporation +Oracle Corporation +Oracle Corporation +OutSystems +EXP Systems LLC +Sober Lemur S.a.s. di Vacondio Andrea +CCPKU +Jan Fiala +NagleCode, LLC +Moonchild Productions +Moonchild Productions +John MacFarlane +John MacFarlane +John MacFarlane +Paradox Interactive +Paragon Software GmbH +Parsec Cloud Inc. +Francesco Sorge +Giorgio Tani +Giorgio Tani +Persepolis Team +Heiko Sommerfeldt +touchbyte GmbH +NGWIN +PicoTorrent contributors. +blupi.org +Sony Interactive Entertainment Network America LLC +Josef Nemec +Plex, Inc. +Plex +Plex, Inc. +Plex, Inc. +Plex, Inc. +Plex, Inc. +www.pokerth.net +Postbox, Inc. +PostgreSQL Global Development Group +PostgreSQL Global Development Group +Microsoft Corporation +Microsoft Corporation +Ironman Software, LLC +Microsoft +Kim Walisch +Private Internet Access, Inc. +Progress Software Corporation +Microsoft Corporation +Proton Technologies AG +Proton Technologies AG +Simon Tatham +Puppet Labs +Puppet Inc +Puppet, Inc. +Puppet Inc +Miller Puckette +Lancaster University Physics +Python Software Foundation +Hubert Pham +Python Software Foundation +Python Software Foundation +Python Software Foundation +Python Software Foundation +Python Software Foundation +Python Software Foundation +Python Software Foundation +Python Software Foundation +QGIS Development Team +QGIS Development Team +QGIS Development Team +Michael Hansen +Hanna Knutsson +LarusStone +Module Art +Paddy Xu +Quicken +R Core Team +R Core Team +R Core Team +RStudio +Rambox +Oleg Danilov +Raspberry Pi +rawtherapee.com +Paul Rawnsley +jklSoft +Devolutions inc. +Devolutions inc. +Remote Mouse +Baldur Karlsson +Antmicro +Responsively +RetroShare Team +VS Revo Group, Ltd. +VS Revo Group, Ltd. +3T Software Labs Ltd +3T Software Labs Ltd +3T Software Labs Ltd +Rocket.Chat Support +Punk Software +Artsoft Entertainment +MarkoBL +code4ward GmbH +Royal Apps GmbH +The R Foundation +RubyInstaller Team +RubyInstaller Team +RubyInstaller Team +Luke Haas +Luke Haas +The Rust Project Developers +The Rust Project Developers +The Rust Project Developers +The Rust Project Developers +The Rust Project Developers +The Rust Project Developers +The Rust Project Developers +The Rust Project Developers +The Rust Project Developers +Topala Software Solutions +Ricardo Villalba +Navimatics LLC +Dotz Softwares +Samsung Electronics Co., Ltd. +mircearoata +Scratch Foundation +Nicke Manarin +The Scribus Team +The ScummVM Team +spikespaz +Sejda BV +Datalust Pty Ltd +Microsoft Corporation +ShareX Team +RandyRants.com +Meltytech, LLC +Sigil-Ebook +Open Whisper Systems +Open Whisper Systems +Open Whisper Systems +Open Whisper Systems +Open Whisper Systems +Open Whisper Systems +Open Whisper Systems +Approximatrix, LLC +Ashley Stone +Skype Technologies S.A. +Skype Technologies S.A. +Skype Technologies S.A. +Slack Technologies +TechSmith Corporation +SnakeNest.com +Cory Plotts +SmartBear Software +Sonic Pi +Sonos, Inc. +Sonos, Inc. +Antoine Aflalo +Atlassian +SpeedCrunch +Spek Project +Standard Notes +Valve Corporation +http://www.sbcl.org +SteelSeries ApS +Stellarium team +Stellarium team +Stellarium team +strawberryperl.com project +General Workings, Inc. +General Workings, Inc. +General Workings, Inc. +Streamlink +Sebastian Meyer +Jan Hovancik +Jan Hovancik +Jan Hovancik +Stride +BrickLink Corporation +Sublime HQ Pty Ltd +Sublime HQ Pty Ltd +Krzysztof Kowalczyk +SuperCollider Community +SuperTuxKart +Microsoft +SyncTrayzor +Mister Group +OpenVPN Technologies, Inc. +erengy +Tailscale Inc. +Tailscale Inc. +Taisei Project +Taskcade Inc. +Taskcade Inc. +"Treasure Data, Inc" +Treasure Data, Inc +Benito van der Zander +TeX Users Group +TeamSpeak Systems GmbH +TechPowerUp +Telegram FZ-LLC +Telegram FZ-LLC +Telegram FZ-LLC +Telegram FZ-LLC +Telegram FZ-LLC +Telegram FZ-LLC +Telegram FZ-LLC +Telegram FZ-LLC +Telegram FZ-LLC +TeraTerm Project +Eugene Pankov +Eugene Pankov +Eugene Pankov +CompuPhase +Tesseract-OCR community +Texmaker +Texnomic +RaMMicHaeL +Appest.com +GlavSoft LLC. +TikzEdt +mapeditor.org +Nadeo +Toggl +Toggl +TortoiseGit +TortoiseSVN +TortoiseSVN +TranslucentTB Open Source Developers +Transmission Project +Yury Sidorov & Transmission Remote GUI working group +Binary Fortress Software +Binary Fortress Software +JAM Software +JAM Software +Trelby.org +Cerulean Studios, LLC +TunnelBear +New Breed Software +Inspect Element Inc. +Xander Frangos +Twitch Interactive, Inc. +G DATA CyberDefense AG +SafelyRemove.com +Drew Naylor +Drew Naylor +Ultimaker B.V. +Ultimaker B.V. +Ultimaker B.V. +uvnc bvba +Reason Software Company Inc. +Unified Intents AB +Unity Technologies Inc. +Microsoft Corporation +Microsoft Corporation +Ubisoft +UMEZAWA Takeshi +VCV +VideoLAN +VideoLAN +VideoLAN +VMware, Inc. +VMware, Inc. +VMware, Inc. +RealVNC Ltd +RealVNC Ltd +Microsoft Corporation +Microsoft Corporation +marha@users.sourceforge.net +Bram Moolenaar et al. +Virt Manager Project +Vivaldi Technologies AS. +Black Tree Gaming Ltd. +VoyagerX, Inc. +LunarG, Inc. +Warzone 2100 Project +Waterfox +Waterfox +Waterfox +Devolutions Inc. +Buds +Buds +Buds +Buds +Machine Learning Group, University of Waikato, Hamilton, NZ +ImageWriter Developers +Sam Hocevar +Timothy Johnson +Timothy Johnson +Timothy Johnson +Navimatics LLC +HTTrack +Thingamahoochie Software +win.rar GmbH +win.rar GmbH +Martin Prikryl +Corel Corporation +Winamp SA +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Dynastream Innovations, Inc. +Silicon Labs Software +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +Microsoft Corporation +WireGuard LLC +The Wireshark developer community, https://www.wireshark.org +The Wireshark developer community, https://www.wireshark.org +The Wireshark developer community, https://www.wireshark.org +The Wireshark developer community, https://www.wireshark.org +Antibody Software +Antibody Software +Antibody Software +Antibody Software +Antibody Software +Automattic Inc. +Automattic Inc. +Automattic Inc. +Automattic Inc. +Rob Caelers & Raymond Penners +Writage +X2Go Project +Bitnami +Christian Hohnstaedt +The TBOOX Open Source Group +XMind Ltd. +Gougelet Pierre-e +Gougelet Pierre-e +Yarn Contributors +Beijing Yinxiang Biji Technologies Co., Ltd. +Beijing Yinxiang Biji Technologies Co., Ltd. +Beijing Yinxiang Biji Technologies Co., Ltd. +Beijing Yinxiang Biji Technologies Co., Ltd. +Beijing Yinxiang Biji Technologies Co., Ltd. +Adler Luiz +Yubico AB +Zentimo.com +ZeroTier, Inc. +Hendrik Erz +Robin Stuart & BogDan Vatra +Zoom +Zoom +Corporation for Digital Scholarship +Kandra Labs, Inc. +Sangoma Technologies Corp. +Zygor Guides +Balena Inc. +Balena Inc. +Balena Inc. +Balena Inc. +Balena Inc. +Balena Inc. +Balena Inc. +Balena Inc. +Nathaniel Johns +Clement Tsang +butterflow-ui @ github +Kovid Goyal +Elliott Zheng +the darktable project +dnGrep Community Contributors +JGraph +Hardcoded Software +eM Client Inc. +Ebbflow.io +f.lux Software LLC +Kurata Sayuri +wereturtle +gnuplot development team +Stefans Tools +Drew Naylor +Drew Naylor +Drew Naylor +eVenture Limited +eVenture Limited +PurpleI2P +Vantage Linguistics +Apple Inc. +KDE e.V. +KDE e.V. +Next Generation Software +Maxima Team +Frank Skare (stax76) +720kb +xiles +ownCloud GmbH +EasternGraphics +Laurent P. Ren© de Cotret +The pgAdmin Development Team +The pgAdmin Development Team +The pgAdmin Development Team +The pgAdmin Development Team +The qBittorrent project +The qBittorrent project +The qBittorrent project +remote.it +remote.it +Lightbend, Inc. +Scilab Enterprises +The Sqlectron Team +Jan Hovancik +Oliver Schwendener +Oliver Schwendener +Oliver Schwendener +Humanity +Humanity +Microsoft Corporation +Alipay.com Co., Ltd. +百度在线网络技术(北京)有限公司 +腾讯科技(深圳)有限公司 diff --git a/src/AppInstallerCLITests/TestData/NormalizationInitialIds.txt b/src/AppInstallerCLITests/TestData/NormalizationInitialIds.txt new file mode 100644 index 0000000000..97b681ff41 --- /dev/null +++ b/src/AppInstallerCLITests/TestData/NormalizationInitialIds.txt @@ -0,0 +1,1137 @@ +WildfireGames.0AD +SweetScapeSoftware.010Editor +360安全中心.360安全卫士 +360安全中心.360杀毒 +OpenMedia.4KSlideshowMaker +OpenMedia.4KStogram +OpenMedia.4KVideoDownloader +OpenMedia.4KVideoDownloader +OpenMedia.4KVideotoMP3 +OpenMedia.4KYouTubetoMP3 +IgorPavlov.7Zip +IgorPavlov.7Zip +IgorPavlov.7Zipalpha +IgorPavlovTinoReichardt.7ZipZSZS +AmazonWebServicesDeveloperRelations.AWSCommandLineInterface +AmazonWebServices.AWSCommandLineInterface +AWSServerlessApplications.AWSSAMCommandLineInterface +AxisCommunications.AXISCameraStation +AbacusResearch.AbaClient +Microsoft.AccessibilityInsightsForWindows +Microsoft.ActiveDirectoryAuthenticationLibraryforSQLServer +AdobeSystems.AdobeAcrobatReaderDCCzech +AdobeSystems.AdobeAcrobatReaderDC +AdobeSystems.AdobeAcrobatReaderDCMUI +AdoptOpenJDK.AdoptOpenJDKJDKwithHotspot +AdoptOpenJDK.AdoptOpenJDKJDKwithHotspot +AdoptOpenJDK.AdoptOpenJDKJDKwithHotspot +AdoptOpenJDK.AdoptOpenJDKJDKwithHotspot +AdoptOpenJDK.AdoptOpenJDKJDKwithHotspot +AdoptOpenJDK.AdoptOpenJDKJDKwithHotspot +AdoptOpenJDK.AdoptOpenJDKJDKwithHotspot +Famatech.AdvancedIPScanner +OndrejSalplachta.AdvancedLogViewer +Famatech.AdvancedPortScanner +PawelPsztyc.AdvancedRestClient +AegisubTeam.Aegisub8975master8d77da3 +AegisubTeam.Aegisub +awandersick.AeroZoombeta2 +Alacritty.Alacritty +AlchemyDevelopmentGroup.AlchemyBeta +Algoryx.Algodoo +StefanSundin.AltDrag +Amazoncom.AmazonChime +Amazon.AmazonCorretto +Amazon.AmazonCorretto8 +AmazonWebServices.AmazonWorkSpaces +Anaconda.Anaconda3 +AngryIPScanner.AngryIPScanner +AntiMicro.AntiMicro +AppGet.AppGet +AppiumDevelopers.Appium +AppiumDevelopers.Appium +Arduino.Arduino +ArmagetronAdvancedTeam.ArmagetronAdvanced +SundaramRamaswamy.Artha +RabidViperProductions.AssaultCube +AudacityTeam.Audacity +CodeUXdesigneU.AuthPass +ArminOsaj.AutoDarkMode +Lexikos.AutoHotkey +Lexikos.AutoHotkey +TheSleuthKit.Autopsy +GPLPublicrelease.AviSynth +OmicronLab.AvroKeyboard +7room.Aya +Microsoft.AzureCosmosDBEmulator +Microsoft.AzureDataStudio +Microsoft.AzureFunctionsCoreTools +Microsoft.AzureIoTExplorer +Microsoft.AzureIoTexplorer +MarcinSzeniak.BCUninstaller +Contosocom.BITSManager +BedaKosata.BKChem +SpaceSciencesLaboratoryUCBerkeley.BOINC +BPBibleDevelopmentTeam.BPBible +Google.BackupandSyncfromGoogle +DebaucheeOpenSourceGroup.Barrier +DebaucheeOpenSourceGroup.Barrier +PaulFrazee.BeakerBrowser +Elastic.Beatswinlogbeat +Elastic.Beatswinlogbeat +MarcoMastroddiSoftware.BeeBEEP +beeftextorg.Beeftext +TheBetaflightopensourceproject.BetaflightConfigurator +ScooterSoftware.BeyondCompare4 +ScooterSoftware.BeyondCompare +ScooterSoftware.BeyondCompare +BiglySoftware.BiglyBT +BitPay.BitPay +Bitwarden.Bitwarden +BleachBit.BleachBit +BlenderFoundation.Blender +BlueJeansNetwork.BlueJeans +HamsterRepublicProductions.BobtheHamsterVGA +Apple.Bonjour +AndrewSampson.BorderlessGaming +Microsoft.BotFrameworkComposer +Microsoft.BotFrameworkComposer +Microsoft.BotFrameworkComposer +Microsoft.BotFrameworkComposer +Microsoft.BotFrameworkEmulator +Microsoft.BotFrameworkEmulator +Microsoft.BotFrameworkEmulator +bracketsio.Brackets +BraveSoftware.Brave +BraveSoftware.BraveNightly +TGRMNSoftware.BulkRenameUtility +Buttercup.Buttercup +Buttercup.Buttercup +CDogsSDLTeam.CDogsSDL +SingularLabs.CCEnhancer +Piriform.CCleaner +Canneverbe.CDBurnerXP +Kitware.CMake +Corsair.CORSAIRiCUESoftware +CPUID.CPUIDCPUZ +CPUID.CPUIDCPUZ +CPUID.CPUIDCPUZ +CPUID.CPUIDHWMonitor +CPUID.CPUIDHWMonitor +PenguinLabs.Cacher +SaeraSoft.CaesiumPH +TechSmith.Camtasia2019 +TechSmith.Camtasia2020 +SindreSorhus.Caprine +SindreSorhus.Caprine +GielCobben.Caption +MathewSachin.Captura +RedDucks.CemUI +AlexandrSubbotin.Cerebro +MITIST.CertAidforWindows +secana.CertDump +Webprofusion.CertifyTheWeb +awandersick.ChMac +ChefSoftware.ChefDK +ChemAxon.ChemAxonChemCurator +ChemAxon.ChemAxonMarkushEditor +ChemAxon.ChemAxonMarvinSuite +ChemAxon.ChemAxonMarvinSuite +TheChromiumAuthors.Chromium +CircuitDiagram.CircuitDiagram +CircuitDiagram.CircuitDiagram +CiscoWebex.CiscoWebexMeetings +DanielScalzi.CitycraftLauncher +alch.ClamWinFreeAntivirus +Fndroid.ClashforWindows +Fndroid.ClashforWindows +Fndroid.ClashforWindows +Fndroid.ClashforWindows +BeijingEEOEducationTechnology.ClassIn +Clementine.Clementine +MartinRidgers.Clink +Cloudflare.CloudflareWARP +TheCodeBlocksTeam.CodeBlocks +EranIfrah.CodeLite +StevenCole.Coffee +TerranovaTeam.ColobotGoldEditionalpha +JayPrall.ColorCop +Toinane.Colorpicker +ConEmuMaximus.ConEmu201011 +Concept2.Concept2Utility +Microsoft.ConfigMgr2012Toolkit +Contasimple.ContasimpleDesktop +ALCPU.CoreTemp +Couchbase.CouchbaseServerCommunityEdition +Couchbase.CouchbaseServerEnterpriseEdition +CozyCloud.CozyDrive +TheCppcheckteam.Cppcheck +HabibRehman.Crypter +cryptomatororg.Cryptomator +CrystalDewWorld.CrystalDiskInfo +CrystalDewWorld.CrystalDiskInfo +CrystalDewWorld.CrystalDiskInfoKureiKeiEdition +CrystalDewWorld.CrystalDiskInfoShizukuEdition +CrystalDewWorld.CrystalDiskInfo +CrystalDewWorld.CrystalDiskInfo +CrystalDewWorld.CrystalDiskInfoKureiKeiEdition +CrystalDewWorld.CrystalDiskInfoShizukuEdition +CrystalDewWorld.CrystalDiskInfo +CrystalDewWorld.CrystalDiskInfo +CrystalDewWorld.CrystalDiskInfoKureiKeiEdition +CrystalDewWorld.CrystalDiskInfoShizukuEdition +CrystalDewWorld.CrystalDiskInfo +CrystalDewWorld.CrystalDiskInfoKureiKeiEdition +CrystalDewWorld.CrystalDiskInfoShizukuEdition +CrystalDewWorld.CrystalDiskMark +CrystalDewWorld.CrystalDiskMarkShizukuEdition +cubicsdrcom.CubicSDRInstaller +AcroSoftware.CutePDFWriter +iterate.Cyberduck +DBBrowserforSQLiteTeam.DBBrowserforSQLite +DBeaver.DBeaver +DBeaver.DBeaver +DBeaver.DBeaver +DBeaver.DBeaver +DBeaver.DBeaver +DBeaver.DBeaver +DBeaver.DBeaver +DBeaver.DBeaver +DBeaver.DBeaver +DJI.DJIAssistant2 +DJI.DJIAssistant2ForAeroscope +DJI.DJIAssistant2ForAutopilot +DJI.DJIAssistant2ForBatteryStation +DJI.DJIAssistant2ForMG +DJI.DJIAssistant2ForMatrice +DJI.DJIAssistant2ForMavic +DJI.DJIAssistant2ForPhantom +TshwaneDJe.DaveGnukem +Boxstar.DeepVocalToolBoxbetaversionbeta +Boxstar.DeepVocalbetaversionbeta +Deezer.Deezer +AshleyStone.DefaultAudio +Piriform.Defraggler +Dell.DellCommandUpdate +Dell.DellUpdate +BloodshedSoftware.DevC +ThinkingManSoftware.Dimension4 +Serraniel.DiscordMediaLoader +Serraniel.DiscordMediaLoader +ScottBrogden.Ditto +Dixa.Dixa +DjVuZone.DjVuLibreDjView +DockStation.DockStation +Docker.DockerDesktop +DokanyProject.DokanLibrary +DokanyProject.DokanLibrary +DolphinTeam.Dolphin +denginenet.Doomsday +Digimezzo.Dopamine +Doxie.Doxie +Dropbox.Dropbox +EasternGraphics.EGRSafenetActivation +EasternGraphics.EGRShellExtension +EagleGet.EagleGet +EagleGet.EagleGet +LukeStratman.EasyConnect +ESComputing.EditPlus +EduMIPS64DevelopmentTeam.EduMIPS64 +Elastic.Elasticsearch +ElgatoSystems.ElgatoStreamDeck +Empochecom.Empoche +Empochecom.Empoche +MacPaw.Encrypto +awandersick.EnglishizeCmd +SinewSoftwareSystemsPrivate.Enpass +TheEraserProject.Eraser +TheEraserProject.Eraser +TheEraserProject.Eraser +TheEraserProject.Eraser +Esteem.Esteem +Ethereum.EthereumGethOfficialGoimplementationoftheEthereumprotocol +Evernote.Evernotev +Evernote.Evernotev +DavidCarpenter.Everything +DavidCarpenter.Everything +DavidCarpenter.Everything +DavidCarpenter.EverythingLite +voidtools.Everything +ExpressVPN.ExpressVPN +Ultrapico.Expresso +TheExtremeTuxRacerteam.ExtremeTuxRacer +EugeneRoshalFarGroup.FarManager3 +HShirouzu.FastCopy +FastStoneSoft.FastStoneCapture +FastStoneSoft.FastStoneImageViewer +FedoraProject.FedoraMediaWriter +AmineMouafik.Ferdi +ProgressSoftware.FiddlerEverywhere +ProgressSoftware.FiddlerEverywhere +ProgressSoftware.FiddlerEverywhere +ProgressSoftware.FiddlerEverywhere +ProgressSoftware.FiddlerEverywhere +ProgressSoftware.FiddlerEverywhere +ProgressSoftware.FiddlerEverywhere +AdrienAllard.FileConverter +BinaryFortressSoftware.FileSeek +TimKosse.FileZillaClient +TimKosse.FileZillaClient +TimKosse.FileZillaClient +TimKosse.FileZillaClient +TimKosse.FileZillaClient +Mozilla.FirefoxDeveloperEdition +Mozilla.FirefoxDeveloperEdition +Mozilla.FirefoxDeveloperEdition +Mozilla.FirefoxDeveloperEdition +OpenSightSoftware.FlashFXP5 +TheFlightGearTeam.FlightGear +DominikLevitskyStudio.FontBase +FontForgeBuilds.FontForge +FreeTime.FormatFactory +FreeTime.FormatFactory +FoxitSoftware.FoxitPhantomPDF +FoxitSoftware.FoxitReader +StefanMalzner.Franz +MarekJasinskiwwwFreeCommandercom.FreeCommanderXE +Humanity.FreeMat +TheGIMPTeam.GIMP +TheGIMPTeam.GIMP +TheGIMPTeam.GIMP +TheGIMPTeam.GIMP +TheGIMPTeam.GIMP +TheGIMPTeam.GIMP +TheGIMPTeam.GIMP +TheGIMPTeam.GIMP +ARM.GNUArmEmbeddedToolchain92020 +TheFreeSoftwareFoundation.GNUMidnightCommander +TheGnuPGProject.GNUPrivacyGuard +GCNDevelopment.GNURadio +GOGcom.GOGGALAXY +ArtifexSoftware.GPLGhostscript +GhostgumSoftware.GSview +Garmin.GarminExpress +ThoughtWorks.Gauge +ThoughtWorks.Gauge +TheGeanydeveloperteam.Geany +PrimateLabs.Geekbench5 +Gephi.Gephi +Outertech.GetDiz +GitExtensionsTeam.GitExtensions +GitExtensionsTeam.GitExtensions +GitExtensionsTeam.GitExtensions +GitHub.GitLFS +TheGitDevelopmentCommunity.Git +TheGitDevelopmentCommunity.Git +TheGitDevelopmentCommunity.Git +TheGitDevelopmentCommunity.Git +TheGitDevelopmentCommunity.Git +TheGitDevelopmentCommunity.Git +GitHub.GitHubCLI +GitHub.GitHubDesktopMachineWideInstaller +StefHeyenrath.GitHubReleaseNotes +TroupeTechnology.Gitter +GlimpseProject.Glimpse +GlimpseProject.Glimpse +GlimpseProject.Glimpse +GnuCashDevelopmentTeam.GnuCash +GnuCashDevelopmentTeam.GnuCash +GnuWin.GnuWin32Grep +GnuWin.GnuWin32Make +GnuWin.GnuWin32Wget +GnuWin.GnuWin32Zip +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +golangorg.GoProgrammingLanguagego +GoldWave.GoldWave +Google.GoogleChrome +Google.GoogleCloudSDK +Google.GoogleEarthPro +TheGpg4winProject.Gpg4win +TheGpg4winProject.Gpg4win +GrafanaLabs.GrafanaEnterprise +GrafanaLabs.GrafanaOSS +Grammarly.GrammarlyforMicrosoftOfficeSuite +TheGrampsproject.GrampsAIO64 +Graphcool.GraphQLPlayground +AdamMiskiewicz.GraphiQL +ATTResearchLabs.Graphviz +Greenshot.Greenshot +GridTeam.Grid +EpiforgeSoftware.Grindstone4 +HHDSoftware.HHDSoftwareFreeHexEditorNeo +HectorMaurcioRodriguezSegura.HMNISEdit +HP.HPCloudRecoveryTool +HuaweiSoftwareTechnologies.HUAWEICloud +MartinMalikREALiX.HWiNFO64 +MartinMalikREALiX.HWiNFO64 +MartinMalikREALiX.HWiNFO64 +MartinMalikREALiX.HWiNFO64 +HandyOrg.HandyWinGet +VincentL.Harmony +ImplbitsSoftware.HashTab +ImplbitsSoftware.HashTab +JAMSoftware.HeavyLoad +HedgewarsProject.Hedgewars +AnsgarBecker.HeidiSQL +AnsgarBecker.HeidiSQL +AnsgarBecker.HeidiSQL +AnsgarBecker.HeidiSQL +AnsgarBecker.HeidiSQL +PerforceSoftware.HelixCoreApps +IBESoftware.HelpNDocPersonalEdition +HexChat.HexChat +ScottLerch.HostsFileEditor +Caphyon.Hover +Borvid.HttpMasterExpressEdition +Borvid.HttpMasterExpressEdition +Borvid.HttpMasterExpressEdition +Borvid.HttpMasterExpressEdition +Borvid.HttpMasterProfessionalEdition +Borvid.HttpMasterProfessionalEdition +Borvid.HttpMasterProfessionalEdition +Huawei.HuaweiQuickAppIDE +HyneSon.HyneTimberDesign +MarquisKurt.HyperspaceDesktop +Google.IAPDesktop +HexRays.IDAFreeware +TibboTechnology.IONinja3 +DavidMoore.IPFilter +IRCCloud.IRCCloud +IvanZahariev.IZArc +DuongDieuPhap.ImageGlass +Inkscape.Inkscape +jrsoftwareorg.InnoSetup +jrsoftwareorg.InnoSetup +CrystalRich.InternetOff +seonglae.Intuiter +IrfanSkiljan.IrfanView +IronPythonTeam.IronPython +IronPythonTeam.IronPython +ISWIX.IsWiX +SmartProjects.IsoBuster +ChemAxon.JChemNETAPI +JabRef.JabRef +Jackett.Jackett +SavoirFaireLinux.Jami +Oracle.Java8Update251 +Oracle.Java8Update261 +JetBrains.JetBrainsToolbox +JitsiTeam.JitsiMeet +JitsiTeam.JitsiMeet +LaurentCozic.Joplin +LaurentCozic.Joplin +LaurentCozic.Joplin +JuliaLanguage.Julia +JuliaLanguage.Julia +JuliaLanguage.Julia +KLCP.KLiteCodecPackStandard +KLCP.KLiteMegaCodecPack +KKBOXTaiwan.KKBOX +ChiaLungChen.Kaku +DominikReichl.KeePassPasswordSafe +DominikReichl.KeePassPasswordSafe +DominikReichl.KeePassPasswordSafe +KeePassXCTeam.KeePassXC +KeeWeb.KeeWeb +Keybase.Keybase +KiCad.KiCad +KiCad.KiCad +KiCad.KiCad +KrispTechnologies.Krisp +KritaFoundation.Krita +RoniLehto.LMath +LBRY.LBRY +LBRY.LBRY +LBRY.LBRY +LBRY.LBRY +LBRY.LBRY +LINE.LINE +JosephAlbahari.LINQPad6 +LLVM.LLVM +LMMSDevelopers.LMMS +LMMSDevelopers.LMMS +love2dorg.LOVE +leokhoa.Laragon +LastPass.LastPass +LazarusTeam.Lazarus +RiotGames.LeagueofLegends +Lenovo.LenovoMigrationAssistant +Lenovo.LenovoSystemUpdate +LakendLabs.Lens +Leonflix.Leonflix +BellSoft.LibericaJDK11 +BellSoft.LibericaJDK11Full +BellSoft.LibericaJDK14 +BellSoft.LibericaJDK14Full +BellSoft.LibericaJDK15 +BellSoft.LibericaJDK15Full +BellSoft.LibericaJDK8 +BellSoft.LibericaJDK8Full +LibreCADTeam.LibreCAD +TheDocumentFoundation.LibreOffice +TheDocumentFoundation.LibreOffice +TeamLidarr.Lidarr +AlexeyTyrrrzGolub.LightBulb +AlexeyTyrrrzGolub.LightBulb +ChristianKaiser.Lightscreen +LeifAsbrinkSM5BSZ.Linrad +LiskFoundation.LiskHub +Listen.Listen1 +Listen.Listen1 +Flywheel.Local +CrystalRich.LockHunter +BinaryFortressSoftware.LogFusion +BinaryFortressSoftware.LogFusion +Logitech.LogitechGamingSoftware +Loom.Loom +LyXTeam.LyX +LyXTeam.LyX +COTILab.MCXStudioversionnightlybuild +COTILab.MCXStudio +MoritzBunkus.MKVToolNix +MoritzBunkus.MKVToolNix +MoritzBunkus.MKVToolNix +MoritzBunkus.MKVToolNix +MoritzBunkus.MKVToolNix +MPCHCTeam.MPCHC +MPCHCTeam.MPCHC +MPCHCTeam.MPCHC +ThomasNordquist.MQTTExplorer +Microsoft.MSIXCore +MaxthonInternational.MX5 +MYCOM.MYGAMESGameCenter +FlyingSnowSamanthaGlocker.MacType +Firetrust.MailWasher +Firetrust.MailWasherPro +MajsoulPlusTeam.MajsoulPlus +GuinpinSoft.MakeMKV +Malwarebytes.Malwarebytes +KDE.Marble +MariaDB.MariaDB +Jocs.MarkText +WestWindTechnologies.MarkdownMonster +WestWindTechnologies.MarkdownMonster +WestWindTechnologies.MarkdownMonster +WestWindTechnologies.MarkdownMonster +WestWindTechnologies.MarkdownMonster +MarkdownOutlook.MarkdownOutlook +MasterPackager.MasterPackager +Mattermost.Mattermost +MediaAreanet.MediaInfo +MediaAreanet.MediaInfoCLI +VentisMedia.MediaMonkey +TheMeldproject.Meld +JaneaSystems.MemuraiDeveloper +Microsoft.MicrosoftNETCoreSDK +Microsoft.MicrosoftNETCoreSDK +Microsoft.MicrosoftNETCoreSDK +Microsoft.MicrosoftNETCoreSDK +Microsoft.MicrosoftNETCoreSDK +Microsoft.MicrosoftNETCoreSDK +Microsoft.MicrosoftNETFrameworkMultiTargetingPack +Microsoft.MicrosoftNETFrameworkMultiTargetingPack +Microsoft.MicrosoftNETFrameworkMultiTargetingPack +Microsoft.MicrosoftNETFrameworkSDK +Microsoft.MicrosoftNETFrameworkMultiTargetingPack +Microsoft.MicrosoftNETFrameworkMultiTargetingPack +Microsoft.MicrosoftNETFrameworkSDK +Microsoft.MicrosoftNETFrameworkTargetingPack +Microsoft.MicrosoftNETFrameworkSDK +Microsoft.MicrosoftNETFrameworkTargetingPack +Microsoft.MicrosoftNETSDK +Microsoft.MicrosoftNETSDK +Microsoft.MicrosoftNETSDK +Microsoft.MicrosoftNETSDK +Microsoft.MicrosoftAzureCLI +Microsoft.MicrosoftAzureStorageEmulator +Microsoft.MicrosoftAzureStorageExplorer +Microsoft.MicrosoftAzureStorageExplorer +Microsoft.MicrosoftDeploymentToolkit +Microsoft.MicrosoftEdge +Microsoft.MicrosoftEdgeBeta +Microsoft.MicrosoftEdgeDev +MicrosoftGarage.MicrosoftGarageMousewithoutBorders +Microsoft.MicrosoftHelpViewer +Microsoft.MicrosoftHelpViewer +Microsoft.MicrosoftMPI +Microsoft.MicrosoftMPI +Microsoft.MicrosoftMPISDK +Microsoft.MicrosoftODBCDriver13forSQLServer +Microsoft.MicrosoftODBCDriver17forSQLServer +Microsoft.MicrosoftOLEDBDriverforSQLServer +Microsoft.MicrosoftROpen +Microsoft.MicrosoftROpen +Microsoft.MicrosoftSQLServer2012NativeClient +Microsoft.MicrosoftSQLServer2014ManagementObjects +Microsoft.MicrosoftSQLServer2016 +Microsoft.MicrosoftSQLServer2016Policies +Microsoft.MicrosoftSQLServer2016TSQLLanguageService +Microsoft.MicrosoftSQLServer2016TSQLScriptDom +Microsoft.MicrosoftSQLServer2017 +Microsoft.MicrosoftSQLServer2017Policies +Microsoft.MicrosoftSQLServer2017TSQLLanguageService +Microsoft.MicrosoftSQLServerDataTierApplicationFramework +Microsoft.MicrosoftSQLServerManagementStudio +Microsoft.MicrosoftSQLServerManagementStudio +Microsoft.MicrosoftSQLServerManagementStudio +Microsoft.MicrosoftSQLServerManagementStudio +Microsoft.MicrosoftSQLServerManagementStudio +Microsoft.MicrosoftSmallBasic +Microsoft.MicrosoftSystemCLRTypesforSQLServer2014 +Microsoft.MicrosoftSystemCLRTypesforSQLServer2016 +Microsoft.MicrosoftSystemCLRTypesforSQLServer2017 +Microsoft.MicrosoftVisioViewer2016 +Microsoft.MicrosoftVisualStudio2010ToolsforOfficeRuntime +Microsoft.MicrosoftVisualStudio2015Shell +Microsoft.MicrosoftVisualStudioCode +Microsoft.MicrosoftVisualStudioCodeInsiders +Microsoft.MicrosoftVisualStudioToolsforApplications2015 +Microsoft.MicrosoftVisualStudioToolsforApplications2015LanguageSupport +Microsoft.MicrosoftVisualStudioToolsforApplications2017 +Microsoft.MicrosoftWebPlatformInstaller +Anaconda.Miniconda3 +Anaconda.Miniconda3py +MongoDB.MongoDB2008PlusSSL +Xamarin.MonoforWindows +TheMonoGameTeam.MonoGameSDK +MoonlightGameStreamingProject.MoonlightGameStreamingClient +AGALWOOD.Motrix +AGALWOOD.Motrix +Mozilla.MozillaFirefoxESR +Mozilla.MozillaFirefoxESR +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefoxESR +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefoxESR +Mozilla.MozillaFirefoxESR +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaFirefox +Mozilla.MozillaMaintenanceService +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +Mozilla.MozillaThunderbird +NicholasHTollervey.Mu +MullvadVPN.MullvadVPN +MullvadVPN.MullvadVPN +Microsoft.MultilingualAppToolkit +canonical.Multipass +TheMumbleDevelopers.Mumble +TheMumbleDevelopers.Mumble +TheMumbleDevelopers.Mumble +WernerSchweerandOthers.MuseScore3 +YoutaTec.Muta +Logitech.MyHarmony +MartinRenoldandtheMyPaintDevelopmentTeam.MyPaint +Oracle.MySQLInstallerCommunity +Feodor.Mypal +JustinAquadro.NBTExplorer +RicoSuter.NSwagStudio +NVAccess.NVDA +NVIDIA.NVIDIANVIDIARTXVoiceDriver +NVIDIA.NVIDIARTXVoiceApplication +NZXT.NZXTCAM +NZXT.NZXTCAM +NZXT.NZXTCAM +NZXT.NZXTCAM +NZXT.NZXTCAM +NZXT.NZXTCAM +AllanCORNET.Nelson +Neotys.NeoLoad +LutzRoeder.Netron +Nitro.NitroPro +NmapProject.Nmap +qinghai.NoSQLBoosterforMongoDB +qinghai.NoSQLBoosterforMongoDB +qinghai.NoSQLBoosterforMongoDB +NodejsFoundation.Nodejs +Nodist.Nodist +NordVPN.NordVPN +TEFINCOM.NordVPN +NordVPN.NordVPNnetworkTAP +NordVPN.NordVPNnetworkTUN +CodingRoad.NoteHighlight2016 +XhmikosR.Notepad2mod +NotionLabs.Notion +NotionLabs.Notion +NmapProject.Npcap +NullNoname.NullpoMino +NullsoftandContributors.NullsoftInstallSystem +OBSProject.OBSStudio +HamsterRepublicProductions.OHRRPGCEgorgonzola20200502 +AscensioSystemSIA.ONLYOFFICEDesktopEditors +GNUOctave.Octave +WetHatLab.OneNoteTaggingKit +OpenShopChannel.OpenShopChannelDownloader +TheOpenShellTeam.OpenShell +namazso.OpenHashTab +namazso.OpenHashTab +ojdkbuildopensourceproject.OpenJDK +ojdkbuildopensourceproject.OpenJDK +ojdkbuildopensourceproject.OpenJDK +ojdkbuildopensourceproject.OpenJDK +OpenMPTDevs.OpenMPT +ApacheSoftwareFoundation.OpenOffice +OpenRAdevelopers.OpenRA +TheOpenSCADDevelopers.OpenSCAD +ShiningLightProductions.OpenSSL +OpenShotStudios.OpenShotVideoEditor +OpenTTD.OpenTTD +OpenTTD.OpenTTD +OpenVPNTechnologies.OpenVPN +SparkLabs.OpenVPNConfigurationGenerator +OpenVPNTechnologies.OpenVPNConnect +OperaSoftware.OperaGXStable +OperaSoftware.OperaGXStable +OperaSoftware.OperaStable +OperaSoftware.OperaStable +OperaSoftware.OperaStable +OperaSoftware.OperaStable +OperaSoftware.OperaStable +OperaSoftware.OperaStable +Oracle.OracleVMVirtualBox +Oracle.OracleVMVirtualBox +Oracle.OracleVMVirtualBox +Oracle.OracleVMVirtualBox +OutSystems.OutSystemsDevelopmentEnvironment11 +EXPSystems.PDFreDirect +SoberLemurSasdiVacondioAndrea.PDFsamBasic +CCPKU.PKUGateway +JanFiala.PSPadeditor +NagleCode.PacketSender +MoonchildProductions.PaleMoon +MoonchildProductions.PaleMoon +JohnMacFarlane.Pandoc +JohnMacFarlane.Pandoc +JohnMacFarlane.Pandoc +ParadoxInteractive.ParadoxLauncher +ParagonSoftware.ParagonBackupRecoveryÃâžÂ17CE +ParsecCloud.Parsec +FrancescoSorge.PasteIntoFile +GiorgioTani.PeaZip +GiorgioTani.PeaZip +PersepolisTeam.PersepolisDownloadManager +HeikoSommerfeldt.PhonerLite +touchbyte.PhotoSync +NGWIN.PicPick +PicoTorrentcontributors.PicoTorrent +blupiorg.PlanetBlupi +SonyInteractiveEntertainmentNetworkAmerica.PlayStationÃâžÂNow +JosefNemec.Playnite +Plex.Plex +Plex.PlexMediaPlayer +Plex.PlexMediaServer +Plex.Plexamp +Plex.Plexamp +Plex.Plexamp +wwwpokerthnet.PokerTH +Postbox.Postbox +PostgreSQLGlobalDevelopmentGroup.PostgreSQL12 +PostgreSQLGlobalDevelopmentGroup.PostgreSQL13 +Microsoft.PowerShell7preview +Microsoft.PowerShell7 +IronmanSoftware.PowerShellUniversal +Microsoft.PowerToys +KimWalisch.Primesieve +PrivateInternetAccess.PrivateInternetAccess +ProgressSoftware.ProgressTelerikFiddler +Microsoft.ProjectMyScreenApp +ProtonTechnologies.ProtonVPN +ProtonTechnologies.ProtonVPNTap +SimonTatham.PuTTY +PuppetLabs.Puppet +Puppet.PuppetAgent +Puppet.PuppetBolt +Puppet.PuppetDevelopmentKit +MillerPuckette.PureData +LancasterUniversityPhysics.PyMODA +PythonSoftwareFoundation.Python +HubertPham.PythonPyAudio +PythonSoftwareFoundation.Python +PythonSoftwareFoundation.Python +PythonSoftwareFoundation.Python +PythonSoftwareFoundation.Python +PythonSoftwareFoundation.Python +PythonSoftwareFoundation.Python +PythonSoftwareFoundation.Python +PythonSoftwareFoundation.PythonLauncher +QGISDevelopmentTeam.QGISACoru +QGISDevelopmentTeam.QGISBucuresti +QGISDevelopmentTeam.QGISPi +MichaelHansen.QTextPad +HannaKnutsson.Qalculate +LarusStone.QtSpim +ModuleArt.QuickPictureViewer +PaddyXu.QuickLook +Quicken.Quicken +RCoreTeam.RforWindows +RCoreTeam.RforWindows +RCoreTeam.RforWindows +RStudio.RStudio +Rambox.Rambox +OlegDanilov.RapidEnvironmentEditor +RaspberryPi.RaspberryPiImager +rawtherapeecom.RawTherapee +PaulRawnsley.RedditWallpaperChanger +jklSoft.Rekodecompilerfor +Devolutions.RemoteDesktopManager +Devolutions.RemoteDesktopManagerFree +RemoteMouse.RemoteMouse +BaldurKarlsson.RenderDoc +Antmicro.Renode +Responsively.ResponsivelyApp +RetroShareTeam.RetroShare +VSRevoGroup.RevoUninstaller +VSRevoGroup.RevoUninstallerPro +3TSoftwareLabs.Robo3T +3TSoftwareLabs.Robo3T +3TSoftwareLabs.Robo3T +RocketChatSupport.RocketChat +PunkSoftware.RocketDock +ArtsoftEntertainment.RocksnDiamonds +MarkoBL.Rosi +code4ward.RoyalTS +RoyalApps.RoyalTS +TheRFoundation.Rtools +RubyInstallerTeam.Ruby +RubyInstallerTeam.RubywithMSYS2 +RubyInstallerTeam.Ruby +LukeHaas.RunJS +LukeHaas.RunJS +TheRustProjectDevelopers.Rust +TheRustProjectDevelopers.Rust +TheRustProjectDevelopers.Rust +TheRustProjectDevelopers.Rust +TheRustProjectDevelopers.Rust +TheRustProjectDevelopers.Rust +TheRustProjectDevelopers.Rust +TheRustProjectDevelopers.Rust +TheRustProjectDevelopers.Rust +TopalaSoftwareSolutions.SIW2020aTrial +RicardoVillalba.SMPlayer +Navimatics.SSHFSWin2020 +DotzSoftwares.SVGExplorerExtension +SamsungElectronics.SamsungDeX +mircearoata.SatisfactoryModLauncher +ScratchFoundation.ScratchDesktop +NickeManarin.ScreenToGif +TheScribusTeam.Scribus +TheScummVMTeam.ScummVM +spikespaz.SearchDeflector +Sejda.SejdaPDFDesktop +Datalust.Seq +Microsoft.SharePointOnlineManagementShell +ShareXTeam.ShareX +RandyRantscom.SharpKeys +Meltytech.Shotcut +SigilEbook.Sigil +OpenWhisperSystems.Signal +OpenWhisperSystems.Signal +OpenWhisperSystems.Signal +OpenWhisperSystems.Signal +OpenWhisperSystems.Signal +OpenWhisperSystems.Signal +OpenWhisperSystems.Signal +Approximatrix.SimplyFortran3 +AshleyStone.SitdownMW +SkypeTechnologies.Skype +SkypeTechnologies.Skype +SkypeTechnologies.Skype +SlackTechnologies.SlackMachineWide +TechSmith.Snagit2020 +SnakeNestcom.SnakeTail +CoryPlotts.Snoop +SmartBearSoftware.SoapUI +SonicPi.SonicPi +Sonos.Sonos +Sonos.SonosController +AntoineAflalo.SoundSwitch +Atlassian.Sourcetree +SpeedCrunch.SpeedCrunch +SpekProject.Spek +StandardNotes.StandardNotes +Valve.Steam +wwwsbclorg.SteelBankCommonLisp +SteelSeries.SteelSeriesEngine +Stellariumteam.Stellarium +Stellariumteam.Stellarium +Stellariumteam.Stellarium +strawberryperlcomproject.StrawberryPerl +GeneralWorkings.StreamlabsOBS +GeneralWorkings.StreamlabsOBS +GeneralWorkings.StreamlabsOBS +Streamlink.Streamlink +SebastianMeyer.StreamlinkTwitchGUI +JanHovancik.Stretchly +JanHovancik.Stretchly +JanHovancik.Stretchly +Stride.Stride +BrickLink.Studio +SublimeHQ.SublimeMerge +SublimeHQ.SublimeText3 +KrzysztofKowalczyk.SumatraPDF +SuperColliderCommunity.SuperCollider +SuperTuxKart.SuperTuxKart3Dopensourcearcaderacerwithavarietycharacterstracksandmodestoplay +Microsoft.SurfaceDuoEmulator +SyncTrayzor.SyncTrayzor +MisterGroup.SystemExplorer +OpenVPNTechnologies.TAPWindows +erengy.Taiga +Tailscale.Tailscale +Tailscale.TailscaleIPN +TaiseiProject.TaiseiProject +Taskcade.Taskade +Taskcade.Taskade +TreasureData.Tdagent +TreasureData.Tdagent +BenitovanderZander.TeXstudioTeXstudioisafullyfeaturedLaTeXeditor +TeXUsersGroup.TeXworks +TeamSpeakSystems.TeamSpeak3Client +TechPowerUp.TechPowerUpGPUZ +TelegramFZ.TelegramDesktop +TelegramFZ.TelegramDesktop +TelegramFZ.TelegramDesktop +TelegramFZ.TelegramDesktop +TelegramFZ.TelegramDesktop +TelegramFZ.TelegramDesktop +TelegramFZ.TelegramDesktop +TelegramFZ.TelegramDesktop +TelegramFZ.TelegramDesktop +TeraTermProject.TeraTerm +EugenePankov.Terminus +EugenePankov.Terminus +EugenePankov.Terminus +CompuPhase.Termite +TesseractOCRcommunity.TesseractOCRopensourceOCRengine +Texmaker.Texmaker +Texnomic.TexnomicSecureDNSTerminal +RaMMicHaeL.Textify +Appestcom.TickTick +GlavSoft.TightVNC +TikzEdt.TikzEdt +mapeditororg.Tiled +Nadeo.TmNationsForever +Toggl.TogglDesktop +Toggl.TogglTrack +TortoiseGit.TortoiseGit +TortoiseSVN.TortoiseSVN +TortoiseSVN.TortoiseSVN +TranslucentTBOpenSourceDevelopers.TranslucentTB +TransmissionProject.Transmission +YurySidorovTransmissionRemoteGUIworkinggroup.TransmissionRemoteGUI +BinaryFortressSoftware.TrayStatus +BinaryFortressSoftware.TrayStatus +JAMSoftware.TreeSizeFree +JAMSoftware.TreeSize +Trelbyorg.Trelby +CeruleanStudios.Trillian +TunnelBear.TunnelBear +NewBreedSoftware.TuxPaint +InspectElement.Tweeten +XanderFrangos.TwinkleTray +TwitchInteractive.Twitch +GDATACyberDefense.TypeRefHasher +SafelyRemovecom.USBSafelyRemove +DrewNaylor.UXLLauncher +DrewNaylor.UXLLauncher +Ultimaker.UltimakerCura +Ultimaker.UltimakerCura +Ultimaker.UltimakerCura +uvncbvba.UltraVnc +ReasonSoftware.Unchecky +UnifiedIntents.UnifiedRemote +UnityTechnologies.UnityHub +Microsoft.UpdateforKB2504637 +Microsoft.UpdateforMicrosoftVisualStudio2015KB3095681 +Ubisoft.Uplay +UMEZAWATakeshi.UtVideoCodecSuite +VCV.VCVRack +VideoLAN.VLCmediaplayer +VideoLAN.VLCmediaplayer +VideoLAN.VLCmediaplayer +VMware.VMwareHorizonClient +VMware.VMwarePlayer +VMware.VMwareWorkstation +RealVNC.VNCServer +RealVNC.VNCViewer +Microsoft.VSCodium +Microsoft.VSCodium +marhauserssourceforgenet.VcXsrv +BramMoolenaaretal.Vim +VirtManagerProject.VirtViewer +VivaldiTechnologies.Vivaldi +BlackTreeGaming.Vortex +VoyagerX.Vrew +LunarG.VulkanSDK +WarzoneProject.Warzone +Waterfox.WaterfoxCurrent +Waterfox.WaterfoxCurrent +Waterfox.WaterfoxCurrent +Devolutions.WaykNow +Buds.WeakAurasCompanion +Buds.WeakAurasCompanion +Buds.WeakAurasCompanion +Buds.WeakAurasCompanion +MachineLearningGroupUniversityofWaikatoHamiltonNZ.Weka +ImageWriterDevelopers.Win32DiskImager +SamHocevar.WinCompose +TimothyJohnson.WinDynamicDesktop +TimothyJohnson.WinDynamicDesktop +TimothyJohnson.WinDynamicDesktop +Navimatics.WinFsp2020 +HTTrack.WinHTTrackWebsiteCopier +ThingamahoochieSoftware.WinMerge +winrar.WinRAR +winrar.WinRAR +MartinPrikryl.WinSCP +Corel.WinZip +Winamp.Winamp +Microsoft.Windows10UpdateAssistant +Microsoft.WindowsAdminCenter +Microsoft.WindowsAssessmentandDeploymentKitWindows10 +Microsoft.WindowsAssessmentandDeploymentKitWindowsPreinstallationEnvironmentAddonsWindows10 +Microsoft.WindowsDriverKitWindows +DynastreamInnovations.WindowsDriverPackageDynastreamInnovationsANTLibUSBDrivers +SiliconLabsSoftware.WindowsDriverPackageSiliconLabsSoftwareUSB +Microsoft.WindowsSDKAddOn +Microsoft.WindowsSoftwareDevelopmentKitWindows +Microsoft.WindowsSoftwareDevelopmentKitWindows +Microsoft.WindowsSoftwareDevelopmentKitWindows +WireGuard.WireGuard +TheWiresharkdevelopercommunitywwwwiresharkorg.Wireshark +TheWiresharkdevelopercommunitywwwwiresharkorg.Wireshark +TheWiresharkdevelopercommunitywwwwiresharkorg.Wireshark +TheWiresharkdevelopercommunitywwwwiresharkorg.Wireshark +AntibodySoftware.WizFile +AntibodySoftware.WizKey +AntibodySoftware.WizMouse +AntibodySoftware.WizTree +AntibodySoftware.WizTree +Automattic.WordPresscom +Automattic.WordPresscom +Automattic.WordPresscom +Automattic.WordPresscom +RobCaelersRaymondPenners.Workrave +Writage.Writage +X2GoProject.X2GoClientforWindows +Bitnami.XAMPP +ChristianHohnstaedt.XCA +TheTBOOXOpenSourceGroup.XMakebuildutility +XMind.XMind +GougeletPierree.XnView +GougeletPierree.XnViewMP +YarnContributors.Yarn +BeijingYinxiangBijiTechnologies.YinxiangBijiv +BeijingYinxiangBijiTechnologies.YinxiangBijiv +BeijingYinxiangBijiTechnologies.YinxiangBijiv +BeijingYinxiangBijiTechnologies.YinxiangBijiv +BeijingYinxiangBijiTechnologies.YinxiangBijiv +AdlerLuiz.YouTubeMusicDesktopApp +Yubico.YubiKeyManager +Zentimocom.ZentimoPRO +ZeroTier.ZeroTierOne +HendrikErz.Zettlr +RobinStuartBogDanVatra.Zint +Zoom.Zoom +Zoom.ZoomOutlookPlugin +CorporationforDigitalScholarship.Zotero +KandraLabs.Zulip +SangomaTechnologies.Zulu +ZygorGuides.ZygorClientUninstaller +Balena.balenaEtcher +Balena.balenaEtcher +Balena.balenaEtcher +Balena.balenaEtcher +Balena.balenaEtcher +Balena.balenaEtcher +Balena.balenaEtcher +Balena.balenaEtcher +NathanielJohns.beatdrop +ClementTsang.bottom +butterflowuigithub.butterflowui +KovidGoyal.calibre +ElliottZheng.copytranslator +thedarktableproject.darktable +dnGrepCommunityContributors.dnGREP +JGraph.drawio +HardcodedSoftware.dupeGuru +eMClient.eMClient +Ebbflowio.ebbflow +fluxSoftware.flux +KurataSayuri.ffftp +wereturtle.ghostwriter +gnuplotdevelopmentteam.gnuplotpatchlevel8 +StefansTools.grepWin +DrewNaylor.guinget +DrewNaylor.guinget +DrewNaylor.guinget +eVenture.hidemeVPN +eVenture.hidemeVPN +PurpleI2P.i2pd +VantageLinguistics.iSEEKAnswerWorksEnglishRuntime +Apple.iTunes +KDE.kdenlive +KDE.kdiff3 +NextGenerationSoftware.mRemoteNG +MaximaTeam.maxima +FrankSkare.mpvnet +720kb.ndm +xiles.nexusfont +ownCloud.ownCloud +EasternGraphics.pConplannerPRO +LaurentPRendeCotret.pandocplot +ThepgAdminDevelopmentTeam.pgAdmin4 +ThepgAdminDevelopmentTeam.pgAdmin4 +ThepgAdminDevelopmentTeam.pgAdmin4 +ThepgAdminDevelopmentTeam.pgAdmin4 +TheqBittorrentproject.qBittorrent +TheqBittorrentproject.qBittorrent +TheqBittorrentproject.qBittorrent +remoteit.remoteit +remoteit.remoteit +Lightbend.sbt +ScilabEnterprises.scilab +TheSqlectronTeam.sqlectron +JanHovancik.stretchly +OliverSchwendener.ueli +OliverSchwendener.ueli +OliverSchwendener.ueli +Humanity.xmoto +Humanity.xmoto +Microsoft.微软设备健康助手 +Alipaycom.支付宝安全控件 +百度在线网络技术有限公司.百度网盘 +腾讯科技有限公司.腾讯QQ diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj index 28da9287c3..44ac4991a9 100644 --- a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj +++ b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj @@ -270,6 +270,8 @@ + + @@ -310,6 +312,8 @@ true + + diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters index 1f5a663e35..a4dc3bbca8 100644 --- a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters +++ b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters @@ -141,6 +141,12 @@ Public\winget + + Public\winget + + + Public\winget + @@ -236,6 +242,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/src/AppInstallerCommonCore/AppInstallerStrings.cpp b/src/AppInstallerCommonCore/AppInstallerStrings.cpp index 9a57111b4c..838703f1f4 100644 --- a/src/AppInstallerCommonCore/AppInstallerStrings.cpp +++ b/src/AppInstallerCommonCore/AppInstallerStrings.cpp @@ -1,8 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #include "pch.h" -#include "Public/AppInstallerLogging.h" #include "Public/AppInstallerStrings.h" +#include "Public/AppInstallerErrors.h" +#include "Public/AppInstallerLogging.h" #include "icu.h" namespace AppInstaller::Utility @@ -27,28 +28,28 @@ namespace AppInstaller::Utility if (U_FAILURE(err)) { AICLI_LOG(Core, Error, << "utext_openUTF8 returned " << err); - THROW_HR(E_UNEXPECTED); + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR); } m_brk.reset(ubrk_open(type, nullptr, nullptr, 0, &err)); if (U_FAILURE(err)) { AICLI_LOG(Core, Error, << "ubrk_open returned " << err); - THROW_HR(E_UNEXPECTED); + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR); } ubrk_setUText(m_brk.get(), m_text.get(), &err); if (U_FAILURE(err)) { AICLI_LOG(Core, Error, << "ubrk_setUText returned " << err); - THROW_HR(E_UNEXPECTED); + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR); } int32_t i = ubrk_first(m_brk.get()); if (i != 0) { AICLI_LOG(Core, Error, << "ubrk_first returned " << i); - THROW_HR(E_UNEXPECTED); + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR); } } @@ -58,7 +59,7 @@ namespace AppInstaller::Utility // Gets the current byte offset, throwing if the value is UBRK_DONE or negative. size_t CurrentOffset() const { - THROW_HR_IF(E_UNEXPECTED, m_currentBrk < 0); + THROW_HR_IF(E_NOT_VALID_STATE, m_currentBrk < 0); return static_cast(m_currentBrk); } @@ -318,14 +319,14 @@ namespace AppInstaller::Utility if (U_FAILURE(errorCode)) { AICLI_LOG(Core, Error, << "ucasemap_open returned " << errorCode); - THROW_HR(E_UNEXPECTED); + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR); } int32_t cch = ucasemap_utf8FoldCase(caseMap.get(), nullptr, 0, input.data(), static_cast(input.size()), &errorCode); if (errorCode != U_BUFFER_OVERFLOW_ERROR) { AICLI_LOG(Core, Error, << "ucasemap_utf8FoldCase returned " << errorCode); - THROW_HR(E_UNEXPECTED); + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR); } errorCode = UErrorCode::U_ZERO_ERROR; @@ -335,7 +336,7 @@ namespace AppInstaller::Utility if (U_FAILURE(errorCode)) { AICLI_LOG(Core, Error, << "ucasemap_utf8FoldCase returned " << errorCode); - THROW_HR(E_UNEXPECTED); + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR); } while (result.back() == '\0') @@ -353,17 +354,24 @@ namespace AppInstaller::Utility return result; } - bool IsEmptyOrWhitespace(std::wstring_view str) + bool IsEmptyOrWhitespace(std::string_view str) { if (str.empty()) { return true; } - std::wstring inputAsWStr(str.data()); - bool nonWhitespaceNotFound = inputAsWStr.find_last_not_of(s_WideSpaceChars) == std::wstring::npos; + return str.find_last_not_of(s_SpaceChars) == std::string_view::npos; + } + + bool IsEmptyOrWhitespace(std::wstring_view str) + { + if (str.empty()) + { + return true; + } - return nonWhitespaceNotFound; + return str.find_last_not_of(s_WideSpaceChars) == std::wstring_view::npos; } bool FindAndReplace(std::string& inputStr, std::string_view token, std::string_view value) @@ -381,16 +389,39 @@ namespace AppInstaller::Utility std::string& Trim(std::string& str) { - size_t begin = str.find_first_not_of(s_SpaceChars); - size_t end = str.find_last_not_of(s_SpaceChars); - - if (begin == std::string_view::npos || end == std::string_view::npos) + if (!str.empty()) { - str.clear(); + size_t begin = str.find_first_not_of(s_SpaceChars); + size_t end = str.find_last_not_of(s_SpaceChars); + + if (begin == std::string_view::npos || end == std::string_view::npos) + { + str.clear(); + } + else if (begin != 0 || end != str.length() - 1) + { + str = str.substr(begin, (end - begin) + 1); + } } - else + + return str; + } + + std::wstring& Trim(std::wstring& str) + { + if (!str.empty()) { - str = str.substr(begin, (end - begin) + 1); + size_t begin = str.find_first_not_of(s_WideSpaceChars); + size_t end = str.find_last_not_of(s_WideSpaceChars); + + if (begin == std::string_view::npos || end == std::string_view::npos) + { + str.clear(); + } + else if (begin != 0 || end != str.length() - 1) + { + str = str.substr(begin, (end - begin) + 1); + } } return str; diff --git a/src/AppInstallerCommonCore/Errors.cpp b/src/AppInstallerCommonCore/Errors.cpp index d0a9db2495..ce849d984a 100644 --- a/src/AppInstallerCommonCore/Errors.cpp +++ b/src/AppInstallerCommonCore/Errors.cpp @@ -107,6 +107,12 @@ namespace AppInstaller return "Installer failed security check"; case APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH: return "Download size does not match expected content length"; + case APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR: + return "ICU break iterator error"; + case APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR: + return "ICU casemap error"; + case APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR: + return "ICU regex error"; default: return "Unknown Error Code"; } diff --git a/src/AppInstallerCommonCore/NameNormalization.cpp b/src/AppInstallerCommonCore/NameNormalization.cpp new file mode 100644 index 0000000000..2621037ba8 --- /dev/null +++ b/src/AppInstallerCommonCore/NameNormalization.cpp @@ -0,0 +1,443 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "Public/winget/NameNormalization.h" +#include "Public/AppInstallerStrings.h" +#include "Public/winget/Regex.h" + + +namespace AppInstaller::Utility +{ + namespace + { + struct InterimNameNormalizationResult + { + std::wstring Name; + Architecture Architecture; + std::wstring Locale; + }; + + struct InterimPublisherNormalizationResult + { + std::wstring Publisher; + }; + + // To maintain consistency, changes that result in different output must be done in a new version. + // This can potentially be ignored (if thought through) when the changes will only increase the + // number of matches being made, with no impact to existing matches. For instance, removing an + // arbitrary new processor architecture from names would hopefully only affect existing packages + // that were not matching properly. Fixing a bug that was causing bad strings to be produced would + // be impactful, and thus should likely result in a new iteration. + class NormalizationInitial : public details::INameNormalizer + { + static std::wstring PrepareForValidation(std::string_view value) + { + std::wstring result = Utility::Normalize(ConvertToUTF16(value)); + Trim(result); + size_t atPos = result.find(L"@@", 3); + if (atPos != std::wstring::npos) + { + result = result.substr(0, atPos); + } + return result; + } + + // If the string is wrapped with some character groups, remove them. + // Returns true if string was wrapped; false if not. + static bool Unwrap(std::wstring& value) + { + if (value.length() >= 2) + { + bool unwrap = false; + + switch (value[0]) + { + case L'"': + unwrap = value.back() == L'"'; + break; + + case L'(': + unwrap = value.back() == L')'; + break; + } + + if (unwrap) + { + value = value.substr(1, value.length() - 2); + return true; + } + } + + return false; + } + + // Removes all matches from the input string. + static bool Remove(const Regex::Expression& re, std::wstring& input) + { + std::wstring output = re.Replace(input, {}); + bool result = (output != input); + input = std::move(output); + return result; + } + + // Removes the architecture and returns the value, if any + Architecture RemoveArchitecture(std::wstring& value) const + { + Architecture result = Architecture::Unknown; + + // Must detect this first because "32/64 bit" is a superstring of "64 bit" + if (Remove(Architecture32Or64Bit, value)) + { + // If the program is 32 and 64 bit in the same installer, leave as unknown. + } + // Must detect 64 bit before 32 bit because of "x86-64" being a superstring of "x86" + else if (Remove(ArchitectureX64, value) || Remove(Architecture64Bit, value)) + { + result = Architecture::X64; + } + else if (Remove(ArchitectureX32, value) || Remove(Architecture32Bit, value)) + { + result = Architecture::X86; + } + + return result; + } + + // Removes all matches for the given regular expressions + static bool RemoveAll(const std::vector& regexes, std::wstring& value) + { + bool result = false; + + for (const auto& re : regexes) + { + result = Remove(*re, value) || result; + } + + return result; + } + + // Removes all locales and returns the common value, if any + std::wstring RemoveLocale(std::wstring& value) const + { + bool localeFound = false; + std::wstring result; + + std::wstring newValue; + auto newValueInserter = std::back_inserter(newValue); + + Locale.ForEach(value, + [&](bool isMatch, std::wstring_view text) + { + bool copy = !isMatch; + + if (isMatch) + { + std::wstring foldedText = ConvertToUTF16(FoldCase(text)); + + // Ensure that the value is in the locale list + auto bound = std::lower_bound(Locales.begin(), Locales.end(), foldedText); + + if (bound == Locales.end() || *bound != foldedText) + { + // Match was not a locale in our list, so copy it out + copy = true; + } + else if (!localeFound) + { + // First/only match, just extract the value + result = foldedText; + localeFound = true; + } + else if (!result.empty()) + { + // For some reason, there are multiple locales listed. + // See if they have anything in common. + if (result != foldedText) + { + // Not completely the same (expected), see if they are at least the same language + result.erase(result.find(L'-')); + foldedText.erase(foldedText.find(L'-')); + + if (result != foldedText) + { + // Not the same language, abandon having a locale and just clean them + result.clear(); + } + } + } + } + + if (copy) + { + std::copy(text.begin(), text.end(), newValueInserter); + } + + return true; + }); + + value = std::move(newValue); + + return result; + } + + // Splits the string based on the regex matches, excluding empty/whitespace strings + // and any values found in the exclusions. + static std::vector Split(const Regex::Expression& re, const std::wstring& value, const std::vector& exclusions, bool stopOnExclusion = false) + { + std::vector result; + + re.ForEach(value, + [&](bool, std::wstring_view text) + { + if (IsEmptyOrWhitespace(text)) + { + return true; + } + + // Do not stop for an exclusion if it is the first word found + if (!result.empty()) + { + std::wstring foldedText = ConvertToUTF16(FoldCase(text)); + + auto bound = std::lower_bound(exclusions.begin(), exclusions.end(), foldedText); + + if (bound != exclusions.end() && *bound == foldedText) + { + return !stopOnExclusion; + } + } + + result.emplace_back(std::wstring{ text }); + return true; + }); + + return result; + } + + // Joins all of the given strings into a single value + static std::wstring Join(const std::vector& values) + { + std::wstring result; + + for (const auto& v : values) + { + result += v; + } + + return result; + } + + static constexpr Regex::Options reOptions = Regex::Options::CaseInsensitive; + + // Architecture + Regex::Expression ArchitectureX32{ R"((?<=^|[^\p{L}\p{Nd}])(X32|X86)(?=\P{Nd}|$)(?:\sEDITION)?)", reOptions }; + Regex::Expression ArchitectureX64{ R"((?<=^|[^\p{L}\p{Nd}])(X64|AMD64|X86([\p{Pd}\p{Pc}]64))(?=\P{Nd}|$)(?:\sEDITION)?)", reOptions }; + Regex::Expression Architecture32Bit{ R"((?<=^|[^\p{L}\p{Nd}])(32[\p{Pd}\p{Pc}\p{Z}]?BIT)S?(?:\sEDITION)?)", reOptions }; + Regex::Expression Architecture64Bit{ R"((?<=^|[^\p{L}\p{Nd}])(64[\p{Pd}\p{Pc}\p{Z}]?BIT)S?(?:\sEDITION)?)", reOptions }; + Regex::Expression Architecture32Or64Bit{ R"((?<=^|[^\p{L}\p{Nd}])((64[\\\/]32|32[\\\/]64)[\p{Pd}\p{Pc}\p{Z}]?BIT)S?(?:\sEDITION)?)", reOptions }; + + // Locale + Regex::Expression Locale{ R"((? ProgramNameRegexes + { + &Roblox, + &Bomgar, + &PrefixParens, + &EmptyParens, + &FilePathGHS, + &FilePathParens, + &FilePathQuotes, + &FilePath, + &VersionLetter, + &VersionDelimited, + &Version, + &EN, + &NonNestedBracket, + &BracketEnclosed, + &URIProtocol, + &LeadingSymbols, + &TrailingSymbols + }; + + const std::vector PublisherNameRegexes + { + &VersionDelimited, + &Version, + &NonNestedBracket, + &BracketEnclosed, + &URIProtocol, + &NonLetters, + &TrailingNonLetters, + &AcronymSeparators + }; + + // Add values here but use Locales in code. + const std::vector LocaleViews + { + L"AF-ZA", L"AM-ET", L"AR-AE", L"AR-BH", L"AR-DZ", L"AR-EG", L"AR-IQ", L"AR-JO", L"AR-KW", L"AR-LB", L"AR-LY", + L"AR-MA", L"ARN-CL", L"AR-OM", L"AR-QA", L"AR-SA", L"AR-SY", L"AR-TN", L"AR-YE", L"AS-IN", L"BA-RU", L"BE-BY", + L"BG-BG", L"BN-BD", L"BN-IN", L"BO-CN", L"BR-FR", L"CA-ES", L"CA-ES-VALENCIA", + L"CO-FR", L"CS-CZ", L"CY-GB", L"DA-DK", L"DE-AT", + L"DE-CH", L"DE-DE", L"DE-LI", L"DE-LU", L"DSB-DE", L"DV-MV", L"EL-GR", L"EN-AU", L"EN-BZ", L"EN-CA", L"EN-GB", + L"EN-IE", L"EN-IN", L"EN-JM", L"EN-MY", L"EN-NZ", L"EN-PH", L"EN-SG", L"EN-TT", L"EN-US", L"EN-ZA", L"EN-ZW", + L"ES-AR", L"ES-BO", L"ES-CL", L"ES-CO", L"ES-CR", L"ES-DO", L"ES-EC", L"ES-ES", L"ES-GT", L"ES-HN", L"ES-MX", + L"ES-NI", L"ES-PA", L"ES-PE", L"ES-PR", L"ES-PY", L"ES-SV", L"ES-US", L"ES-UY", L"ES-VE", L"ET-EE", L"EU-ES", + L"FA-IR", L"FI-FI", L"FIL-PH", L"FO-FO", L"FR-BE", L"FR-CA", L"FR-CH", L"FR-FR", L"FR-LU", L"FR-MC", L"FY-NL", + L"GA-IE", L"GD-DB", L"GL-ES", L"GSW-FR", L"GU-IN", L"HE-IL", L"HI-IN", L"HR-BA", L"HR-HR", L"HSB-DE", L"HU-HU", + L"HY-AM", L"ID-ID", L"IG-NG", L"II-CN", L"IS-IS", L"IT-CH", L"IT-IT", L"JA-JP", L"KA-GE", L"KK-KZ", L"KL-GL", + L"KM-KH", L"KN-IN", L"KOK-IN", L"KO-KR", L"KY-KG", L"LB-LU", L"LO-LA", L"LT-LT", L"LV-LV", L"MI-NZ", L"MK-MK", + L"ML-IN", L"MN-MN", L"MOH-CA", L"MR-IN", L"MS-BN", L"MS-MY", L"MT-MT", L"NB-NO", L"NE-NP", L"NL-BE", L"NL-NL", + L"NN-NO", L"NSO-ZA", L"OC-FR", L"OR-IN", L"PA-IN", L"PL-PL", L"PRS-AF", L"PS-AF", L"PT-BR", L"PT-PT", L"QUT-GT", + L"QUZ-BO", L"QUZ-EC", L"QUZ-PE", L"RM-CH", L"RO-RO", L"RU-RU", L"RW-RW", L"SAH-RU", L"SA-IN", L"SE-FI", L"SE-NO", + L"SE-SE", L"SI-LK", L"SK-SK", L"SL-SI", L"SMA-NO", L"SMA-SE", L"SMJ-NO", L"SMJ-SE", L"SMN-FI", L"SMS-FI", L"SQ-AL", + L"SV-FI", L"SV-SE", L"SW-KE", L"SYR-SY", L"TA-IN", L"TE-IN", L"TH-TH", L"TK-TM", L"TN-ZA", L"TR-TR", L"TT-RU", + L"UG-CN", L"UK-UA", L"UR-PK", L"VI-VN", L"WO-SN", L"XH-ZA", L"YO-NG", L"ZH-CN", L"ZH-HK", L"ZH-MO", L"ZH-SG", + L"ZH-TW", L"ZU-ZA", L"AZ-CYRL-AZ", L"AZ-LATN-AZ", L"BS-CYRL-BA", L"BS-LATN-BA", L"HA-LATN-NG", L"IU-CANS-CA", + L"IU-LATN-CA", L"MN-MONG-CN", L"SR-CYRL-BA", L"SR-CYRL-CS", L"SR-CYRL-ME", L"SR-CYRL-RS", L"SR-LATN-BA", + L"SR-LATN-CS", L"SR-LATN-ME", L"SR-LATN-RS", L"TG-CYRL-TJ", L"TZM-LATN-DZ", L"UZ-CYRL-UZ", L"UZ-LATN-UZ", + }; + + // The folded and sorted version of LocaleViews. + const std::vector Locales; + + // Add values here but use LegalEntitySuffixes in code. + const std::vector LegalEntitySuffixViews + { + // Acronyms + L"AB", L"AD", L"AG", L"APS", L"AS", L"ASA", L"BV", L"CO", L"CV", L"DOO", L"eV", L"GES", L"GESMBH", L"GMBH", L"INC", L"KG", + L"KS", L"PS", L"LLC", L"LP", L"LTD", L"LTDA", L"MBH", L"NV", L"PLC", L"SL", L"PTY", L"PVT", L"SA", L"SARL", + L"SC", L"SCA", L"SL", L"SP", L"SPA", L"SRL", L"SRO", + + // Words + L"COMPANY", L"CORP", L"CORPORATION", L"HOLDING", L"HOLDINGS", L"INCORPORATED", L"LIMITED", L"SUBSIDIARY" + }; + + // The folded and sorted version of LocaleViews. + const std::vector LegalEntitySuffixes; + + static std::vector FoldAndSort(const std::vector& input) + { + std::vector result; + std::transform(input.begin(), input.end(), std::back_inserter(result), [](const std::wstring_view wsv) { return Utility::ConvertToUTF16(Utility::FoldCase(wsv)); }); + std::sort(result.begin(), result.end()); + return result; + } + + public: + NormalizationInitial() : Locales(FoldAndSort(LocaleViews)), LegalEntitySuffixes(FoldAndSort(LegalEntitySuffixViews)) + { + } + + InterimNameNormalizationResult NormalizeName(std::string_view name) const + { + InterimNameNormalizationResult result; + result.Name = PrepareForValidation(name); + while (Unwrap(result.Name)); // remove wrappers + + // handle (large majority of) SAP Business Object programs + if (SAPPackage.IsMatch(result.Name)) + { + return result; + } + + result.Architecture = RemoveArchitecture(result.Name); + result.Locale = RemoveLocale(result.Name); + + // Extract KB numbers from their parens and preserve them + result.Name = KBNumbers.Replace(result.Name, L"$1"); + + // Repeatedly remove matches for the regexes to create the minimum name + while (RemoveAll(ProgramNameRegexes, result.Name)); + + auto tokens = Split(ProgramNameSplit, result.Name, LegalEntitySuffixes); + result.Name = Join(tokens); + + // Drop all undesired characters + Remove(NonLettersAndDigits, result.Name); + + return result; + } + + InterimPublisherNormalizationResult NormalizePublisher(std::string_view publisher) const + { + InterimPublisherNormalizationResult result; + + result.Publisher = PrepareForValidation(publisher); + while (Unwrap(result.Publisher)); // remove wrappers + + while (RemoveAll(PublisherNameRegexes, result.Publisher)); + + auto tokens = Split(PublisherNameSplit, result.Publisher, LegalEntitySuffixes, true); + result.Publisher = Join(tokens); + + // Drop all undesired characters + Remove(NonLettersAndDigits, result.Publisher); + + return result; + } + + NormalizedName Normalize(std::string_view name, std::string_view publisher) const override + { + InterimNameNormalizationResult nameResult = NormalizeName(name); + InterimPublisherNormalizationResult pubResult = NormalizePublisher(publisher); + + NormalizedName result; + result.Name(ConvertToUTF8(nameResult.Name)); + result.Architecture(nameResult.Architecture); + result.Locale(ConvertToUTF8(nameResult.Locale)); + result.Publisher(ConvertToUTF8(pubResult.Publisher)); + + return result; + } + }; + } + + NameNormalizer::NameNormalizer(NormalizationVersion version) + { + switch (version) + { + case AppInstaller::Utility::NormalizationVersion::Initial: + m_normalizer = std::make_unique(); + break; + default: + THROW_HR(E_INVALIDARG); + } + } + + NormalizedName NameNormalizer::Normalize(std::string_view name, std::string_view publisher) const + { + return m_normalizer->Normalize(name, publisher); + } +} diff --git a/src/AppInstallerCommonCore/Public/AppInstallerErrors.h b/src/AppInstallerCommonCore/Public/AppInstallerErrors.h index 358cd2570f..8cb137bb97 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerErrors.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerErrors.h @@ -59,8 +59,11 @@ #define APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE ((HRESULT)0x8A15002C) #define APPINSTALLER_CLI_ERROR_INSTALLER_SECURITY_CHECK_FAILED ((HRESULT)0x8A15002D) #define APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH ((HRESULT)0x8A15002E) -#define APPINSTALLER_CLI_ERROR_NO_UNINSTALL_INFO_FOUND ((HRESULT)0x8a15002F) -#define APPINSTALLER_CLI_ERROR_EXEC_UNINSTALL_COMMAND_FAILED ((HRESULT)0x8a150030) +#define APPINSTALLER_CLI_ERROR_NO_UNINSTALL_INFO_FOUND ((HRESULT)0x8A15002F) +#define APPINSTALLER_CLI_ERROR_EXEC_UNINSTALL_COMMAND_FAILED ((HRESULT)0x8A150030) +#define APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR ((HRESULT)0x8A150031) +#define APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR ((HRESULT)0x8A150032) +#define APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR ((HRESULT)0x8A150033) namespace AppInstaller { diff --git a/src/AppInstallerCommonCore/Public/AppInstallerStrings.h b/src/AppInstallerCommonCore/Public/AppInstallerStrings.h index 4772e8c8f0..9f83062561 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerStrings.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerStrings.h @@ -113,6 +113,7 @@ namespace AppInstaller::Utility NormalizedString FoldCase(const NormalizedString& input); // Checks if the input string is empty or whitespace + bool IsEmptyOrWhitespace(std::string_view str); bool IsEmptyOrWhitespace(std::wstring_view str); // Find token in the input string and replace with value. @@ -122,6 +123,9 @@ namespace AppInstaller::Utility // Removes whitespace from the beginning and end of the string. std::string& Trim(std::string& str); + // Removes whitespace from the beginning and end of the string. + std::wstring& Trim(std::wstring& str); + // Reads the entire stream into a string. std::string ReadEntireStream(std::istream& stream); diff --git a/src/AppInstallerCommonCore/Public/winget/NameNormalization.h b/src/AppInstallerCommonCore/Public/winget/NameNormalization.h new file mode 100644 index 0000000000..7f17ce91e8 --- /dev/null +++ b/src/AppInstallerCommonCore/Public/winget/NameNormalization.h @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include + +#include +#include + + +namespace AppInstaller::Utility +{ + // The specific version of normalization being used. + enum class NormalizationVersion + { + Initial, + }; + + struct NameNormalizer; + + // A package publisher and name that has been normalized, allowing direct + // comparison across versions and many other facet. Also allows use in + // generating and Id for local packages. + struct NormalizedName + { + NormalizedName() = default; + + const std::string& Name() const { return m_name; } + void Name(std::string&& name) { m_name = std::move(name); } + + Utility::Architecture Architecture() const { return m_arch; } + void Architecture(Utility::Architecture arch) { m_arch = arch; } + + const std::string& Locale() const { return m_locale; } + void Locale(std::string&& locale) { m_locale = std::move(locale); } + + const std::string& Publisher() const { return m_publisher; } + void Publisher(std::string&& publisher) { m_publisher = std::move(publisher); } + + private: + std::string m_name; + Utility::Architecture m_arch = Utility::Architecture::Unknown; + std::string m_locale; + std::string m_publisher; + }; + + namespace details + { + // NameNormalizer interface to allow different versions. + struct INameNormalizer + { + virtual ~INameNormalizer() = default; + + virtual NormalizedName Normalize(std::string_view name, std::string_view publisher) const = 0; + }; + } + + // Helper that manages the lifetime of the internals required to + // execute the name normalization. + struct NameNormalizer + { + NameNormalizer(NormalizationVersion version); + + NormalizedName Normalize(std::string_view name, std::string_view publisher) const; + + private: + std::unique_ptr m_normalizer; + }; +} diff --git a/src/AppInstallerCommonCore/Public/winget/Regex.h b/src/AppInstallerCommonCore/Public/winget/Regex.h new file mode 100644 index 0000000000..8f824e71b3 --- /dev/null +++ b/src/AppInstallerCommonCore/Public/winget/Regex.h @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include +#include +#include + + +namespace AppInstaller::Regex +{ + // Options for regular expression use. + enum class Options + { + None = 0, + CaseInsensitive, + }; + + // Stores the compiled regular expression. + // All pattern strings are considered UTF-8. + // All input strings are considered UTF-16, as this is what ICU operates on internally. + struct Expression + { + Expression(); + Expression(std::string_view pattern, Options options = Options::None); + + Expression(const Expression&); + Expression& operator=(const Expression&); + + Expression(Expression&&); + Expression& operator=(Expression&&); + + ~Expression(); + + // Determines if the expression contains a value. + operator bool() const; + + // Returns a value indicating whether the *entire* input matches the expression. + bool IsMatch(std::wstring_view input) const; + + // Replaces all matches in the input with the replacement. + std::wstring Replace(std::wstring_view input, std::wstring_view replacement) const; + + // For each section of the input, invoke the given functor. This allows the caller + // to iterate over the entire string, taking action as appropriate for each part. + // The parameters are: + // bool :: indicates whether this section was a match + // string_view :: the text for the section + // The functor should return true to continue the loop, or false to break it. + void ForEach(std::wstring_view input, const std::function& f) const; + + private: + struct impl; + std::unique_ptr pImpl; + }; +} diff --git a/src/AppInstallerCommonCore/Regex.cpp b/src/AppInstallerCommonCore/Regex.cpp new file mode 100644 index 0000000000..d0ce534b89 --- /dev/null +++ b/src/AppInstallerCommonCore/Regex.cpp @@ -0,0 +1,211 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "Public/winget/Regex.h" +#include "Public/AppInstallerErrors.h" +#include "Public/AppInstallerLogging.h" + +#define WINGET_THROW_REGEX_ERROR_IF_FAILED(_err_,_func_) \ + if (U_FAILURE(_err_)) \ + { \ + AICLI_LOG(Core, Error, << #_func_ " returned " << _err_); \ + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR); \ + } + + +namespace AppInstaller::Regex +{ + struct Expression::impl + { + using uregex_ptr = wil::unique_any; + using utext_ptr = wil::unique_any; + + impl(std::string_view pattern, Options options) + { + UErrorCode uec = U_ZERO_ERROR; + + utext_ptr patternUtext{ utext_openUTF8(nullptr, pattern.data(), pattern.length(), &uec) }; + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, utext_openUTF8); + + // For now, just handle the one option + uint32_t flags = 0; + + if (options == Options::CaseInsensitive) + { + flags = UREGEX_CASE_INSENSITIVE; + } + + UParseError parseError{}; + + m_regex.reset(uregex_openUText(patternUtext.get(), flags, &parseError, &uec)); + + if (U_FAILURE(uec)) + { + AICLI_LOG(Core, Error, << "uregex_openUText failed with error [" << uec << "] at line " << parseError.line << ", position " << parseError.offset << '\n' << pattern); + THROW_HR(APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR); + } + } + + impl(const impl& other) + { + UErrorCode uec = U_ZERO_ERROR; + + m_regex.reset(uregex_clone(other.m_regex.get(), &uec)); + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, uregex_clone); + } + + impl& operator=(const impl& other) + { + *this = impl{ other }; + } + + impl(impl&&) = default; + impl& operator=(impl&&) = default; + + ~impl() = default; + + bool IsMatch(std::wstring_view input) const + { + UErrorCode uec = U_ZERO_ERROR; + + SetText(input); + + UBool result = uregex_matches(m_regex.get(), -1, &uec); + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, uregex_matches); + + return !!result; + } + + std::wstring Replace(std::wstring_view input, std::wstring_view replacement) const + { + UErrorCode uec = U_ZERO_ERROR; + + SetText(input); + + std::u16string_view u16replacement = Convert(replacement); + utext_ptr replacementUtext{ utext_openUChars(nullptr, u16replacement.data(), u16replacement.length(), &uec) }; + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, utext_openUTF8); + + utext_ptr resultUText{ uregex_replaceAllUText(m_regex.get(), replacementUtext.get(), nullptr, &uec) }; + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, uregex_replaceAllUText); + + int64_t cch = utext_nativeLength(resultUText.get()); + std::wstring result(static_cast(cch), '\0'); + + utext_extract(resultUText.get(), 0, std::numeric_limits::max(), reinterpret_cast(&result[0]), static_cast(result.size()), &uec); + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, utext_extract); + + return result; + } + + void ForEach(std::wstring_view input, const std::function&f) const + { + UErrorCode uec = U_ZERO_ERROR; + + SetText(input); + int32_t startPos = 0; + + while (uregex_findNext(m_regex.get(), &uec)) + { + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, uregex_findNext); + + int32_t pos = uregex_start(m_regex.get(), 0, &uec); + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, uregex_start); + THROW_HR_IF(E_UNEXPECTED, pos == -1); + + // First, send off the unmatched part before the match + if (pos > startPos) + { + if (!f(false, input.substr(startPos, pos - startPos))) + { + return; + } + } + + // Now send the matched part + int32_t end = uregex_end(m_regex.get(), 0, &uec); + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, uregex_end); + THROW_HR_IF(E_UNEXPECTED, end == -1); + + if (!f(true, input.substr(pos, end - pos))) + { + return; + } + + startPos = end; + } + + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, uregex_findNext); + + // Finally, send any remaining part + if (input.length() > static_cast(startPos)) + { + f(false, input.substr(startPos)); + } + } + + private: + static std::u16string_view Convert(std::wstring_view input) + { + static_assert(sizeof(wchar_t) == sizeof(char16_t), "wchar_t and char16_t must be the same size"); + return { reinterpret_cast(input.data()), input.size() }; + } + + void SetText(std::wstring_view input) const + { + UErrorCode uec = U_ZERO_ERROR; + + std::u16string_view u16 = Convert(input); + + uregex_setText(m_regex.get(), u16.data(), static_cast(u16.length()), &uec); + WINGET_THROW_REGEX_ERROR_IF_FAILED(uec, uregex_setText); + } + + uregex_ptr m_regex; + }; + + Expression::Expression() = default; + + Expression::Expression(std::string_view pattern, Options options) : pImpl(std::make_unique(pattern, options)) {} + + Expression::Expression(const Expression& other) + { + if (other.pImpl) + { + pImpl = std::make_unique(*other.pImpl); + } + } + + Expression& Expression::operator=(const Expression& other) + { + return *this = Expression{ other }; + } + + Expression::Expression(Expression&&) = default; + Expression& Expression::operator=(Expression&&) = default; + + Expression::~Expression() = default; + + Expression::operator bool() const + { + return static_cast(pImpl); + } + + bool Expression::IsMatch(std::wstring_view input) const + { + THROW_HR_IF(E_NOT_VALID_STATE, !pImpl); + return pImpl->IsMatch(input); + } + + std::wstring Expression::Replace(std::wstring_view input, std::wstring_view replacement) const + { + THROW_HR_IF(E_NOT_VALID_STATE, !pImpl); + return pImpl->Replace(input, replacement); + } + + void Expression::ForEach(std::wstring_view input, const std::function& f) const + { + THROW_HR_IF(E_NOT_VALID_STATE, !pImpl); + return pImpl->ForEach(input, f); + } +} diff --git a/src/AppInstallerCommonCore/pch.h b/src/AppInstallerCommonCore/pch.h index a5dad48fc7..057f23e19a 100644 --- a/src/AppInstallerCommonCore/pch.h +++ b/src/AppInstallerCommonCore/pch.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "TraceLogging.h"