惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
宝玉的分享
宝玉的分享
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
爱范儿
爱范儿
小众软件
小众软件
K
Kaspersky official blog
P
Proofpoint News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
V
Vulnerabilities – Threatpost
博客园_首页
Microsoft Security Blog
Microsoft Security Blog
C
Cybersecurity and Infrastructure Security Agency CISA
V
V2EX
C
Check Point Blog
S
Schneier on Security
P
Palo Alto Networks Blog
IT之家
IT之家
GbyAI
GbyAI
T
Threat Research - Cisco Blogs
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Apple Machine Learning Research
Apple Machine Learning Research
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tailwind CSS Blog
Project Zero
Project Zero
Y
Y Combinator Blog
V
Visual Studio Blog
Simon Willison's Weblog
Simon Willison's Weblog
T
Threatpost
Scott Helme
Scott Helme
L
LINUX DO - 热门话题
S
Securelist
C
CERT Recently Published Vulnerability Notes
A
Arctic Wolf
M
MIT News - Artificial intelligence
人人都是产品经理
人人都是产品经理

博客园 - NickyYe

DYNAMIC LINK LIBRARY - DLL 分布式系统中Unique ID 的生成方法 205. Isomorphic Strings 201. Bitwise AND of Numbers Range 189. Rotate Array 187. Repeated DNA Sequences 167. Two Sum II - Input array is sorted Convert BST to Greater Tree Uncommon Words from Two Sentences Path Sum III Delete Node in a BST Sliding Window Maximum Find K Closest Elements C++ TUTORIAL - MEMORY ALLOCATION - 2016 多线程 SetConsoleCtrlHandler() -- 设置控制台信号处理函数 SetConsoleCtrlHandler 处理控制台消息 总结open与fopen的区别 LevelDB
Console Event Handling
NickyYe · 2016-05-20 · via 博客园 - NickyYe

Introduction

Everyone programs console applications one time or the other. This programming is more prevalent when people are learning to program, especially while learning the DOS based C/C++ programming. However, when one migrates to Windows programming, console application development takes a back seat. But the Win32 console development holds an important place, especially when the Win32 API contains a good amount of API dedicated to console application development. If you have noticed, even VC++, and latest development technologies like C#, also supports console project development. Console applications are good candidates for testing the core functionality of your Windows application without the unnecessary overhead of a GUI.

But there's always been a sense of helplessness in regard to how to know when certain system related events have occurred, like when user if logging off, or the system is being shutdown, or handling control+break or control+C keyboard events, etc. For a Windows based application, getting to know when such events occur is no problem since they are having a message queue assigned to them that is polled, and assuming that the concerned event is programmed for, it can be handled pretty easily. But this isn't the case with a console application that has no concept of a message queue.

This article intends to discuss how you can handle all kinds of console-based events in any console application. Once you have gone through it, you will see for yourself how trivial this seemingly helpless task is Smile | :)

Setting Console Traps

The first step in handling console application events is to setup an even trap, technically referred to as installing an event handler. For this purpose, we utilize the SetConsoleCtrlHandler Win32 API that is prototyped as shown below:

Hide   Copy Code

BOOL SetConsoleCtrlHandler(
    PHANDLER_ROUTINE HandlerRoutine, 

The HandlerRoutine parameter is a pointer to a function that has the following prototype:

Hide   Copy Code

BOOL WINAPI HandlerRoutine(
    DWORD dwCtrlType   

All the HandlerRoutine takes is a DWORD parameter that tells what console event has taken place. The parameter can take the following values:

  • CTRL_C_EVENT - occurs when the user presses CTRL+C, or when it is sent by theGenerateConsoleCtrlEvent API.
  • CTRL_BREAK_EVENT - occurs when the user presses CTRL+BREAK, or when it is sent by theGenerateConsoleCtrlEvent API.
  • CTRL_CLOSE_EVENT - occurs when attempt is made to close the console, when the system sends the close signal to all processes associated with a given console.
  • CTRL_LOGOFF_EVENT - occurs when the user is logging off. One cannot determine, however, which user is logging off.
  • CTRL_SHUTDOWN_EVENT - occurs when the system is being shutdown, and is typically sent to services.

Upon receiving the event, the HandlerRoutine can either choose to do some processing, or ignore the event. If the routine chooses not to handle the event, it should return FALSE, and the system shall then proceed to the next installed handler. But incase the routine does handle the event, it should then return TRUE, after doing all the processing it requires. The CTRL_CLOSE_EVENTCTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT are typically used to perform any cleanup that is required by the application, and then call the ExitProcess API. Thus, the system has has some timeouts associated with these three events, which is 5 seconds forCTRL_CLOSE_EVENT, and 20 seconds for the other two. If the process doesn't respond within the timeout period, Windows shall then proceed to display the End Task dialog box to the user. If the user proceeds to end the task, then the application will not have any opportunity to perform cleanup. Thus, any cleanup that is required should complete well within the timeout period. Below is an exemplification of the handler routine:

Hide   Shrink    Copy Code

BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
    char mesg[128];

    switch(CEvent)
    {
    case CTRL_C_EVENT:
        MessageBox(NULL,
            "CTRL+C received!","CEvent",MB_OK);
        break;
    case CTRL_BREAK_EVENT:
        MessageBox(NULL,
            "CTRL+BREAK received!","CEvent",MB_OK);
        break;
    case CTRL_CLOSE_EVENT:
        MessageBox(NULL,
            "Program being closed!","CEvent",MB_OK);
        break;
    case CTRL_LOGOFF_EVENT:
        MessageBox(NULL,
            "User is logging off!","CEvent",MB_OK);
        break;
    case CTRL_SHUTDOWN_EVENT:
        MessageBox(NULL,
            "User is logging off!","CEvent",MB_OK);
        break;

    }
    return TRUE;
}

Now that we have seen how the handler routine works, lets see how to install the handler. To do so, as mentioned earlier in the article, we use the SetConsoleCtrlHandler API as shown below:

Hide   Copy Code

if (SetConsoleCtrlHandler(
    (PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE)
{
    

The first parameter is a function pointer of the type PHANDLER_ROUTINE, whose prototype has been discussed earlier. The second parameter, if set to TRUE, tries installing the handler, and if set to FALSE, attempts the un-installation. If either attempts are successful, the return value is TRUE. Otherwise FALSE is returned.

So, that's all there is to handling the console application events. After handler is installed, your application will receive the events as and by they come, and when the execution is about to be terminated, the handler maybe un-installed. Pretty easy, eh Smile | :) ?