I have a service that launches an executable into a user session with CreateProcessAsUser
, specifying the desktop in the STARTUPINFO
parameter. It works well.
My executable is not manifested, nor does it call any DPI-related API.
When I launch my executable manually by double-clicking or via cmd.exe, Task Manager correctly shows the DPI Awareness as "Unaware".
However, when my executable is launched by the service, Task Manager shows DPI Awareness as "Per Monitor" - and indeed, it behaves as such.
Setting the default DPI awareness for a process says:
There are two main methods to specify the default DPI awareness of a process:
- through an application manifest setting
- programmatically through an API call
I am doing neither of these things.
I confirmed that the .exe is not manifested by using mt.exe. I set function breakpoints on the following:
- user32.dll!SetProcessDpiAwarenessContext
- user32.dll!SetThreadDpiAwarenessContext
- shcore.dll!SetProcessDpiAwareness
No breakpoint is hit; however when launched from the service, I can only attach my debugger once I'm already inside main
- and it seems that the DPI awareness is already set at that point.
Is there anywhere else the DPI awareness can be getting set?
This is a hybrid rust / C application - there is no (for example) .NET dependency referenced.
EDIT:
Using the JIT debugger, I can break at mainCRTStartup
and see the DPI Awareness is already "PerMonitor" at that point. Calling SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE)
or SetProcessDpiAwareness(PROCESS_DPI_UNAWARE)
have no effect.
EDIT:
When launched from my service with CreateProcessAsUser
; the executable has this environment variable:
__COMPAT_LAYER=HighDpiAware
The environment passed to CreateProcessAsUser
is created by calling:
CreateEnvironmentBlock
with my user handle. The rest of the environment is as expected. Where is this coming from? There are no compatibility options set on the executable when I inspect it's properties in explorer...