调用AddFontResource API后,新增字体无法在MS PowerPoint中使用
问题:调用AddFontResource添加字体后,PowerPoint无法识别
我们开发了C#代码,通过调用AddFontResource API将字体添加至系统环境,代码执行成功,但新增字体仍无法在MS PowerPoint等应用中被识别使用。
实现代码
private static BooleanResult InstallFont(string fontSource, string contentFontName) { _log.Info("Start installing "+ contentFontName); var userFontDir = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\Windows\Fonts"); var systemFontDir = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); var fontPathInUserFontDir = Path.Combine(userFontDir, contentFontName); var fontPathInSystemFontDir = Path.Combine(systemFontDir, contentFontName); if (!File.Exists(fontPathInSystemFontDir)) { try { _log.Info("Coping " + contentFontName + " to " + fontPathInSystemFontDir); File.Copy(fontSource, fontPathInSystemFontDir); _log.Info("Font successfully Copied."); } catch (Exception ex) { _log.Error($"Unexpected error when copying to system font dir", ex); } } try // Check Windows font folder again and add font resource { if (File.Exists(fontPathInSystemFontDir)) { _log.Info("Font file found: " + fontPathInSystemFontDir); _log.Info("Adding " + fontPathInSystemFontDir + "to Env."); var addFontResourceResult = AddFontResource(fontPathInSystemFontDir); _log.Info("AddFontResource call returned: " + addFontResourceResult); if (addFontResourceResult != 0) { _log.Info("AddFontResource call successful. Font added."); return BooleanResult.DefaultResult; } } } catch (Exception ex) { _log.Error($"Unexpected error when adding font resource from system font dir", ex); } if (!File.Exists(fontPathInUserFontDir)) { try { _log.Info("copying " + contentFontName + " to " + fontPathInUserFontDir); File.Copy(fontSource, fontPathInUserFontDir); _log.Info("Font successfully Copied."); } catch (Exception ex) { _log.Error($"Unexpected error when copying to user's font dir", ex); } } try // Check user's font folder again and add font resource { if (File.Exists(fontPathInUserFontDir)) { _log.Info("Font file found: " + fontPathInUserFontDir); _log.Info("Adding " + fontPathInUserFontDir + "to Env."); var addFontResourceResult = AddFontResource(fontPathInUserFontDir); _log.Info("AddFontResource call returned: " + addFontResourceResult); if (addFontResourceResult != 0) { _log.Info("AddFontResource call Successfull."); return BooleanResult.DefaultResult; } } } catch (Exception ex) { _log.Error($"Unexpected error when adding font resource from user's font dir", ex); } return BooleanResult.FailResult("Font installation failed."); } [System.Runtime.InteropServices.DllImport("gdi32.dll")] private static extern int AddFontResource(string lpszFilename);
执行日志内容
Start installing [目标字体名] Coping [目标字体名] to C:\Windows\Fonts\[目标字体名] Font successfully Copied. Font file found: C:\Windows\Fonts\[目标字体名] Adding C:\Windows\Fonts\[目标字体名] to Env. AddFontResource call returned: 1 AddFontResource call successful. Font added.
问题原因及解决方案
核心原因
AddFontResource仅将字体加载到当前进程会话,不会主动通知系统和已运行应用刷新字体列表;- 仅复制字体文件到字体目录,未在注册表中注册字体信息,系统无法持久化识别该字体;
- PowerPoint等Office应用会缓存字体列表,即使系统更新字体,已运行的实例也不会自动重新加载。
解决步骤
1. 发送系统通知刷新字体列表
在AddFontResource调用成功后,发送WM_FONTCHANGE广播消息,通知系统和所有应用字体已更新:
[System.Runtime.InteropServices.DllImport("user32.dll")] private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); private const int WM_FONTCHANGE = 0x001D; private const int HWND_BROADCAST = 0xFFFF; // 在AddFontResource成功后调用 SendMessage((IntPtr)HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
2. 注册字体到注册表(可选,实现持久化)
如果需要重启系统后字体仍可用,需将字体信息写入注册表:
using Microsoft.Win32; // 系统级注册(需管理员权限) using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", true)) { // 注意:字体显示名需与字体文件内部名称一致,可通过字体文件属性查看 key.SetValue("字体显示名 (TrueType)", contentFontName); } // 用户级注册(无需管理员权限) using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Fonts", true)) { key.SetValue("字体显示名 (TrueType)", contentFontName); }
3. 重启目标应用
Office应用的字体缓存不会随系统通知自动刷新,需关闭并重新打开PowerPoint等应用,才能识别新增字体。
修改后的完整代码示例
private static BooleanResult InstallFont(string fontSource, string contentFontName, string fontDisplayName) { _log.Info("Start installing "+ contentFontName); var userFontDir = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\Windows\Fonts"); var systemFontDir = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); var fontPathInSystemFontDir = Path.Combine(systemFontDir, contentFontName); var fontPathInUserFontDir = Path.Combine(userFontDir, contentFontName); bool isFontAdded = false; // 尝试系统目录安装 if (!File.Exists(fontPathInSystemFontDir)) { try { _log.Info("Coping " + contentFontName + " to " + fontPathInSystemFontDir); File.Copy(fontSource, fontPathInSystemFontDir); _log.Info("Font successfully Copied."); } catch (Exception ex) { _log.Error($"Unexpected error when copying to system font dir", ex); } } if (File.Exists(fontPathInSystemFontDir)) { try { _log.Info("Font file found: " + fontPathInSystemFontDir); _log.Info("Adding " + fontPathInSystemFontDir + " to Env."); var addFontResourceResult = AddFontResource(fontPathInSystemFontDir); _log.Info("AddFontResource call returned: " + addFontResourceResult); if (addFontResourceResult != 0) { // 注册到系统注册表(需管理员权限) try { using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", true)) { key.SetValue($"{fontDisplayName} (TrueType)", contentFontName); } } catch (Exception ex) { _log.Error($"Failed to register font in system registry", ex); } isFontAdded = true; } } catch (Exception ex) { _log.Error($"Unexpected error when adding font resource from system font dir", ex); } } // 系统目录失败则尝试用户目录 if (!isFontAdded && !File.Exists(fontPathInUserFontDir)) { try { _log.Info("copying " + contentFontName + " to " + fontPathInUserFontDir); File.Copy(fontSource, fontPathInUserFontDir); _log.Info("Font successfully Copied."); } catch (Exception ex) { _log.Error($"Unexpected error when copying to user's font dir", ex); } } if (!isFontAdded && File.Exists(fontPathInUserFontDir)) { try { _log.Info("Font file found: " + fontPathInUserFontDir); _log.Info("Adding " + fontPathInUserFontDir + " to Env."); var addFontResourceResult = AddFontResource(fontPathInUserFontDir); _log.Info("AddFontResource call returned: " + addFontResourceResult); if (addFontResourceResult != 0) { // 注册到用户注册表 try { using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Fonts", true)) { key.SetValue($"{fontDisplayName} (TrueType)", contentFontName); } } catch (Exception ex) { _log.Error($"Failed to register font in user registry", ex); } isFontAdded = true; } } catch (Exception ex) { _log.Error($"Unexpected error when adding font resource from user's font dir", ex); } } if (isFontAdded) { // 发送字体更新通知 SendMessage((IntPtr)HWND_BROADCAST, WM_FONTCHANGE, 0, 0); _log.Info("Font installation completed successfully."); return BooleanResult.DefaultResult; } return BooleanResult.FailResult("Font installation failed."); } [System.Runtime.InteropServices.DllImport("gdi32.dll")] private static extern int AddFontResource(string lpszFilename); [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); private const int WM_FONTCHANGE = 0x001D; private const int HWND_BROADCAST = 0xFFFF;
内容的提问来源于stack exchange,提问作者jayapriya T jayan
相关产品推荐
相关产品推荐

