Windows 服务程序实现鼠标模拟

```cpp
#include <windows.h>
#include <fstream>
#include <string>
#include <tchar.h>
#include <thread>
#include <vector>

#define SERVICE_NAME _T("MouseSimulationService")

// 全局变量
SERVICE_STATUS        g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE                g_ServiceStopEvent = INVALID_HANDLE_VALUE;

// 日志类
class Logger {
private:
    std::ofstream logFile;

public:
    Logger(const std::string& filename) {
        logFile.open(filename, std::ios::app);
    }

    void Log(const std::string& message) {
        if (logFile.is_open()) {
            SYSTEMTIME st;
            GetLocalTime(&st);
            logFile << st.wYear << "-" << st.wMonth << "-" << st.wDay << " "
                   << st.wHour << ":" << st.wMinute << ":" << st.wSecond << " - "
                   << message << std::endl;
            logFile.flush();
        }
    }

    ~Logger() {
        if (logFile.is_open()) {
            logFile.close();
        }
    }
};

// 全局日志对象
Logger* g_Logger = nullptr;

// 鼠标模拟类
class MouseSimulator {
public:
    static bool MoveTo(int x, int y) {
        // 获取桌面窗口的句柄
        HWND desktopHwnd = GetDesktopWindow();
        if (!desktopHwnd) {
            if (g_Logger) g_Logger->Log("Failed to get desktop window handle");
            return false;
        }

        // 获取输入桌面
        HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
            DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
            DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
        if (!hDesk) {
            if (g_Logger) g_Logger->Log("Failed to open input desktop");
            return false;
        }

        // 设置线程桌面
        if (!SetThreadDesktop(hDesk)) {
            if (g_Logger) g_Logger->Log("Failed to set thread desktop");
            CloseDesktop(hDesk);
            return false;
        }

        // 计算绝对坐标
        double screenWidth = GetSystemMetrics(SM_CXSCREEN) - 1;
        double screenHeight = GetSystemMetrics(SM_CYSCREEN) - 1;
        double dx = x * (65535.0f / screenWidth);
        double dy = y * (65535.0f / screenHeight);

        INPUT input = { 0 };
        input.type = INPUT_MOUSE;
        input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK | MOUSEEVENTF_MOVE;
        input.mi.dx = static_cast<LONG>(dx);
        input.mi.dy = static_cast<LONG>(dy);

        UINT result = SendInput(1, &input, sizeof(INPUT));
        
        CloseDesktop(hDesk);

        if (result != 1) {
            if (g_Logger) g_Logger->Log("Failed to move mouse");
            return false;
        }

        if (g_Logger) g_Logger->Log("Mouse moved to " + std::to_string(x) + "," + std::to_string(y));
        return true;
    }

    static bool Click() {
        INPUT inputs[2] = { 0 };
        inputs[0].type = INPUT_MOUSE;
        inputs[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
        inputs[1].type = INPUT_MOUSE;
        inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;

        UINT result = SendInput(2, inputs, sizeof(INPUT));
        if (result != 2) {
            if (g_Logger) g_Logger->Log("Failed to perform click");
            return false;
        }

        if (g_Logger) g_Logger->Log("Click performed");
        return true;
    }
};

// 命名管道处理类
class PipeHandler {
private:
    static const int BUFFER_SIZE = 1024;
    HANDLE pipe;

public:
    PipeHandler() : pipe(INVALID_HANDLE_VALUE) {}

    bool Create() {
        pipe = CreateNamedPipe(
            TEXT("\\\\.\\pipe\\MouseSimulationPipe"),
            PIPE_ACCESS_DUPLEX,
            PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
            PIPE_UNLIMITED_INSTANCES,
            BUFFER_SIZE,
            BUFFER_SIZE,
            0,
            NULL);

        if (pipe == INVALID_HANDLE_VALUE) {
            if (g_Logger) g_Logger->Log("Failed to create pipe");
            return false;
        }
        return true;
    }

    bool WaitForConnection() {
        if (!ConnectNamedPipe(pipe, NULL)) {
            if (GetLastError() != ERROR_PIPE_CONNECTED) {
                if (g_Logger) g_Logger->Log("Failed to connect to pipe");
                return false;
            }
        }
        return true;
    }

    bool ReadCommand(std::string& command) {
        char buffer[BUFFER_SIZE];
        DWORD bytesRead;

        if (ReadFile(pipe, buffer, BUFFER_SIZE, &bytesRead, NULL)) {
            buffer[bytesRead] = '\0';
            command = std::string(buffer);
            return true;
        }
        return false;
    }

    void Close() {
        if (pipe != INVALID_HANDLE_VALUE) {
            DisconnectNamedPipe(pipe);
            CloseHandle(pipe);
            pipe = INVALID_HANDLE_VALUE;
        }
    }

    ~PipeHandler() {
        Close();
    }
};

// 服务控制处理函数
VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{
    switch (CtrlCode)
    {
    case SERVICE_CONTROL_STOP:
        if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
            break;

        g_ServiceStatus.dwControlsAccepted = 0;
        g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
        g_ServiceStatus.dwWin32ExitCode = 0;
        g_ServiceStatus.dwCheckPoint = 4;

        SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
        SetEvent(g_ServiceStopEvent);
        break;

    default:
        break;
    }
}

// 解析命令
void ProcessCommand(const std::string& cmd) {
    try {
        size_t pos = cmd.find(' ');
        if (pos == std::string::npos) return;

        std::string action = cmd.substr(0, pos);
        std::string coords = cmd.substr(pos + 1);

        if (action == "move") {
            pos = coords.find(',');
            if (pos != std::string::npos) {
                int x = std::stoi(coords.substr(0, pos));
                int y = std::stoi(coords.substr(pos + 1));
                MouseSimulator::MoveTo(x, y);
            }
        }
        else if (action == "click") {
            MouseSimulator::Click();
        }
    }
    catch (const std::exception& e) {
        if (g_Logger) g_Logger->Log("Error processing command: " + std::string(e.what()));
    }
}

// 服务主函数
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
    g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
    if (g_StatusHandle == NULL) return;

    g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    g_ServiceStatus.dwWin32ExitCode = 0;
    g_ServiceStatus.dwServiceSpecificExitCode = 0;
    g_ServiceStatus.dwCheckPoint = 0;

    // 初始化日志
    g_Logger = new Logger("C:\\MouseService.log");
    g_Logger->Log("Service starting...");

    // 创建停止事件
    g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (g_ServiceStopEvent == NULL)
    {
        g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        g_ServiceStatus.dwWin32ExitCode = GetLastError();
        SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
        return;
    }

    // 服务已启动
    g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    g_ServiceStatus.dwCheckPoint = 0;
    g_ServiceStatus.dwWaitHint = 0;
    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);

    // 主服务循环
    PipeHandler pipe;
    while (true)
    {
        if (WaitForSingleObject(g_ServiceStopEvent, 0) == WAIT_OBJECT_0)
            break;

        if (pipe.Create())
        {
            if (pipe.WaitForConnection())
            {
                std::string command;
                if (pipe.ReadCommand(command))
                {
                    g_Logger->Log("Received command: " + command);
                    ProcessCommand(command);
                }
            }
            pipe.Close();
        }
    }

    // 清理
    if (g_ServiceStopEvent)
    {
        CloseHandle(g_ServiceStopEvent);
        g_ServiceStopEvent = NULL;
    }

    delete g_Logger;
    g_Logger = nullptr;

    g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    g_ServiceStatus.dwCheckPoint = 0;
    g_ServiceStatus.dwWaitHint = 0;
    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
}

// 主函数
int main()
{
    SERVICE_TABLE_ENTRY ServiceTable[] =
    {
        { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
        { NULL, NULL }
    };

    if (!StartServiceCtrlDispatcher(ServiceTable))
    {
        return GetLastError();
    }

    return 0;
}
```

