{"record":{"id":"c6d3fe7be3311ea6","repo":"unoplatform/uno","slug":"pinvoke-registerclassex-failed-win32helper-geter","errorCode":null,"errorMessage":"PInvoke.RegisterClassEx failed: {Win32Helper.GetErrorMessage()}","messagePattern":"PInvoke\\.RegisterClassEx failed: (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/AddIns/Uno.UI.MediaPlayer.Skia.Win32/Win32MediaPlayerPresenterExtension.cs","lineNumber":59,"sourceCode":"\tprivate readonly HWND _hwnd;\n\n\tstatic unsafe Win32MediaPlayerPresenterExtension()\n\t{\n\t\tusing var lpClassName = new Win32Helper.NativeNulTerminatedUtf16String(WindowClassName);\n\n\t\t_windowClass = new WNDCLASSEXW\n\t\t{\n\t\t\tcbSize = (uint)Marshal.SizeOf<WNDCLASSEXW>(),\n\t\t\tlpfnWndProc = &WndProc,\n\t\t\thInstance = Win32Helper.GetHInstance(),\n\t\t\tlpszClassName = lpClassName,\n\t\t\tstyle = WNDCLASS_STYLES.CS_HREDRAW | WNDCLASS_STYLES.CS_VREDRAW // https://learn.microsoft.com/en-us/windows/win32/winmsg/window-class-styles\n\t\t};\n\n\t\tvar classAtom = PInvoke.RegisterClassEx(_windowClass);\n\t\tif (classAtom is 0)\n\t\t{\n\t\t\tthrow new InvalidOperationException($\"{nameof(PInvoke.RegisterClassEx)} failed: {Win32Helper.GetErrorMessage()}\");\n\t\t}\n\t}\n\n\tpublic unsafe Win32MediaPlayerPresenterExtension(MediaPlayerPresenter presenter)\n\t{\n\t\t_presenter = presenter;\n\n\t\tusing var lpClassName = new Win32Helper.NativeNulTerminatedUtf16String(WindowClassName);\n\n\t\t_extForNextCreateWindow = new WeakReference<Win32MediaPlayerPresenterExtension>(this);\n\t\t_hwnd = PInvoke.CreateWindowEx(\n\t\t\t0,\n\t\t\tlpClassName,\n\t\t\tnew PCWSTR(),\n\t\t\t0,\n\t\t\tPInvoke.CW_USEDEFAULT,\n\t\t\tPInvoke.CW_USEDEFAULT,\n\t\t\tPInvoke.CW_USEDEFAULT,","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/unoplatform/uno/blob/04183404888ea21b4e5bfa3493e8d5f15e972c3a/src/AddIns/Uno.UI.MediaPlayer.Skia.Win32/Win32MediaPlayerPresenterExtension.cs#L41-L77","documentation":"InvalidOperationException thrown in the static constructor of Win32MediaPlayerPresenterExtension when the Win32 RegisterClassEx call returns a 0 atom, meaning the window class 'UnoPlatformVLCWindow' could not be registered. This class is needed to host the LibVLC media player surface on the Skia/Win32 desktop target. A static-constructor failure type-initializes the extension and prevents any media player window from being created.","triggerScenarios":"Type initialization of Win32MediaPlayerPresenterExtension (first use of MediaPlayerPresenter on Skia.Win32) when RegisterClassEx fails: the class name already exists (duplicate registration), hInstance is wrong, or the lpfnWndProc delegate was collected. Because _windowClass is static and holds the WndProc function pointer, GC collection of the delegate is mitigated, but a duplicate class name across processes/instances or a corrupt process state can still return 0.","commonSituations":"Running two Uno hosts in the same process that both register 'UnoPlatformVLCWindow'; a LibVLC initialization ordering issue; running under a constrained session (e.g. service/session-0) where window class registration is blocked; DLL/HINSTANCE corruption. The formatted Win32Helper.GetErrorMessage() reveals the OS reason (e.g. ERROR_CLASS_ALREADY_EXISTS).","solutions":["Read Win32Helper.GetErrorMessage() in the exception text — ERROR_CLASS_ALREADY_EXISTS (1410) means a duplicate registration; ensure only one Skia Win32 host registers the class.","Confirm LibVLC native dependencies are present and the process has a usable window station/desktop.","Avoid instantiating MediaPlayerPresenter in a non-interactive session (services, headless tests).","If hosting multiple Skia windows in one process, verify the static class is initialized once (it is, by design — duplicate calls shouldn't happen, so a 1410 implies a different component already took the name).","Update the Uno.UI.MediaPlayer.Skia.Win32 add-in; class-registration robustness has been improved across versions."],"exampleFix":"// The class is registered once in a static ctor; you cannot easily change it.\n// Guard usage: only create the presenter in an interactive desktop session.\nif (OperatingSystem.IsWindows() && Environment.UserInteractive)\n{\n    _presenter = new Win32MediaPlayerPresenterExtension(mediaPresenter);\n}","handlingStrategy":"validation","validationCode":"// Only construct the Win32 media extension in an interactive Windows session\nif (OperatingSystem.IsWindows() && Environment.UserInteractive && !System.Windows.Forms.SystemInformation.TerminalServerSession)\n    _presenter = new Win32MediaPlayerPresenterExtension(mediaPresenter);","typeGuard":"bool CanHostWin32MediaPlayer()\n    => OperatingSystem.IsWindows() && Environment.UserInteractive;","tryCatchPattern":"try { _presenter = new Win32MediaPlayerPresenterExtension(mediaPresenter); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"RegisterClassEx\"))\n{ Log.Error($\"Win32 window class registration failed: {ex.Message}\"); }","preventionTips":["Run the Skia Win32 host in an interactive desktop session only.","Ensure only one host registers the 'UnoPlatformVLCWindow' class per process.","Keep LibVLC native deps and Uno.UI.MediaPlayer.Skia.Win32 versions aligned."],"tags":["win32","media-player","libvlc","skia","windows","uno-platform"],"backgroundTag":null,"analyzedSha":"04183404888ea21b4e5bfa3493e8d5f15e972c3a","analyzedAt":"2026-08-13T21:08:11.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}