Есть ли способ обнаружить изменения в Focus Assist (ранее Quiet Hours) в Windows 10 из приложения Win32 - PullRequest
0 голосов
/ 21 ноября 2018

Я бы хотел изменить состояние присутствия в приложении автоматически на DND, когда Focus Assist включен.

Итак, два вопроса в основном:

  • Это так?можно проверить состояние Focus Assist через, например, Windows 10 SDK?

    Здесь есть похожий вопрос для тихих часов в Windows 8: Получить окна тихих часов из Win32 или C # API , хотя это не такясно, относится ли оно также к «Помощнику фокусировки», поскольку это больше не является истинным или ложным значением.Тихие часы имели только состояние ВКЛ / ВЫКЛ, в то время как помощь при фокусировке может быть ВЫКЛ / ПРИОРИТЕТ / ТРЕВОГИ.

  • Тем не менее, более интересный вопрос, на который нет ответа в упомянутом выше посте:событие, на которое я могу зарегистрироваться, чтобы получать уведомления об изменениях состояния?

    Цель состоит в том, чтобы получать уведомления сразу же, когда изменяется статус Focus Assist, чтобы не приходилось регулярно запрашивать реестр.

1 Ответ

0 голосов
/ 21 ноября 2018

Насколько я знаю, официально зарегистрированного способа получения статуса помощи фокусировки не существует.

Доступ к нему все еще можно получить, запросив Состояние WNF функции, хотя этополностью недокументировано и официально не поддерживается.

Различные состояния для данных WNF были обработаны в обратном порядке , поэтому для Focus Assist используется WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED.

Пример C ++ниже показано, как получить состояние функции поддержки фокусировки (в основном off, priority_only и alarm_only).

Еще раз, будьте осторожны, что официально не поддерживается 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;
}
...