Quick answer
Run the app as the logged-in user (not as SYSTEM or in session 0). If it's a service, enable "Allow service to interact with desktop" or use a user-level helper process.
What's actually happening here
Windows restricts which processes can present graphics to the desktop. The error 0xC0262007 — ERROR_GRAPHICS_PRESENT_DENIED — means your application tried to call D3DKMTPresent or similar, but the Desktop Window Manager (DWM) rejected it because the calling process lacks the right session or integrity level.
This almost always happens in one of two scenarios:
- Session 0 isolation: Windows Vista and later run services in session 0, which is non-interactive. A service in session 0 cannot present to the user's desktop (session 1, 2, etc.). Microsoft did this for security — services run with SYSTEM privileges, and letting them touch the desktop was a huge attack surface.
- Permission mismatch: A process running as a different user (e.g., NETWORK SERVICE) tries to present on a desktop owned by the logged-in user. DWM checks the access token and says no.
I've seen this most often with remote desktop-like tools, screen capture utilities running as services, or GPU compute apps launched from Task Scheduler with the wrong account. You won't hit it with normal desktop games or apps — only when something is running outside the user's login session.
Fix steps
Step 1: Confirm the session
Open Task Manager, go to the Details tab. Find your process. The Session ID column tells you which session it's in. If it's 0, you've found the problem. If it's 1 or higher, move to Step 2.
You can also run this in a command prompt:
tasklist /fi "PID eq YOUR_PID" /fo list | findstr /i "Session"Step 2: Run the app as the current user
If you're launching from a service or script, don't use CreateProcessAsUser with SYSTEM. Instead, get the active user session token. Here's the safe way:
- Find the active session:
query sessionin cmd — look for the session with > in the State column. - Launch your process in that session using
psexec -i 1 -d your_app.exe(replace 1 with the actual session ID). - Or, if you're coding: call
WTSQueryUserTokento get the user token for the active session, thenCreateProcessAsUserwith that token.
What you're doing is telling Windows: "Hey, this process belongs to the human sitting at the screen, so let it present."
Step 3: For services specifically
If the app must run as a service, you can't just flip the "Allow service to interact with desktop" checkbox — that hasn't worked properly since Windows Vista. Instead, architect it as two parts:
- A Windows service (no GPU access, runs in session 0)
- A user-mode helper app (starts at login, communicates via named pipe or TCP, does all the GPU work)
This is what Chrome and Steam do. Their service handles updates and background tasks; the actual rendering happens in the user process.
Alternative fixes (if the main one fails)
If you can't change the app's architecture:
- Disable Session 0 isolation entirely — not recommended, but possible via
Interactive Services Detectionservice (UI0Detect). This only shows a popup asking to switch to session 0 — it doesn't actually fix the present call. - Switch to a different graphics API that doesn't go through DWM. For example, use Vulkan with
VK_EXT_swapchain_colorspaceand a fullscreen exclusive mode — but this still has session checks in the driver. - Run the app via
PsExecwith the-iflag from an admin command prompt, specifying the correct session ID. This is a quick test, not a permanent solution.
If the error is intermittent:
- Check if Fast User Switching is enabled. Multiple sessions cause locking conflicts. Disable it via Group Policy if needed.
- Update GPU drivers. Some old NVIDIA drivers (pre-400 series) had a bug where they'd return this error incorrectly for certain swap chain flags.
Prevention tip
Never run interactive code as SYSTEM. The one rule that avoids 90% of these errors. If you need to present graphics, your process must have the same user SID and session ID as the logged-in desktop user. Use WTSGetActiveConsoleSessionId to find the session, then duplicate the user token properly. Services that need GPU access should delegate to a user-launched process — no shortcuts.