HandyOrg/HandyControl · error · Win32Exception

Win32Exception

Error message

Win32Exception

What it means

WindowHelper.SystemDpi (or the DPI-Y cache slot) calls the Win32 GetDC(NULL) to obtain a device context for the desktop window and read LOGPIXELSY. When GetDC returns IntPtr.Zero the helper throws a parameterless Win32Exception, whose ErrorCode is Marshal.GetLastWin32Error(). It means Windows refused to hand out a screen DC, so the library cannot determine vertical screen DPI.

Solutions

  1. Ensure the code runs in an interactive user session (WPF apps cannot compute screen DPI in Session 0 — move DPI work into the UI process).
  2. Check/relieve GDI handle pressure: leak GDI objects elsewhere in the app can make GetDC fail; inspect with Task Manager's GDI Objects column.
  3. Wrap the first HandyControl window/show call in a try-catch for Win32Exception and fall back to a fixed 96.0 DPI value.
  4. Reconnect a disconnected RDP session or log in interactively before launching the app.
  5. Update HandyControl; newer versions cache DPI differently and handle headless environments more gracefully.

Example fix

// before
var dpi = WindowHelper.SystemDPI; // throws Win32Exception headless

// after
double dpi = 96.0;
try { dpi = WindowHelper.SystemDPI; }
catch (Win32Exception) { /* non-interactive session: assume 96 DPI */ }
Defensive patterns

Strategy: try-catch

Validate before calling

// not applicable: failure is environmental, cannot be pre-validated safely
// optional session check:
bool hasDesktop = Environment.UserInteractive;

Try / catch

try { dpi = WindowHelper.SystemDPI; }
catch (Win32Exception ex) { Log.Warn($"DPI detection failed: {ex.NativeErrorCode}"); dpi = 96.0; }

Prevention

When it happens

Trigger: Calling any HandyControl API that reads SystemDpi/DPI-aware window metrics when InteropMethods.GetDC(new HandleRef(null, IntPtr.Zero)) fails and returns IntPtr.Zero, e.g. during WindowHelper initialization in a non-interactive session.

Common situations: App running as a Windows Service or scheduled task without an interactive desktop; Session 0 isolation; remote desktop disconnecting right at startup; heavily locked-down terminal servers or GDI handle exhaustion in the process; WindowsCitrix/virtual sessions where the desktop window is unavailable.

Related errors


AI-assisted analysis of HandyOrg/HandyControl@2c0875ebd6 (2026-09-14). Data as JSON: /api/errors/20607fa84ed7a8cd. Report an issue: GitHub.

Appendix: source

Thrown at src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs:58

    {
        [SecurityCritical, SecuritySafeCritical]
        get
        {
            if (!_dpiInitialized)
            {
                lock (_dpiLock)
                {
                    if (!_dpiInitialized)
                    {
                        var desktopWnd = new HandleRef(null, IntPtr.Zero);

                        // Win32Exception will get the Win32 error code so we don't have to
                        var dc = InteropMethods.GetDC(desktopWnd);

                        // Detecting error case from unmanaged call, required by PREsharp to throw a Win32Exception
                        if (dc == IntPtr.Zero)
                        {
                            throw new Win32Exception();
                        }

                        try
                        {
                            _dpi = InteropMethods.GetDeviceCaps(new HandleRef(null, dc), InteropValues.LOGPIXELSY);
                            _dpiInitialized = true;
                        }
                        finally
                        {
                            InteropMethods.ReleaseDC(desktopWnd, new HandleRef(null, dc));
                        }
                    }
                }
            }
            return _dpi;
        }
    }

View on GitHub (pinned to 2c0875ebd6)