dotnet/wpf · critical · DllNotFoundException
dwrite.dll
Error message
dwrite.dll
What it means
DWriteLoader.LoadDWrite loads dwrite.dll and locates DWriteCreateFactory. If the library cannot be loaded, it throws DllNotFoundException("dwrite.dll") wrapping the Win32 error. DirectWrite is a Windows system component that WPF's text stack requires, so its absence is fatal at text-stack initialization.
Solutions
- Run on a Windows installation that includes DirectWrite (dwrite.dll in System32) — install Desktop Experience on Server SKUs
- Run 'sfc /scannow' or 'DISM /Online /Cleanup-Image /RestoreHealth' to repair a corrupt system copy
- Check that no stray dwrite.dll in the app directory or PATH shadows the system one
- Verify the container/CI image is a full Windows base image (e.g. servercore with the right features), not a minimal one
Example fix
// before
// app starts text stack unconditionally on a minimal container
App.Main();
// after
try
{
App.Main();
}
catch (DllNotFoundException ex) when (ex.Message.Contains("dwrite.dll"))
{
Console.Error.WriteLine("DirectWrite is unavailable: install a Windows image with Desktop Experience. " + ex.Message);
return 1;
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify DirectWrite is available before starting the text stack
string sys32 = Environment.GetFolderPath(Environment.SpecialFolder.System);
if (!File.Exists(Path.Combine(sys32, "dwrite.dll")))
throw new InvalidOperationException("dwrite.dll missing — install Windows with Desktop Experience"); Type guard
static bool DirectWriteAvailable() =>
File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "dwrite.dll")); Try / catch
try { textStack.Initialize(); }
catch (DllNotFoundException ex) when (ex.Message.Contains("dwrite.dll"))
{
Log.Fatal("DirectWrite unavailable: {0}. Win32 error: {1}", ex.Message, new Win32Exception().Message);
Environment.Exit(1);
} Prevention
- Run WPF apps only on Windows images that include DirectWrite/Desktop Experience
- Avoid placing third-party dwrite.dll copies in the app folder or PATH
- Repair corrupted systems with sfc /scannow or DISM
- Use full Windows base images in containers/CI, not minimal ones
- Check DirectWrite availability at startup and fail fast with a clear message
When it happens
Trigger: Constructing the DirectWrite loader on a system where dwrite.dll cannot be LoadLibrary'd — missing/corrupt system DLL, a broken Windows installation, or a sandbox/containers environment without DirectWrite.
Common situations: Running WPF apps on stripped-down Windows images or Server Core without the Desktop Experience; corrupted system files; CI containers missing Graphics/Text runtime features; DLL search-path hijacking placing a bad dwrite.dll earlier on the path.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Failed to initialize GestureRecognizer.
- InvalidOperationException
- PrintSystemException.PrintServer.Generic
- " }} " element found. Expected fixed page element ( }} ).
- ' ' can only host a ' ' or a ' '. ' ' is an invalid…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/fd4b970b2ef6ad66.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Text/TextInterface/DWriteLoader.cs:21
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace MS.Internal.Text.TextInterface
{
internal static unsafe class DWriteLoader
{
private static IntPtr _dwrite;
private static delegate* unmanaged<int, void*, void*, int> _dwriteCreateFactory;
internal static void LoadDWrite()
{
// We load dwrite here because it's cleanup logic is different from the other native dlls
// and don't want to abstract that
_dwrite = LoadDWriteLibraryAndGetProcAddress(out delegate* unmanaged<int, void*, void*, int> dwriteCreateFactory);
if (_dwrite == IntPtr.Zero)
throw new DllNotFoundException("dwrite.dll", new Win32Exception());
if (dwriteCreateFactory == null)
throw new InvalidOperationException();
_dwriteCreateFactory = dwriteCreateFactory;
}
internal static void UnloadDWrite()
{
ClearDWriteCreateFactoryFunctionPointer();
if (_dwrite != IntPtr.Zero)
{
NativeLibrary.Free(_dwrite);
_dwrite = IntPtr.Zero;
}
}View on GitHub (pinned to 81131a70a4)