Winapi 进程DPI感知

Winapi 进程DPI感知,winapi,dpi,Winapi,Dpi,我有一个服务,它使用CreateProcessAsUser将可执行文件启动到用户会话中,并在STARTUPINFO参数中指定桌面。它工作得很好 我的可执行文件没有显示,也没有调用任何与DPI相关的API 当我通过双击或通过cmd.exe手动启动可执行文件时,Task Manager会正确地将DPI感知显示为“未察觉” 但是,当服务启动我的可执行文件时,Task Manager会将DPI感知显示为“每个监视器”——事实上,它的行为也是如此 说: 有两种主要方法可以指定流程的默认DPI感知: 通过应

我有一个服务,它使用
CreateProcessAsUser
将可执行文件启动到用户会话中,并在
STARTUPINFO
参数中指定桌面。它工作得很好

我的可执行文件没有显示,也没有调用任何与DPI相关的API

当我通过双击或通过cmd.exe手动启动可执行文件时,Task Manager会正确地将DPI感知显示为“未察觉”

但是,当服务启动我的可执行文件时,Task Manager会将DPI感知显示为“每个监视器”——事实上,它的行为也是如此

说:

有两种主要方法可以指定流程的默认DPI感知:

  • 通过应用程序清单设置
  • 通过API调用以编程方式
  • 这两件事我都不做

    我确认使用mt.exe不会显示.exe。我在以下位置设置函数断点:

    • user32.dll!SetProcessDpiAwarenessContext
    • user32.dll!SetThreadDpiAwarenessContext
    • shcore.dll!SetProcessdPiaware
    未命中断点;然而,当从服务启动时,我只能在已经进入
    main
    之后连接我的调试器,而且似乎DPI感知已经设置好了

    还有其他地方可以设置DPI意识吗

    这是一个混合的rust/C应用程序-没有引用(例如).NET依赖项


    编辑:

    使用JIT调试器,我可以在
    mainCRTStartup
    处中断,并看到此时DPI感知已经是“PerMonitor”。调用
    setProcessDPIaarEnesContext(DPI\U感知\U上下文\U不知道)
    setProcessDPIaarEnesContext(PROCESS\U DPI\U不知道)
    无效


    编辑:

    使用
    CreateProcessAsUser
    从我的服务启动时;可执行文件具有以下环境变量:

    __COMPAT_层=HighDpiAware

    传递给
    CreateProcessAsUser
    的环境是通过调用以下命令创建的:


    CreateEnvironmentBlock
    与我的用户句柄。环境的其余部分与预期一样。这是从哪里来的?当我在资源管理器中检查可执行文件的属性时,没有在可执行文件上设置兼容性选项…

    我的服务正在作为系统运行。在本例中,当我调用
    CreateProcessAsUser
    时,可执行文件也作为系统运行。我为
    lpEnvironment
    参数传递
    nullptr
    。他说:

    指向新进程的环境块的指针。如果此参数为NULL,则新进程将使用调用进程的环境

    但是,当我检查可执行文件的环境时,我看到:

    __COMPAT_层=HighDpiAware

    这是强制每个监视器DPI意识。这很神秘,因为事实上,AppCompatFlag是在S-1-5-18(系统)的注册表中为该可执行文件设置的,但我不知道该值是如何或从何而来的

    我的服务(也作为系统运行)上没有设置该变量-可能服务没有获得AppCompat环境?但为什么我的子进程会拥有它,尽管据说它继承了其父进程的环境?我想这些兼容性标志必须有特殊的处理


    无论如何,我的问题的答案是:从
    \uu COMPAT\u层
    环境变量中删除
    HighDpiAware

    进程是否继承自父进程?比如,由于DPI感知线程正在启动进程。。。我想我们可以做个测试。创建一个DPI感知应用程序,然后让它启动一个DPI感知应用程序并查看。如果在子进程中调用
    SetProcessDpiAwareness
    并使用
    PROCESS\u DPI\u unknowledge
    ,会发生什么情况?@Andy“DPI感知不是从启动进程继承的。进程启动的应用程序将其DPI感知设置为这些应用程序想要的任何设置。”@那么您考虑过子进程的下一个吗?将
    DEBUG\u PROCESS
    传递到
    CreateProcessAsUser()
    ,它将自动将您的服务作为调试器附加,然后让服务等待子进程中DPI函数上的
    CREATE\u PROCESS\u DEBUG\u EVENT
    ,恢复其正常执行,并查看是否收到任何
    异常\u DEBUG\u事件(异常断点)
    对于它们。从第一条指令开始真正调试进程没有问题。如果要调试二进制文件,我将使用JIT调试器直接在
    mainCRTStartup
    停止。从cmd.exe执行时,我的DPI感知是“不知道的”。当使用
    CreateProcessAsUser
    从服务启动时,我的DPI感知是“每监视器".aaaa我发现了。在高DPI系统上,如果您的进程不支持高DPI,则调用DXGI函数为您调用
    SetProcessDpiAwarenessContext
    ,并添加兼容性标志。这似乎是未记录的。很好的检测工作,两次+1。想知道如果孩子有dpiAware/ne清单,是否会有任何区别ss设置为false/unknowledge。@dxiv No-没有区别;我尝试添加清单,但它被兼容性标志覆盖