Skip to content

Commit 329b197

Browse files
dkbennettmdanish-khTrenly
authored
Font Install, Uninstall, additional Font List (microsoft#5566)
Implements a good chunk of microsoft#166 Key features and changes: All of the below are experimental behind the fonts experimental feature. Font install is implemented as a winget-common installer that models most of the font install behavior of the operating system in its key components. It deviates from a normal font install in that the install locations and registry key paths are a little different in order to map fonts to an identifiable version-specific deterministic location. This is so we may more easily identify font packages and remove them and avoid font collisions, torn state, or removing fonts from other packages. **Font List update** - Added new font list "--files" option that lists fonts by installed files and their known validity state - Fonts are listed by file where they are located and have an assigned identifier for later use in removal. - The Font Status reflects whether the registry matches an actual font file on disk (fonts without a file are labeled "Corrupt"). - The intent here is to add filters later to get a better idea of what fonts are on the system, where they came from, and which might need repair or removal. At present my system had over 300 font files installed so the list is quite large. **Font Install** - Add font support for install. This is the base WinGet install command, not the 'font' sub-command. - Requires font experimental feature to be enabled. - Added the core Font evaluation code to AppInstallerCommonCore so it is not strictly bound to the CLI. - The font install scheme puts WinGet installed font packages in sub folders and subkeys where they can exist side-by-side with other font packages without worry of file collision and easier high-confidence removal/upgrade and rollback. - Registers the font with the current session and notifies other apps of the new font availability. - Configures the font to be loaded on subsequent sessions. - Install works for machine and user fonts. **Font Uninstall* - Added font support for uninstall. This is the base WinGet uninstall command, not the 'font' sub-command. - Requires font Experimental feature to be enabled. - Uninstall works for WinGet-installed fonts only at this time. ** Font List* - Added font package detection to the PredefinedInstalledSource. - This allows font packages to be detected for uninstall. **Workflows** - Support for Font Install and Uninstall **Tested** - Added many unit tests which exercise the the Font install, uninstall, information gathering, listing, for machine and user scopes. All of the new core code added is exercised in unit tests. - All scopes for install using unit tests and local web server. - Install and uninstall with manifest an local server. - Install and uninstall and list with package from a private package source. - Verified ACLs on the folders match expected permissions for visibility. - Verified per-user and per-machine fonts are installed correctly and show up in Font Settings immediately. **NOT part of this PR and is likely a future PR** - Font upgrade (a new version will be installed side-by-side) - Uninstall of non-packaged fonts. This is in plan, just not in the scope of this PR. - [x] I have signed the [Contributor License Agreement](https://cla.opensource.microsoft.com/microsoft/winget-pkgs). - [x] I have updated the [Release Notes](../doc/ReleaseNotes.md). - [x] This pull request is related to an issue. ----- ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/microsoft/winget-cli/pull/5566) --------- Co-authored-by: Muhammad Danish <[email protected]> Co-authored-by: Kaleb Luedtke <[email protected]>
1 parent 4d740f6 commit 329b197

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2286
-56
lines changed

.github/actions/spelling/expect.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ flargle
177177
flexera
178178
FOF
179179
FOLDERID
180+
FONTCHANGE
181+
FONTHASH
180182
FORPARSING
181183
foundfr
182184
fsanitize
@@ -417,12 +419,15 @@ placeholders
417419
PMS
418420
positionals
419421
posix
422+
postuninstall
420423
powershellgallery
421424
pri
422425
PRIMARYKEY
423426
processthreads
424427
productcode
425428
PRODUCTICON
429+
propkey
430+
PROPVARIANT
426431
proxystub
427432
pscustomobject
428433
pseudocode
@@ -437,6 +442,7 @@ pvm
437442
pwabuilder
438443
PWAs
439444
PWSTR
445+
pwsz
440446
QUERYENDSESSION
441447
qword
442448
RAII
@@ -604,6 +610,7 @@ wincodec
604610
windir
605611
windowsdeveloper
606612
winerror
613+
wingdi
607614
wingetconfigroot
608615
wingetcreate
609616
wingetdev

doc/ReleaseNotes.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,9 @@ The following snippet enables experimental support for fonts via `winget setting
2020
"fonts": true
2121
}
2222
}
23-
2423
```
24+
Manifest Schema version updated to 1.12.0 to add support for fonts.
25+
26+
Experimental initial Font Install and Uninstall via manifest for user and machine scopes has been added.
27+
28+
The font 'list' command has been updated with a new '--details' feature for an alternate view of the installed fonts.

doc/windows/package-manager/winget/returnCodes.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@ ms.localizationpriority: medium
146146
| 0x8A150084 | -1978335100 | APPINSTALLER_CLI_ERROR_SFSCLIENT_PACKAGE_NOT_SUPPORTED | The Microsoft Store package does not support download command. |
147147
| 0x8A150085 | -1978335099 | APPINSTALLER_CLI_ERROR_LICENSING_API_FAILED_FORBIDDEN | Failed to retrieve Microsoft Store package license. The Microsoft Entra Id account does not have required privilege. |
148148
| 0x8A150086 | -1978335098 | APPINSTALLER_CLI_ERROR_INSTALLER_ZERO_BYTE_FILE | Downloaded zero byte installer; ensure that your network connection is working properly. |
149+
| 0x8A150087 | -1979335097 | APPINSTALLER_CLI_ERROR_FONT_INSTALL_FAILED | Failed installing one or more fonts. |
150+
| 0x8A150088 | -1979335096 | APPINSTALLER_CLI_ERROR_FONT_FILE_NOT_SUPPORTED | Font file is not supported and cannot be installed. |
151+
| 0x8A150089 | -1979335095 | APPINSTALLER_CLI_ERROR_FONT_ALREADY_INSTALLED | Font package is already installed. |
152+
| 0x8A15008A | -1979335094 | APPINSTALLER_CLI_ERROR_FONT_FILE_NOT_FOUND | Font file not found. |
153+
| 0x8A15008B | -1979335093 | APPINSTALLER_CLI_ERROR_FONT_UNINSTALL_FAILED | Font uninstall failed. The font may not be in a good state. Try uninstalling after a restart. |
154+
| 0x8A15008C | -1979335092 | APPINSTALLER_CLI_ERROR_FONT_VALIDATION_FAILED | Font validation failed. |
155+
| 0x8A15008D | -1979335091 | APPINSTALLER_CLI_ERROR_FONT_ROLLBACK_FAILED | Font rollback failed. The font may not be in a good state. Try uninstalling after a restart. |
149156

150157
## Install errors.
151158

@@ -170,7 +177,7 @@ ms.localizationpriority: medium
170177
| 0x8A150111 | -1978334959 | APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE_BY_APPLICATION | Application is currently in use by another application. |
171178
| 0x8A150112 | -1978334958 | APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER | Invalid parameter. |
172179
| 0x8A150113 | -1978334957 | APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED | Package not supported by the system. |
173-
| 0x8A150114 | -1978334956 | APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED | The installer does not support upgrading an existing package. |
180+
| 0x8A150114 | -1978334956 | APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED | The installer does not support upgrading an existing package. |
174181
| 0x8A150115 | -1978334955 | APPINSTALLER_CLI_ERROR_INSTALL_CUSTOM_ERROR | Installation failed with installer custom error. |
175182

176183
## Check for package installed status

src/AppInstallerCLICore/Argument.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ namespace AppInstaller::CLI
203203
// Font command
204204
case Execution::Args::Type::Family:
205205
return { type, "family"_liv, ArgTypeCategory::None };
206+
case Execution::Args::Type::Details:
207+
return { type, "details"_liv, ArgTypeCategory::None };
206208

207209
// Configuration commands
208210
case Execution::Args::Type::ConfigurationFile:
@@ -472,6 +474,8 @@ namespace AppInstaller::CLI
472474
return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions };
473475
case Args::Type::Family:
474476
return Argument{ type, Resource::String::FontFamilyNameArgumentDescription, ArgumentType::Positional, false };
477+
case Args::Type::Details:
478+
return Argument{ type, Resource::String::FontDetailsArgumentDescription, ArgumentType::Flag, false };
475479
case Args::Type::Correlation:
476480
return Argument{ type, Resource::String::CorrelationArgumentDescription, ArgumentType::Standard, Argument::Visibility::Hidden };
477481
default:

