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



我在设置Windows计时器的回调/窗口proc时遇到问题。在这个例子中,我希望控制台窗口显示三条"计时器单击!"消息,然后退出。

#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;
}

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

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

你必须重新考虑这一点。 就像创建自己的窗口和消息循环一样,通常在另一个线程上,以防止它干扰正常的控制台 I/O。 或者通过使用 CreateTimerQueueTimer() 更容易地,请注意它的回调在另一个线程上运行。 必然如此,因为操作系统没有任何方法可以闯入您的主线程。 正确执行此操作的困难提供了对本机Windows程序为什么以这种方式工作的见解。 消息循环是生产者-消费者问题的通用解决方案。 控制台模式程序不会尝试解决它。

最新更新