c ++注销前调用函数

时间:2018-04-30 15:20:09

标签: c++ winapi

我试图在用户注销时执行一个函数,但程序在函数调用之前关闭,有没有办法等待函数完成函数执行?

#include "stdafx.h"
#include <windows.h>
#include <fstream>  
using namespace std;
bool done = false;

void createFile() {
    ofstream outfile("test.txt");
    outfile << "test" << std::endl;
    outfile.close();
}

BOOL WINAPI consoleHandler(DWORD signal) {
    switch (signal)
    {
    case CTRL_LOGOFF_EVENT:
        printf("Logoff");
        done = true;
        Sleep(20000); // force exit after 20 seconds
        return TRUE;
    case CTRL_C_EVENT:
        printf("Ctrl+c");
        done = true;
        Sleep(20000); // force exit after 20 seconds
        return TRUE;

    case CTRL_CLOSE_EVENT:
        printf("close");
        done = true;
        Sleep(20000); // force exit after 20 seconds
        return TRUE;

    default:
        // Pass signal on to the next handler
        return FALSE;
    }
}


int main()
{
    if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) {
        printf("\nERROR: Could not set control handler");
        return 1;
    }

    printf("Runing");
    while (!done) {
        printf(".");
        Sleep(1000);
    }
    createFile(); //Dont called on user logout but called on close and ctrl+c
    printf("\nEnding\n");
    Sleep(1000);
    return 0;
}
  

CTRL_C_EVENT CTRL_CLOSE_EVENT

文件 test.txt 已创建,但在

  

CTRL_LOGOFF_EVENT

程序立即关闭,无需调用函数。

2 个答案:

答案 0 :(得分:0)

首先,请允许我道歉:我不会回答具体的问题&nbsp; CTRL_LOGOFF_EVENT&#39;你指的是,但是你正在尝试完成的通用功能:&#39;执行用户注销功能&#39;。

通用方法:

据我所知,没有通用的方法。

您可以尝试各种解决方案:

  • 像你一样抓住事件
  • 使用try catch / finally
  • 生成Windows计时器并对其做出反应
  • 生成将等待主线程结束的线程

但是(据我所知)他们所有人都有一种关闭或另一种方式的弱点。

例如,我最近不得不与我必须使用的编码不佳的dll斗争。这个dll正在调用&#34;退出(0)&#34;。我没有找到优雅的方法来优雅地处理这种行为。

我必须在一个独立的进程(而不是线程)中启动它,我正在从我的主进程监视。要实现和维护一个简单的结果,需要做很多工作。

另一种方法:

根据你想要做的事情,做出你的最终成绩可能是一个好习惯。逐步操作,使用允许您恢复部分写入文件的格式。

这是我一般会做的,但它总是取决于你想要达到的目标。

例如,如果您正在尝试清理工作区,则可能需要:

  • 在上一次运行中未完成的情况下在开始时执行
  • 在临时文件夹中工作

另一种情况,如果你有一个很长的过程并且想要生成摘要文件,你可能想要:

  • 不时生成部分摘要文件
  • 生成新文件时,移动上一个文件
这样,您就可以在流程的每个步骤中获得部分摘要文件。

答案 1 :(得分:-1)

由于我的答案已被拒绝投票,我想我需要更加迂腐。

首先,由于您没有获得CTRL_LOGOFF_EVENT,因此您可能需要查阅此文档(https://docs.microsoft.com/en-us/windows/console/setconsolectrlhandler)。关键部分是:

If a console application loads the gdi32.dll or user32.dll library, the 
HandlerRoutine function that you specify when you call SetConsoleCtrlHandler 
does not get called for the CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT events. The 
operating system recognizes processes that load gdi32.dll or user32.dll as Windows 
applications rather than console applications. This behavior also occurs for 
console applications that do not call functions in gdi32.dll or user32.dll 
directly, but do call functions such as Shell functions that do in turn call 
functions in gdi32.dll or user32.dll.

To receive events when a user signs out or the device shuts down in these 
circumstances, create a hidden window in your console application, and then handle 
the WM_QUERYENDSESSION and WM_ENDSESSION window messages that the hidden window 
receives. You can create a hidden window by calling the CreateWindowEx method with 
the dwExStyle parameter set to 0.

您可能还想阅读(https://msdn.microsoft.com/en-us/library/windows/desktop/aa376890(v=vs.85).aspx)。

现在,我之前建议的是使用SetWindowsHookEx,它应该在所有Windows消息都通过它时起作用(这是Spy用来查看消息队列(https://blogs.msdn.microsoft.com/vcblog/2007/01/16/spy-internals/))的内容。 20年前,对于某些未传递到窗口的消息,您必须执行类似的操作 - 就像在当前窗口的流上处理Windows消息的情况一样。您可能会遇到执行此操作的旧代码,或者您可能仍需要执行此操作。