PrivateFontCollection.AddMemoryFont вызывает случайные ошибки в Windows Server 2012 R2
У меня есть приложение.NET 3.5, которое загружает шрифты в память с помощью PrivateFontCollection.AddMemoryFont и использует их для создания изображений. Я недавно установил это на Windows Server 2012 R2, и это вызывает периодические ошибки.
Проблема иллюстрируется этим методом:
private Bitmap getImage(byte[] fontFile)
{
using (PrivateFontCollection fontCollection = new PrivateFontCollection())
{
IntPtr fontBuffer = Marshal.AllocCoTaskMem(fontFile.Length);
Marshal.Copy(fontFile, 0, fontBuffer, fontFile.Length);
fontCollection.AddMemoryFont(fontBuffer, fontFile.Length);
Bitmap image = new Bitmap(200, 50);
using (Font font = new Font(fontCollection.Families[0], 11f, FontStyle.Regular))
{
using (Graphics graphics = Graphics.FromImage(image))
{
graphics.DrawString(String.Format("{0:HH:mm:ss}", DateTime.Now), font, Brushes.White, new PointF(0f, 0f));
}
}
return image;
}
}
На Windows 7 это работает последовательно. В Windows Server 2012 R2 происходит сбой при повторном вызове с использованием более одного шрифта. Например:
getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Arial.ttf"));
работает, даже если вызывается сотни раз, но вызывает более одного шрифта:
getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Wingding.ttf"));
getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Arial.ttf"));
будет работать для первых нескольких вызовов (20 или около того), но затем начнет давать случайные результаты (второй вызов иногда возвращает изображение с текстом в wingdings - то есть он смешивает шрифты).
Я также иногда (редко) получаю сообщение "Произошла общая ошибка в GDI+" при вызове DrawString.
Ни одна из этих ошибок не возникает в Windows 7.
Я пробовал различные варианты очистки без какого-либо успеха.
В качестве обходного пути я попытался записать файл шрифта на диск, а затем загрузить его с помощью AddFontFile, но (в Windows 2012 R2) файл шрифта блокируется на весь срок службы процесса, поэтому его нельзя удалить. Это делает эту опцию неприемлемой.
Будем очень благодарны за любую помощь в том, чтобы заставить AddMemoryFont работать согласованно или чтобы AddFontFile разблокировал файл.
0 ответов
Поздний ответ, но, может быть, кто-то еще будет доволен этим: у меня были точно такие же проблемы, и после нескольких часов проб и ошибок я обнаружил, что рабочим решением для меня было сохранение шрифта (bytearray из базы данных) в локальный файл и загрузил файл с помощью метода addFontFile.
Все проблемы исчезли. Не идеальное решение, но рабочее.
var path = Path.Combine(TemporaryFontPath, customFont.FontFileName);
if (!Directory.Exists(Path.GetDirectoryName(path)))
Directory.CreateDirectory(Path.GetDirectoryName(path));
if(!File.Exists(path))
File.WriteAllBytes(path, customFont.FontBytes);
using (var pvc = new PrivateFontCollection())
{
pvc.AddFontFile(path);
return pvc.Families.FirstOrDefault();
}