谁能提供一个如何使用 windows ShutdownBlockReasonCreate 的例子

Can anyone provide an example of how to use windows ShutdownBlockReasonCreate

谁能提供一个简单明了的例子ShutdownBlockReasonCreate?我一直试图通过 MSDN 页面弄清楚它,但我不理解它,而且我真的厌倦了每次我尝试测试它但它不起作用时都必须关闭我的计算机。如果有人熟悉并且可以提供一个简洁的例子,那就太棒了!

这是我目前所拥有的,但我做到了'

#include <Windows.h>
#include <iostream>
std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); 
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

int main(int argc, char* argv[])
{
    if (ShutdownBlockReasonCreate(GetForegroundWindow(), s2ws("TEST").c_str()) != 0)
        std::cout << "Success" << std::endl;
    else
        std::cout << "Failure" << std::endl;

    while (1) 
    {
        Sleep(1000);
        std::cout << "Testing..." << std::endl;
    }
}

这在 Windows 7 中对我有用。如果愿意,您也可以在控制台程序中执行此操作,这是一个编写起来更简单的示例。你应该添加错误检查,我没有保持简短。

#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

HINSTANCE hInst;
HWND hWnd;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    switch(message)
    {
        case WM_QUERYENDSESSION:
            return FALSE;
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
            break;
        case WM_CREATE:
            ShutdownBlockReasonCreate(hWnd, L"Don't do it!");
            break;
        case WM_DESTROY:
            ShutdownBlockReasonDestroy(hWnd);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"TestClass";
    wcex.hIconSm = NULL;
    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    hInst = hInstance;
    RECT sz = {0, 0, 512, 512};
    AdjustWindowRect(&sz, WS_OVERLAPPEDWINDOW, TRUE);
    hWnd = CreateWindow(L"TestClass", L"Test Window", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, sz.right - sz.left, sz.bottom - sz.top,
        NULL, NULL, hInstance, NULL);
    if(!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MyRegisterClass(hInstance);
    if(!InitInstance(hInstance, nCmdShow))
    {
        return FALSE;
    }

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}

控制台版本不需要有太大的不同,尽管你确实需要创建一个 window 和 运行 一个消息泵,所以我不确定它能给你带来什么图形用户界面应用程序。显然,如果您想在任何一个版本中工作,您很可能最终需要一个单独的线程来处理 window 或您的工作。

这是我想出的最简单的控制台程序示例。您会注意到,除了 ConsoleCtrlHandler 拦截关闭控制台 window 和关闭 GUI window 的各种方式之外,它几乎完全相同。它也应该是一个 MBCS 项目,因为我不想在我的测试控制台项目中更改它。

#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

HINSTANCE hInst;
HWND hWnd;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    switch(message)
    {
        case WM_QUERYENDSESSION:
            return FALSE;
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
            break;
        case WM_CREATE:
            ShutdownBlockReasonCreate(hWnd, L"Don't do it!");
            break;
        case WM_DESTROY:
            ShutdownBlockReasonDestroy(hWnd);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = "TestClass";
    wcex.hIconSm = NULL;
    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    hInst = hInstance;
    RECT sz = {0, 0, 512, 512};
    AdjustWindowRect(&sz, WS_OVERLAPPEDWINDOW, TRUE);
    hWnd = CreateWindow("TestClass", "Test Window", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, sz.right - sz.left, sz.bottom - sz.top,
        NULL, NULL, hInstance, NULL);
    if(!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}

BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
{
    if(dwCtrlType == CTRL_C_EVENT ||
        dwCtrlType == CTRL_BREAK_EVENT ||
        dwCtrlType == CTRL_CLOSE_EVENT)
    {
        SendMessage(hWnd, WM_CLOSE, 0, 0);
        return TRUE;
    }
    return FALSE;
}

int main()
{
    SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);

    HINSTANCE hInstance = GetModuleHandle(NULL);

    MyRegisterClass(hInstance);
    if(!InitInstance(hInstance, SW_HIDE))
    {
        return FALSE;
    }

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}

正如您现在可能猜到的那样,ShutdownBlockReasonCreate() 实际上并没有阻止关机。它所做的只是告诉 Windows 当它弹出 this screen.

时要说什么消息

要在 Windows 上阻止关机,您需要有一个 window。这意味着您将需要编写一个使用标准消息泵的 GUI 程序。 WM_QUERYENDSESSION 是系统要关闭时发送给所有 windows 的消息。您可以处理消息以阻止关闭请求。但要理解这一点,您需要了解 Windows GUI 编程。 (您可能不需要实际的 GUI;仅消息 window 可能 工作。我不确定。)

你的第一个问题是关于阻止系统服务关闭。我不是 Windows 服务方面的专家,所以我不知道答案。但是,由于会话 0 上的 运行,服务不应具有 GUI。我也不知道他们是否可以只发送消息 windows。