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

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

问题描述

我想在开启对焦辅助时自动将应用程序中的在线状态更改为免打扰.

所以基本上有两个问题:

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

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

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

解决方案

据我所知,目前还没有官方记录的获取 Focus 辅助状态的方法.

它仍然可以通过查询 WNF 状态来访问 的功能,尽管这完全没有记录并且不受官方支持.

WNF 数据的各种状态已经逆向工程,所以焦点辅助是WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED.

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

再次提醒,微软未正式支持:

#include #include #include <字符串>#include <地图>//来自 ntdef.h#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)//来自 ntdef.htypedef 结构 _WNF_STATE_NAME{超龙数据[2];} WNF_STATE_NAME;typedef struct _WNF_STATE_NAME* PWNF_STATE_NAME;typedef const struct _WNF_STATE_NAME* PCWNF_STATE_NAME;类型定义结构_WNF_TYPE_ID{GUID 类型 ID;} WNF_TYPE_ID, *PWNF_TYPE_ID;typedef const WNF_TYPE_ID* PCWNF_TYPE_ID;typedef ULONG WNF_CHANGE_STAMP, *PWNF_CHANGE_STAMP;枚举 FocusAssistResult{not_supported = -2,失败 = -1,关闭 = 0,priority_only = 1,警报_only = 2};std::map结果地图 = {{-2, "不支持"},{-1, "失败"},{0, "关闭"},{1, "仅限优先级"},{2, 仅报警"}};typedef NTSTATUS (NTAPI *PNTQUERYWNFSTATEDATA)(_In_ PWNF_STATE_NAME 州名,_In_opt_ PWNF_TYPE_ID TypeId,_In_opt_ const VOID* ExplicitScope,_Out_ PWNF_CHANGE_STAMP ChangeStamp,_Out_writes_bytes_to_opt_(*BufferSize, *BufferSize) PVOID 缓冲区,_Inout_ PULONG BufferSize);int main(int argc, CHAR** argv){//注意:ntdll 保证在进程地址空间中.const auto h_ntdll = GetModuleHandle(_T("ntdll"));//获取函数指针const auto pNtQueryWnfStateData = PNTQUERYWNFSTATEDATA(GetProcAddress(h_ntdll, "NtQueryWnfStateData"));如果 (!pNtQueryWnfStateData){std::cerr <<[-] 错误:无法获得指向 NtQueryWnfStateData() 函数的指针."<<std::endl;返回-1;}//活动时间的状态名称(Focus Assist)WNF_STATE_NAME WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED{0xA3BF1C75, 0xD83063E};//注意:我们不会使用它,但它是必需的WNF_CHANGE_STAMP change_stamp = {0};//在输出缓冲区上会告诉我们 Focus Assist 的状态DWORD 缓冲区 = 0;ULONG buffer_size = sizeof(buffer);如果 (NT_SUCCESS(pNtQueryWnfStateData(&WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED, nullptr, nullptr, &change_stamp,&buffer, &buffer_size))){//检查结果是否是 FocusAssistResult 之一如果(result_map.count(缓冲区)== 0){std::cout <<对焦辅助结果未知."<<std::endl;}别的{std::cout <<"对焦辅助状态:<<result_map[缓冲区] <<std::endl;}}别的{std::cerr <<[-] 调用 NtQueryWnfStateData 时出错."<<std::endl;返回-1;}返回0;}

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

So two questions basically:

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

    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?

    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.

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

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

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 中 Focus Assist(以前称为 Quiet Hours)的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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