**测试客户端程序**:

```cpp
#include <windows.h>
#include <iostream>
#include <string>

int main()
{
    while (true)
    {
        HANDLE hPipe = CreateFile(
            TEXT("\\\\.\\pipe\\MouseSimulationPipe"),
            GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);

        if (hPipe != INVALID_HANDLE_VALUE)
        {
            std::string command;
            std::cout << "Enter command (move x,y or click): ";
            std::getline(std::cin, command);

            if (command == "exit")
                break;

            DWORD bytesWritten;
            WriteFile(hPipe, command.c_str(), command.length(), &bytesWritten, NULL);
            CloseHandle(hPipe);
        }
        else
        {
            std::cout << "Failed to connect to pipe. Error: " << GetLastError() << std::endl;
            Sleep(1000);
        }
    }

    return 0;
}
```

**安装和使用说明**:

1. **编译服务程序**:
```batch
cl mouse_service.cpp /EHsc /Fe:MouseService.exe
```

2. **安装服务**:
```batch
sc create MouseSimulationService binPath= "完整路径\MouseService.exe" start= auto
sc start MouseSimulationService
```

3. **注意事项**:
- 服务程序需要以 SYSTEM 账户运行
- 需要适当的权限和桌面访问权限
- 建议在服务属性中设置"允许服务与桌面交互"
- 所有操作都会记录到 C:\MouseService.log
- 服务程序需要管理员权限安装和运行

