This article was contributed by netizen
Blue Creative Elite Team, welcome to repost and shareOriginal author: Blue Creative Elite Team
Original link: https://kesshei.blog.csdn.net/article/details/124955177
Goal
I have always wanted to implement a mass messaging feature for WeChat, but never did because I was worried about legal issues. I recall a certain company that reverse-engineered WeChat's interface and got sued, resulting in a hefty fine.
At that point, I thought, if I use RPA technology, it wouldn’t affect WeChat at all. After all, I’m just simulating my own computer operations, and WeChat cannot detect that my behavior is illegal.
Thus, this approach might be a safe and legitimate technical solution.
So I gave it a try, also drawing inspiration from online resources.
1. What is FlaUI?
FlaUI is a UI automation testing technology based on Microsoft’s UIAutomation framework, introduced with Windows Vista. It is commonly referred to as UIA. In the latest Windows SDK, UIA and other UI automation technologies like MSAA are bundled together as Windows Automation API.
UIA defines new interfaces and patterns for UI automation, including TreeWalker/FindAll for traversing and conditionally querying UI elements, UIA Properties for reading/writing element attributes (Name, ID, Type, ClassName, Location, Visibility, etc.), UIA Patterns for defining element behaviors (Select, Expand, Resize, Check, Value, etc.), and UIA Events for notifying test programs when certain events occur (e.g., a new window opens).
Currently, FlaUI supports two technologies: UIA2 and UIA3. I am mainly using UIA3.
2. Usage Steps
1. Install NuGet Package
Install-Package FlaUI.UIA3 -Version 3.2.0
2. Implement a Simple Message Sending to a Specified Contact
Example code:
Process[] processes = Process.GetProcessesByName("WeChat");
if (processes.Count() != 1)
{
Console.WriteLine("WeChat is not started or multiple instances are running");
}
else
{
//1. Attach to the WeChat process
using (var app = Application.Attach(processes.First().Id))
{
using (var automation = new UIA3Automation())
{
//2. Get the main window
var mainWindow = app.GetMainWindow(automation);
Console.WriteLine("Got main window");
//3. Switch to Contacts tab
var elements = mainWindow.FindAll(FlaUI.Core.Definitions.TreeScope.Subtree, TrueCondition.Default);
var addressBook = mainWindow.FindFirstDescendant(cf => cf.ByName("Contacts"));
addressBook.DrawHighlight(System.Drawing.Color.Red);
var path = Debug.GetXPathToElement(addressBook);
Console.WriteLine("Clicked Contacts");
addressBook.Click();
//4. Search
string target = "File Transfer";
var searchTextBox = mainWindow.FindFirstDescendant(cf => cf.ByName("Search")).AsTextBox();
searchTextBox.Click();
Keyboard.Type(target);
Keyboard.Type(VirtualKeyShort.RETURN);
Console.WriteLine("Searched target object");
//5. Switch to the conversation
Thread.Sleep(500);
var searchList = mainWindow.FindFirstDescendant(cf => cf.ByName("Search Results"));
if (searchList != null)
{
var searchItem = searchList.FindAllDescendants().FirstOrDefault(cf => cf.Name == target && cf.ControlType == FlaUI.Core.Definitions.ControlType.ListItem);
searchItem?.DrawHighlight(System.Drawing.Color.Red);
searchItem?.AsListBoxItem().Click();
}
else
{
Console.WriteLine("No search results found");
}
Thread.Sleep(500);
//6. Type the message
string sendMsg = "This is my WeChat message: " + DateTime.Now.ToString();
var msgInput = mainWindow.FindFirstDescendant(cf => cf.ByName("Input")).AsTextBox();
msgInput?.Click();
System.Windows.Forms.Clipboard.SetText(sendMsg);
Keyboard.TypeSimultaneously(new[] { VirtualKeyShort.CONTROL, VirtualKeyShort.KEY_V });
var sendBtn = mainWindow.FindFirstDescendant(cf => cf.ByName("sendBtn"));
sendBtn?.DrawHighlight(System.Drawing.Color.Red);
sendBtn?.Click();
}
}
}
The code has comments and is easy to understand.
It searches for a specific person and sends a predefined message. Done.
Illustration:

