unoplatform/uno · critical · InvalidOperationException

PInvoke.CreateWindowEx failed: {Win32Helper.GetErrorMessage(

Error message

PInvoke.CreateWindowEx failed: {Win32Helper.GetErrorMessage()}

What it means

InvalidOperationException thrown in the instance constructor of Win32MediaPlayerPresenterExtension when CreateWindowEx returns a null HWND, meaning the child window hosting the LibVLC surface could not be created. The window class must already be registered (error 30) for CreateWindowEx to succeed.

Source

Thrown at src/AddIns/Uno.UI.MediaPlayer.Skia.Win32/Win32MediaPlayerPresenterExtension.cs:87

		_extForNextCreateWindow = new WeakReference<Win32MediaPlayerPresenterExtension>(this);
		_hwnd = PInvoke.CreateWindowEx(
			0,
			lpClassName,
			new PCWSTR(),
			0,
			PInvoke.CW_USEDEFAULT,
			PInvoke.CW_USEDEFAULT,
			PInvoke.CW_USEDEFAULT,
			PInvoke.CW_USEDEFAULT,
			HWND.Null,
			HMENU.Null,
			Win32Helper.GetHInstance(),
			null);
		_extForNextCreateWindow = null;

		if (_hwnd == HWND.Null)
		{
			throw new InvalidOperationException($"{nameof(PInvoke.CreateWindowEx)} failed: {Win32Helper.GetErrorMessage()}");
		}

		if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Trace))
		{
			this.Log().Trace("Created media player window.");
		}

		var success = PInvoke.RegisterTouchWindow(_hwnd, 0);
		if (!success && this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Error))
		{
			this.Log().Error($"{nameof(PInvoke.RegisterTouchWindow)} failed: {Win32Helper.GetErrorMessage()}");
		}

		var cp = new ContentPresenter { Content = new Win32NativeWindow(_hwnd) };
		_presenter.Child = cp;
		cp.SizeChanged += (_, _) => StretchChanged();
	}

View on GitHub (pinned to 0418340488)

Solutions

  1. Inspect Win32Helper.GetErrorMessage() in the exception — common codes: ERROR_INVALID_WINDOW_HANDLE (1400), ERROR_NOT_ENOUGH_MEMORY (8), access-denied on the desktop.
  2. Ensure the process runs on an interactive window station/desktop (not session 0 / service).
  3. Confirm the window class atom from RegisterClassEx is valid (if 30 failed first, 31 follows).
  4. Reduce simultaneous window creation if hitting GDI/user object limits.
  5. Update the Uno.UI.MediaPlayer.Skia.Win32 add-in to the latest version.

Example fix

// No API tweak changes CreateWindowEx outcome; guard the environment.
if (Environment.UserInteractive)
{
    _presenter = new Win32MediaPlayerPresenterExtension(mediaPresenter);
}
Defensive patterns

Strategy: validation

Validate before calling

// Verify an interactive desktop before constructing the media window
if (OperatingSystem.IsWindows() && Environment.UserInteractive)
    _presenter = new Win32MediaPlayerPresenterExtension(mediaPresenter);

Type guard

bool CanCreateWin32MediaWindow()
    => OperatingSystem.IsWindows() && Environment.UserInteractive;

Try / catch

try { _presenter = new Win32MediaPlayerPresenterExtension(mediaPresenter); }
catch (InvalidOperationException ex) when (ex.Message.Contains("CreateWindowEx"))
{ Log.Error($"Win32 media window creation failed: {ex.Message}"); }

Prevention

When it happens

Trigger: Constructing Win32MediaPlayerPresenterExtension (on first media playback on Skia.Win32) when CreateWindowEx fails: the registered class is invalid, hInstance mismatch, the process lacks a window station/desktop, or extended styles are rejected. GetErrorMessage() gives the OS error code.

Common situations: Running the Skia Win32 media player in a headless/service context without an interactive desktop; a race where the window class registration partially failed; insufficient GDI/user objects; antivirus hooking window creation. The companion RegisterClassEx (error 30) typically succeeds first.

Related errors


AI-assisted analysis of unoplatform/uno@0418340488 (2026-08-13). Data as JSON: /api/errors/4e8e3b102e4f5d56. Report an issue: GitHub.