src/AppInstallerCLICore/Commands/FontCommand.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#include "pch.h"
44
#include "FontCommand.h"
55
#include "Workflows/CompletionFlow.h"
6-
#include "Workflows/WorkflowBase.h"
76
#include "Workflows/FontFlow.h"
7+
#include "Workflows/WorkflowBase.h"
88
#include "Resources.h"
99

1010
namespace AppInstaller::CLI
@@ -16,6 +16,8 @@ namespace AppInstaller::CLI
1616

1717
Utility::LocIndView s_FontCommand_HelpLink = "https://aka.ms/winget-command-font"_liv;
1818

19+
// Base Font Command
20+
1921
std::vector<std::unique_ptr<Command>> FontCommand::GetCommands() const
2022
{
2123
return InitializeFromMoveOnly<std::vector<std::unique_ptr<Command>>>({
@@ -43,17 +45,13 @@ namespace AppInstaller::CLI
4345
OutputHelp(context.Reporter);
4446
}
4547

48+
// FontListCommand
49+
4650
std::vector<Argument> FontListCommand::GetArguments() const
4751
{
4852
return {
4953
Argument::ForType(Args::Type::Family),
50-
Argument::ForType(Args::Type::Moniker),
51-
Argument::ForType(Args::Type::Source),
52-
Argument::ForType(Args::Type::Tag),
53-
Argument::ForType(Args::Type::Exact),
54-
Argument::ForType(Args::Type::AuthenticationMode),
55-
Argument::ForType(Args::Type::AuthenticationAccount),
56-
Argument::ForType(Args::Type::AcceptSourceAgreements),
54+
Argument::ForType(Args::Type::Details),
5755
};
5856
}
5957

src/AppInstallerCLICore/ExecutionArgs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ namespace AppInstaller::CLI::Execution
125125

126126
// Font Command
127127
Family,
128+
Details,
128129

129130
// Stub package (extended features)
130131
ExtendedFeaturesEnable,

src/AppInstallerCLICore/Resources.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,16 +303,30 @@ namespace AppInstaller::CLI::Resource
303303
WINGET_DEFINE_RESOURCE_STRINGID(FileNotFound);
304304
WINGET_DEFINE_RESOURCE_STRINGID(FilesRemainInInstallDirectory);
305305
WINGET_DEFINE_RESOURCE_STRINGID(FlagContainAdjoinedError);
306+
WINGET_DEFINE_RESOURCE_STRINGID(FontAlreadyInstalled);
306307
WINGET_DEFINE_RESOURCE_STRINGID(FontCommandLongDescription);
307308
WINGET_DEFINE_RESOURCE_STRINGID(FontCommandShortDescription);
308309
WINGET_DEFINE_RESOURCE_STRINGID(FontFace);
309310
WINGET_DEFINE_RESOURCE_STRINGID(FontFaces);
310311
WINGET_DEFINE_RESOURCE_STRINGID(FontFamily);
311312
WINGET_DEFINE_RESOURCE_STRINGID(FontFamilyNameArgumentDescription);
313+
WINGET_DEFINE_RESOURCE_STRINGID(FontFileNotSupported);
314+
WINGET_DEFINE_RESOURCE_STRINGID(FontDetailsArgumentDescription);
312315
WINGET_DEFINE_RESOURCE_STRINGID(FontFilePaths);
316+
WINGET_DEFINE_RESOURCE_STRINGID(FontInstallFailed);
313317
WINGET_DEFINE_RESOURCE_STRINGID(FontListCommandLongDescription);
314318
WINGET_DEFINE_RESOURCE_STRINGID(FontListCommandShortDescription);
319+
WINGET_DEFINE_RESOURCE_STRINGID(FontPackage);
320+
WINGET_DEFINE_RESOURCE_STRINGID(FontRollbackFailed);
321+
WINGET_DEFINE_RESOURCE_STRINGID(FontStatus);
322+
WINGET_DEFINE_RESOURCE_STRINGID(FontStatusCorrupt);
323+
WINGET_DEFINE_RESOURCE_STRINGID(FontStatusOK);
324+
WINGET_DEFINE_RESOURCE_STRINGID(FontStatusUnknown);
325+
WINGET_DEFINE_RESOURCE_STRINGID(FontTitle);
326+
WINGET_DEFINE_RESOURCE_STRINGID(FontUninstallFailed);
327+
WINGET_DEFINE_RESOURCE_STRINGID(FontValidationFailed);
315328
WINGET_DEFINE_RESOURCE_STRINGID(FontVersion);
329+
WINGET_DEFINE_RESOURCE_STRINGID(FontWinGetSupported);
316330
WINGET_DEFINE_RESOURCE_STRINGID(ForceArgumentDescription);
317331
WINGET_DEFINE_RESOURCE_STRINGID(GatedVersionArgumentDescription);
318332
WINGET_DEFINE_RESOURCE_STRINGID(GetManifestResultVersionNotFound);
@@ -461,8 +475,8 @@ namespace AppInstaller::CLI::Resource
461475
WINGET_DEFINE_RESOURCE_STRINGID(MSStoreStoreClientBlocked);
462476
WINGET_DEFINE_RESOURCE_STRINGID(MultipleExclusiveArgumentsProvided);
463477
WINGET_DEFINE_RESOURCE_STRINGID(MultipleInstalledPackagesFound);
464-
WINGET_DEFINE_RESOURCE_STRINGID(MultipleNonPortableNestedInstallersSpecified);
465478
WINGET_DEFINE_RESOURCE_STRINGID(MultiplePackagesFound);
479+
WINGET_DEFINE_RESOURCE_STRINGID(MultipleUnsupportedNestedInstallersSpecified);
466480
WINGET_DEFINE_RESOURCE_STRINGID(MultiQueryArgumentDescription);
467481
WINGET_DEFINE_RESOURCE_STRINGID(MultiQueryPackageAlreadyInstalled);
468482
WINGET_DEFINE_RESOURCE_STRINGID(MultiQueryPackageNotFound);

src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ namespace AppInstaller::CLI::Workflow
106106
<< std::endl;
107107
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_NOT_FOUND);
108108
}
109-
else if (!IsPortableType(installer.NestedInstallerType))
109+
else if (!DoesInstallerTypeSupportMultipleNestedInstallers(installer.NestedInstallerType))
110110
{
111111
// Update the installerPath to the extracted non-portable installer.
112112
AICLI_LOG(CLI, Info, << "Setting installerPath to: " << nestedInstallerPath);
@@ -138,10 +138,10 @@ namespace AppInstaller::CLI::Workflow
138138
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_INVALID_MANIFEST);
139139
}
140140

