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"