0

我四处寻找试图解决此错误的帖子,但在每种情况下,我都已经在按照他们的建议进行操作。

我的编译输出:

main.obj:-1:错误:LNK2019:函数 _main 中引用的未解析外部符号“public:__thiscall KeyLogger::~KeyLogger(void)”(??1KeyLogger@@QAE@XZ)

main.obj:-1:错误:LNK2019:函数 _main 中引用的未解析外部符号“public:__thiscall KeyLogger::KeyLogger(void)”(??0KeyLogger@@QAE@XZ)

debug\AccipioKeyDemo.exe:-1: error: LNK1120: 2 unresolved externals

我知道这是说我定义了 KeyLogger 构造函数和析构函数但未实现,但实际上我已经实现了所有内容。

主文件

#include <QCoreApplication>
#include "keylogger.h"

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    KeyLogger k;

    return a.exec();
}

键盘记录器.h

#ifndef KEYLOGGER_H
#define KEYLOGGER_H

#include <Windows.h>

class KeyLogger {

public:
    KeyLogger();
    ~KeyLogger();

    void start();
    void stop();

private:
    HHOOK hook;

    LRESULT CALLBACK intercept(int code, WPARAM wparam, LPARAM lparam);
};

#endif // KEYLOGGER_H

键盘记录器.cpp

#include "keylogger.h"
#include <QDebug>

KeyLogger::KeyLogger() : hook(NULL) {
    hook = SetWindowsHookEx(WH_KEYBOARD_LL, intercept, NULL,0);

    if (hook == NULL) {
        qDebug() << "HOOK FAILED";
    } else {
        qDebug() << "HOOK SUCCESS";
    }
}

KeyLogger::~KeyLogger() {

}

void KeyLogger::start() {
    qDebug() << "start";
}

void KeyLogger::stop() {
    qDebug() << "stop";
}

LRESULT CALLBACK KeyLogger::intercept(int code, WPARAM wparam, LPARAM lparam) {
    qDebug() << "Key Pressed";
    return CallNextHookEx(hook, code, wparam, lparam);
}

QT Pro 配置

#-------------------------------------------------
#
# Project created by QtCreator 2013-10-10T19:58:51
#
#-------------------------------------------------

QT       += core

QT       -= gui

TARGET = AccipioKeyDemo
CONFIG   += console
CONFIG   -= app_bundle

LIBS += user32.lib

TEMPLATE = app

SOURCES += main.cpp \
    keylogger.cpp

HEADERS += \
    keylogger.h
4

2 回答 2

2

您的代码已损坏,因为回调方法必须是静态成员 - 本质上它们必须是自由函数。由于无法将指向KeyLogger实例的指针传递给拦截回调函数,因此您的钩子必须是类成员,而不是实例成员。用互斥锁保护钩子可能不是一个坏主意,以防您后来忘记了自己并尝试KeyLogger在多个线程中实例化 s 。

在您的情况下,KeyLogger对象可复制也是一个错误。Q_DISABLE_COPY在不打算复制的类上使用宏。

您可能想删除构建目录并重新构建您的项目,但请记住按如下所示修复错误,否则将无法正常工作。

下面的最小化版本(只是一个main.cpp文件)可以正常工作和编译。它演示了如何正确处理从事件队列中转储数据:您必须在持有互斥锁的同时从队列中复制一小块数据,然后释放互斥锁,然后再将其转储到其他地方。

#include <QCoreApplication>
#include <QMutex>
#include <QDebug>
#include <QQueue>
#include <QDataStream>
#include <windows.h>

struct KeyLoggerEvent {
   WPARAM event;
   KBDLLHOOKSTRUCT key;
   KeyLoggerEvent(WPARAM ev, KBDLLHOOKSTRUCT k) : event(ev), key(k) {}
};
QDataStream & operator<<(QDataStream & s, const KeyLoggerEvent & kev) {
   s << kev.event
     << (quint32)kev.key.flags << (quint32)kev.key.scanCode
     << (quint32)kev.key.time << (quint32)kev.key.vkCode;
   return s;
}

class KeyLogger {
   Q_DISABLE_COPY(KeyLogger)
   static QMutex m_hookMutex;
   static HHOOK m_hook;
   static QQueue<KeyLoggerEvent> m_events;
   static LRESULT CALLBACK intercept(int code, WPARAM wparam, LPARAM lparam);
public:
   KeyLogger() {
      QMutexLocker lock(&m_hookMutex);
      Q_ASSERT(!m_hook);
      m_hook = SetWindowsHookEx(WH_KEYBOARD_LL, intercept, NULL,0);
      if (!m_hook) qDebug() << "HOOK FAILED";
      lock.unlock();
   }
   ~KeyLogger() {
      QMutexLocker lock(&m_hookMutex);
      if (m_hook) UnhookWindowsHookEx(m_hook);
      m_hook = NULL;
   }
   //! Dumps a bunch of events to the stream. Returns false if no more events remain in the
   //! log. To avoid lock contention, it keeps the queue lock for a very short amount of time.
   bool dump(QDataStream & s) {
      int batchCount = 1000;
      QQueue<KeyLoggerEvent> dumpQueue;
      QMutexLocker lock(&m_hookMutex);
      while (batchCount-- && !m_events.empty()) {
         dumpQueue.enqueue(m_events.dequeue());
      }
      bool more = !m_events.empty();
      lock.unlock();
      // The below could block for a long time, thus it works from a local copy.
      while (! dumpQueue.empty()) s << dumpQueue.dequeue();
      return more;
   }
};

QMutex KeyLogger::m_hookMutex;
HHOOK KeyLogger::m_hook = NULL;
QQueue<KeyLoggerEvent> KeyLogger::m_events;

LRESULT CALLBACK KeyLogger::intercept(int code, WPARAM wparam, LPARAM lparam) {
   qDebug() << "Key Event";
   QMutexLocker lock(&m_hookMutex);
   if (code >= 0) {
      KBDLLHOOKSTRUCT * key = reinterpret_cast<KBDLLHOOKSTRUCT*>(lparam);
      m_events.enqueue(KeyLoggerEvent(wparam, *key));
   }
   HHOOK hook = KeyLogger::m_hook;
   lock.unlock();
   return CallNextHookEx(hook, code, wparam, lparam);
}

int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   KeyLogger k;
   return a.exec();
}
于 2013-10-11T17:58:19.683 回答
0

您收到链接错误,链接器无法找到带有构造函数和析构函数的 obj 文件。这意味着 keylogger.cpp 要么未编译,要么链接器找不到它的 obj 文件。检查项目的设置。

于 2013-10-11T03:32:24.120 回答