#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 не поддерживаются в службах.