(19)C#自动添加微信好友(可批量申请)--微信UI自动化(.Net)

news2024/11/13 11:08:00
往期知识回顾

(1)C#开启探索微信自动化之路-微信UI自动化

(2)C#创建微信窗体自动化实例-微信UI自动化

(3)C#针对系统热键管理-微信UI自动化

(4)C#采集微信通讯录和联系人-微信UI自动化

(5)C#实现针对微信窗体鼠标静默点击-微信UI自动化

(6)C#搜索微信通讯录联系人-微信UI自动化

(7)C#实现微信消息群发-微信UI自动化

(8)C#监控微信进程运行状态-微信UI自动化

(9)C#监控微信网络连接状态-微信UI自动化

(11)C#实现微信窗体尺寸跟随调整-微信UI自动化

(12)C#采集微信聊天记录及历史消息-微信UI自动化

(13)C#实现自动回复微信消息-微信UI自动化

(14)C#针对微信界面元素截图操作-微信UI自动化

(15)C#实现对微信窗体的行为管控-微信UI自动化

(16)C#实现微信多开-微信UI自动化

(17)C#实现微信聊天文件接收及下载-微信UI自动化

👆😀以上文章是以往使用自动化方案操作微信的一些案例!如有兴趣请点击浏览!

因为文章可能无法满足读者要求,如需源码和支持请联系本人 QQ 978124155 

本篇目的

    近日一位同行,他对象是做保险业务的,经常需要大量添加微信好友来做业务扩展,非常枯燥,他说他对象经过半个月的手工添加感觉非常累,还有几千上万个的微信号需要添加,后续还会陆续新增,工作量巨大,他说他在博客园上看到了我的文章,说想实现基于UI自动化批量添加微信好友功能。

    我经过沟通整理的需求如下,通过微信的添加朋友按钮切换搜索微信号界面,自动填写需要搜索微信号,如果存在账号,则点击“添加到通讯录”,弹出申请添加朋友界面,自动填写“发送添加朋友申请”,“备注名”,“标签”这些常规信息后点击确认按钮完成申请好友的操作。

    经过对微信窗体的研究,发现是可行的,所以完成了该功能,并交付给他。

    经过半个月的磨合和速度调整,已经彻底解放了他对象的双手。实现全自动化操作。

软件视频及截图

   各位朋友如果时间允许可观看视频感受下软件添加微信好友的执行过程,更加直观清晰,本人将自动化速度调节的慢些,以便更加清晰的感受到自动化带来的魅力。

 先模拟添加两位微信好友,点击确定将会根据构造的信息自动执行添加好友的任务。

自动化程序会将申请信息填写至对应的微信窗体UI元素中,并点击确定发送申请。

执行添加好友任务完毕后会有相对应的结果反馈,如果出现微信号不存在,操作频率过高,UI自动化元素操作失败等也会出现对应的日志提示,供后期排查和完善。

实现思路
  1. 执行微信主面板“通讯录”按钮点击事件,切换到微信通讯录面板。
  2. 切换到通讯录后,寻找“添加朋友”按钮,执行点击事件。
  3. 继续寻找到“微信号/手机号”的文本搜索框,将需要添加的微信号或者手机号填写到搜索框中。
  4. 等待微信窗体的搜索结果列表出现,一般只会出现一个搜索结果项,执行该项的点击事件,等待微信结果的反馈。
  5. 根据点击该搜索项的结果判断是否存在该微信用户,如果不存在或者频率过快则终止本次好友添加或者本轮任务。
  6. 如果存在该微信号,则寻找微信号信息弹出面板(右边的弹出面板),如果发现面板中存在"添加至通讯录按钮"则代表该微信号不是你的好友,则可继续下一步,如果不存在该按钮,则代表该微信号已经存在你微信中,则终止本次好友添加。
  7. 执行“添加至通讯录”按钮点击事件,弹出“申请添加朋友”窗体。通过UI自动化对象找到该窗体,如果存在该窗体则执行下一步,不存在则终止本次好友添加。
  8. 在“申请添加朋友”窗体寻找到“发送添加朋友申请”,“备注名”,“标签”,“确定”等UI元素。
  9. “发送添加朋友申请”,“备注名”为文本框,直接设置文本值即可。
  10. “标签”为复选框集合面板,如果发现最后一个元素对象为Button,则代表有更多的标签,需要执行点击展开,展开后在复选框集合面板中寻找对应的标签控件,执行点击事件将该好友设置成对应的标签。
  11. 最后执行“确定”按钮点击事件,发送好友申请,执行下一轮等待操作后继续添加,因为不等待直接操作微信会提示操作频繁。
技术细节

以下代码都为实现思路中的核心代码,并不涉及到更多底层的实现。

查找对应微信号并执行搜索操作

		/// <summary>
		/// 查找好友
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		public bool FindAddFriend(string name)
		{
            ClickContactsButton();
            Thread.Sleep(200);
            ClickAddFriendButton();
            Thread.Sleep(200);
            GetSearchElement();
            if (Search != null)
            {
                SystemLog.Info("开始查找联系人【" + name + "】");

                 //设置搜索框的值
                ClickSetInputValue(new WeChatInputMsgEntity { Info = name, Type = WXMessageType.Text }, Search);
               //寻找搜索列表项目
                var element = GetSearchFriendResultElement("搜索:"+name);

                if (element != null)
                {
                    SystemLog.Info("查找【" + name + "】成功,开始发送消息");
                    //执行好友添加点击操作
                    UI_WX_Window.Current.ClickElement(element);
                    return true;
                }
                else
                {
                    SystemLog.Info("查找【" + name + "】失败");
                    return false;

                }
            }
            return false;
        }

在搜索成功后弹出微信信息面板中执行”添加至通讯录“的点击,弹出”申请添加朋友“窗体

	private bool ExecuteClickAddFriendElement(AddWeChatFriendEntity newFriend)
	{
		var addPanel = UI_WX_Window.Current.ShowFriendInfoPanel();
		if (addPanel != null)
		{
			var addButton = addPanel.FindFirstByXPath("/Pane[1]/Pane/Pane/Pane[1]/Pane[2]/Button");
			if (addButton != null)
			{
				addButton.Click();

				Thread.Sleep(400);

				return SendAddFriendRequest(newFriend);
			}
			else
			{
				newFriend.Log = "添加至通讯录按钮不存在,该微信可能为您的好友已经";
			}
		}
		else
		{
			newFriend.Log = "添加微信号至通讯录面板未找到";
		}
		return false;
	}

控制"申请添加朋友"窗体的基类,设置“发送添加朋友申请”,“备注名”,“标签”,“确定”的值和点击事件

	/// <summary>
	/// 控制申请好友面板发送好友请求(添加好友和群添加好友)
	/// </summary>
	public abstract class UI_WX_SendFriendRequest_Task : UI_WX_Element_Base_Task
	{  

		/// <summary>
		/// 每个输入控制的休眠时间
		/// </summary>
		public int SleepTick { get { return 600; } }

		/// <summary>
		/// 发送好友请求
		/// </summary>
		/// <param name="newFriend"></param>
		/// <returns></returns>
		protected bool SendAddFriendRequest(AddWeChatFriendEntity newFriend)
		{
			var addFriendWindow = UI_WX_Window.Current.GetAddFriendWindow();

			if (addFriendWindow != null)
			{
				#region 设置验证消息
				if (!string.IsNullOrEmpty(newFriend.ValidText))
				{
					var vaildEdit = addFriendWindow.FindFirstByXPath("/Pane[2]/Pane[1]/Pane/Pane[1]/Pane/Edit");//验证文本框
					if (vaildEdit != null)
					{
						DoubleClickSetInputValue(new WeChatInputMsgEntity
						{
							Type = WXMessageType.Text,
							Info = newFriend.ValidText
						}, vaildEdit, true);
					}
					Thread.Sleep(SleepTick);
				}
				#endregion

				#region 设置备注名称
				if (!string.IsNullOrEmpty(newFriend.RemarkName))
				{
					var remarkEdit = addFriendWindow.FindFirstByXPath("/Pane[2]/Pane[1]/Pane/Pane[2]/Pane/Edit");//备注名
					if (remarkEdit != null)
					{
						DoubleClickSetInputValue(new WeChatInputMsgEntity
						{
							Type = WXMessageType.Text,
							Info = newFriend.RemarkName
						}, remarkEdit, true);
					}
					Thread.Sleep(SleepTick);
				}
				#endregion

				#region 设置标签
				if (!string.IsNullOrEmpty(newFriend.Label))
				{
					var labelElement = addFriendWindow.FindFirstByXPath("/Pane[2]/Pane[1]/Pane/Pane[3]/Pane[2]");//标签面板
					if (labelElement != null)
					{
						var childCheckSource = labelElement.FindAllChildren();
						var lastCheckElement = childCheckSource[childCheckSource.Length - 1];
						if (lastCheckElement.ControlType == FlaUI.Core.Definitions.ControlType.Button)
						{
							//执行点击
							lastCheckElement.Click();
							Thread.Sleep(SleepTick);
						}
						childCheckSource = labelElement.FindAllChildren();
						foreach (var child in childCheckSource)
						{
							if (child.Name == newFriend.Label)
							{
								child.Click();
								Thread.Sleep(SleepTick);
								break;
							}
						}
					}
				}
				#endregion

				#region  添加
				var sumbitButton = addFriendWindow.FindFirstByXPath("/Pane[2]/Pane[1]/Button[1]");//确定

				if (sumbitButton != null)
				{
					sumbitButton.Click();
					Thread.Sleep(SleepTick);
					return true;
				}
				else
				{
					newFriend.Log = "添加朋友请求面板确定按钮不存在,无法添加";
				}
				#endregion
			}
			else
			{
				newFriend.Log = "添加朋友请求面板不存在,请关闭多余微信窗体重试";
			}
			return false;
		}

	}

因为文章中很多基类和通用方法无法具体描述,如需源码和支持请联系本人 QQ 978124155 

(18)C#采集微信群成员信息-微信UI自动化(.Net)icon-default.png?t=N7T8https://blog.csdn.net/lichao19897314/article/details/136784971

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

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

相关文章

JavaMySQL高级一(下)

目录 1.常用函数 1.字符串函数 2.时间日期函数 3.聚合函数 4.数学函数 2.分布查询 3.子查询基础 1.简单子查询 1.常用函数 在程序开发过程中&#xff0c;除了简单的数据查询&#xff0c;还有基于已数据进行数据的统计分析计算等需求。因此&#xff0c;在SQL中将一…

zookeeper底层细节

zk 临时节点和watch机制实现注册中心自动注册和发现&#xff0c;数据都在内存&#xff0c;nio 多线程模型&#xff1b; cp注重一致性&#xff0c;数据不一致时集群不可用 事务请求处理方式 1.all事务由唯一服务器处理 2.将客户端事务请求转成proposal分发follower 3.等待半…

windows访问远程服务器上容器的几种直接方式

远程服务器 host上有一个docker container&#xff0c;如何通过 client 直接登陆 container 呢&#xff1f; container 使用 host 的网络&#xff0c;即使用了 --networkhost先配置 container的 ssdh&#xff08;/etc/ssh/sshd_config&#xff09;&#xff0c;相关参数设置 po…

使用导入车辆出险报告接口API接口实现车辆出险查询

引言&#xff1a; 现在&#xff0c;汽车事故频发&#xff0c;我们经常听到车辆出险的消息。对于购车用户而言&#xff0c;了解车辆的出险、理赔和事故记录是十分重要的。而如何快速查询到这些信息&#xff0c;成为了用户们在掌握车辆情况上的一个难点。幸运的是&#xff0c;挖数…

高效备考2024年AMC10:吃透2000-2023年1250道真题(限时免费送)

我们今天继续来随机看5道AMC10真题&#xff0c;以及详细解析&#xff0c;这些题目来自1250道完整的官方历年AMC10真题库。通过系统研究和吃透AMC10的历年真题&#xff0c;参加AMC10的竞赛就能拿到好名次。即使不参加AMC10竞赛&#xff0c;掌握了这些知识和解题思路后初中和高中…

【NBUOJ刷题笔记】递推_递归+分治策略1

0. 前言 PS&#xff1a;本人并不是集训队的成员&#xff0c;因此代码写的烂轻点喷。。。本专题一方面是巩固自己的算法知识&#xff0c;另一方面是给NBU学弟学妹们参考解题思路&#xff08;切勿直接搬运抄袭提交作业&#xff01;&#xff01;&#xff01;&#xff09;最后&…

QT5.14.2 Qt布局调和术:精妙UI设计背后的自适应魔法

欢迎来到Qt世界的一角&#xff0c;今天我们要探索的是Qt中的布局管理以及控件自适应大小调整的艺术。在这篇文章中&#xff0c;我们不仅会讨论理论&#xff0c;还会一起动手实践&#xff0c;弄清楚如何打造出既美观又实用的用户界面。 一、布局管理概览 布局管理是Qt中的核心概…

2024腾讯云优惠券领取_云服务器代金券_优惠券查询和使用方法

腾讯云代金券领取渠道有哪些&#xff1f;腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券&#xff0c;大家也可以在腾讯云百科蹲守代金券&#xff0c;因为腾讯云代金券领取渠道比较分散&#xff0c;腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

HTML5语法总结

文章目录 一.HTML基本框架二.标题标签三.段落标签四.换行与水平线标签五.文本格式化标签(加粗、倾斜、下划线、删除线)六.图像标签扩展&#xff1a;相对路径,绝对路径与在线网址 七.超链接标签八.音频标签九.视频标签十.列表标签十一.表格标签扩展&#xff1a;表格结构标签合并…

表情生成器微信小程序版

1.纯前端输出&#xff0c;无需后台&#xff0c;无需域名&#xff0c;速度杠杠快&#xff01; 2.完美支持微信端和抖音端&#xff1b; 3.双端均支持配置开启流量主广告&#xff0c;包括&#xff1a;激励视频广告、插屏广告、banner广告、原生广告、封面广告等&#xff1b; 4.…

【蓝桥杯入门记录】继电器、蜂鸣器及原理图分析

一、继电器、继电器概述 &#xff08;1&#xff09;蜂鸣器原理 蜂鸣器的发声原理由振动装置和谐振装置组成&#xff0c;而蜂鸣器又分为无源他激型与有源自激型&#xff0c;蜂鸣器的发声原理为: 1、无源他激型蜂鸣器的工作发声原理是&#xff1a;方波信号输入谐振装置转换为声…

阿里云服务器2核4G服务器收费价格表,1个月和一年报价

阿里云2核4G服务器多少钱一年&#xff1f;2核4G服务器1个月费用多少&#xff1f;2核4G服务器30元3个月、85元一年&#xff0c;轻量应用服务器2核4G4M带宽165元一年&#xff0c;企业用户2核4G5M带宽199元一年。本文阿里云服务器网整理的2核4G参加活动的主机是ECS经济型e实例和u1…

【unity实战】时间控制 昼夜交替 四季变化 天气变化效果

最终效果 文章目录 最终效果日期季节控制时间昼夜交替素材如果没有天空盒&#xff0c;需要自己配置新增SkyboxBlendingShader.shader&#xff0c;控制天空盒平滑过渡交替变化 下雨下雨粒子效果控制雨一直跟随玩家&#xff0c;但是旋转不跟随控制不同天气 源码完结 日期季节控制…

C++ —— 内存管理

目录 1. C内存分布 2. C 内存管理方式 2.1 new 和 delete 操作内置类型 2.2 new 和 delete 操作自定义类型 3. operator new与operator delete函数 4. new和delete的实现原理 5. malloc/free 和 new/delete 的区别 1. C内存分布 首先看一段代码&#xff1a; int globalV…

短视频矩阵系统源头技术开发--每一次技术迭代

短视频矩阵系统源头开发3年的我们&#xff0c;肯定是需求不断的迭代更新的&#xff0c;目前我们已经迭代了3年之久&#xff0c;写技术文章已经写了短视频矩阵系统&#xff0c;写了3年了&#xff0c;开发了3年了 短视频矩阵获客系统是一种基于短视频平台的获客游戏。短视频矩阵系…

18个惊艳的可视化大屏(第29辑):机械自动化设备仪器

当涉及到机械自动化生产管理时&#xff0c;可视化大屏可以提供以下九个价值&#xff1a; 实时监控 可视化大屏可以实时显示生产线上的各个环节和设备的运行状态。运营人员可以通过大屏实时监控生产线的生产效率、设备运行状况等关键指标&#xff0c;及时发现并解决问题&#…

面试笔记——Redis(集群方案:主从复制、哨兵模式和分片集群)

主从复制 在 Redis 主从集群中&#xff0c;一个主节点&#xff08;Master&#xff09;负责处理客户端的读写请求&#xff0c;而多个从节点&#xff08;Slave&#xff09;则负责复制主节点的数据&#xff0c;并对外提供读取服务——解决高并发问题。 主节点&#xff08;Master&…

echart多折线图堆叠 y轴和实际数据不对应

当使用 ECharts 绘制堆叠折线图时&#xff0c;有时会遇到 y 轴与实际数据不对应的问题。 比如明明值是50&#xff0c;但折线点在y轴的对应点却飙升到了二百多 解决办法&#xff1a; 查看了前端代码发现在echart的图表中有一个‘stack’的属性&#xff0c;尝试把他删除之后y轴的…

带大家深入理解redis的主从复制

为何需要主从复制 Redis作为开发过程中经常用到的缓存数据库&#xff0c;我们在开发过程中可能会遇到各种各样的问题&#xff0c;比如&#xff1a; Redis的读并发量太大怎么办&#xff1f; 单机版的Redis挂掉怎么办&#xff1f; 我们不仅需要并发&#xff0c;更需要安全&…

力扣热门算法题 52. N 皇后 II,53. 最大子数组和,54. 螺旋矩阵

52. N 皇后 II&#xff0c;53. 最大子数组和&#xff0c;54. 螺旋矩阵&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.20 可通过leetcode所有测试用例。 目录 52. N 皇后 II 解题思路 完整代码 Python Java 53. 最大子数组…