【问题标题】:Windows Logoff Capture with C使用 C 进行 Windows 注销捕获
【发布时间】:2013-04-23 12:24:58
【问题描述】:

我正在尝试使用 C 来捕获 Windows Server 2008 64 位系统上的注销事件。目前我正在使用此处说明的控制台注销事件代码:http://www.cplusplus.com/forum/beginner/1501/(Gray Wolf 的第 6 条评论,他的第二个编码示例)将附在本文的末尾。

这段代码有几个问题。它可以独立运行,并且在用户启动程序时运行良好。当我开始向我们的一些专有代码添加调用时,它会停止捕获注销事件。没有 GUI 代码,这都是控制台。任何人都知道会阻止这个工作吗?似乎比较挑剔。

此外,如果该程序在登录期间由另一个程序自动启动(在用户级别和相同的会话 ID 上启动,就好像您要双击 .exe 并自己激活它一样),它也无法捕获注销事件。任何想法都会很棒。

示例: 如果由用户手动启动,这可以很好地独立运行。

#include <windows.h>
#include <tchar.h>
#include <signal.h>


BOOL WINAPI ConsoleHandler(
    DWORD dwCtrlType   //  control signal type
);

static int startup;

int main(int argc, char *argv[])
{
    if (SetConsoleCtrlHandler( (PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE)
    {
        // unable to install handler...
        // display message to the user
        printf("Unable to install handler!\n");
        return -1;
    }

    startup=1;

    while(1)
    {

    }
}

BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
    char mesg[128];
    static   FILE * pFile;

    char FileName[32] = "ControlHandle.txt";
    if(startup) {
        /* create the filename */

     pFile = fopen(FileName, "at");
     printf("creating a file\n");

    fprintf(pFile, "This file contains the message when a control character is received.\n\n\n");
    fclose(pFile);
    startup=0;
    }

    switch(CEvent)
    {
    case CTRL_C_EVENT:
        pFile = fopen(FileName, "at");
        if(pFile > 0){
            printf("Got File Handle");
        }
fprintf( pFile,"in handler got an CTRL_C_EVENTevent\n" );
fclose(pFile);
        break;
    case CTRL_BREAK_EVENT:
pFile = fopen(FileName, "at");
fprintf( pFile,"in handler got an CTRL_BREAK_EVENTevent\n" );
fclose(pFile);
        break;
    case CTRL_CLOSE_EVENT:
       pFile = fopen(FileName, "at");
fprintf( pFile,"in handler got an CTRL_CLOSE_EVENTevent\n" );
fclose(pFile);
        break;
    case CTRL_LOGOFF_EVENT:
        pFile = fopen(FileName, "at");
fprintf( pFile,"in handler got an CTRL_LOGOFF_EVENTevent\n" );
fclose(pFile);
        break;
    case CTRL_SHUTDOWN_EVENT:
        pFile = fopen(FileName, "at");
fprintf( pFile,"in handler got an CTRL_SHUTDOWN_EVENTevent\n" );
fclose(pFile);
        break;

    }
    return TRUE;
}

【问题讨论】:

  • 您是否启用了UAC
  • 也许MSDN 会有用。
  • 当前目录呢?您应该首先尝试使用绝对路径。
  • 茴香-我不确定。我没有收到任何 UAC 通知,但系统在用户端被严重锁定。我目前正在使用管理员帐户。
  • 根据 MSDN 上的this(msdn.microsoft.com/en-us/library/windows/desktop/…) 文档,LOGOFF 事件仅针对服务。交互式进程不会收到它。

标签: c++ c windows winapi event-handling


【解决方案1】:

您可以收听WM_QUERYENDSESSIONWM_ENDSESSION 消息。这适用于 GUI 和控制台应用程序,只要您有一个带有消息循环的窗口(不必可见)。

编辑:检查this thread,尤其是上一篇文章中的代码。

额外信息:

【讨论】:

    【解决方案2】:

    您可能必须将代码实现为服务,因为您希望程序一直运行到最后并在登录的最开始时开始。这样,程序在系统模式下运行,并且在开始强制相当用户级别(包括管理程序)时不会关闭 yoru 程序。

    【讨论】:

      【解决方案3】:

      有两种方法

      • 如果您使用的是控制台应用程序,那么您可以使用

        main()
        {
        ...
        SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlEventHandler, TRUE );
        ...
        }
        BOOL CtrlEventHandler(DWORD eventType)
        {
        if(eventType == CTRL_C_EVENT)
        {
        printf(""Sample text");
        return FALSE
        }
        else if(eventType == CTRL_LOGOFF_EVENT)
        {
        printf(""Sample text");
        return FALSE
        }
        }
        
      • 如果您使用的是基于 Windows UI 的应用程序,那么您可以使用虚拟函数 WindowProc 并使用以下代码

        LRESULT CMainDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)    
        {
        if(message == WM_ENDSESSION)
        {
        if(lParam == ENDSESSION_LOGOFF)
        {
        /*Handle event*/
        }
        }
        return CDialogEx::WindowProc(message, wParam, lParam);
        }
        

        对于第一个选项,您可以使用This MSDN link

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-18
        • 2012-01-05
        • 2020-08-30
        • 1970-01-01
        • 1970-01-01
        • 2013-01-06
        • 2012-02-06
        • 1970-01-01
        相关资源
        最近更新 更多