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();
}
Другие вопросы по тегам