4. **主要改进**:
- 添加了适当的桌面访问权限处理
- 使用命名管道进行通信
- 完整的服务生命周期管理
- 详细的日志记录
- 错误处理和异常恢复

5. **限制**:
- 由于 Windows 安全限制,某些鼠标操作可能在某些情况下不响应
- 需要正确配置服务权限
- 在某些 Windows 版本中可能需要额外的安全配置

这个版本的程序已经适配了 Windows 服务环境,但仍然需要注意 Windows 服务的各种限制和安全考虑。建议在实际部署前进行充分测试。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/893189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ui设计公司分享:浅色 UI 设计

在数字化产品琳琅满目的今天&#xff0c;用户对于界面的要求早已不止于功能的实现&#xff0c;更追求一种舒适、无压的交互体验。而浅色UI设计&#xff0c;凭借其独特的魅力&#xff0c;正逐渐成为众多设计师营造优质体验的首选。 一、浅色UI设计的视觉优势 &#xff08;一&a…

Nacos:使用PgSQL数据源

数据源插件开源仓库地址&#xff1a;nacos-datasource-extend-plugins 一、PostgreSQL数据库安装 1、本文使用Docker进行数据库的安装&#xff0c;使用docker命令拉取的PG14版本的数据库&#xff1a; docker pull postgres:14.6 2、创建PG容器并启动&#xff0c;映射了5432…

Linux——入门基本指令汇总

目录 1. ls指令2. pwd3. whoami指令4. cd指令5. clear指令6. touch指令7. mkdir指令8. rm指令9. man指令10. cp指令11. mv指令12. cat指令13. tac指令14. more指令15. less指令16. head指令17. tail指令18. date指令19. cal指令20. find指令21. which指令22. alias指令23. grep…

C语言之装甲车库车辆动态监控辅助记录系统

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之装甲车库车辆动态监控辅助记录系统 目录 一、前言 1.1 &#xff08;一&#xff09;…

2024年Vue面试题汇总

流程图如下&#xff1a; vue核心知识——语法篇 1.请问 v-if 和 v-show 有什么区别&#xff1f; 相同点&#xff1a; 两者都是在判断DOM节点是否要显示。 不同点&#xff1a; a.实现方式&#xff1a; v-if是根据后面数据的真假值判断直接从Dom树上删除或重建元素节点。 v-…

centos搭建 Node.js 开发环境

Node.js &#xff0c;通常简称为Node&#xff0c;是一个事件驱动 I/O 服务端 JavaScript 环境&#xff0c;基于 Chrome V8引擎&#xff0c;具备速度快、性能强等特点&#xff0c;可用于搭建各类网络应用&#xff0c;及作为小程序后端服务环境。npm 和 npx 都是和 Node.js 相关的…

DuckDB:精通Insert语句处理数据冲突

本文介绍DuckDB insert语句用法&#xff0c;包括常规的批量插入&#xff0c;尤其是插入数据冲突的处理&#xff0c;最后还提及returning子句的用法&#xff0c;每个用法提供示例说明。 insert插入数据 INSERT INTO向表中插入新行。可以插入由值表达式指定的一行或多行&#xf…

【Linux系统】Ext系列磁盘文件系统二:引入文件系统(续篇)

inode 和 block 的映射 该博文中有详细解释&#xff1a;【Linux系统】inode 和 block 的映射原理 目录与文件名 这里有几个问题&#xff1a; 问题一&#xff1a; 我们访问文件&#xff0c;都是用的文件名&#xff0c;没用过 inode 号啊&#xff1f; 之前总是说可以通过一个…

SpringBoot实现定时任务,使用自带的定时任务以及调度框架quartz的配置使用