141-
if (installer.NestedInstallerType != InstallerTypeEnum::Portable && nestedInstallerFiles.size() != 1)
141+
if (!DoesInstallerTypeSupportMultipleNestedInstallers(installer.NestedInstallerType) && (nestedInstallerFiles.size() != 1))
142142
{
143-
AICLI_LOG(CLI, Error, << "Multiple nested installers specified for non-portable nested installerType");
144-
context.Reporter.Error() << Resource::String::MultipleNonPortableNestedInstallersSpecified << std::endl;
143+
AICLI_LOG(CLI, Error, << "Multiple nested installers specified for unsupported nested installerType");
144+
context.Reporter.Error() << Resource::String::MultipleUnsupportedNestedInstallersSpecified << std::endl;
145145
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_INVALID_MANIFEST);
146146
}
147147
}

src/AppInstallerCLICore/Workflows/DownloadFlow.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ namespace AppInstaller::CLI::Workflow
6363
return L".msix"sv;
6464
case InstallerTypeEnum::Zip:
6565
return L".zip"sv;
66+
case InstallerTypeEnum::Font:
67+
{
68+
const auto& fileName = GetFileNameFromURI(installer->Url);
69+
if (fileName.has_extension())
70+
{
71+
return fileName.extension().c_str();
72+
}
73+
else
74+
{
75+
THROW_HR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
76+
}
77+
}
6678
default:
6779
THROW_HR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
6880
}
@@ -288,6 +300,7 @@ namespace AppInstaller::CLI::Workflow
288300
case InstallerTypeEnum::Nullsoft:
289301
case InstallerTypeEnum::Portable:
290302
case InstallerTypeEnum::Wix:
303+
case InstallerTypeEnum::Font:
291304
case InstallerTypeEnum::Zip:
292305
context << DownloadInstallerFile;
293306
break;

0 commit comments

Comments
 (0)