This commit is contained in:
Julian Freeman
2025-11-26 09:04:52 -04:00
parent 4fc501f941
commit 19b18d091a
4 changed files with 886 additions and 486 deletions

348
src-tauri/Cargo.lock generated
View File

@@ -280,6 +280,24 @@ dependencies = [
"piper",
]
[[package]]
name = "breakpad-symbols"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b002797414ffc34425bdf5b21a9e50d102013292625749eeba0a59923176ab05"
dependencies = [
"async-trait",
"cachemap2",
"circular",
"debugid",
"futures-util",
"minidump-common",
"nom",
"range-map",
"thiserror 1.0.69",
"tracing",
]
[[package]]
name = "brotli"
version = "8.0.2"
@@ -328,6 +346,12 @@ dependencies = [
"serde",
]
[[package]]
name = "cachemap2"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7bba2f68a9fefca870fed897de7c655f9d5c1eaf1cd9517db96c9a3861f648b"
[[package]]
name = "cairo-rs"
version = "0.18.5"
@@ -458,6 +482,12 @@ dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "circular"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fc239e0f6cb375d2402d48afb92f76f5404fd1df208a41930ec81eda078bea"
[[package]]
name = "combine"
version = "4.6.7"
@@ -585,6 +615,31 @@ version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crossterm"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
dependencies = [
"bitflags 2.10.0",
"crossterm_winapi",
"libc",
"mio 0.8.11",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "crypto-common"
version = "0.1.7"
@@ -667,6 +722,15 @@ dependencies = [
"syn 2.0.111",
]
[[package]]
name = "debugid"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
dependencies = [
"uuid",
]
[[package]]
name = "deranged"
version = "0.5.5"
@@ -833,6 +897,15 @@ version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
[[package]]
name = "encoding_rs"
version = "0.8.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
dependencies = [
"cfg-if",
]
[[package]]
name = "endi"
version = "1.1.0"
@@ -1976,6 +2049,15 @@ version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "memmap2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"
dependencies = [
"libc",
]
[[package]]
name = "memoffset"
version = "0.9.1"
@@ -1991,6 +2073,82 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minidump"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c671544a05d0e8daa3018c8fb6687c11935c4ae8f122de8f2386c2896b4e9b8"
dependencies = [
"debugid",
"encoding_rs",
"memmap2",
"minidump-common",
"num-traits",
"range-map",
"scroll",
"thiserror 1.0.69",
"time",
"tracing",
"uuid",
]
[[package]]
name = "minidump-common"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dbc11dfb55b3b7b5684fb16d98e0fc9d1e93a64d6b00bf383eabfc4541aaac2"
dependencies = [
"bitflags 2.10.0",
"debugid",
"num-derive",
"num-traits",
"range-map",
"scroll",
"smart-default",
]
[[package]]
name = "minidump-processor"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76b49bde7c0ae9a7142c540c27c7fc29db2288fd9614f11a9ce57badeb74af43"
dependencies = [
"async-trait",
"breakpad-symbols",
"debugid",
"futures-util",
"memmap2",
"minidump",
"minidump-common",
"minidump-unwind",
"scroll",
"serde",
"serde_json",
"thiserror 1.0.69",
"tracing",
"yaxpeax-x86",
]
[[package]]
name = "minidump-unwind"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63aef4cd2e018881680b152296ae28e674242823faa1767b417b6669a1896cdc"
dependencies = [
"async-trait",
"breakpad-symbols",
"minidump",
"minidump-common",
"scroll",
"tracing",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
@@ -2001,6 +2159,18 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi 0.11.1+wasi-snapshot-preview1",
"windows-sys 0.48.0",
]
[[package]]
name = "mio"
version = "1.1.0"
@@ -2088,6 +2258,16 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "ntapi"
version = "0.4.1"
@@ -2103,6 +2283,17 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-derive"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.111",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -2904,6 +3095,15 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "range-map"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12a5a2d6c7039059af621472a4389be1215a816df61aa4d531cfe85264aee95f"
dependencies = [
"num-traits",
]
[[package]]
name = "raw-window-handle"
version = "0.6.2"
@@ -3134,6 +3334,26 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "scroll"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da"
dependencies = [
"scroll_derive",
]
[[package]]
name = "scroll_derive"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.111",
]
[[package]]
name = "selectors"
version = "0.24.0"
@@ -3349,6 +3569,27 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc"
dependencies = [
"libc",
"mio 0.8.11",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.7"
@@ -3388,6 +3629,17 @@ version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "smart-default"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.111",
]
[[package]]
name = "socket2"
version = "0.6.1"
@@ -3575,6 +3827,8 @@ name = "system-doctor"
version = "0.1.0"
dependencies = [
"chrono",
"minidump",
"minidump-processor",
"serde",
"serde_json",
"sysinfo",
@@ -4009,7 +4263,7 @@ checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
dependencies = [
"bytes",
"libc",
"mio",
"mio 1.1.0",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
@@ -4189,6 +4443,7 @@ version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -4876,6 +5131,15 @@ dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
@@ -4918,6 +5182,21 @@ dependencies = [
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
@@ -4975,6 +5254,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
@@ -4993,6 +5278,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
@@ -5011,6 +5302,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
@@ -5041,6 +5338,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
@@ -5059,6 +5362,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
@@ -5077,6 +5386,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
@@ -5095,6 +5410,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
@@ -5228,6 +5549,31 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "yaxpeax-arch"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f005c964432a1f9ee04598e094a3eb5f7568f6b33e89a2762d7bef6fbe8b255"
dependencies = [
"crossterm",
"num-traits",
"serde",
"serde_derive",
]
[[package]]
name = "yaxpeax-x86"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9107477944697db42c41326f82d4c65b769b32512cdad1e086f36f0e0f25ff45"
dependencies = [
"cfg-if",
"num-traits",
"serde",
"serde_derive",
"yaxpeax-arch",
]
[[package]]
name = "yoke"
version = "0.8.1"

View File

@@ -26,6 +26,8 @@ sysinfo = "0.30"
wmi = "0.13"
chrono = { version = "0.4", features = ["serde"] }
tokio = { version = "1", features = ["full"] }
minidump = "0.19"
minidump-processor = "0.19"
[features]
# this feature is used for production builds or when `devPath` points to the filesystem

View File

@@ -8,13 +8,15 @@ use serde::Serialize;
use sysinfo::{System, Disks};
use wmi::{COMLibrary, WMIConnection};
use std::fs;
// 引入 tauri::Emitter 用于发送事件 (Tauri v2)
use std::path::Path;
use tauri::Emitter;
use chrono::{Duration, FixedOffset, Local, NaiveDate, TimeZone};
use chrono::{Duration, FixedOffset, Local, NaiveDate, TimeZone, DateTime};
// [修改] 只引入 minidump 基础库,移除 processor 依赖以避免 API 冲突
use minidump::{Minidump, MinidumpException, MinidumpSystemInfo};
// --- 1. 数据结构 (保持不变,用于序列化部分数据) ---
// --- 1. 数据结构 (保持不变) ---
#[derive(Serialize, Clone)] // 增加 Clone trait 方便使用
#[derive(Serialize, Clone)]
struct HardwareSummary {
cpu_name: String,
sys_vendor: String,
@@ -67,51 +69,39 @@ struct BatteryInfo {
explanation: String,
}
#[derive(Serialize, Clone)]
struct BsodFileItem {
filename: String,
path: String,
size_kb: u64,
created_time: String,
}
#[derive(Serialize, Clone)]
struct BsodAnalysisReport {
crash_reason: String,
crash_address: String,
bug_check_code: String,
crashing_thread: Option<String>,
human_analysis: String,
recommendation: String,
}
// --- WMI 反序列化结构 ---
#[derive(serde::Deserialize, Debug)]
struct Win32_DiskDrive {
Model: Option<String>,
Status: Option<String>,
}
struct Win32_DiskDrive { Model: Option<String>, Status: Option<String> }
#[derive(serde::Deserialize, Debug)]
struct Win32_NTLogEvent {
TimeGenerated: String,
EventCode: u32,
SourceName: String,
Message: Option<String>,
}
struct Win32_NTLogEvent { TimeGenerated: String, EventCode: u32, SourceName: String, Message: Option<String> }
#[derive(serde::Deserialize, Debug)]
struct Win32_PnPEntity {
Name: Option<String>,
ConfigManagerErrorCode: Option<u32>,
}
struct Win32_PnPEntity { Name: Option<String>, ConfigManagerErrorCode: Option<u32> }
#[derive(serde::Deserialize, Debug)]
struct Win32_Battery {
DesignCapacity: Option<u32>,
FullChargeCapacity: Option<u32>,
BatteryStatus: Option<u16>,
}
struct Win32_Battery { DesignCapacity: Option<u32>, FullChargeCapacity: Option<u32>, BatteryStatus: Option<u16> }
#[derive(serde::Deserialize, Debug)]
struct Win32_BIOS {
SMBIOSBIOSVersion: Option<String>,
}
struct Win32_BIOS { SMBIOSBIOSVersion: Option<String> }
#[derive(serde::Deserialize, Debug)]
struct Win32_BaseBoard {
Manufacturer: Option<String>,
Product: Option<String>,
}
struct Win32_BaseBoard { Manufacturer: Option<String>, Product: Option<String> }
#[derive(serde::Deserialize, Debug)]
struct Win32_ComputerSystem {
Manufacturer: Option<String>,
Model: Option<String>,
}
struct Win32_ComputerSystem { Manufacturer: Option<String>, Model: Option<String> }
// --- 辅助函数 ---
fn get_wmi_query_time(days_ago: i64) -> String {
@@ -120,9 +110,7 @@ fn get_wmi_query_time(days_ago: i64) -> String {
}
fn format_wmi_time(wmi_str: &str) -> String {
if wmi_str.len() < 25 {
return wmi_str.to_string();
}
if wmi_str.len() < 25 { return wmi_str.to_string(); }
let year = wmi_str[0..4].parse::<i32>().unwrap_or(1970);
let month = wmi_str[4..6].parse::<u32>().unwrap_or(1);
let day = wmi_str[6..8].parse::<u32>().unwrap_or(1);
@@ -141,14 +129,146 @@ fn format_wmi_time(wmi_str: &str) -> String {
}
}
// --- 核心逻辑:分步流式传输 ---
// --- 新增功能:翻译蓝屏代码为人话 (手动映射常见代码) ---
fn translate_bugcheck_u32(code: u32) -> (String, String) {
// 这些是 Windows 最常见的 BSOD 代码
match code {
0x000000D1 => (
"DRIVER_IRQL_NOT_LESS_OR_EQUAL (0xD1)".to_string(),
"驱动程序使用了不正确的内存地址。通常是驱动程序冲突或损坏。请检查最近安装的硬件驱动(显卡、网卡等),尝试回滚或更新驱动。"
.to_string(),
),
0x0000007E | 0x1000007E => (
"SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (0x7E)".to_string(),
"系统线程抛出了未捕获的异常。可能是显卡驱动不兼容或者BIOS设置问题。建议重装显卡驱动或恢复BIOS默认设置。"
.to_string(),
),
0x0000001A => (
"MEMORY_MANAGEMENT (0x1A)".to_string(),
"严重的内存管理错误。高度怀疑内存条物理故障。建议立即运行 Windows 内存诊断工具,或者尝试拔插内存条。"
.to_string(),
),
0x000000EF => (
"CRITICAL_PROCESS_DIED (0xEF)".to_string(),
"Windows 核心进程意外终止。通常是系统文件损坏或硬盘故障。建议运行 'sfc /scannow' 修复系统,并检查硬盘健康度。"
.to_string(),
),
0x00000124 => (
"WHEA_UNCORRECTABLE_ERROR (0x124)".to_string(),
"硬件发生无法纠正的物理错误。这是纯硬件故障。通常是 CPU 电压不足、超频失败、过热,或者主板/PCIe设备如 NVMe 硬盘)故障。"
.to_string(),
),
0x00000116 => (
"VIDEO_TDR_FAILURE (0x116)".to_string(),
"显卡响应超时。显卡驱动崩溃或显卡过热。如果你在玩游戏,可能是显卡超频不稳定或散热硅脂干了。"
.to_string(),
),
0x00000050 => (
"PAGE_FAULT_IN_NONPAGED_AREA (0x50)".to_string(),
"试图访问无效的内存地址。可能是内存条故障,或者是防病毒软件/驱动程序冲突。建议检查内存。"
.to_string(),
),
0x0000000A => (
"IRQL_NOT_LESS_OR_EQUAL (0x0A)".to_string(),
"驱动程序使用了不正确的内存地址。通常由有缺陷的驱动程序或硬件兼容性问题引起。"
.to_string(),
),
0x0000003B => (
"SYSTEM_SERVICE_EXCEPTION (0x3B)".to_string(),
"系统服务执行异常。通常与图形驱动程序或过时的系统文件有关。"
.to_string(),
),
0x00000133 => (
"DPC_WATCHDOG_VIOLATION (0x133)".to_string(),
"DPC 看门狗超时。通常是 SSD 固件过旧或无线网卡驱动冲突导致系统卡死时间过长。"
.to_string(),
),
_ => (
format!("未知错误代码: 0x{:X}", code),
"请尝试在搜索引擎中搜索此错误代码。通用建议:更新驱动、检查内存、扫描病毒。".to_string(),
),
}
}
// --- 命令:列出 Minidump 文件 ---
#[tauri::command]
async fn list_minidumps() -> Result<Vec<BsodFileItem>, String> {
let path = Path::new("C:\\Windows\\Minidump");
let mut files = Vec::new();
if path.exists() {
if let Ok(entries) = fs::read_dir(path) {
for entry in entries {
if let Ok(entry) = entry {
// [修复] 使用 .as_ref() 防止 metadata 所有权被移动
let metadata = entry.metadata().ok();
let created = metadata.as_ref()
.and_then(|m| m.modified().ok()) // 通常用修改时间
.map(|t| {
let dt: DateTime<Local> = t.into();
dt.format("%Y-%m-%d %H:%M:%S").to_string()
})
.unwrap_or("Unknown".to_string());
// [修复] 使用 .as_ref() 再次访问 metadata
let size = metadata.as_ref().map(|m| m.len() / 1024).unwrap_or(0);
files.push(BsodFileItem {
filename: entry.file_name().to_string_lossy().to_string(),
path: entry.path().to_string_lossy().to_string(),
size_kb: size,
created_time: created,
});
}
}
}
}
// 按时间倒序排列
files.sort_by(|a, b| b.created_time.cmp(&a.created_time));
Ok(files)
}
// --- 命令:分析指定的 Minidump 文件 ---
#[tauri::command]
async fn analyze_minidump(filepath: String) -> Result<BsodAnalysisReport, String> {
let path = Path::new(&filepath);
// 1. 读取文件 (使用基础 minidump 库)
let dump = Minidump::read_path(path).map_err(|e| format!("无法读取文件: {}", e))?;
// 2. 直接获取异常流 (Exception Stream)
let exception_stream = dump.get_stream::<MinidumpException>()
.map_err(|_| "无法找到异常信息流 (No Exception Stream)".to_string())?;
// [修复] 使用 .raw 访问内部原始结构
let exception_code = exception_stream.raw.exception_record.exception_code;
let exception_address = exception_stream.raw.exception_record.exception_address;
// 3. 尝试获取系统信息 (OS Version)
let sys_info_str = match dump.get_stream::<MinidumpSystemInfo>() {
// [修复] 使用 .raw 访问 build_number
Ok(info) => format!("Windows Build {}", info.raw.build_number),
Err(_) => "Unknown OS".to_string(),
};
// 4. 翻译
let (reason_str, recommend) = translate_bugcheck_u32(exception_code);
Ok(BsodAnalysisReport {
crash_reason: reason_str,
crash_address: format!("0x{:X}", exception_address),
bug_check_code: format!("0x{:X} ({})", exception_code, sys_info_str),
crashing_thread: None, // 基础解析不包含线程栈回溯
human_analysis: "根据错误代码自动匹配的分析结果。".to_string(),
recommendation: recommend,
})
}
// --- 现有命令run_diagnosis (保持不变) ---
#[tauri::command]
async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
// 使用 spawn 在后台线程运行,避免阻塞 Tauri 主线程
// 注意:这里不等待 join而是让它在后台跑通过 window.emit 发送进度
std::thread::spawn(move || {
// 1. 硬件概览 (最快)
// 1. 硬件概览
{
let mut sys = System::new();
sys.refresh_memory();
@@ -180,7 +300,6 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
}
}
// C盘
let mut c_total = 0u64;
let mut c_used = 0u64;
let disks = Disks::new_with_refreshed_list();
@@ -209,15 +328,12 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
c_drive_total_gb: c_total,
c_drive_used_gb: c_used,
};
// 发送硬件事件
let _ = window.emit("report-hardware", hardware);
}
// WMI 连接复用 (如果需要) 或者重新建立
let wmi_con = WMIConnection::new(COMLibrary::new().unwrap()).ok();
// 2. 存储设备 (较快)
// 2. 存储设备
{
let mut storage = Vec::new();
if let Some(con) = &wmi_con {
@@ -242,7 +358,7 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
let _ = window.emit("report-storage", storage);
}
// 3. 驱动 (快)
// 3. 驱动
{
let mut driver_issues = Vec::new();
if let Some(con) = &wmi_con {
@@ -267,7 +383,7 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
let _ = window.emit("report-drivers", driver_issues);
}
// 4. Minidump (快)
// 4. Minidump
{
let mut minidump = MinidumpInfo { found: false, count: 0, explanation: "无蓝屏记录".to_string() };
if let Ok(entries) = fs::read_dir("C:\\Windows\\Minidump") {
@@ -283,7 +399,7 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
let _ = window.emit("report-minidumps", minidump);
}
// 5. 电池 (快)
// 5. 电池
{
let mut battery_info = None;
if let Some(con) = &wmi_con {
@@ -309,12 +425,10 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
}
}
}
// 即使是 None 也要发,以便前端知道检查完成了
// 这里为了简化,直接发 Option
let _ = window.emit("report-battery", battery_info);
}
// 6. 日志 (最慢,放在最后)
// 6. 日志
{
let mut events = Vec::new();
if let Some(con) = &wmi_con {
@@ -366,7 +480,7 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![run_diagnosis])
.invoke_handler(tauri::generate_handler![run_diagnosis, list_minidumps, analyze_minidump])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}