2

我想在更新过程中以编程方式部署字体包。因此,我需要用\Windows\Fonts从 ZIP 存档中提取的新字体文件替换旧字体文件。删除现有字体文件将导致IOException, 因为另一个进程正在访问该文件。

我试图通过调用RemoveFontResource并使用WM_FONTCHANGE消息传播更改来释放字体,但没有运气。RemoveFontResource返回false本机错误 2(找不到文件?)和 HRESULT -2147467259。该文件确实存在。

示例代码:

[DllImport("coredll.dll", SetLastError = true)]
private static extern int RemoveFontResource(string lpName);

[DllImport("coredll.dll", SetLastError = true)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

private const int WM_FONTCHANGE = 0x001D;
private const int HWND_BROADCAST = 0xffff;

public const string SAMPLE_FILE = @"\Windows\Fonts\MyFont.ttf";

public void RemoveFont()
{
  if (!RemoveFontResource(SAMPLE_FILE)) 
  {
    throw new Win32Exception(Marshal.GetLastWin32Error());
  }

  SendMessage(new IntPtr(HWND_BROADCAST), WM_FONTCHANGE, IntPtr.Zero, IntPtr.Zero);

  File.Delete(SAMPLE_FILE);
}

实际上是否有一种干净的方法可以在系统范围内部署和替换字体?

4

1 回答 1

2

如果字体文件是 OS 映像的一部分,则它们具有 eXecute-In-Place (XIP) 属性集(只读、系统、ROM)并且不能简单地替换。虽然可以在上面复制一个同名文件,但隐藏了原始文件。如果顶部复制的文件被删除,则原始文件又回来了。所有 XIP 文件都是这种情况。

我建议您使用 SysCache 目录来替换文件。这将适用于所有文件替换,无论它们是 XIP、驱动程序、DLL、正在使用还是以其他方式锁定以进行替换。

如果您将与原始文件同名的文件放在 syscache 目录中,则将使用这些文件而不是原始文件。但是您必须在将文件放入 syscache 目录后对设备进行热启动。Windows CE/Mobile 将仅在操作系统启动期间识别和“使用”系统缓存文件。

syscache 目录的位置可能会有所不同,具体取决于操作系统版本和 OEM 决策。在 WM 6 设备上,它应该是 \Windows\System\syscache。检查设备的文件系统是否存在现有的 syscache 目录。

BTW:字体文件不需要放在\Windows\Fonts 下,放在\Windows 下就可以了。

于 2013-07-04T03:57:12.270 回答