有没有办法以编程方式将字体永久添加到Windows 7/8 PC? 我已经阅读了几篇关于AddFontResource DLL-Import的帖子,但似乎没有用。
除此之外,MSDN Documentation表示在重新启动计算机后将删除字体,除非将字体添加到注册表中。
如何永久安装字体?如何将字体添加到注册表?是否总是相同的名称/条目?
我必须在运行时动态添加字体,因为我会在用户选择字体后立即获取字体。
备注:我知道如何添加注册表项。我的问题更多的是关于Windows XP,Vista,7和8与不同字体类型之间的兼容性。也许有办法启动另一个为我安装字体的exe。
答案 0 :(得分:8)
正如您所提到的,您可以启动其他可执行文件来为您安装TrueType字体。我不知道你的具体使用案例,但我会按照我所知道的方法运行,也许会对你有用。
Windows有一个名为 fontview.exe 的内置实用程序,只需在任何有效的TrueType字体上调用Process.Start("Path\to\file.ttf")
即可调用它...假设默认文件关联。这类似于从Windows资源管理器手动启动它。这里的优点是它非常简单,但它仍然需要每个字体的用户交互才能安装。据我所知,没有办法调用此过程的“安装”部分作为参数,但即使你仍然需要提升权限并与UAC作战。
更有趣的选项是名为FontReg的实用程序,它替换旧版Windows中包含的已弃用的fontinst.exe。 FontReg 使您能够通过使用 / copy 开关调用可执行文件以编程方式安装整个字体目录:
var info = new ProcessStartInfo()
{
FileName = "Path\to\FontReg.exe",
Arguments = "/copy",
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden
};
Process.Start(info);
请注意,字体必须位于 FontReg.exe 所在位置的根目录中。您还必须拥有管理员权限。如果您需要将Font安装完全透明,我建议您使用提升的权限启动应用程序并预先批准UAC,这样当您生成子进程时,您将不需要用户批准Permissions stuff
答案 1 :(得分:5)
过去几天我一直有同样的问题,我找到的每个解决方案都会产生不同的问题。
我设法与我的同事提出了一份工作代码,我想我会为每个人分享。代码可以在以下pastebin链接中找到:
Installing a font programatically in C#
修改强> 如果此代码在将来变得无法恢复,我将其直接复制到答案中。
[DllImport("gdi32", EntryPoint = "AddFontResource")]
public static extern int AddFontResourceA(string lpFileName);
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
private static extern int AddFontResource(string lpszFilename);
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
private static extern int CreateScalableFontResource(uint fdwHidden, string
lpszFontRes, string lpszFontFile, string lpszCurrentPath);
/// <summary>
/// Installs font on the user's system and adds it to the registry so it's available on the next session
/// Your font must be included in your project with its build path set to 'Content' and its Copy property
/// set to 'Copy Always'
/// </summary>
/// <param name="contentFontName">Your font to be passed as a resource (i.e. "myfont.tff")</param>
private static void RegisterFont(string contentFontName)
{
// Creates the full path where your font will be installed
var fontDestination = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts), contentFontName);
if (!File.Exists(fontDestination))
{
// Copies font to destination
System.IO.File.Copy(Path.Combine(System.IO.Directory.GetCurrentDirectory(), contentFontName), fontDestination);
// Retrieves font name
// Makes sure you reference System.Drawing
PrivateFontCollection fontCol = new PrivateFontCollection();
fontCol.AddFontFile(fontDestination);
var actualFontName = fontCol.Families[0].Name;
//Add font
AddFontResource(fontDestination);
//Add registry entry
Registry.SetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts",actualFontName, contentFontName, RegistryValueKind.String);
}
}
答案 2 :(得分:3)
此功能仅为当前会话安装字体。当。。。的时候 系统重新启动,字体将不存在。要有字体 即使在重新启动系统后安装,也必须列出该字体 注册表。
所以我找到的最佳选择是将字体复制到windows字体目录
File.Copy("MyNewFont.ttf",
Path.Combine(Environment.GetFolderPath(SpecialFolder.Windows),
"Fonts", "MyNewFont.ttf"));
然后在注册表中添加相应的条目,比如
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts");
key.SetValue("My Font Description", "fontname.tff");
key.Close();
答案 3 :(得分:1)
internal static void InstalarFuente(string NombreFnt,string RutaFnt)
{
string CMD = string.Format("copy /Y \"{0}\" \"%WINDIR%\\Fonts\" ", RutaFnt);
EjecutarCMD(CMD);
System.IO.FileInfo FInfo = new System.IO.FileInfo(RutaFnt);
CMD = string.Format("reg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\" /v \"{0}\" /t REG_SZ /d {1} /f", NombreFnt, FInfo.Name);
EjecutarCMD(CMD);
}
public static void EjecutarCMD(string Comando)
{
System.Diagnostics.ProcessStartInfo Info = new System.Diagnostics.ProcessStartInfo("cmd.exe");
Info.Arguments = string.Format("/c {0}", Comando);
Info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
System.Diagnostics.Process.Start(Info);
}
.....
答案 4 :(得分:1)
这个解决方案很干净,无需重启即 (!),但它确实显示了一个&#34;安装字体...&#34;对话框(它自己消失)。
首先,在项目中添加对system32 \ shell32.dll的引用 然后,只使用这3行代码来安装字体:
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder fontFolder = shell.NameSpace(0x14);
fontFolder.CopyHere(@"path_to\the_font.ttf");
3行代码:)
答案 5 :(得分:0)
如果您有Visual Studio 2017,则可以创建新的Visual Studio安装程序 - 安装项目。您可以编辑安装程序以删除对话框,只留下“完成”对话框以向用户显示它运行正常。
从目标计算机上的文件系统(在Visual Studio项目中)中,添加名为Fonts的特殊目录。然后将所需的所有字体添加到Fonts目录中。如果查看添加的每种字体的属性,您将看到Visual Studio已经假定您要注册每种字体。
编译项目,您有一个可以部署的setup.exe的MSI。当然,您需要以管理员身份运行它,但除此之外,这个小程序可以快速有效地运行。我发现这是在Windows上安装字体的最简单方法。
答案 6 :(得分:0)
建立在Erik Bongers答案的基础上,它具有以下优点:无需重启即可工作,并显示一个“正在安装字体...”对话框,该对话框会自动消失,但似乎不适用于Windows 8 +。
using System;
using System.IO;
namespace YourApp.Common
{
public static class FontHandling
{
public static bool IsFontInstalled(string fontName)
{
using (var testFont = new System.Drawing.Font(fontName, 8))
return 0 == string.Compare(fontName, testFont.Name, StringComparison.InvariantCultureIgnoreCase);
}
public static void InstallFont(string fontSourcePath)
{
var shellAppType = Type.GetTypeFromProgID("Shell.Application");
var shell = Activator.CreateInstance(shellAppType);
var fontFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { Environment.GetFolderPath(Environment.SpecialFolder.Fonts) });
if (File.Exists(fontSourcePath))
fontFolder.CopyHere(fontSourcePath);
}
}
}
不应从system32文件夹中直接引用所需的shell32.dll。而是转到“ AddReferences-> COM”,然后在其中搜索“ Microsoft Shell控件和自动化”并引用它。
最后,如果要确保程序中存在自定义字体,可以将字体添加到源代码中(例如,在单独的Fonts文件夹中)并设置其属性:生成操作:无,复制到输出目录:如果较新则复制。