How to install a Font programmatically (C#)

I've been having the same issue for the past few days and each solution I found was producing different problems.

I managed to come up with a working code with my colleague and I thought I'd share it for everyone. The code can be found in the following pastebin link:

Installing a font programatically in C#

EDIT In the event this code becomes irretrievable in the future, I have copied it directly into the answer.

[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);
    }
}

As you mentioned, you can launch other executables to install TrueType Fonts for you. I don't know your specific use cases but I'll run down the methods I know of and maybe one will be of use to you.

Windows has a built-in utility called fontview.exe, which you can invoke simply by calling Process.Start("Path\to\file.ttf") on any valid TrueType Font... assuming default file associations. This is akin to launching it manually from Windows Explorer. The advantage here is it's really trivial, but it still requires user interaction per font to install. As far as I know there is no way to invoke the "Install" portion of this process as an argument, but even if there was you'd still have to elevate permissions and battle UAC.

The more intriguing option is a utility called FontReg that replaces the deprecated fontinst.exe that was included on older versions of Windows. FontReg enables you to programatically install an entire directory of Fonts by invoking the executable with the /copy switch:

    var info = new ProcessStartInfo()
        {
            FileName = "Path\to\FontReg.exe",
            Arguments = "/copy",
            UseShellExecute = false,
            WindowStyle = ProcessWindowStyle.Hidden

        };

   Process.Start(info);

Note that the Fonts have to be in the root of wherever FontReg.exe is located. You'll also have to have administrator privileges. If you need your Font installations to be completely transparent, I would suggest launching your application with elevated permissions and approve of the UAC up front, that way when you spawn your child processes you wont need user approval Permissions stuff