You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用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.

问题原因及解决方案

核心原因

  1. AddFontResource仅将字体加载到当前进程会话,不会主动通知系统和已运行应用刷新字体列表;
  2. 仅复制字体文件到字体目录,未在注册表中注册字体信息,系统无法持久化识别该字体;
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:42:02