设置Windows计时器,访问被拒绝

时间:2017-05-17 12:10:16

标签: c++ windows timer

我在设置Windows计时器的回调/ windowproc时遇到问题。我在这个例子中想要的是控制台窗口显示三个“Timer Click!”消息然后退出。

#include "stdafx.h"
#include <strsafe.h>
#include "Windows.h"

using namespace System;

int receivedCalls = 0;

LRESULT CALLBACK WindowProc(
    HWND hwnd,          // handle to main window 
    UINT msg,       // type of message 
    WPARAM  wParam,     // additional information 
    LPARAM  lParam     // additional information
)
{

    switch (msg)
    {
    case WM_TIMER:
        receivedCalls += 1;
        Console::WriteLine("Timer click!");
        return 0;
    }
}

int main()
{
    UINT result;
    UINT_PTR IDT_TIMER1 = 1;
    HWND hwnd = GetConsoleWindow();
    result = SetTimer(hwnd,IDT_TIMER1,5000,(TIMERPROC) NULL);
    if (result == 0)
    {
        LPTSTR lpszFunction = TEXT("SetTimer");
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
        DWORD dw = GetLastError();

        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dw,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR)&lpMsgBuf,
            0, NULL);

        lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
            (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
        StringCchPrintf((LPTSTR)lpDisplayBuf,
            LocalSize(lpDisplayBuf) / sizeof(TCHAR),
            TEXT("%s failed with error %d: %s"),
            lpszFunction, dw, lpMsgBuf);
        MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

        LocalFree(lpMsgBuf);
        LocalFree(lpDisplayBuf);
    }
    while (receivedCalls < 3) {
        Sleep(100);
    }
    KillTimer(hwnd, IDT_TIMER1);
    return 0;
}

MessageBox错误代码来自Windows页面。我收到错误代码5:访问被拒绝。我无法设置计时器的可能原因是什么?我真的需要管理员权限来设置计时器吗?如果是这样,定期检查某些内容的首选方法是什么(例如,轮询网站以获取新信息)。

1 个答案:

答案 0 :(得分:1)

这是准确的。控制台窗口由完全不同的进程conhost.exe拥有。它充当安全边界,主要是为了确保程序不能执行从屏幕缓冲区窃取密码等操作。击败这一点,它永远不会按预期工作。实际的窗口过程内置于conhost.exe中,它不知道如何处理这些WM_TIMER消息。

你必须重新考虑这一点。就像创建自己的窗口和消息循环一样,通常在另一个线程上,以防止它干扰正常的控制台I / O.或者更容易使用CreateTimerQueueTimer(),请注意其回调在另一个线程上运行。必须这样,因为操作系统没有任何方法可以打入你的主线程。正确执行此操作的难度提供了本机Windows程序以其工作方式工作的原因。消息循环是producer-consumer problem的通用解决方案。控制台模式程序不会尝试解决它。​​