3. Implement Batch Message Sending from Session List
Example code:
Process[] processes = Process.GetProcessesByName("WeChat");
if (processes.Count() != 1)
{
Console.WriteLine("WeChat is not started or multiple instances are running");
}
else
{
//1. Attach to the WeChat process
using (var app = Application.Attach(processes.First().Id))
{
using (var automation = new UIA3Automation())
{
//2. Get the main window
var mainWindow = app.GetMainWindow(automation);
Console.WriteLine("Got main window");
//3. Switch to Chat tab
var elements = mainWindow.FindAll(TreeScope.Subtree, TrueCondition.Default);
var addressBook = mainWindow.FindFirstDescendant(cf => cf.ByName("Chat"));
addressBook.DrawHighlight(System.Drawing.Color.Red);
var path = Debug.GetXPathToElement(addressBook);
addressBook.Click();
Console.WriteLine("Switched to Chat");
Thread.Sleep(2000);
//4. Get the chat list
// Only send to the first six
var count = 0;
var searchTextBox = mainWindow.FindFirstDescendant(cf => cf.ByName("Conversations")).AsListBoxItem();
while (searchTextBox != null)
{
var list = searchTextBox.FindAllChildren();
foreach (var item in list)
{
count++;
var name = item.Name;
item.Click();
var type = item.ControlType;
item.DrawHighlight(System.Drawing.Color.Red);
var MsgSend = mainWindow.FindFirstDescendant(cf => cf.ByName("Input")).AsTextBox();
var MsgSendButton = mainWindow.FindFirstDescendant(cf => cf.ByName("sendBtn"));
if (MsgSend != null && MsgSendButton != null)
{
MsgSend.Click();
System.Windows.Forms.Clipboard.SetText($"Mass message, please ignore: {DateTime.Now}");
Keyboard.TypeSimultaneously(new[] { VirtualKeyShort.CONTROL, VirtualKeyShort.KEY_V });
MsgSendButton.Click();
Console.WriteLine($"Sent message to: {name}");
Thread.Sleep(500);
}
if (count == 6)
{
break;
}
}
if (count == 6)
{
break;
}
for (int i = 0; i < list.Length; i++)
{
searchTextBox.Focus();
Keyboard.Press(VirtualKeyShort.DOWN);
Thread.Sleep(100);
}
searchTextBox = mainWindow.FindFirstDescendant(cf => cf.ByName("Conversations")).AsListBoxItem();
Thread.Sleep(2000);
}
}
}
}
This code is mainly for sending messages to the first six contacts in the session list. If a session does not have a send button, the message is not sent to avoid affecting more people.
Illustration:

I recorded it several times... In the end, someone even deleted me, awkward.
4. How to Get Page Information with FlaUI
Open the FlaUInspect tool.

You can see the XPath address through the following:


The FlaUInspect project is a WPF project. If you want to study it in depth, you can look at the source code and debug it.
The main point here is that you can get the required content in two ways:
The first way is as shown below, by getting a unique name on the same page:
var addressBook = mainWindow.FindFirstDescendant(cf => cf.ByName("Chat"));
The second way is as follows:
You can find the desired control via the XPath address shown in item 2 of the image above:
var infoData = automationElement.FindAllByXPath("/Pane/Pane[1]");
Summary
Overall, this technology is very convenient. However, for applications like QQ, which use custom drawing technology (e.g., Qt, Java), it may not work. It is only applicable to Microsoft technology products like WinForms and WPF.
In general, it reduces the difficulty of use.
For example, with this WeChat message sending feature, once you have the functionality, you can extend it yourself—send to specific people, bulk send, schedule sending, send by tags, etc. It can be quite useful on a personal level.
Revision on May 30, 2022
Solutions for Other Users Who Can't Run It
If you encounter this error:

You can download the source code from https://github.com/FlaUI/FlaUI, reference it directly instead of using NuGet, to solve the issue.
I haven’t investigated the exact cause yet.