Skip to content

COM class not registered (0x80040154) on wakeup from sleep #469

Description

@ptx96

Describe the bug
After resuming from sleep/suspend, FancyWM crashes with a REGDB_E_CLASSNOTREG (0x80040154) exception when attempting to instantiate the Virtual Desktop COM class ({C2F03A33-21F5-47FA-B4BB-156362A2F239}). This appears to be a race condition between FancyWM's initialization and Windows Shell/Explorer re-registering its COM classes after wakeup.

Note: this is related to but distinct from #466, which reports 0x800706BF (RPC failed). The underlying CLSID and trigger scenario are the same, but the error code differs, suggesting the shell is at a different stage of initialization when FancyWM queries it.

A secondary symptom occurs when the crash does not happen: the lock screen / login UI becomes extremely slow and unresponsive for several seconds after wakeup, with high CPU usage, likely due to FancyWM repeatedly retrying the failed COM call before eventually giving up or recovering.

To Reproduce

  1. Run FancyWM normally
  2. Put the machine to sleep (sleep/suspend)
  3. Wake the machine up
  4. FancyWM crashes with the exception below, OR the login screen becomes sluggish for several seconds with high CPU before recovering

Expected behavior
FancyWM should gracefully handle the temporary unavailability of the Virtual Desktop COM interface on wakeup, either by delaying initialization or retrying with a backoff until the shell is ready.

Stack trace

System.Runtime.InteropServices.COMException (0x80040154): Retrieving the COM class factory for component with CLSID {C2F03A33-21F5-47FA-B4BB-156362A2F239} failed due to the following error: 80040154 Class not registered (0x80040154 (REGDB_E_CLASSNOTREG)).
   at System.RuntimeTypeHandle.AllocateComObject(Void* pClassFactory)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
   at WinMan.Windows.Windows.Win32VirtualDesktopService26100.Connect()
   at WinMan.Windows.FaultTolerantWin32VirtualDesktopService.ExecuteWithRetry[T](Func1 func)
--- End of stack trace from previous location ---
   at WinMan.Windows.FaultTolerantWin32VirtualDesktopService.ExecuteWithRetry[T](Func1 func)
   at WinMan.Windows.Win32VirtualDesktopManager.WinMan.Windows.IWin32VirtualDesktopManagerInternal.IsNotOnCurrentDesktop(IntPtr hwnd)
   at WinMan.Windows.Win32Window.<GetIsTopLevelVisible>g__CheckCloaked|130_0(<>c__DisplayClass130_0&)
   at WinMan.Windows.Win32Window.GetIsTopLevelVisible(IWorkspace workspace, IntPtr hwnd)
   at WinMan.Windows.Win32Workspace.GetVisibility(Win32WindowHandle window)
   at WinMan.Windows.Win32Workspace.CheckVisibilityChanges(Win32WindowHandle window)
   at WinMan.Windows.Win32Workspace.CheckVisibilityChanges()
   at WinMan.Windows.Utilities.EventLoop.Run()
--- End of stack trace from previous location ---
   at FancyWM.Utilities.Dispatchers.<>c__DisplayClass4_0.<RethrowOnDispatcher>b__0()
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at FancyWM.Startup.AppMain(String[] args)
   at FancyWM.Startup.Main(String[] args)
   at FancyWM.GUI.Program.Main(String[] args)

Desktop:

  • OS: Windows 11
  • OS Build: 26200.8655
  • FancyWM Version: 2.19.0.0 (latest)

Additional context

  • Setup uses 3 monitors with different resolutions and layouts. The multi-monitor configuration likely increases the time Windows needs to reconfigure displays on wakeup, widening the window in which the COM class is unavailable.
  • The FaultTolerantWin32VirtualDesktopService.ExecuteWithRetry wrapper does not appear to recover from this specific error, it either crashes or causes sustained high CPU while retrying.
  • Workaround applied: a scheduled task that kills and restarts FancyWM ~15 seconds after wakeup (to be tested).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions