dotnet/maui · critical · Exception

Unable to initialize GDI+

Error message

Unable to initialize GDI+

What it means

NativeMethods.Startup throws Exception("Unable to initialize GDI+") when GdiplusStartup returns a Status other than Ok. GDI+ must be initialised exactly once per process before any GDI+ rendering API is used; a non-Ok status means the runtime could not load or initialise GDI+ (gdiplus.dll).

Source

Thrown at src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/NativeMethods.cs:1614

		protected override bool ReleaseHandle()
		{
			Status s = NativeMethods.GdiplusShutdown(this.handle);
			return s == Status.Ok;
		}

		[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		[SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
		public static SafeGdiplusStartupToken Startup()
		{
			IntPtr unsafeHandle;
			StartupOutput output;
			Status s = NativeMethods.GdiplusStartup(out unsafeHandle, new StartupInput(), out output);
			if (s == Status.Ok)
			{
				SafeGdiplusStartupToken safeHandle = new SafeGdiplusStartupToken(unsafeHandle);
				return safeHandle;
			}
			throw new Exception("Unable to initialize GDI+");
		}
	}

	internal sealed class SafeConnectionPointCookie : SafeHandleZeroOrMinusOneIsInvalid
	{
		IConnectionPoint _cp;
		// handle holds the cookie value.

		[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IConnectionPoint")]
		public SafeConnectionPointCookie(IConnectionPointContainer target, object sink, Guid eventId)
			: base(true)
		{
			Verify.IsNotNull(target, "target");
			Verify.IsNotNull(sink, "sink");
			Verify.IsNotDefault(eventId, "eventId");

			handle = IntPtr.Zero;

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Ensure gdiplus.dll is present and loadable (run sfc /scannow to repair system files).
  2. Confirm the process runs on a supported Windows desktop session.
  3. Avoid calling Startup concurrently; let the SafeGdiplusStartupToken singleton manage it.
  4. Free GDI+ resources (images, graphics) promptly to avoid exhaustion that can cause Startup to fail.

Example fix

// before
var token = NativeMethods.Startup(); // throws if gdiplus.dll missing

// after
if (!System.IO.File.Exists(System.IO.Path.Combine(Environment.SystemDirectory, "gdiplus.dll")))
    throw new InvalidOperationException("gdiplus.dll not available");
var token = NativeMethods.Startup();
Defensive patterns

Strategy: validation

Validate before calling

if (!System.IO.File.Exists(System.IO.Path.Combine(Environment.SystemDirectory, "gdiplus.dll")))
    throw new InvalidOperationException("gdiplus.dll not available");
var token = NativeMethods.Startup();

Type guard

static bool GdiplusAvailable =>
    System.IO.File.Exists(System.IO.Path.Combine(Environment.SystemDirectory, "gdiplus.dll"));

Try / catch

try { var token = NativeMethods.Startup(); }
catch (Exception ex) when (ex.Message.Contains("GDI+"))
{ /* repair system files or run on supported Windows; cannot recover at runtime */ }

Prevention

When it happens

Trigger: GdiplusStartup fails due to missing/corrupt gdiplus.dll; out of memory or GDI+ object exhaustion; calling Startup concurrently without the SafeHandle guard; locked-down environment preventing native DLL load.

Common situations: Stripped Windows image lacking gdiplus.dll; sandboxed/app-container environment; corrupted system files; running on a non-Windows platform where the shell assembly is force-loaded.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/f1daa541ee8f3d85. Report an issue: GitHub.