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

```

  1. **安装服务**:

```batch

sc create MouseSimulationService binPath= "完整路径\MouseService.exe" start= auto

sc start MouseSimulationService

```

  1. **注意事项**:
  • 服务程序需要以 SYSTEM 账户运行

  • 需要适当的权限和桌面访问权限

  • 建议在服务属性中设置"允许服务与桌面交互"

  • 所有操作都会记录到 C:\MouseService.log

  • 服务程序需要管理员权限安装和运行

  1. **主要改进**:
  • 添加了适当的桌面访问权限处理

  • 使用命名管道进行通信

  • 完整的服务生命周期管理

  • 详细的日志记录

  • 错误处理和异常恢复

  1. **限制**:
  • 由于 Windows 安全限制,某些鼠标操作可能在某些情况下不响应

  • 需要正确配置服务权限

  • 在某些 Windows 版本中可能需要额外的安全配置

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

相关推荐
半吊子全栈工匠4 小时前
性能优化之动态加载
windows
马立杰4 小时前
H3CNE-17-DHCP动态主机配置协议
网络·windows·h3cne
monstercl5 小时前
MySQL 8.4及以上版本压缩包安装 windows
windows·mysql
renhl25218 小时前
opengrok_windows_多工程环境搭建
windows
0xCC说逆向19 小时前
Windows图形界面(GUI)-QT-C/C++ - QT 窗口属性
c语言·开发语言·c++·windows·qt·mfc
来自外太空的鱼-张小张1 天前
阿里云oss简单获取视频第一帧工具类
windows·阿里云·音视频
^@^lemon tea^@^1 天前
WPF 引发类型为“System.Windows.Forms.AxHost+InvalidActiveXStateException”的异常 解决办法
windows·wpf·ocx控件开发错误
hmywillstronger1 天前
【Grasshopper】【Python】点集排序:带索引的Z字形排序算法
windows·python·排序算法
skywalk81631 天前
Windows下建立Jupyter-lab 编程环境
ide·windows·python·jupyter