mirror of
https://github.com/huiyadanli/RevokeMsgPatcher.git
synced 2025-05-23 05:38:12 +08:00
[+] 清除微信的互斥标记句柄
This commit is contained in:
parent
336c864cdf
commit
4dc97cdfdb
|
@ -28,6 +28,7 @@
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
this.txtPath = new System.Windows.Forms.TextBox();
|
this.txtPath = new System.Windows.Forms.TextBox();
|
||||||
this.lblPathTag = new System.Windows.Forms.Label();
|
this.lblPathTag = new System.Windows.Forms.Label();
|
||||||
this.btnChoosePath = new System.Windows.Forms.Button();
|
this.btnChoosePath = new System.Windows.Forms.Button();
|
||||||
|
@ -38,6 +39,8 @@
|
||||||
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
|
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
|
||||||
this.label3 = new System.Windows.Forms.Label();
|
this.label3 = new System.Windows.Forms.Label();
|
||||||
this.label4 = new System.Windows.Forms.Label();
|
this.label4 = new System.Windows.Forms.Label();
|
||||||
|
this.button1 = new System.Windows.Forms.Button();
|
||||||
|
this.mutexHandleCloseTimer = new System.Windows.Forms.Timer(this.components);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.startNum)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.startNum)).BeginInit();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
|
@ -94,7 +97,7 @@
|
||||||
0,
|
0,
|
||||||
0});
|
0});
|
||||||
this.startNum.Minimum = new decimal(new int[] {
|
this.startNum.Minimum = new decimal(new int[] {
|
||||||
2,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0});
|
0});
|
||||||
|
@ -102,7 +105,7 @@
|
||||||
this.startNum.Size = new System.Drawing.Size(55, 21);
|
this.startNum.Size = new System.Drawing.Size(55, 21);
|
||||||
this.startNum.TabIndex = 12;
|
this.startNum.TabIndex = 12;
|
||||||
this.startNum.Value = new decimal(new int[] {
|
this.startNum.Value = new decimal(new int[] {
|
||||||
2,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0});
|
0});
|
||||||
|
@ -146,11 +149,26 @@
|
||||||
this.label4.TabIndex = 16;
|
this.label4.TabIndex = 16;
|
||||||
this.label4.Text = "注意:\r\n1. 使用本程序多开前不能存在正在运行的微信进程。\r\n2. 多开的成功率取决于你的机器性能,不保证每次都能成功";
|
this.label4.Text = "注意:\r\n1. 使用本程序多开前不能存在正在运行的微信进程。\r\n2. 多开的成功率取决于你的机器性能,不保证每次都能成功";
|
||||||
//
|
//
|
||||||
|
// button1
|
||||||
|
//
|
||||||
|
this.button1.Location = new System.Drawing.Point(369, 190);
|
||||||
|
this.button1.Name = "button1";
|
||||||
|
this.button1.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.button1.TabIndex = 17;
|
||||||
|
this.button1.Text = "button1";
|
||||||
|
this.button1.UseVisualStyleBackColor = true;
|
||||||
|
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||||
|
//
|
||||||
|
// mutexHandleCloseTimer
|
||||||
|
//
|
||||||
|
this.mutexHandleCloseTimer.Tick += new System.EventHandler(this.mutexHandleCloseTimer_Tick);
|
||||||
|
//
|
||||||
// FormMultiInstance
|
// FormMultiInstance
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(472, 133);
|
this.ClientSize = new System.Drawing.Size(472, 259);
|
||||||
|
this.Controls.Add(this.button1);
|
||||||
this.Controls.Add(this.label4);
|
this.Controls.Add(this.label4);
|
||||||
this.Controls.Add(this.linkLabel1);
|
this.Controls.Add(this.linkLabel1);
|
||||||
this.Controls.Add(this.label3);
|
this.Controls.Add(this.label3);
|
||||||
|
@ -181,6 +199,8 @@
|
||||||
private System.Windows.Forms.LinkLabel linkLabel1;
|
private System.Windows.Forms.LinkLabel linkLabel1;
|
||||||
private System.Windows.Forms.Label label3;
|
private System.Windows.Forms.Label label3;
|
||||||
private System.Windows.Forms.Label label4;
|
private System.Windows.Forms.Label label4;
|
||||||
|
private System.Windows.Forms.Button button1;
|
||||||
|
private System.Windows.Forms.Timer mutexHandleCloseTimer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,25 +47,21 @@ namespace RevokeMsgPatcher.MultiInstance
|
||||||
{
|
{
|
||||||
if (File.Exists(txtPath.Text))
|
if (File.Exists(txtPath.Text))
|
||||||
{
|
{
|
||||||
// 检测微信进程是否存在
|
Process[] processes = Process.GetProcessesByName("WeChat");
|
||||||
Process[] ps = Process.GetProcessesByName("WeChat");
|
ProcessUtil.CloseMutexHandle(processes);
|
||||||
if (ps.Length > 0)
|
|
||||||
{
|
|
||||||
DialogResult result = MessageBox.Show("当前存在运行中的微信进程,请先关闭当前微信才能使用该功能。点击【确定】强制关闭当前所有微信进程并进行多开,点击【取消】不做任何处理。", "当前存在运行中的微信进程", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
|
|
||||||
if (result == DialogResult.OK)
|
|
||||||
{
|
|
||||||
foreach (Process p in ps)
|
|
||||||
p.Kill();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 启动多个实例
|
// 启动多个实例
|
||||||
for (int i = 0; i < startNum.Value; i++)
|
for (int i = 0; i < startNum.Value; i++)
|
||||||
{
|
{
|
||||||
Process.Start(txtPath.Text);
|
//var t = new Task(() =>
|
||||||
|
//{
|
||||||
|
// Process newInstance = Process.Start(txtPath.Text);
|
||||||
|
// newInstance.WaitForInputIdle();
|
||||||
|
// ProcessUtil.CloseMutexHandle(newInstance);
|
||||||
|
//});
|
||||||
|
//t.Start();
|
||||||
|
Process newInstance = Process.Start(txtPath.Text);
|
||||||
|
//newInstance.WaitForInputIdle();
|
||||||
|
//ProcessUtil.CloseMutexHandle(newInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,5 +103,16 @@ namespace RevokeMsgPatcher.MultiInstance
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void button1_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Process[] processes = Process.GetProcessesByName("WeChat");
|
||||||
|
ProcessUtil.CloseMutexHandle(processes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mutexHandleCloseTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,4 +117,7 @@
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<metadata name="mutexHandleCloseTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
</root>
|
</root>
|
229
RevokeMsgPatcher.MultiInstance/ProcessUtil.cs
Normal file
229
RevokeMsgPatcher.MultiInstance/ProcessUtil.cs
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RevokeMsgPatcher.MultiInstance
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 微信多开原理:
|
||||||
|
/// https://mp.weixin.qq.com/s/bb7XMxop7e8rd7YqQ88nyA
|
||||||
|
/// 参考:
|
||||||
|
/// https://stackoverflow.com/questions/54872228/c-sharp-how-to-find-all-handles-associated-with-current-process
|
||||||
|
/// https://hintdesk.com/2010/05/22/c-get-all-handles-of-a-given-process-in-64-bits/
|
||||||
|
/// </summary>
|
||||||
|
public class ProcessUtil
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/handle_table_entry.htm?ts=0,242
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
public struct SYSTEM_HANDLE_INFORMATION
|
||||||
|
{ // Information Class 16
|
||||||
|
public ushort ProcessID;
|
||||||
|
public ushort CreatorBackTrackIndex;
|
||||||
|
public byte ObjectType;
|
||||||
|
public byte HandleAttribute;
|
||||||
|
public ushort Handle;
|
||||||
|
public IntPtr Object_Pointer;
|
||||||
|
public IntPtr AccessMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum OBJECT_INFORMATION_CLASS : int
|
||||||
|
{
|
||||||
|
ObjectBasicInformation = 0,
|
||||||
|
ObjectNameInformation = 1,
|
||||||
|
ObjectTypeInformation = 2,
|
||||||
|
ObjectAllTypesInformation = 3,
|
||||||
|
ObjectHandleInformation = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
private struct OBJECT_NAME_INFORMATION
|
||||||
|
{ // Information Class 1
|
||||||
|
public UNICODE_STRING Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct UNICODE_STRING
|
||||||
|
{
|
||||||
|
public ushort Length;
|
||||||
|
public ushort MaximumLength;
|
||||||
|
public IntPtr Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
private enum PROCESS_ACCESS_FLAGS : uint
|
||||||
|
{
|
||||||
|
All = 0x001F0FFF,
|
||||||
|
Terminate = 0x00000001,
|
||||||
|
CreateThread = 0x00000002,
|
||||||
|
VMOperation = 0x00000008,
|
||||||
|
VMRead = 0x00000010,
|
||||||
|
VMWrite = 0x00000020,
|
||||||
|
DupHandle = 0x00000040,
|
||||||
|
SetInformation = 0x00000200,
|
||||||
|
QueryInformation = 0x00000400,
|
||||||
|
Synchronize = 0x00100000
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll")]
|
||||||
|
private static extern uint NtQuerySystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, ref int returnLength);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern IntPtr OpenProcess(PROCESS_ACCESS_FLAGS dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern IntPtr GetCurrentProcess();
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll")]
|
||||||
|
private static extern int NtQueryObject(IntPtr ObjectHandle, int ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength, ref int returnLength);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern bool CloseHandle(IntPtr hObject);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern bool GetHandleInformation(IntPtr hObject, out uint lpdwFlags);
|
||||||
|
|
||||||
|
private const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
|
||||||
|
private const int DUPLICATE_CLOSE_SOURCE = 0x1;
|
||||||
|
private const int DUPLICATE_SAME_ACCESS = 0x2;
|
||||||
|
|
||||||
|
private const int CNST_SYSTEM_HANDLE_INFORMATION = 0x10;
|
||||||
|
private const int OBJECT_TYPE_MUTANT = 17;
|
||||||
|
|
||||||
|
public static List<SYSTEM_HANDLE_INFORMATION> GetHandles(Process process)
|
||||||
|
{
|
||||||
|
List<SYSTEM_HANDLE_INFORMATION> aHandles = new List<SYSTEM_HANDLE_INFORMATION>();
|
||||||
|
int handle_info_size = Marshal.SizeOf(new SYSTEM_HANDLE_INFORMATION()) * 20000;
|
||||||
|
IntPtr ptrHandleData = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ptrHandleData = Marshal.AllocHGlobal(handle_info_size);
|
||||||
|
int nLength = 0;
|
||||||
|
|
||||||
|
while (NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ptrHandleData, handle_info_size, ref nLength) == STATUS_INFO_LENGTH_MISMATCH)
|
||||||
|
{
|
||||||
|
handle_info_size = nLength;
|
||||||
|
Marshal.FreeHGlobal(ptrHandleData);
|
||||||
|
ptrHandleData = Marshal.AllocHGlobal(nLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
long handle_count = Marshal.ReadIntPtr(ptrHandleData).ToInt64();
|
||||||
|
IntPtr ptrHandleItem = ptrHandleData + Marshal.SizeOf(ptrHandleData);
|
||||||
|
|
||||||
|
for (long lIndex = 0; lIndex < handle_count; lIndex++)
|
||||||
|
{
|
||||||
|
SYSTEM_HANDLE_INFORMATION oSystemHandleInfo = new SYSTEM_HANDLE_INFORMATION();
|
||||||
|
oSystemHandleInfo = (SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ptrHandleItem, oSystemHandleInfo.GetType());
|
||||||
|
ptrHandleItem += Marshal.SizeOf(new SYSTEM_HANDLE_INFORMATION());
|
||||||
|
if (oSystemHandleInfo.ProcessID != process.Id) { continue; }
|
||||||
|
aHandles.Add(oSystemHandleInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(ptrHandleData);
|
||||||
|
}
|
||||||
|
return aHandles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void FindAndCloseWeChatMutexHandle(SYSTEM_HANDLE_INFORMATION systemHandleInformation, Process process)
|
||||||
|
{
|
||||||
|
IntPtr ipHandle = IntPtr.Zero;
|
||||||
|
IntPtr openProcessHandle = IntPtr.Zero;
|
||||||
|
IntPtr hObjectName = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PROCESS_ACCESS_FLAGS flags = PROCESS_ACCESS_FLAGS.DupHandle | PROCESS_ACCESS_FLAGS.VMRead;
|
||||||
|
openProcessHandle = OpenProcess(flags, false, process.Id);
|
||||||
|
// 通过 DuplicateHandle 访问句柄
|
||||||
|
if (!DuplicateHandle(openProcessHandle, new IntPtr(systemHandleInformation.Handle), GetCurrentProcess(), out ipHandle, 0, false, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nLength = 0;
|
||||||
|
hObjectName = Marshal.AllocHGlobal(256 * 1024);
|
||||||
|
|
||||||
|
// 查询句柄名称
|
||||||
|
while ((uint)(NtQueryObject(ipHandle, (int)OBJECT_INFORMATION_CLASS.ObjectNameInformation, hObjectName, nLength, ref nLength)) == STATUS_INFO_LENGTH_MISMATCH)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(hObjectName);
|
||||||
|
if (nLength == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Length returned at zero!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hObjectName = Marshal.AllocHGlobal(nLength);
|
||||||
|
}
|
||||||
|
OBJECT_NAME_INFORMATION objObjectName = new OBJECT_NAME_INFORMATION();
|
||||||
|
objObjectName = (OBJECT_NAME_INFORMATION)Marshal.PtrToStructure(hObjectName, objObjectName.GetType());
|
||||||
|
|
||||||
|
if (objObjectName.Name.Buffer != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
string strObjectName = Marshal.PtrToStringUni(objObjectName.Name.Buffer);
|
||||||
|
Console.WriteLine(strObjectName);
|
||||||
|
// \Sessions\1\BaseNamedObjects\_WeChat_App_Instance_Identity_Mutex_Name
|
||||||
|
if (strObjectName.Contains("_Instance_Identity_Mutex_Name"))
|
||||||
|
{
|
||||||
|
// 通过 DuplicateHandle DUPLICATE_CLOSE_SOURCE 关闭句柄
|
||||||
|
IntPtr mHandle = IntPtr.Zero;
|
||||||
|
if (DuplicateHandle(openProcessHandle, new IntPtr(systemHandleInformation.Handle), GetCurrentProcess(), out mHandle, 0, false, DUPLICATE_CLOSE_SOURCE))
|
||||||
|
{
|
||||||
|
CloseHandle(mHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(hObjectName);
|
||||||
|
CloseHandle(ipHandle);
|
||||||
|
CloseHandle(openProcessHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭微信的互斥句柄
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="processes">微信的进程</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static void CloseMutexHandle(Process[] processes)
|
||||||
|
{
|
||||||
|
foreach (Process process in processes)
|
||||||
|
{
|
||||||
|
CloseMutexHandle(process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CloseMutexHandle(Process process)
|
||||||
|
{
|
||||||
|
List<SYSTEM_HANDLE_INFORMATION> aHandles = GetHandles(process);
|
||||||
|
foreach (SYSTEM_HANDLE_INFORMATION handle in aHandles)
|
||||||
|
{
|
||||||
|
// Mutant 类型的句柄
|
||||||
|
if (handle.ObjectType == OBJECT_TYPE_MUTANT)
|
||||||
|
{
|
||||||
|
FindAndCloseWeChatMutexHandle(handle, process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,7 @@
|
||||||
<Compile Include="FormMultiInstance.Designer.cs">
|
<Compile Include="FormMultiInstance.Designer.cs">
|
||||||
<DependentUpon>FormMultiInstance.cs</DependentUpon>
|
<DependentUpon>FormMultiInstance.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="ProcessUtil.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<EmbeddedResource Include="FormMultiInstance.resx">
|
<EmbeddedResource Include="FormMultiInstance.resx">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user