3 Commits
v0.5 ... v0.6

Author SHA1 Message Date
Suxue
31c28d8111 新增用户名推定key地址,请确保新建工作区时填写当前账号
现在用户搜索支持了昵称、备注模糊搜索
增加了3.9.8.15 key地址
2023-11-15 16:40:55 +08:00
Suxue
e3cfc67dbd 1.修复新版获取不到微信的问题
2.修复导出聊天记录时,视频被移动的问题
3.标题新增版本号
2023-11-02 14:07:35 +08:00
Suxue
ba8e9f7e18 Update README.md 2023-11-01 16:25:23 +08:00
15 changed files with 383 additions and 76 deletions

View File

@@ -9,6 +9,7 @@ using System.Security.Cryptography;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Windows;
using WechatPCMsgBakTool.Model;
namespace WechatPCMsgBakTool.Helpers
@@ -22,7 +23,7 @@ namespace WechatPCMsgBakTool.Helpers
const int DEFAULT_ITER = 64000;
const int DEFAULT_PAGESIZE = 4096; //4048数据 + 16IV + 20 HMAC + 12
const string SQLITE_HEADER = "SQLite format 3";
public static byte[]? GetWechatKey()
public static byte[]? GetWechatKey(bool mem_find_key,string account)
{
Process? process = ProcessHelper.GetProcess("WeChat");
if (process == null)
@@ -40,31 +41,56 @@ namespace WechatPCMsgBakTool.Helpers
return null;
}
List<VersionInfo>? info = null;
string json = File.ReadAllText("version.json");
info = JsonConvert.DeserializeObject<List<VersionInfo>?>(json);
if (info == null)
return null;
if (info.Count == 0)
return null;
VersionInfo? cur = info.Find(x => x.Version == version);
if (cur == null)
return null;
//这里加的是版本偏移量,兼容不同版本把这个加给改了
long baseAddress = (long)module.BaseAddress + cur.BaseAddr;
byte[]? bytes = ProcessHelper.ReadMemoryDate(process.Handle, (IntPtr)baseAddress, 8);
if (bytes != null)
if (!mem_find_key)
{
IntPtr baseAddress2 = (IntPtr)(((long)bytes[7] << 56) + ((long)bytes[6] << 48) + ((long)bytes[5] << 40) + ((long)bytes[4] << 32) + ((long)bytes[3] << 24) + ((long)bytes[2] << 16) + ((long)bytes[1] << 8) + (long)bytes[0]);
byte[]? twoGet = ProcessHelper.ReadMemoryDate(process.Handle, baseAddress2, 32);
if (twoGet != null)
List<VersionInfo>? info = null;
string json = File.ReadAllText("version.json");
info = JsonConvert.DeserializeObject<List<VersionInfo>?>(json);
if (info == null)
return null;
if (info.Count == 0)
return null;
VersionInfo? cur = info.Find(x => x.Version == version);
if (cur == null)
return null;
//这里加的是版本偏移量,兼容不同版本把这个加给改了
long baseAddress = (long)module.BaseAddress + cur.BaseAddr;
byte[]? bytes = ProcessHelper.ReadMemoryDate(process.Handle, (IntPtr)baseAddress, 8);
if (bytes != null)
{
string key = BytesToHex(twoGet);
return twoGet;
IntPtr baseAddress2 = (IntPtr)(((long)bytes[7] << 56) + ((long)bytes[6] << 48) + ((long)bytes[5] << 40) + ((long)bytes[4] << 32) + ((long)bytes[3] << 24) + ((long)bytes[2] << 16) + ((long)bytes[1] << 8) + (long)bytes[0]);
byte[]? twoGet = ProcessHelper.ReadMemoryDate(process.Handle, baseAddress2, 32);
if (twoGet != null)
{
string key = BytesToHex(twoGet);
return twoGet;
}
}
}
else
{
List<int> read = ProcessHelper.FindProcessMemory(process.Handle, module, account);
if(read.Count >= 2)
{
byte[] buffer = new byte[8];
int key_offset = read[1] - 64;
if (ProcessHelper.ReadProcessMemory(process.Handle, module.BaseAddress + key_offset, buffer, buffer.Length, out _))
{
ulong addr = BitConverter.ToUInt64(buffer, 0);
byte[] key_bytes = new byte[32];
if(ProcessHelper.ReadProcessMemory(process.Handle, (IntPtr)addr, key_bytes, key_bytes.Length, out _))
{
return key_bytes;
}
}
}
else
{
MessageBox.Show("搜索不到微信账号,请确认用户名是否正确,如错误请重新新建工作区,务必确认账号是否正确", "错误");
}
}
return null;

