Skip to content

Instantly share code, notes, and snippets.

@SAPikachu
Created April 12, 2012 13:41
Show Gist options
  • Save SAPikachu/2367370 to your computer and use it in GitHub Desktop.
Save SAPikachu/2367370 to your computer and use it in GitHub Desktop.
For use with https://gist.github.com/2367357 . Get font's file path by font name, requires Windows 7 (2008R2 should be OK too). Uses undocumented feature, not sure whether it still works on Win8. Compiled version: http://nmm.me/fq
using System;
using System.Collections.Generic;
using System.Text;
using SharpDX.DirectWrite;
using System.Reflection;
using System.Runtime.InteropServices;
namespace GetFontPath
{
class Program
{
static int Main(string[] args)
{
if (args.Length == 0)
{
Console.Error.WriteLine("Usage: {0} <Font name>");
return 1;
}
var factory = new Factory();
var collection = factory.GetSystemFontCollection(true);
int fontIndex = 0;
var name = args[0];
bool found = collection.FindFamilyName(name, out fontIndex);
if (!found)
{
Console.Error.WriteLine("Can't find <{0}>", name);
return 1;
}
var fontFamily = collection.GetFontFamily(fontIndex);
var fileNames = new List<string>();
for (int font_i = 0; font_i < fontFamily.FontCount; font_i++)
{
var font = fontFamily.GetFont(font_i);
var fontFace = new FontFace(font);
var fontFiles = fontFace.GetFiles();
foreach (var file in fontFiles)
{
// Can't directly use the public interface, it will throw an exception when attempting to read from the stream
var method = file.GetType().GetMethod("GetReferenceKey", BindingFlags.NonPublic | BindingFlags.Instance);
IntPtr pointer = IntPtr.Zero;
unsafe
{
IntPtr pptr = new IntPtr(&pointer);
object[] parameters = { pptr, 0 };
SharpDX.Result result = (SharpDX.Result)method.Invoke(file, parameters);
byte[] data = new byte[(int)parameters[1]];
Marshal.Copy(pointer, data, 0, data.Length);
string fileName = Encoding.Unicode.GetString(data, 8, data.Length - 10);
if (fileName.StartsWith("*"))
{
fileName = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\Fonts\" + fileName.Substring(1));
}
if (fileNames.Find(x => StringComparer.CurrentCultureIgnoreCase.Equals(x, fileName)) == null)
{
fileNames.Add(fileName);
}
}
}
}
foreach (var fileName in fileNames)
{
Console.WriteLine(fileName);
}
return 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment