资讯动态

C#微信PC端消息监听与自动回复技术实现

发布时间:2026/10/24 17:11:21 来源:尧图企业网站定制
简介本资源是一份基于C#实现的微信PC客户端消息监听与自动回复技术探索方案面向具备Windows桌面开发基础、熟悉.NET生态及逆向/钩子原理的中高级开发者适用于自动化办公、客服辅助或安全研究等场景。压缩包共364个文件体量达46.85MB包含96个运行依赖DLL、65个API文档XML、22个核心C#源码文件、7个可执行程序含调试用EXE、以及log4net等日志配置文件和Visual Studio项目文件.sln/.csproj整体结构体现完整构建流程与调试支持能力。已有4072人学习下载反映出社区对微信PC端HOOK技术的持续关注。读者可获得一套可编译运行的工程框架涵盖WeChat进程通信、内存注入逻辑雏形、消息解析入口及基础回复机制代码同时附带多版本配置文件与缓存策略参考有助于理解微信PC版协议交互边界与Hook落地难点。1. 这不是微信官方API但能真正在PC端捕获每一条消息并自动触发回复——适合做客服中台、内部通知聚合、多账号消息归档的C#桌面程序某公司内部有个老系统每天要盯着三台电脑上的微信PC客户端回客户咨询人工复制粘贴手动点击平均响应延迟83秒。他们试过用UI自动化PyAutoGUI OpenCV找图结果一开深色模式就失灵也接入过企业微信API但客户坚持用个人微信沟通流程卡死。最后上线的方案就是基于「C# PC版微信消息监听自动回复」这个项目改出来的——它不依赖微信网页版、不走服务器中转、不调用任何未公开Web API而是直接在Windows进程内存层面对微信PC客户端WeChat.exe做消息钩子注入实时捕获WM_COPYDATA和WM_USER0x1234这类私有消息解析出原始文本、发送人ID、时间戳再模拟键盘输入回车完成自动回复。整个链路全程离线运行单机可同时监控3个微信实例CPU占用稳定在1.2%以下。如果你正被“微信PC不能自动化”这句话困住又不想碰逆向黑盒或买商业SDK这个项目就是你该打开的第一个源码包。2. 技术栈与架构设计为什么选C# EasyHook Win32 API而不是Python或Electron这个项目不是玩具Demo而是一个能在生产环境跑满7×24小时的桌面服务。它的技术选型背后是几个硬性约束倒逼出来的必须零依赖用户安装运行时排除.NET Core需额外部署、必须精确拦截微信主窗口消息排除UI级模拟、必须绕过微信的Anti-Debug检测排除简单DLL注入。最终落地为三层结构注入层Injector→ 钩子层Hooker→ 业务层BotCore全部用C# 4.7.2编写依赖仅两个NuGet包EasyHookv2.7.6869和Microsoft.Win32.Registry系统自带。没有WPF界面纯控制台宿主Windows服务封装能力启动后托盘常驻日志写入%APPDATA%\WeChatMonitor\logs\按天滚动。2.1 注入层用CreateRemoteThread精准把Hooker.dll塞进WeChat.exe地址空间注入不是靠Process.Start()拉起微信再Attach而是主动扫描已运行的WeChat.exe进程拿到其PID和主线程句柄再调用CreateRemoteThread在目标进程内分配内存、写入Shellcode、执行LoadLibraryA加载我们编译好的Hooker.dll。关键点在于微信PC版会校验模块签名所以Hooker.dll必须用自签名证书项目里已提供devcert.pfx签名否则会被ntdll!LdrpCheckModuleSignature拦截。注入代码核心段如下// Injector.cs 第142行远程线程注入逻辑 IntPtr hProcess OpenProcess(PROCESS_ALL_ACCESS, false, pid); IntPtr pLoadLib GetProcAddress(GetModuleHandle(kernel32.dll), LoadLibraryA); IntPtr pRemoteMem VirtualAllocEx(hProcess, IntPtr.Zero, (uint)hookDllBytes.Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); WriteProcessMemory(hProcess, pRemoteMem, hookDllBytes, (uint)hookDllBytes.Length, out _); IntPtr hThread CreateRemoteThread(hProcess, IntPtr.Zero, 0, pLoadLib, pRemoteMem, 0, IntPtr.Zero); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess);提示hookDllBytes是Hooker.dll的二进制流不是路径字符串。这是为了规避杀毒软件对LoadLibrary(C:\xxx\Hooker.dll)的路径监控。实际项目中我一般会把DLL资源嵌入Injector.exe的Manifest中运行时解密释放到临时目录再读取防静态查杀。2.2 钩子层拦截WeChat.exe的WndProc捕获WM_COPYDATA中的消息体微信PC版的消息收发本质是主窗口类名WeChatMainWndForPC通过SendMessage向自身或子窗口发送WM_COPYDATA消息其中COPYDATASTRUCT.lpData指向一块共享内存结构体前4字节是消息类型0x1文本0x2图片0x3链接后面紧跟着UTF-16编码的JSON字符串。Hooker.dll做的就是在SetWindowsHookEx(WH_CALLWNDPROC)之后拦截所有发给微信主窗口的消息在CallWndProc回调里检查wParamHWND_BROADCAST且messageWM_COPYDATA然后用ReadProcessMemory从微信进程地址空间读出lpData指向的内容。关键代码在Hooker/HookManager.cs第89行// HookManager.cs 第89行解析WM_COPYDATA消息体 if (nCode 0 wParam (IntPtr)HWND_BROADCAST msg.message WM_COPYDATA) { COPYDATASTRUCT cds Marshal.PtrToStructureCOPYDATASTRUCT(lParam); IntPtr remoteBuffer cds.lpData; byte[] jsonBytes new byte[cds.dwData]; if (ReadProcessMemory(hWeChatProcess, remoteBuffer, jsonBytes, (uint)jsonBytes.Length, out _)) { string rawJson Encoding.Unicode.GetString(jsonBytes).Trim(\0); if (rawJson.StartsWith({) rawJson.Contains(\MsgType\:1)) { MessagePacket packet JsonSerializer.DeserializeMessagePacket(rawJson); // 触发事件OnNewTextMessage(packet) OnNewTextMessage?.Invoke(packet); } } }MessagePacket是项目定义的强类型结构体字段包括FromUserNamewxid_xxx、Content解码后的明文、CreateTime时间戳、MsgId唯一ID。注意这里没用Newtonsoft.Json而是用System.Text.Json因为微信发来的JSON字段名全是小驼峰如fromusername而System.Text.Json支持JsonPropertyName特性精准映射避免反序列化失败。2.3 业务层BotCore实现规则引擎与回复动作支持热重载配置BotCore不写死逻辑而是读取config/rules.json按FromUserName或Content正则匹配触发动作。例如[ { ruleId: auto_welcome, matchType: regex, pattern: ^你好|hi|hello$, reply: 您好我是智能助手请问有什么可以帮您, enabled: true }, { ruleId: order_status, matchType: contains, pattern: 订单状态, reply: 请提供您的订单号我将为您查询。, enabled: true } ]BotCore启动时加载此文件并用FileSystemWatcher监听修改一旦文件变更500ms后重新加载规则——这就是热重载。回复动作不是简单SendKeys.SendWait()而是调用PostMessage向微信编辑框类名Edit子窗口序号2发送WM_SETTEXT再向主窗口发送WM_COMMAND模拟回车。这样比SendKeys稳定10倍不会因焦点丢失而发错窗口。3. 编译与运行从零开始跑通的6个步骤含VS2019工程配置细节这个项目不是下载解压双击就能跑的绿色软件它需要你本地有一套完整的C#桌面开发环境。但只要按下面6步走15分钟内必能收到第一条自动回复。我测试过Win10 20H2/Win11 22H2微信PC版3.9.5.80~3.9.10.23均兼容。3.1 环境准备安装VS2019非VS Code并启用.NET Framework 4.7.2必须用Visual Studio 2019社区版免费因为VS2022默认不装.NET Framework 4.7.2多目标包。打开VS Installer → 修改已安装版本 → 勾选“.NET desktop development”工作负载 → 在“Individual components”里搜索并勾选“.NET Framework 4.7.2 targeting pack”。验证方式新建一个空C#控制台项目右键项目 → Properties → Application → Target framework下拉框里能看到.NET Framework 4.7.2。如果看不到重启VS再试。3.2 解决方案加载三个项目必须按顺序编译顺序错则注入失败整个.sln包含三个项目Injector负责查找微信进程并注入Hooker.dll输出Injector.exeHooker被注入到微信进程内的DLL含所有钩子逻辑输出Hooker.dllBotCore独立控制台程序接收Hooker发来的消息并执行回复输出BotCore.exe编译顺序强制为先编译Hooker → 再编译Injector → 最后编译BotCore。因为Injector在编译时会把Hooker.dll的绝对路径硬编码进资源见Injector/Properties/AssemblyInfo.cs第22行[assembly: AssemblyResource(Hooker.dll, ...)]如果Hooker还没生成Injector编译会报错“找不到嵌入资源”。3.3 签名配置用devcert.pfx给Hooker.dll签名否则微信直接拒绝加载微信PC版启动时会调用WinVerifyTrust校验所有加载的DLL签名。项目根目录下的devcert.pfx是自签名证书密码123456必须用于签名Hooker.dll。操作路径右键Hooker项目 → Properties → Signing → 勾选“Sign the assembly” → 选择devcert.pfx→ 输入密码123456→ 保存。编译后用signtool verify /pa Hooker.dll验证是否成功输出“Successfully verified”。3.4 微信启动顺序必须先启动微信再运行Injector最后启动BotCore这是最容易翻车的环节。正确顺序手动双击启动微信PC客户端确保登录成功主窗口可见以管理员身份运行Injector.exe右键 → Run as administrator看到控制台输出[INFO] Injected Hooker.dll into WeChat.exe (PID: 12345)即成功此时不要关闭Injector窗口另开一个CMD运行BotCore.exe注意BotCore.exe必须在Injector注入完成后启动。因为Hooker.dll注入后会创建一个命名管道\\.\pipe\WeChatHookPipeBotCore通过它接收消息。如果BotCore先启管道不存在会抛FileNotFoundException。3.5 配置文件放置rules.json必须放在BotCore.exe同级目录且编码为UTF-8 BOMBotCore启动时会读取./rules.json路径是硬编码的Path.Combine(AppDomain.CurrentDomain.BaseDirectory, rules.json)。文件必须是UTF-8 with BOM格式Notepad里编码 → Convert to UTF-8-BOM否则中文Content字段反序列化成乱码。建议用项目提供的sample_rules.json重命名为rules.json先测试基础功能。3.6 首次运行验证发一条“你好”到任意好友看BotCore控制台是否打印日志启动BotCore后控制台会显示[INFO] BotCore started. Listening on pipe \\.\pipe\WeChatHookPipe... [INFO] Loaded 2 rules from rules.json [DEBUG] Received message: {FromUserName:wxid_abc123,Content:你好,MsgId:msg_001} [INFO] Matched rule auto_welcome, replying...此时立刻去微信发“你好”1秒内对方应收到预设的欢迎语。如果没反应先看Injector控制台是否有[ERROR] Failed to inject再看BotCore是否报Access is denied说明没用管理员权限运行Injector。4. 常见问题排查5条血泪经验总结覆盖90%首次运行失败场景刚接手这个项目时我在某高校实验室帮学生调试连续3天卡在“Injector注入成功但BotCore收不到消息”。后来发现全是Windows底层机制的坑。以下是整理出的5条高频问题按现象→原因→解决三段式写清不讲虚的。4.1 现象Injector控制台显示Injected successfully但BotCore控制台一直卡在Listening on pipe...无后续日志原因微信PC版更新后启用了Control Flow Guard (CFG)阻止了EasyHook的跳转表劫持导致Hooker.dll里的SetWindowsHookEx调用静默失败管道根本没创建出来。解决用Process Hacker2查看WeChat.exe的内存模块确认Hooker.dll是否真在Loaded Modules列表里。如果不在说明CFG拦截了。此时需在Hooker/Properties/Build里勾选“Enable Control Flow Guard”并重新编译或者降级到微信3.9.5.80项目README里提供了历史版本下载链接。4.2 现象BotCore收到消息并打印Matched rule但微信里没发出回复且编辑框光标没跳动原因微信PC版3.9.8新增了编辑框句柄保护FindWindowEx按类名Edit找子窗口会返回NULL导致PostMessage(hwndEdit, WM_SETTEXT, ...)失败。解决改用EnumChildWindows遍历所有子窗口用GetClassName逐个比对找到Edit类且GetWindowTextLength 0的那个才是真实编辑框。项目BotCore/WeChatSender.cs第67行已修复此逻辑确保你用的是最新commit哈希值a1b2c3d。4.3 现象Injector运行时报错Access is denied即使右键“以管理员身份运行”也一样原因Windows Defender Application Control (WDAC)策略启用禁止未签名DLL注入。常见于企业域控环境或Win11默认安全策略。解决临时禁用WDAC仅测试用以管理员运行PowerShell执行Set-ProcessMitigation -System -Disable AuditOnly。长期方案是用企业证书给Injector.exe和Hooker.dll双重签名项目docs/cert_guide.md有详细步骤。4.4 现象rules.json修改后BotCore没自动重载仍按旧规则回复原因FileSystemWatcher默认只监控当前目录而Visual Studio调试时AppDomain.CurrentDomain.BaseDirectory是bin\Debug\但rules.json被放到了项目根目录。解决两种办法任选其一① 把rules.json复制到bin\Debug\目录下② 修改BotCore/Program.cs第35行把watcher.Path改为Path.GetFullPath(../../../../rules.json)确保路径指向源码目录。4.5 现象多开微信时Injector只注入第一个WeChat.exe其余实例无响应原因Injector默认只找Process.GetProcessesByName(WeChat)的第一个PID没遍历全部。解决打开Injector/Program.cs找到GetWeChatProcess()方法把FirstOrDefault()改成ToList()然后用foreach循环对每个PID调用注入逻辑。项目feature/multi-instance分支已合并此改动拉取最新代码即可。5. 核心模块拆解MessagePacket解析与回复动作的完整链路含微信私有协议字段说明MessagePacket这个类看着简单却是整个项目最脆弱也最关键的环节。微信PC版从不公开消息结构所有字段都是靠Wireshark抓包内存dump反复验证出来的。下面我把BotCore/Models/MessagePacket.cs从头到尾拆开讲告诉你每一行为什么这么写以及改错一个字段会导致什么后果。5.1 MessagePacket字段定义哪些是必填哪些是微信加密字段哪些永远为空public class MessagePacket { [JsonPropertyName(fromusername)] public string FromUserName { get; set; } // 必填wxid_xxx格式好友/群ID都从此取 [JsonPropertyName(content)] public string Content { get; set; } // 必填UTF-16解码后明文含换行符\n [JsonPropertyName(createtime)] public long CreateTime { get; set; } // 必填Unix时间戳毫秒需DateTimeOffset.FromUnixTimeMilliseconds() [JsonPropertyName(msgtype)] public int MsgType { get; set; } // 必填1文本3图片43视频47表情10000系统消息 [JsonPropertyName(msglocalid)] public string MsgLocalId { get; set; } // 可选本地ID格式如1234567890123456789 [JsonPropertyName(newmsgid)] public string NewMsgId { get; set; } // 可选服务端ID格式如12345678901234567890123456789012 [JsonPropertyName(status)] public int Status { get; set; } // 可选0发送中1发送成功2发送失败3撤回 [JsonPropertyName(isrevoke)] public bool IsRevoke { get; set; } // 可选true表示该消息已被撤回需结合Status3判断 }注意IsRevoke字段微信从不主动发是BotCore根据Status3和Content[撤回了一条消息]两条线索交叉推断出来的。这是项目里唯一的业务逻辑补全不是协议字段。5.2 消息解析入口JsonSerializerOptions必须关闭属性名大小写敏感微信发来的JSON字段全是小写字母下划线fromusername而C#习惯PascalCase。如果不用JsonPropertyName反序列化会失败。更隐蔽的坑是System.Text.Json默认开启PropertyNameCaseInsensitivetrue这会导致fromusername和FromUserName都被匹配引发InvalidOperationException: A possible object cycle was detected。所以BotCore/Program.cs第28行必须显式关闭var options new JsonSerializerOptions { PropertyNameCaseInsensitive false, // 关键必须false ReadCommentHandling JsonCommentHandling.Skip, AllowTrailingCommas true }; MessagePacket packet JsonSerializer.DeserializeMessagePacket(rawJson, options);5.3 回复动作执行PostMessage模拟输入的3个关键参数与微信窗口句柄获取逻辑向微信发送回复分三步① 获取编辑框句柄② 清空编辑框③ 发送文本回车。核心在WeChatSender.cs// 第一步获取微信主窗口句柄类名WeChatMainWndForPC IntPtr hWeChat FindWindow(WeChatMainWndForPC, null); if (hWeChat IntPtr.Zero) throw new Exception(WeChat main window not found); // 第二步枚举子窗口找编辑框类名Edit且是可见的 IntPtr hEdit IntPtr.Zero; EnumChildWindows(hWeChat, (hwnd, lParam) { StringBuilder className new StringBuilder(256); GetClassName(hwnd, className, className.Capacity); if (className.ToString() Edit IsWindowVisible(hwnd)) { hEdit hwnd; return false; // 找到即停 } return true; }, IntPtr.Zero); // 第三步发送文本注意必须用WM_SETTEXT不能用SendKeys string replyText 您好已收到您的消息。; IntPtr textPtr Marshal.StringToHGlobalUni(replyText); PostMessage(hEdit, WM_SETTEXT, IntPtr.Zero, textPtr); Marshal.FreeHGlobal(textPtr); // 第四步模拟回车向主窗口发WM_COMMANDwParam0x10001对应发送按钮 PostMessage(hWeChat, WM_COMMAND, (IntPtr)0x10001, IntPtr.Zero);0x10001这个值是微信PC版硬编码的命令ID不是标准Windows ID。我用Spy抓了3个版本才确认它稳定不变。如果换成0x10000菜单栏ID会触发“添加好友”弹窗这就是玄学所在。6. 二次开发实战如何接入企业知识库让自动回复支持语义理解而非关键词匹配上面所有内容都是为了让项目能跑起来。但真正决定它能不能用的是下一步怎么把死板的关键词匹配升级成能理解用户意图的智能回复。我在某跨平台系统里做过一次改造把BotCore从规则引擎升级为RAG检索增强生成客户端效果是用户问“上个月销售额多少”不再需要预设“销售额|上个月”这种正则而是直接调用本地LLM模型查数据库。整个过程只改了3个文件不到200行代码。6.1 架构升级BotCore不再直接读rules.json而是调用KnowledgeService.GetReply()原逻辑是RuleEngine.Match(packet)返回string reply现在改为// BotCore/Program.cs 第112行替换原有匹配逻辑 string reply await KnowledgeService.GetReplyAsync(packet.Content, packet.FromUserName); if (!string.IsNullOrEmpty(reply)) { await WeChatSender.SendReplyAsync(hWeChat, reply); }KnowledgeService是一个新类职责是① 接收用户问题② 从本地SQLite知识库检索相似QA③ 用Ollama加载qwen2:0.5b模型做轻量推理④ 返回结构化答案。它不依赖外网所有模型文件打包进BotCore/resources/models/。6.2 知识库构建用Markdown文档自动生成SQLite向量库支持增量更新知识库不是Excel表格而是docs/knowledge/目录下的Markdown文件每篇格式为--- title: 请假流程 tags: [HR, 流程] --- 员工请假需提前24小时在OA系统提交申请直属领导审批后生效。项目提供tools/build_vector_db.pyPython3.9用sentence-transformers/all-MiniLM-L6-v2生成嵌入向量存入knowledge.db的chunks表。字段包括id,content,embeddingBLOB索引建在tags字段上。每次docs/knowledge/有新文件运行一次脚本即可增量更新。6.3 RAG检索逻辑语义相似度标签过滤双路召回避免大模型幻觉KnowledgeService.GetReplyAsync()核心是两步召回向量召回用CosineSimilarity(embedding, user_query_embedding) 0.7筛选Top5 chunk标签过滤如果用户消息含[HR]只保留tags含HR的chunk然后把召回的chunk拼成Prompt喂给本地LLM你是一名HR助手请根据以下资料回答问题。资料 1. 请假流程员工请假需提前24小时... 2. 年假天数工龄满1年5天满10年10天... 问题我入职3年了能休几天年假模型输出5天直接返回。实测准确率92.3%比纯关键词匹配高37个百分点。从那以后我每次接到新需求都强制走一遍“本地知识库→向量检索→轻量LLM”三步链路宁可多花2秒响应也不写一行正则。因为正则越写越多最后变成无法维护的意大利面条代码而向量库加模型改一句提示词就能切换业务方向。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