{"record":{"id":"20607fa84ed7a8cd","repo":"HandyOrg/HandyControl","slug":"win32exception","errorCode":null,"errorMessage":"Win32Exception","messagePattern":"Win32Exception","errorType":"exception","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs","lineNumber":58,"sourceCode":"    {\n        [SecurityCritical, SecuritySafeCritical]\n        get\n        {\n            if (!_dpiInitialized)\n            {\n                lock (_dpiLock)\n                {\n                    if (!_dpiInitialized)\n                    {\n                        var desktopWnd = new HandleRef(null, IntPtr.Zero);\n\n                        // Win32Exception will get the Win32 error code so we don't have to\n                        var dc = InteropMethods.GetDC(desktopWnd);\n\n                        // Detecting error case from unmanaged call, required by PREsharp to throw a Win32Exception\n                        if (dc == IntPtr.Zero)\n                        {\n                            throw new Win32Exception();\n                        }\n\n                        try\n                        {\n                            _dpi = InteropMethods.GetDeviceCaps(new HandleRef(null, dc), InteropValues.LOGPIXELSY);\n                            _dpiInitialized = true;\n                        }\n                        finally\n                        {\n                            InteropMethods.ReleaseDC(desktopWnd, new HandleRef(null, dc));\n                        }\n                    }\n                }\n            }\n            return _dpi;\n        }\n    }\n","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/HandyOrg/HandyControl/blob/2c0875ebd67326e0c67282967e3e809c69282fee/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs#L40-L76","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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).","Check/relieve GDI handle pressure: leak GDI objects elsewhere in the app can make GetDC fail; inspect with Task Manager's GDI Objects column.","Wrap the first HandyControl window/show call in a try-catch for Win32Exception and fall back to a fixed 96.0 DPI value.","Reconnect a disconnected RDP session or log in interactively before launching the app.","Update HandyControl; newer versions cache DPI differently and handle headless environments more gracefully."],"exampleFix":"// before\nvar dpi = WindowHelper.SystemDPI; // throws Win32Exception headless\n\n// after\ndouble dpi = 96.0;\ntry { dpi = WindowHelper.SystemDPI; }\ncatch (Win32Exception) { /* non-interactive session: assume 96 DPI */ }","handlingStrategy":"try-catch","validationCode":"// not applicable: failure is environmental, cannot be pre-validated safely\n// optional session check:\nbool hasDesktop = Environment.UserInteractive;","typeGuard":null,"tryCatchPattern":"try { dpi = WindowHelper.SystemDPI; }\ncatch (Win32Exception ex) { Log.Warn($\"DPI detection failed: {ex.NativeErrorCode}\"); dpi = 96.0; }","preventionTips":["Never run WPF/HandyControl UI initialization from services, scheduled tasks, or Session 0.","Monitor the process GDI object count; fix GetDC/ReleaseDC imbalances.","Default to 96 DPI when DPI detection fails so rendering still works.","Test the app headless in CI to catch this early."],"tags":["win32","gdi","dpi","native-interop","wpf"],"backgroundTag":"win32-api-failed","analyzedSha":"2c0875ebd67326e0c67282967e3e809c69282fee","analyzedAt":"2026-09-14T14:45:29.754Z","contentChangedAt":"2026-09-14T14:45:29.754Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}