NetLabels & WPF Printing Issue

Recently came across an error when trying to print labels via NetLabels 3.0. The print job would fail and would throw an error. The problem is that a Windows registry key for a font (or fonts) gets corrupt. More details below.

The NetLabels error will look something like this:

Version: 2012.4.18.821
Operating System: Microsoft Windows NT 5.1.2600 Service Pack 3 (32 bit)

Log File:
2012-07-26 10:16:47.5488 6700-DC5-XP012T 1 ERROR GBS.NetLabels.CustomerClient.App.cea37ca54156dd22ff711fe6b4c1336aa - An error has occurred while attempting to process your request. Please contact a system administrator if the problem continues. System.ArgumentException: Illegal characters in path.
at System.IO.Path.CheckInvalidPathChars(String path)
at System.IO.Path.Combine(String path1, String path2)
at Microsoft.Internal.GDIExporter.BuildFontList(String fontdir)
at Microsoft.Internal.GDIExporter.CGDIDevice.CheckFont(GlyphTypeface typeface, String name)
at Microsoft.Internal.GDIExporter.CGDIRenderTarget.CreateFontW(GlyphRun pGlyphRun, Double fontSize, Double scaleY)
at Microsoft.Internal.GDIExporter.CGDIRenderTarget.RenderTextThroughGDI(GlyphRun pGlyphRun, Brush pBrush)
at Microsoft.Internal.GDIExporter.CGDIRenderTarget.DrawGlyphRun(Brush pBrush, GlyphRun glyphRun)
at Microsoft.Internal.AlphaFlattener.BrushProxyDecomposer.Microsoft.Internal.AlphaFlattener.IProxyDrawingContext.DrawGlyphs(GlyphRun glyphrun, Geometry clip, Matrix trans, BrushProxy foreground)
at Microsoft.Internal.AlphaFlattener.PrimitiveRenderer.DrawGlyphs(GlyphRun glyphrun, Rect bounds, Matrix trans, String desp)
at Microsoft.Internal.AlphaFlattener.Flattener.AlphaRender(Primitive primitive, List`1 overlapping, Int32 overlapHasTransparency, Boolean disjoint, String desp)
at Microsoft.Internal.AlphaFlattener.Flattener.AlphaFlatten(IProxyDrawingContext dc, Boolean disjoint)
at Microsoft.Internal.AlphaFlattener.Flattener.Convert(Primitive tree, ILegacyDevice dc, Double width, Double height, Double dpix, Double dpiy, Nullable`1 quality)
at Microsoft.Internal.AlphaFlattener.MetroDevice0.FlushPage(ILegacyDevice sink, Double width, Double height, Nullable`1 outputQuality)
at Microsoft.Internal.AlphaFlattener.MetroToGdiConverter.FlushPage()
at System.Windows.Xps.Serialization.NgcSerializationManager.EndPage()
at System.Windows.Xps.Serialization.NgcSerializationManager.WalkVisual(Visual visual)
at System.Windows.Xps.Serialization.NgcReachVisualSerializer.SerializeObject(Object serializedObject)
at System.Windows.Xps.Serialization.NgcSerializationManager.SaveAsXaml(Object serializedObject)
at System.Windows.Xps.XpsDocumentWriter.SaveAsXaml(Object serializedObject, Boolean isSync)
at System.Windows.Xps.XpsDocumentWriter.Write(Visual visual)
at System.Windows.Controls.PrintDialog.PrintVisual(Visual visual, String description)
at GBS.NetLabels.Rendering.PrintingService.Print(FrameworkElement view, PrintQueue printer, PrintTicket printerSettings, String description)
at GBS.NetLabels.Rendering.Engines.PrintEngine.c645f7168458ecfa06950e0de208ea44a.cadaba4adea9d27818279d21e292b435d(Object c8e2d78626e24e8ded5f2d71804de1f51)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

 

The WPF error may look a little more generic and could look something like this:

ArgumentException
Message: Illegal characters in path.
Stack Trace:=
at System.IO.Path.CheckInvalidPathChars(String path)
at System.IO.Path.Combine(String path1, String path2)
at Microsoft.Internal.GDIExporter.BuildFontList(String fontdir)
at Microsoft.Internal.GDIExporter.CGDIDevice.CheckFont(GlyphTypeface typeface, String name)
at Microsoft.Internal.GDIExporter.CGDIRenderTarget.CreateFontW(GlyphRun pGlyphRun, Double fontSize, Double scaleY)
at Microsoft.Internal.GDIExporter.CGDIRenderTarget.RenderTextThroughGDI(GlyphRun pGlyphRun, Brush pBrush)
at Microsoft.Internal.GDIExporter.CGDIRenderTarget.DrawGlyphRun(Brush pBrush, GlyphRun glyphRun)
at Microsoft.Internal.AlphaFlattener.BrushProxyDecomposer.Microsoft.Internal..AlphaFlattener.IProxyDrawingContext.DrawGlyphs(GlyphRun glyphrun, Geometry clip, Matrix trans, BrushProxy foreground)
at Microsoft.Internal.AlphaFlattener.PrimitiveRenderer.DrawGlyphs(GlyphRun glyphrun, Rect bounds, Matrix trans, String desp)
at Microsoft.Internal.AlphaFlattener.Flattener.AlphaRender(Primitive primitive, List`1 overlapping, Int32 overlapHasTransparency, Boolean disjoint, String desp)
at Microsoft.Internal.AlphaFlattener.Flattener.AlphaFlatten(IProxyDrawingContext dc, Boolean disjoint)
at Microsoft.Internal.AlphaFlattener.Flattener.Convert(Primitive tree, ILegacyDevice dc, Double width, Double height, Double dpix, Double dpiy, Nullable`1 quality)
at Microsoft.Internal.AlphaFlattener.MetroDevice0.FlushPage(ILegacyDevice sink, Double width, Double height, Nullable`1 outputQuality)
at Microsoft.Internal.AlphaFlattener.MetroToGdiConverter.FlushPage()
at System.Windows.Xps.Serialization.NgcSerializationManager.EndPage()
at System.Windows.Xps.Serialization.NgcFixedPageSerializer.SerializeObject(Object serializedObject)
at System.Windows.Xps.Serialization.NgcDocumentPageSerializer.SerializeObject(Object serializedObject)
at System.Windows.Xps.Serialization.NgcDocumentPaginatorSerializer.SerializeObject(Object serializedObject)
at System.Windows.Xps.Serialization.NgcSerializationManager.SaveAsXaml(Object serializedObject)
at System.Windows.Xps.XpsDocumentWriter.SaveAsXaml(Object serializedObject, Boolean isSync)
at System.Windows.Xps.XpsDocumentWriter.Write(DocumentPaginator documentPaginator)
at System.Windows.Controls.PrintDialog.PrintDocument(DocumentPaginator documentPaginator, String description)

This exception occurs because of corrupt fonts values in the registry (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts). When using WPF printing (System.Printing), it builds a list of fonts by combining the font names from the registry and the Windows Font Directory path. If there are any illegal characters in the path, we know there are, then the WPF application throws the exception that we see in the stack traces above.

The fix for this issue is pretty straight forward. We can find the corrupt font values in the registry and fix them by opening and saving the key. When we open and save the key it seems to remove the bad character(s) from the string. However, finding the corrupt fonts manually is not so easy. On my system, for example, I have over 500 font entries in the registry.

To make it easier Bradford Systems has written a small .NET (4.0) application that will loop through all the font entries in the registry, identify the bad one(s), and fix them automatically.

The utility can be downloaded here.
Source