View File

@@ -13,11 +13,9 @@ namespace WechatPCMsgBakTool.Helpers
public class ProcessHelper
{
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 Process GetProcess(string ProcessName)
{
@@ -50,6 +48,41 @@ namespace WechatPCMsgBakTool.Helpers
return null;
}
public static List<int> FindProcessMemory(IntPtr processHandle, ProcessModule module, string content)
{
byte[] buffer = new byte[module.ModuleMemorySize];
byte[] search = Encoding.ASCII.GetBytes(content);
// 逐页读取数据
List<int> offset = new List<int>();
int readBytes;
bool success = ReadProcessMemory(processHandle, module.BaseAddress, buffer, buffer.Length,out readBytes);
if (!success || readBytes == 0)
{
int error = Marshal.GetLastWin32Error();
Console.WriteLine($"ReadProcessMemory failed. GetLastError: {error}");
}
else
{
for (int i = 0; i < buffer.Length; i++)
{
if (buffer[i] == search[0])
{
for (int s = 1; s < search.Length; s++)
{
if (buffer[i + s] != search[s])
break;
if (s == search.Length - 1)
offset.Add(i);
}
}
}
}
return offset;
}
public static List<SYSTEM_HANDLE_INFORMATION> GetHandles(Process process)
{
List<SYSTEM_HANDLE_INFORMATION> aHandles = new List<SYSTEM_HANDLE_INFORMATION>();
@@ -147,14 +180,15 @@ namespace WechatPCMsgBakTool.Helpers
public static byte[]? ReadMemoryDate(IntPtr hProcess, IntPtr lpBaseAddress, int nSize = 100)
{
byte[] array = new byte[nSize];
if (ReadProcessMemory(hProcess, lpBaseAddress, array, nSize, 0) == 0)
int readByte;
if (ReadProcessMemory(hProcess, lpBaseAddress, array, nSize, out readByte))
return null;
else
return array;
}
[DllImport("kernel32.dll")]
public static extern int ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, int lpNumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int nSize, out int lpNumberOfBytesRead);
[DllImport("ntdll.dll")]
private static extern uint NtQuerySystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, ref int returnLength);
@@ -174,10 +208,6 @@ namespace WechatPCMsgBakTool.Helpers
[DllImport("kernel32.dll")]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
private static extern bool GetHandleInformation(IntPtr hObject, out uint lpdwFlags);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SYSTEM_HANDLE_INFORMATION
{ // Information Class 16

View File

@@ -18,9 +18,9 @@
</ListView>
<Label Content="工作区:" HorizontalAlignment="Left" Margin="15,15,0,0" VerticalAlignment="Top" Height="25" Width="58"/>
<Button Content="新增" Width="50" HorizontalAlignment="Left" Margin="194,20,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.343,0.521" Height="19" Click="Button_Click_1"/>
<Label Content="用户路径:-" Name="user_path" HorizontalAlignment="Left" Margin="278,50,0,0" VerticalAlignment="Top" Height="25" Width="500"/>
<Label Content="用户路径:-" Name="user_path" HorizontalAlignment="Left" Margin="278,68,0,0" VerticalAlignment="Top" Height="25" Width="500"/>
<Button Content="解密" IsEnabled="False" Width="50" HorizontalAlignment="Left" Margin="285,20,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.343,0.521" Name="btn_decrypt" Click="btn_decrypt_Click" Height="19"/>
<Button Content="读取" IsEnabled="False" Width="50" HorizontalAlignment="Left" Margin="365,20,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.343,0.521" Name="btn_read" Click="btn_read_Click" Height="19" />
<Button Content="读取" IsEnabled="False" Width="50" HorizontalAlignment="Left" Margin="285,47,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.343,0.521" Name="btn_read" Click="btn_read_Click" Height="19" />
<ListView Name="list_sessions" Margin="278,130,0,20" HorizontalAlignment="Left" Width="290" MouseDoubleClick="list_sessions_MouseDoubleClick">
<ListView.View>
@@ -36,5 +36,7 @@
<Button Name="btn_search" Content="搜索" HorizontalAlignment="Left" Margin="525,96,0,0" VerticalAlignment="Top" Width="43" Click="btn_search_Click"/>
<Button Name="btn_analyse" Content="消息分析工具" HorizontalAlignment="Left" Margin="609,160,0,0" VerticalAlignment="Top" Width="140" Click="btn_analyse_Click"/>
<CheckBox Name="cb_del_search" Content="已删除人员强制从记录搜索" HorizontalAlignment="Left" Margin="610,99,0,0" VerticalAlignment="Top"/>
<RadioButton Name="rb_find_file" GroupName="find_addr_function" Content="使用version.json进行基址查找" HorizontalAlignment="Left" Margin="348,22,0,0" VerticalAlignment="Top" IsChecked="True"/>
<RadioButton Name="rb_find_mem" GroupName="find_addr_function" Content="使用推定进行基址查找【推荐】" HorizontalAlignment="Left" Margin="546,22,0,0" VerticalAlignment="Top" Checked="rb_find_mem_Checked"/>
</Grid>
</Window>

View File

@@ -36,6 +36,7 @@ namespace WechatPCMsgBakTool
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
InitializeComponent();
LoadWorkspace();
this.Title += $" {Application.ResourceAssembly.GetName().Version}";
}
private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
@@ -85,10 +86,16 @@ namespace WechatPCMsgBakTool
{
if (!CurrentUserBakConfig.Decrypt)
{
bool? mem_find_key = rb_find_mem.IsChecked;
if(mem_find_key == null)
{
MessageBox.Show("请选择key获取方式");
return;
}
byte[]? key = null;
try
{
key = DecryptionHelper.GetWechatKey();
key = DecryptionHelper.GetWechatKey((bool)mem_find_key,CurrentUserBakConfig.Account);
}
catch (Exception ex)
{
@@ -195,7 +202,7 @@ namespace WechatPCMsgBakTool
string path = selectWechat.SelectProcess.DBPath.Replace("\\Msg\\MicroMsg.db", "");
try
{
WXWorkspace wXWorkspace = new WXWorkspace(path);
WXWorkspace wXWorkspace = new WXWorkspace(path, selectWechat.SelectProcess.Account);
wXWorkspace.MoveDB();
MessageBox.Show("创建工作区成功");
LoadWorkspace();
@@ -245,5 +252,17 @@ namespace WechatPCMsgBakTool
Analyse analyse = new Analyse(CurrentUserBakConfig, UserReader);
analyse.Show();
}
private void rb_find_mem_Checked(object sender, RoutedEventArgs e)
{
if(CurrentUserBakConfig!= null)
{
if (string.IsNullOrEmpty(CurrentUserBakConfig.Account))
{
MessageBox.Show("使用该功能需要填写用户名,请务必确认用户名已经正确填写,否则请重建工作区");
return;
}
}
}
}
}

View File

@@ -11,6 +11,7 @@ namespace WechatPCMsgBakTool.Model
public string ProcessName { get; set; } = "";
public string ProcessId { get; set; } = "";
public string DBPath { get; set; } = "";
public string Account { get; set; } = "";
}
public class DBInfo
{

View File

@@ -16,6 +16,7 @@ namespace WechatPCMsgBakTool.Model
public string Hash { get; set; } = "";
public string NickName { get; set; } = "";
public string UserName { get; set; } = "";
public string Account { get; set; } = "";
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged(string propertyName)

View File

@@ -1,37 +1,43 @@
# WechatPCMsgBakTool
微信PC聊天记录备份工具仅支持Windows
微信PC聊天记录备份工具仅支持Windows
- 支持3.9.6.33版本后若版本更新可在version.json添加版本号和地址即可完成新版本支持
- 导出图片、视频、音频、分享链接
- 导出Html文件
- 支持聊天频率分析,全消息库内容搜索
- 支持3.9.6.33版本后若版本更新可在version.json添加版本号和地址即可完成新版本支持
- 导出图片、视频、音频、分享链接
- 导出Html文件
- 支持聊天频率分析,全消息库内容搜索
**本项目仅做学习使用,主要供个人备份自己的微信记录,请勿用于非法用途。**
**本项目严禁商用**
如果有什么好的建议或意见或者遇到什么问题欢迎提issue看到会回。
** 本项目仅做学习使用,主要供个人备份自己的微信记录,请勿用于非法用途。 **
** 本项目严禁商用 **
如果有什么好的建议或意见或者遇到什么问题欢迎提issue看到会回。
> [!NOTE]
> 反馈群815054692
> 如果觉得不错欢迎右上角点个star这是对作者的鼓励谢谢
> 反馈群815054692<br/>
> 如果觉得不错欢迎右上角点个star这是对作者的鼓励谢谢
<br/>
#### 使用
<p>1.打开微信,并登录。</p>
<p>2.在工作区上方点击新增,选择要创建的工作区微信</p>
<p>3.如同时运行多个微信,请选择微信,请注意通过路径进行区别</p>
<p>4.选中刚刚创建的工作区,点击解密。(如当前多开微信,请选择对应的微信进行解密)</p>
<p>5.选中刚刚创建的工作区,点击读取</p>
<p><b>尽情使用吧!</b></p>
### 使用
<p>1.打开微信,并登录。</p>
<p>2.在工作区上方点击新增,选择要创建的工作区微信</p>
<p>3.如同时运行多个微信,请选择微信,请注意通过路径进行区别</p>
<p>4.选中刚刚创建的工作区,点击解密。(如当前多开微信,请选择对应的微信进行解密)</p>
<p>5.选中刚刚创建的工作区,点击读取</p>
<p><b>尽情使用吧!</b></p>
<br/>
#### 注意
<p>本项目基于.NET开发需要安装.NET Desktop Runtime如未安装双击EXE时会提示。</p>
<p>如果使用过程中发生崩溃请删除工作区试一下工作区即根据用户名在运行目录下生成的md5文件夹。</p>
<p>已解密的工作区可以直接读取。</p>
<p>再次强调,主要用于个人备份自己微信使用,请勿用于非法用途,严禁商用!</p>
### 注意
<p>本项目基于.NET开发需要安装.NET Desktop Runtime如未安装双击EXE时会提示。</p>
<p>如果使用过程中发生崩溃请删除工作区试一下工作区即根据用户名在运行目录下生成的md5文件夹。</p>
<p>已解密的工作区可以直接读取。</p>
<p>再次强调,主要用于个人备份自己微信使用,请勿用于非法用途,严禁商用!</p>
<br/>
#### 参考/引用
都是站在大佬们的肩膀上完成的项目,本项目 参考/引用 了以下 项目/文章 内代码。
### 参考/引用
都是站在大佬们的肩膀上完成的项目,本项目 参考/引用 了以下 项目/文章 内代码。
##### [Mr0x01/WXDBDecrypt.NET](https://github.com/Mr0x01/WXDBDecrypt.NET)
##### [AdminTest0/SharpWxDump](https://github.com/AdminTest0/SharpWxDump)
##### [kn007/silk-v3-decoder](https://github.com/kn007/silk-v3-decoder)
##### [吾爱破解chenhahacjl/微信 DAT 图片解密 C#](https://www.52pojie.cn/forum.php?mod=viewthread&tid=1507922)
##### [吾爱破解chenhahacjl/微信 DAT 图片解密 C#](https://www.52pojie.cn/forum.php?mod=viewthread&tid=1507922)
##### [huiyadanli/RevokeMsgPatcher](https://github.com/huiyadanli/RevokeMsgPatcher)

View File

@@ -6,10 +6,10 @@
xmlns:local="clr-namespace:WechatPCMsgBakTool"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="选择微信" Height="300" Width="600">
Title="选择微信" Height="310" Width="600">
<Grid>
<Label Content="请选择您要打开的微信:" HorizontalAlignment="Left" Margin="29,27,0,0" VerticalAlignment="Top"/>
<ListView Name="list_process" Margin="32,55,32,67" SelectionChanged="list_process_SelectionChanged">
<ListView Name="list_process" Margin="32,55,32,110" SelectionChanged="list_process_SelectionChanged" >
<ListView.View>
<GridView>
<GridViewColumn Header="进程名" Width="80" DisplayMemberBinding="{Binding ProcessName}" />
@@ -18,7 +18,10 @@
</GridView>
</ListView.View>
</ListView>
<Button Name="btn_close" Content="确定并返回" HorizontalAlignment="Left" Margin="240,231,0,0" VerticalAlignment="Top" Width="97" Click="btn_close_Click"/>
<Button Name="btn_close" Content="确定并返回" HorizontalAlignment="Left" Margin="241,245,0,0" VerticalAlignment="Top" Width="97" Click="btn_close_Click"/>
<Label Content="用户名:" HorizontalAlignment="Left" Margin="34,190,0,0" VerticalAlignment="Top"/>
<TextBox Name="txt_username" HorizontalAlignment="Left" Margin="95,195,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="297"/>
<Label Content="注意确认用户名是否正确如修改过用户名请自行填写如果需要使用推定方式获取Key必须正确" HorizontalAlignment="Left" Margin="35,215,0,0" VerticalAlignment="Top" FontWeight="Bold"/>
</Grid>
</Window>

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -15,6 +16,7 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml.Linq;
using WechatPCMsgBakTool.Helpers;
using WechatPCMsgBakTool.Model;
@@ -39,14 +41,19 @@ namespace WechatPCMsgBakTool
{
processInfos.Clear();
Process[] processes = Process.GetProcessesByName("wechat");
foreach(Process p in processes)
foreach (Process p in processes)
{
var h_list = ProcessHelper.GetHandles(p);
foreach(var h in h_list)
foreach (var h in h_list)
{
if(h.ObjectType == 40)
string name = ProcessHelper.FindHandleName(h, p);
if (name != "")
{
string name = ProcessHelper.FindHandleName(h, p);
// 预留handle log
if (File.Exists("handle.log"))
{
File.AppendAllText("handle.log", string.Format("{0}|{1}|{2}|{3}\n", p.Id, h.ObjectType, h.Handle, name));
}
if (name.Contains("\\MicroMsg.db") && name.Substring(name.Length - 3, 3) == ".db")
{
ProcessInfo info = new ProcessInfo();
@@ -115,10 +122,21 @@ namespace WechatPCMsgBakTool
private void list_process_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectProcess = list_process.SelectedItem as ProcessInfo;
if(SelectProcess != null)
{
string[] name_raw = SelectProcess.DBPath.Split("\\");
txt_username.Text = name_raw[name_raw.Length - 3];
}
}
private void btn_close_Click(object sender, RoutedEventArgs e)
{
if (SelectProcess != null)
{
SelectProcess.Account = txt_username.Text;
}
Close();
}
}

15
Tools.xaml Normal file
View File

@@ -0,0 +1,15 @@
<Window x:Class="WechatPCMsgBakTool.Tools"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WechatPCMsgBakTool"
mc:Ignorable="d"
Title="资源回退工具" Height="450" Width="800" WindowStartupLocation="CenterScreen">
<Grid>
<Button Name="back_video_file" Content="回退视频文件" HorizontalAlignment="Left" Margin="191,39,0,0" VerticalAlignment="Top" Height="28" Width="96" Click="back_video_file_Click"/>
<TextBox Name="txt_log" VerticalScrollBarVisibility="Auto" Margin="40,88,40,31" TextWrapping="Wrap" Text="" AcceptsReturn="True" IsReadOnly="True"/>
<ComboBox Name="list_workspace" DisplayMemberPath="UserName" HorizontalAlignment="Left" Margin="40,43,0,0" VerticalAlignment="Top" Width="120"/>
</Grid>
</Window>

167
Tools.xaml.cs Normal file
View File

@@ -0,0 +1,167 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using WechatPCMsgBakTool.Model;
namespace WechatPCMsgBakTool
{
/// <summary>
/// Tools.xaml 的交互逻辑
/// </summary>
public partial class Tools : Window
{
public Tools()
{
InitializeComponent();
LoadWorkspace();
}
private void LoadWorkspace()
{
list_workspace.Items.Clear();
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "workspace");
if (Directory.Exists(path))
{
string[] files = Directory.GetFiles(path);
foreach (string file in files)
{
string type = file.Substring(file.Length - 5, 5);
if (type == ".json")
{
string jsonString = File.ReadAllText(file);
UserBakConfig? userBakConfig = null;
try
{
userBakConfig = JsonConvert.DeserializeObject<UserBakConfig>(jsonString);
}
catch
{
MessageBox.Show("读取到异常工作区文件,请确认备份数据是否正常\r\n文件路径" + file, "错误");
}
if (userBakConfig != null)
{
list_workspace.Items.Add(userBakConfig);
}
}
}
}
}
private void back_video_file_Click(object sender, RoutedEventArgs e)
{
Task.Run(() => {
UserBakConfig? selectConfig = null;
Dispatcher.Invoke(() => {
selectConfig = list_workspace.SelectedItem as UserBakConfig;
});
if (selectConfig != null)
{
if (!selectConfig.Decrypt)
{
MessageBox.Show("工作区未解密,请先用主程序进行解密");
return;
}
// 检查工作区视频文件夹
string video_dir = Path.Combine(selectConfig.UserWorkspacePath, "Video");
string[] files = Directory.GetFiles(video_dir);
if (!Directory.Exists(video_dir))
{
Dispatcher.Invoke(() => {
txt_log.Text += video_dir + "不存在\r\n";
txt_log.ScrollToEnd();
});
return;
}
WXUserReader UserReader = new WXUserReader(selectConfig);
// 获取用户
var atc_list = UserReader.GetWXMsgAtc();
if(atc_list == null)
{
Dispatcher.Invoke(() => {
txt_log.Text += "视频列表没有内容,无法回退\r\n";
txt_log.ScrollToEnd();
});
return;
}
foreach (string file in files)
{
FileInfo fileInfo = new FileInfo(file);
var search = atc_list.FindAll(x => x.attachPath.Contains(fileInfo.Name));
if (search != null)
{
WXSessionAttachInfo? select_atc = null;
if (search.Count > 1)
{
foreach (var s in search)
{
Dispatcher.Invoke(() =>
{
txt_log.Text += s + "\r\n";
txt_log.ScrollToEnd();
});
if (s.attachPath.Contains("_raw"))
select_atc = s;
}
}
else if (search.Count == 1)
select_atc = search[0];
else
{
Dispatcher.Invoke(() =>
{
txt_log.Text += "匹配不到文件\r\n";
txt_log.ScrollToEnd();
});
continue;
}
if (select_atc == null)
{
Dispatcher.Invoke(() =>
{
txt_log.Text += "匹配失败\r\n";
txt_log.ScrollToEnd();
});
continue;
}
// 建立路径
string source_video_file = Path.Combine(selectConfig.UserResPath, select_atc.attachPath);
if (File.Exists(source_video_file))
{
Dispatcher.Invoke(() => {
txt_log.Text += source_video_file + "已经存在\r\n";
txt_log.ScrollToEnd();
});
continue;
}
else
{
Dispatcher.Invoke(() => {
txt_log.Text += source_video_file + "开始发起回退\r\n";
txt_log.ScrollToEnd();
});
File.Copy(fileInfo.FullName, source_video_file);
}
}
}
}
});
}
}
}

View File

@@ -46,8 +46,8 @@ namespace WechatPCMsgBakTool
string query = "select * from contact";
if (name != null)
{
query = "select * from contact where username = ? or alias = ?";
return con.Query<WXContact>(query, name, name);
query = "select * from contact where username like ? or alias like ? or nickname like ? or remark like ?";
return con.Query<WXContact>(query, $"%{name}%", $"%{name}%", $"%{name}%", $"%{name}%");
}
return con.Query<WXContact>(query);
}
@@ -88,6 +88,21 @@ namespace WechatPCMsgBakTool
}
return tmp;
}
public List<WXSessionAttachInfo>? GetWXMsgAtc()
{
SQLiteConnection con = DBInfo["MultiSearchChatMsg"];
if (con == null)
return null;
string query = "select * from SessionAttachInfo";
List<WXSessionAttachInfo> list = con.Query<WXSessionAttachInfo>(query);
if (list.Count != 0)
{
return list;
}
else
return null;
}
public WXSessionAttachInfo? GetWXMsgAtc(WXMsg msg)
{
SQLiteConnection con = DBInfo["MultiSearchChatMsg"];
@@ -187,7 +202,7 @@ namespace WechatPCMsgBakTool
// 视频的路径是相对路径,需要加上资源目录
path = Path.Combine(UserBakConfig.UserResPath, path);
if(!File.Exists(video_file_path))
File.Move(path, video_file_path);
File.Copy(path, video_file_path);
path = video_file_path;
}

