有没有办法从 Win32 应用程序检测 Windows 10 中的焦点辅助(以前称为安静时间)的变化 [英] Is there a way to detect changes in Focus Assist (formerly Quiet Hours) in Windows 10 from a Win32 App

查看:17
本文介绍了有没有办法从 Win32 应用程序检测 Windows 10 中的焦点辅助(以前称为安静时间)的变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在启用 Focus Assist 时将应用中的在线状态自动更改为 DND.

I'd like to change the presence state in an App automatically to DND when Focus Assist is turned on.

所以基本上是两个问题:

So two questions basically:

  • 是否可以通过例如检查焦点辅助状态Windows 10 SDK?

  • Is it possible to check Focus Assist state through e.g. Windows 10 SDK?

这里有一个关于 Windows 8 中的安静时间的类似问题:从 Win32 或 C# API 获取 windows 安静时间,但不清楚它是否还适用于Focus Assist";因为这不再是真值或假值.安静时间只有 ON/OFF 状态,而 Focus Assist 可以是 OFF/PRIORITY/ALARMS.

There is a similar question for Quiet Hours in Windows 8 here: Get windows Quiet hours from Win32 or C# API, though it's not clear whether it also still applies to "Focus Assist" since this is no longer a true or false value. Quiet hours had only ON/OFF state while Focus Assist can be OFF/PRIORITY/ALARMS.

不过,更有趣的问题在上面提到的帖子中没有得到回答:有没有我可以注册的事件,以获得有关状态变化的通知?

The more interesting question though, which is not answered in the post mentioned above: is there an event I could register to, to get notified about state changes?

目标是在 Focus Assist 状态发生变化时立即获得通知,以便不必定期查询注册表.

The goal is to get notified right away, when Focus Assist status changes in order to not have to query the registry on a regular basis.

推荐答案

据我所知,没有官方记录的获取焦点辅助状态的方法.

As far as I know there is no officially documented way of getting the Focus assist status.

它仍然可以通过查询 WNF 状态来访问 的功能,尽管这完全没有文档记录,也没有得到官方支持.

It still can be accessed by querying the WNF State of the feature, although this is completely undocumented and not officially supported.

WNF 数据的各种状态是 逆向工程,因此 Focus Assist 是 WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED.

The various states for WNF Data have been reverse engineered, so the one for Focus Assist is WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED.

下面的 C++ 示例展示了如何获取 Focus Assist 功能的状态(主要是 offpriority_onlyalarm_only).

The C++ sample below shows how to get the state of Focus Assist feature (mostly off, priority_only and alarm_only).

再次提醒您注意这不是微软官方支持的:

Once again, be wary that this is not officially supported by Microsoft:

#include <Windows.h>
#include <iostream>
#include <string>
#include <map>

// from ntdef.h
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)

// from ntdef.h
typedef struct _WNF_STATE_NAME
{
    ULONG Data[2];
} WNF_STATE_NAME;

typedef struct _WNF_STATE_NAME* PWNF_STATE_NAME;
typedef const struct _WNF_STATE_NAME* PCWNF_STATE_NAME;

typedef struct _WNF_TYPE_ID
{
    GUID TypeId;
} WNF_TYPE_ID, *PWNF_TYPE_ID;

typedef const WNF_TYPE_ID* PCWNF_TYPE_ID;

typedef ULONG WNF_CHANGE_STAMP, *PWNF_CHANGE_STAMP;


enum FocusAssistResult
{
    not_supported = -2,
    failed = -1,
    off = 0,
    priority_only = 1,
    alarms_only = 2
};

std::map<int, std::string> result_map = {
    {-2, "Not Supported"},
    {-1, "Failed"},
    {0, "Off"},
    {1, "Priority Only"},
    {2, "Alarm Only"}
};

typedef NTSTATUS (NTAPI *PNTQUERYWNFSTATEDATA)(
    _In_ PWNF_STATE_NAME StateName,
    _In_opt_ PWNF_TYPE_ID TypeId,
    _In_opt_ const VOID* ExplicitScope,
    _Out_ PWNF_CHANGE_STAMP ChangeStamp,
    _Out_writes_bytes_to_opt_(*BufferSize, *BufferSize) PVOID Buffer,
    _Inout_ PULONG BufferSize);

int main(int argc, CHAR** argv)
{
    // note: ntdll is guaranteed to be in the process address space.
    const auto h_ntdll = GetModuleHandle(_T("ntdll"));

    // get pointer to function
    const auto pNtQueryWnfStateData = PNTQUERYWNFSTATEDATA(GetProcAddress(h_ntdll, "NtQueryWnfStateData"));
    if (!pNtQueryWnfStateData)
    {
        std::cerr << "[-] Error: couldn't get pointer to NtQueryWnfStateData() function." << std::endl;
        return -1;
    }

    // state name for active hours (Focus Assist)
    WNF_STATE_NAME WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED{0xA3BF1C75, 0xD83063E};

    // note: we won't use it but it's required
    WNF_CHANGE_STAMP change_stamp = {0};

    // on output buffer will tell us the status of Focus Assist
    DWORD buffer = 0;
    ULONG buffer_size = sizeof(buffer);

    if (NT_SUCCESS(pNtQueryWnfStateData(&WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED, nullptr, nullptr, &change_stamp, 
        &buffer, &buffer_size)))
    {
        // check if the result is one of FocusAssistResult
        if (result_map.count(buffer) == 0)
        {
            std::cout << "Focus Assist result is unknown." << std::endl;
        }
        else
        {
            std::cout << "Focus assist state: " << result_map[buffer] << std::endl;
        }
    }
    else
    {
        std::cerr << "[-] Error while calling NtQueryWnfStateData." << std::endl;
        return -1;
    }

    return 0;
}

这篇关于有没有办法从 Win32 应用程序检测 Windows 10 中的焦点辅助(以前称为安静时间)的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