GetFontData возвращает -1 (GDI_ERROR) в ASP.NET Приложение, но не в консольном приложении. Что могло вызвать это?

#c# #asp.net #pinvoke #32bit-64bit #pdfsharp

#c# #asp.net #pinvoke #32-64-битный #pdfsharp

Вопрос:

Мы используем 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 работает так, как вы указали в своем вопросе.

Комментарии:

1. PDFsharp может использовать либо GDI , либо WPF. В вопросе уже сказано, что сборка WPF работает нормально: «Сборка WPF из PDFsharp отлично работает, кстати». Спасибо за информацию, я не знал, что функции GDI не поддерживаются в службах.