View File

@@ -14,8 +14,8 @@ namespace WechatPCMsgBakTool
public class WXWorkspace
{
private UserBakConfig UserBakConfig = new UserBakConfig();
public WXWorkspace(string path) {
string checkResult = Init(path);
public WXWorkspace(string path,string account = "") {
string checkResult = Init(path, account);
if (checkResult != "")
new Exception(checkResult);
}
@@ -64,7 +64,7 @@ namespace WechatPCMsgBakTool
}
}
}
private string Init(string path)
private string Init(string path,string account = "")
{
string curPath = AppDomain.CurrentDomain.BaseDirectory;
string md5 = GetMd5Hash(path);
@@ -74,6 +74,7 @@ namespace WechatPCMsgBakTool
UserBakConfig.UserWorkspacePath = Path.Combine(curPath, "workspace", md5);
UserBakConfig.Hash = md5;
UserBakConfig.UserName = username;
UserBakConfig.Account = account;
if (!Directory.Exists(UserBakConfig.UserResPath))
{

View File

@@ -6,9 +6,9 @@
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<AssemblyVersion>0.5.0.0</AssemblyVersion>
<FileVersion>0.5.0.0</FileVersion>
<Version>0.5.0.0</Version>
<AssemblyVersion>0.5.0.1</AssemblyVersion>
<FileVersion>0.5.0.1</FileVersion>
<Version>0.5.0.1</Version>
</PropertyGroup>
<ItemGroup>

View File

@@ -8,5 +8,8 @@
},{
"Version":"3.9.7.29",
"BaseAddr": 63488256
},{
"Version":"3.9.8.15",
"BaseAddr": 64997904
}
]