SpringBoot实现定时任务&#xff0c;使用自带的定时任务以及调度框架quartz的配置使用 文章目录 SpringBoot实现定时任务&#xff0c;使用自带的定时任务以及调度框架quartz的配置使用一. 使用SpringBoot自带的定时任务&#xff08;适用于小型应用&#xff09;二. 使用调度框架…

flutter 使用google_mlkit_image_labeling做图片识别

在AI横行的如今&#xff0c;相信大家或多或少都做过跟AI接轨的需求了吧&#xff1f;今天我说的是关于图片识别的需求&#xff0c;flutter的专属图片识别插件google_mlkit_image_labeling。 google_mlkit_image_labeling它是Google旗下的Google Cloud Vision API中分支出来的一部…

国产编辑器EverEdit - 合并行

1 合并行 1.1 应用场景 在编写代码或其他场景下&#xff0c;有时需要把多行的内容缩减成一行&#xff0c;或者纯粹减少行数进行合并&#xff0c;比如&#xff1a;下面的字典的定义&#xff0c;每个元素占了一行&#xff0c;有点浪费&#xff0c;现在需要把它们缩减行数。 typ…

3 前端(中):JavaScript

文章目录 前言&#xff1a;JavaScript简介一、ECMAscript&#xff08;JavaScript基本语法&#xff09;1 JavaScript与html结合方式&#xff08;快速入门&#xff09;2 基本知识&#xff08;1&#xff09;JavaScript注释&#xff08;和Java注释一样&#xff09;&#xff08;2&am…

RIME-CNN-LSTM-Attention多变量多步时序预测Matlab实现

SCI一区级 | Matlab实现RIME-CNN-LSTM-Multihead-Attention多变量多步时序预测 目录 SCI一区级 | Matlab实现RIME-CNN-LSTM-Multihead-Attention多变量多步时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现RIME-CNN-LSTM-Multihead-Attention霜冰算法…

一文读懂服务器的HBA卡

什么是 HBA 卡 HBA 卡&#xff0c;全称主机总线适配器&#xff08;Host Bus Adapter&#xff09; &#xff0c;是服务器与存储装置间的关键纽带&#xff0c;承担着输入 / 输出&#xff08;I/O&#xff09;处理及物理连接的重任。作为一种电路板或集成电路适配器&#xff0c;HBA…

mfc操作json示例

首先下载cJSON,加入项目; 构建工程,如果出现, fatal error C1010: unexpected end of file while looking for precompiled head 在cJSON.c文件的头部加入#include "stdafx.h"; 看情况,可能是加到.h或者是.cpp文件的头部,它如果有包含头文件, #include &…

综述:大语言模型在机器人导航中的最新进展!

简介 机器人导航是指机器人能够在环境中自主移动和定位的能力。本文系统地回顾了基于大语言模型&#xff08;LLMs&#xff09;的机器人导航研究&#xff0c;将其分为感知、规划、控制、交互和协调等方面。具体来说&#xff0c;机器人导航通常被视为一个几何映射和规划问题&…

owasp SQL 注入-03 (原理)

1: 先看一下注入界面: 点submit 后&#xff0c;可以看到有语法报错&#xff0c;说明已经起作用了: 报如下的错误: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near at line 1 2:…

Vscode:问题解决办法 及 Tips 总结

Visual Studio Code&#xff08;简称VSCode&#xff09;是一个功能强大的开源代码编辑器&#xff0c;广泛用于各种编程语言和开发场景&#xff0c;本博客主要记录在使用 VSCode 进行verilog开发时遇到的问题及解决办法&#xff0c;使用过程中的技巧 文章目录 扩展安装失败调试配…

Linux(NFS服务)

赛题拓扑&#xff1a; 题目&#xff1a; NFS&#xff1a; 共享/webdata/目录。用于存储AppSrv主机的WEB数据。仅允许AppSrv主机访问该共享。 [rootstoragesrv ~]# yum install nfs-utils -y [rootstoragesrv ~]# mkdir /webdata [rootstoragesrv ~]# chmod -R ow /webdata …

c.p.api.config.MyAuthenticationProvider

文章目录 1、URL1、AdminController3、AuthenticationProvider 2025-01-15 14:21:31.017 WARN 1972 --- [nio-8087-exec-8] c.p.api.config.MyAuthenticationProvider : 管理员:13524972741 登录失败:密码错误解释: 时间戳: 2025-01-15 14:21:31.017 - 表示日志记录的时间…