如何在SYSTEM用户进程中侦听关机消息

贪食蛇男 2016-03-18 11:33:45
在一个窗口程序中,只需要响应 WM_QUERYENDSESSION WM_ENDSESSION 消息即可侦听到关机。
MSDN说了:
Console applications can use the SetConsoleCtrlHandler function to receive shutdown notification.

Service applications can use the RegisterServiceCtrlHandlerEx function to receive shutdown notifications in a handler routine.

即是服务和控制台子系统都有方法侦测关机,但是一个不是服务的“SYSTEM用户下的进程”(如在服务中 CreateProcessW 直接创建的)我没有找到方法来侦听关机,我在这种进程中创建了窗口线程,但未收到 WM_QUERYENDSESSION 消息,同一时刻的普通SESSION下的进程用同样的方式可以侦听到。
求教如何在SYSTEM用户下进程中侦听关机。
...全文
493 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
贪食蛇男 2016-03-21
  • 打赏
  • 举报
回复
好了,我来公布是如何解决的吧,方法比较笨,用了轮询检查 GetSystemMetrics(SM_SHUTTINGDOWN); 放码:

#include <Windows.h>
#include <gdcommon/cpplug.h>

#define CLASS_NAME                      L"GdSessionMonWnd"

static HMODULE gs_hThisModule = NULL;
static DWORD gs_dwPlugType = PT_UNKNOWN;

BOOL WINAPI DllMain(HMODULE hThisModule, DWORD dwReason, LPVOID reserved)
{
    if (DLL_PROCESS_ATTACH == dwReason)
    {
        gs_hThisModule = hThisModule;
        DisableThreadLibraryCalls(hThisModule);
    }

    return TRUE;
}

static void _BroadcastSessionEnd()
{
    static DWORD s_dwLastNotify = 0;
    if (GetTickCount() - s_dwLastNotify > 10000)    // 10秒内可能出现多个,没必要广播多次
    {
        CPPLUGLOG_WARNW(L"向插件系统广播 PMC_SESSIONEND");
        CpPlugBroadcastNotify(PMC_SESSIONEND);
    }

    s_dwLastNotify = GetTickCount();
}

static LRESULT CALLBACK _WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_QUERYENDSESSION)
    {
        _BroadcastSessionEnd();
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

static void WINAPI _MessageLoop()
{
    WNDCLASSEX wcex     = {sizeof(wcex)};
    wcex.lpszClassName  = CLASS_NAME;
    wcex.hInstance      = gs_hThisModule;
    wcex.lpfnWndProc    = _WndProc;
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hIcon          = LoadIcon(NULL, MAKEINTRESOURCE(IDI_INFORMATION));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);

    if (RegisterClassExW(&wcex))
    {
        HWND hWindow = CreateWindowExW(
            0,
            CLASS_NAME,
            CLASS_NAME,
            WS_OVERLAPPEDWINDOW,
            0,
            0,
            0,
            0,
            NULL,
            NULL,
            gs_hThisModule,
            NULL
            );

        if (IsWindow(hWindow))
        {
            UpdateWindow(hWindow);

            MSG msg = {0};
            while (GetMessage(&msg, NULL, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
}

static DWORD WINAPI _SessionMonThread(void* lpParam)
{
    if (PT_PROXY == gs_dwPlugType)
    {
        _MessageLoop();
    }
    else
    {
        for ( ; ;)
        {
            if (GetSystemMetrics(SM_SHUTTINGDOWN))
            {
                _BroadcastSessionEnd();
                break;
            }

            Sleep(SEC_TOMILLISEC(1));   // 快一点,可能有电脑关机特别迅速
        }
    }

    return 0;
}

BOOL WINAPI CpPlugStart(DWORD dwPlugType)
{
    gs_dwPlugType = dwPlugType;

    CPPLUGLOG_CLOSETHREAD(_SessionMonThread, NULL, L"SESSION监测线程");

    return TRUE;
}

// 32位服务插件
void WINAPI PR_b35bdb82() {}
// 32位代理插件
void WINAPI PR_5fe0a478() {}
// 64位服务插件
void WINAPI PR_26e6dcd5() {}
// 64位代理插件
void WINAPI PR_ca5da32f() {}

贪食蛇男 2016-03-18
  • 打赏
  • 举报
回复
引用 1 楼 zgl7903 的回复:
MSDN 的注释部分有说明 Console applications can use the SetConsoleCtrlHandler function to receive shutdown notification. Service applications can use the RegisterServiceCtrlHandlerEx function to receive shutdown notifications in a handler routine.
请仔细看题……RegisterServiceCtrlHandlerExW 必须在服务中,而我的问题是“普通”的进程,只是以SYSTEM身份运行,我已经试过 RegisterServiceCtrlHandlerEx 不传服务名会失败。
代码转载自:https://pan.quark.cn/s/eefcd5647328 在信息技术行业,BIOS(基本输入输出系统)扮演着计算机硬件与操作系统之间的重要桥梁角色,其主要职责包括对硬件进行初始化和检测,以及负责启动操作系统的加载流程。联想Y430P作为一款广受用户青睐的便携式计算设备,而“联想Y430P-刷BIOS V3.66”特指将这款设备的BIOS版本升级至V3.66的具体操作。此类操作有时是不可或缺的,因为BIOS的升级能够修正已知的系统缺陷,优化硬件的互操作性,或者提升整体运行效能。 我们必须明确为何需要进行BIOS的刷新操作。联想Y430P设备可能存在某些功能上的约束,比如网卡白名单机制,这种机制会限制用户更换非原装硬件设备,例如无线网络适配器。网卡白名单是BIOS内嵌的一种安全防护措施,它仅允许经过认证的特定型号网卡在系统正常工作,以此来保障系统的兼容性与稳定性。然而,这种安全特性同时也对用户自主进行硬件升级造成了限制。通过安装新版本的BIOS,我们可以移除这类限制条件,使系统能够识别并兼容更多种类的网卡设备,具体而言,在更新至BIOS V3.66版本后,用户可以自由更换网卡和显卡,而不会触发设备未获授权的警示信息。 在执行BIOS刷新操作之前,必须保持高度的审慎态度,因为不恰当的BIOS更新可能导致设备无法正常启动。以下是进行BIOS刷新的标准流程: 1. **保存当前BIOS状态**:在执行更新之前,强烈建议对现有的BIOS进行备份,以便在更新后出现问题时能够迅速恢复至初始状态。 2. **获取精确版本的BIOS更新包**:需从官方渠道或可信赖的第三方资源下载与联想Y430P设备相匹配的BIOS V3.66升级文件。 3. *...

15,465

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