GetFontData возвращает -1 (GDI_ERROR) в приложении ASP.NET, но не в консольном приложении. Что может вызвать это?
Мы используем PDFSharp (сборка GDI+) в одном из наших веб-приложений. В одном экспортере PDF мы используем несистемный шрифт TrueType, и он работает как шарм в нашей среде разработки, но вылетает, когда мы запускаем его в производство.
Основное различие (я думаю) между нашим разработчиком и производством заключается в том, что наши производственные серверы работают на 64-разрядной Windows Server 2008, а наш разработчик - на 32-разрядной версии 2008. Я написал крошечную тестовую программу для отладки.
try
{
new XFont("ocrb10", 10, XFontStyle.Regular, new XPdfFontOptions(PdfFontEncoding.Unicode, PdfFontEmbedding.Always));
}
catch (Exception exc) { Console.WriteLine(exc.StackTrace); }
Сообщение об ошибке InvalidOperationException: Внутренняя ошибка. Данные о шрифте не могут быть восстановлены.
at PdfSharp.Fonts.OpenType.FontData.CreateGdiFontImage(XFont font, XPdfFontOptions options)
at PdfSharp.Fonts.OpenType.FontData..ctor(XFont font, XPdfFontOptions options)
at PdfSharp.Fonts.OpenType.OpenTypeDescriptor..ctor(XFont font, XPdfFontOptions options)
at PdfSharp.Fonts.OpenType.OpenTypeDescriptor..ctor(XFont font)
at PdfSharp.Fonts.FontDescriptorStock.CreateDescriptor(XFont font)
at PdfSharp.Drawing.XFont.get_Metrics()
at PdfSharp.Drawing.XFont.Initialize()
at PdfSharp.Drawing.XFont..ctor(String familyName, Double emSize, XFontStyle style, XPdfFontOptions pdfOptions)
Я собрал PDFSharp из исходного кода и добавил отладочный код, чтобы понять, что происходит. Проблема в том, что вызов pinvoke для GetFontData возвращает -1 (GDI_ERROR). Автор PdfSharp добавил комментарии об этом в FontData.cs, где происходит ошибка (поиск GDI_ERROR), но он также не нашел правильного разрешения.
// Line 138 in FontData.cs, this GetFontData returns -1 here when
// running as a web application on a 64bit windows host (regardles of WOW64
// being enabled or not)
int size = NativeMethods.GetFontData(hdc, 0, 0, null, 0);
Теперь проблема для меня заключается в том, что я не могу воспроизвести эту ошибку в любой среде, когда я запускаю код как консольное приложение. Я пытался включать и выключать WOW64 для пула приложений и пробовал запускать пул приложений под своими собственными учетными данными на случай, если возникли какие-либо проблемы, связанные с разрешениями, но безрезультатно.
WPF-сборка PDFSharp прекрасно работает, и вполне возможно, что мы просто переключимся на это, если не найдем никакого решения, но мне действительно любопытно, что может вызвать это.
Может кто-нибудь, пожалуйста, помогите мне с дальнейшими шагами отладки? Чем среда отличается при работе в IIS/ASP.NET от консольного приложения, когда дело доходит до PInvokes?
1 ответ
Разработчики очень часто полагаются на GDI+ для получения метрик шрифта, однако в соответствии с MSDN:
Функции и классы GDI+ не поддерживаются для использования в службе Windows. Попытка использовать эти функции и классы из службы Windows может привести к непредвиденным проблемам, таким как снижение производительности службы и исключений или ошибок во время выполнения.
В FontData.cs я нашел следующее:
#if GDI
100 /// <summary>
101 /// Create the font image using GDI+ functionality.
102 /// </summary>
103 void CreateGdiFontImage(XFont font, XPdfFontOptions options/*, XPrivateFontCollection privateFontCollection*/)
104 {
105 System.Drawing.Font gdiFont = font.RealizeGdiFont();
106 NativeMethods.LOGFONT logFont;
...
Вот почему GDI+ сборка PDFSharp не работает в сервисах, в то время как сборка WPF работает так, как вы заявили на свой вопрос.