10 Comments
In this article I am going to describe how to install a font when your application is installed on a user's machine. You can do this directly in the application code which I will demonstrate, but for completeness I will demonstrate how it could be done when creating setup files for your application in Visual Studio.

1. To install the font using a Windows Installer MSI:
First thing you need to to after you add a Setup Project is add the Fonts Folder. Do this by right clicking File System on Target Machine -> Add Special Folder -> Fonts Folder.



Add your font file (the one you want to install) into the Fonts Folder by right clicking the right hand panel -> Add -> File... You will notice that theRegister property of the font file is vsdrfFont. This will automatically register your font in Windows when your application installs. That's it!

2. To Install the font directly from your application using code:
This is also relatively simple but you need to use some external calls. To add fonts add the following to the class that will contain the method to install the font:
[DllImport("gdi32.dll", EntryPoint="AddFontResourceW", SetLastError=true)]
public static extern int AddFontResource([In][MarshalAs(UnmanagedType.LPWStr)]
                                         string lpFileName);
To remove fonts add the following to the class that will contain the method to uninstall the font:
[DllImport("gdi32.dll", EntryPoint="RemoveFontResourceW", SetLastError=true)]
public static extern int RemoveFontResource([In][MarshalAs(UnmanagedType.LPWStr)]
                                            string lpFileName);
These methods can then easily be called in any method of the class, all you need to pass in is the full path of the font. A return value of 1 means the operation was successful, anything else means there was a problem. Here is some example code:
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace InstallMyFontExample
{
  class Program
  {
    static void Main(string[] args)
    {
      int result = -1;
      int error = 0;

      // Try remove the font.
      result = RemoveFontResource(@"C:\MY_FONT_LOCATION\MY_NEW_FONT.TTF");
      error = Marshal.GetLastWin32Error();
      if (error != 0)
      {
        Console.WriteLine(new Win32Exception(error).Message);
      }
      else
      {
        Console.WriteLine((result == 0) ? "Font was not found." :
                                          "Font removed successfully.");
      }

      // Try install the font.
      result = AddFontResource(@"C:\MY_FONT_LOCATION\MY_NEW_FONT.TTF");
      error = Marshal.GetLastWin32Error();
      if (error != 0)
      {
        Console.WriteLine(new Win32Exception(error).Message);
      }
      else
      {
        Console.WriteLine((result == 0) ? "Font is already installed." :
                                          "Font installed successfully.");
      }
      
      Console.ReadKey();
    }
  }
}

And that's all there is to it.

NOTE: You may not see the font appear in the Windows Fonts directory however the font is really installed, just open up Word and check the font list.

UPDATE: Quite a few developers are using this font installation code when and having problems using the font in their own applications immediately afterward. You should use the code above if you are installing a font that you want other applications to use. If you just want to use a custom font in your own app, there is no need to install it. Here is some code you can use to assign a custom font to a label without actually installing it first:

var pfc = new PrivateFontCollection();
pfc.AddFontFile(@"C:\MyFont.ttf");
myLabel.Font = new Font(pfc.Families[0], 14, FontStyle.Regular);

Comments

Comment by Nasser

Nice work . . .

Nasser
Comment by Mark Ward

This is easily the most useful posting I have found on this subject - thank you.
The only problem is, it doesn't *seem* to work! (For me anyway)
I am running this on Windows 7 64-bit and Windows 2008 server (C# 4.0 out of VSTS 2010). The code all works and the AddFontResource call returns a non-zero number but... the font doesn't show as installed (I look in the Control Panel / Fonts window AND I use the InstalledFontCollection class). Why am I unable to see this font as installed when everything seems to have worked?

Thanks for any ideas on this.

Mark Ward
Comment by Werner

Apologies for this but it's actually a terrible example. I wrote about this when I started figuring out P/Invoke calls and I thought I as really clever. The main issue with this code is that the entry point can point to ANSI or Unicode and could misinterpret the string unless you marshal it correctly. Since all strings in .NET are Unicode I should have been using the 'W' version of the native function explicitly. On top of that, I never set last error on the calls and never checked last error either so the native calls may fail silently like in your case.

The post has been updated with a much more solid example and a side note about the font not appearing in the directory although it is actually installed.

Werner
Comment by liron

Hey,
Windows 7 64 bit, .net 4.0.
I get result=1; error=183.
The font is not installed and not installing.
Any ideas what the problem is?

Thanks

liron
Comment by SteveDude

If you run the code as administrator or shut UAC off, it works fine.

SteveDude
Comment by Heinz

Hi,
Windows 8.1 64 bit
The installation of the font works fine. I can see and use it in Word. But I can not use it on a label in the same application in which I install it. No error. It just does not change the font.
Any help possible?
Thank you

Heinz
Comment by Pal

Does this code work if the user does not have Admin Rights and any other privileges?

Pal
Comment by Werner

@Pal - Yes, to install a Font on a machine you need to at least have local administrator rights.

Comment by Andrzej

Windows 7 64 bit, .net 4.0.
I can see new font in (e.g. Word) only till reboot.
Any ideas what the problem is?
Thanks

Andrzej
Post comment