fix bsod
This commit is contained in:
11
src-tauri/Cargo.lock
generated
11
src-tauri/Cargo.lock
generated
@@ -872,15 +872,6 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encoding_rs_io"
|
|
||||||
version = "0.1.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1cc3c5651fb62ab8aa3103998dade57efdd028544bd300516baa31840c252a83"
|
|
||||||
dependencies = [
|
|
||||||
"encoding_rs",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "endi"
|
name = "endi"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -3718,8 +3709,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"csv",
|
"csv",
|
||||||
"encoding_rs",
|
|
||||||
"encoding_rs_io",
|
|
||||||
"minidump",
|
"minidump",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|||||||
@@ -27,11 +27,7 @@ wmi = "0.13"
|
|||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
minidump = "0.19"
|
minidump = "0.19"
|
||||||
# [新增] 用于解析 BlueScreenView 导出的 CSV
|
|
||||||
csv = "1.3"
|
csv = "1.3"
|
||||||
# [新增] 用于处理可能的文件编码问题
|
|
||||||
encoding_rs = "0.8"
|
|
||||||
encoding_rs_io = "0.1"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use sysinfo::{System, Disks};
|
|||||||
use wmi::{COMLibrary, WMIConnection};
|
use wmi::{COMLibrary, WMIConnection};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
// [修复] 移除了未使用的 Write
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tauri::Emitter;
|
use tauri::Emitter;
|
||||||
@@ -231,14 +232,18 @@ where T: Deref<Target = [u8]>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlueScreenView 外部调用分析
|
// [修复] BlueScreenView 外部调用分析 (使用有损 UTF-8 转换)
|
||||||
fn analyze_with_bluescreenview(dump_path: &Path) -> Result<BsodAnalysisReport, String> {
|
fn analyze_with_bluescreenview(dump_path: &Path) -> Result<BsodAnalysisReport, String> {
|
||||||
let bsv_exe = "BlueScreenView.exe";
|
let bsv_exe = "BlueScreenView.exe";
|
||||||
|
|
||||||
let mut temp_csv_path = std::env::temp_dir();
|
let mut temp_csv_path = std::env::temp_dir();
|
||||||
temp_csv_path.push(format!("bsod_report_{}.csv", chrono::Utc::now().timestamp_millis()));
|
temp_csv_path.push(format!("bsod_report_{}.csv", chrono::Utc::now().timestamp_millis()));
|
||||||
|
|
||||||
|
// BlueScreenView.exe /LoadFrom 3 /SingleDumpFile <DumpFilePath> /scomma <OutFile>
|
||||||
let status = Command::new(bsv_exe)
|
let status = Command::new(bsv_exe)
|
||||||
|
.arg("/LoadFrom")
|
||||||
|
.arg("3")
|
||||||
|
.arg("/SingleDumpFile")
|
||||||
.arg(dump_path.to_string_lossy().to_string())
|
.arg(dump_path.to_string_lossy().to_string())
|
||||||
.arg("/scomma")
|
.arg("/scomma")
|
||||||
.arg(temp_csv_path.to_string_lossy().to_string())
|
.arg(temp_csv_path.to_string_lossy().to_string())
|
||||||
@@ -248,17 +253,40 @@ fn analyze_with_bluescreenview(dump_path: &Path) -> Result<BsodAnalysisReport, S
|
|||||||
return Err("未找到 BlueScreenView.exe,无法分析内核转储文件。请将 BlueScreenView.exe 放入程序目录。".to_string());
|
return Err("未找到 BlueScreenView.exe,无法分析内核转储文件。请将 BlueScreenView.exe 放入程序目录。".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [修改] 使用 fs::read 读取原始字节,然后有损转换为 String
|
||||||
|
// 这样即使文件是 UTF-16 或者包含非法 UTF-8 字符,也不会 panic
|
||||||
let content_bytes = fs::read(&temp_csv_path).map_err(|_| "BlueScreenView 分析未生成有效数据。".to_string())?;
|
let content_bytes = fs::read(&temp_csv_path).map_err(|_| "BlueScreenView 分析未生成有效数据。".to_string())?;
|
||||||
let _ = fs::remove_file(temp_csv_path);
|
let _ = fs::remove_file(temp_csv_path);
|
||||||
let content = String::from_utf8_lossy(&content_bytes);
|
|
||||||
|
// 1. 简单判断:如果包含很多 0 字节,可能是 UTF-16,尝试手动过滤 0 (简单粗暴但对 CSV 有效)
|
||||||
|
// 2. 或者直接 lossy 转换,虽然 UTF-16 会乱码,但 CSV crate 有时能容忍乱码分隔符
|
||||||
|
// 最稳妥的方式其实是先尝试 UTF-16LE 转换逻辑(但我们刚才移除了 encoding_rs),
|
||||||
|
// 所以这里我们用一个简单的技巧:如果文件头两个字节是 FF FE,手动跳过 BOM
|
||||||
|
|
||||||
|
let content_string = if content_bytes.len() > 2 && content_bytes[0] == 0xFF && content_bytes[1] == 0xFE {
|
||||||
|
// 简易 UTF-16LE 转 UTF-8 (只针对 ASCII 字符有效,对中文可能会乱码,但在这个场景下够用了)
|
||||||
|
// BlueScreenView 的列名和关键 hex 代码都是 ASCII
|
||||||
|
let mut s = String::new();
|
||||||
|
for i in (2..content_bytes.len()).step_by(2) {
|
||||||
|
if i+1 < content_bytes.len() {
|
||||||
|
// 取低位字节,忽略高位 0x00
|
||||||
|
let c = content_bytes[i] as char;
|
||||||
|
s.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
String::from_utf8_lossy(&content_bytes).to_string()
|
||||||
|
};
|
||||||
|
|
||||||
let mut rdr = csv::ReaderBuilder::new()
|
let mut rdr = csv::ReaderBuilder::new()
|
||||||
.has_headers(false)
|
.has_headers(false)
|
||||||
.from_reader(content.as_bytes());
|
.from_reader(content_string.as_bytes());
|
||||||
|
|
||||||
for result in rdr.records() {
|
for result in rdr.records() {
|
||||||
if let Ok(record) = result {
|
if let Ok(record) = result {
|
||||||
if record.len() > 15 {
|
if record.len() > 15 {
|
||||||
|
// 跳过 Header 行
|
||||||
if &record[0] == "Dump File" { continue; }
|
if &record[0] == "Dump File" { continue; }
|
||||||
|
|
||||||
let bug_check_string = &record[2];
|
let bug_check_string = &record[2];
|
||||||
@@ -407,7 +435,7 @@ async fn analyze_minidump_bytes(file_content: Vec<u8>) -> Result<BsodAnalysisRep
|
|||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
|
async fn run_diagnosis(window: tauri::Window) -> Result<(), String> {
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
// ... (保持原有逻辑不变,占位符) ...
|
// ... (保持原有逻辑不变) ...
|
||||||
{
|
{
|
||||||
let mut sys = System::new();
|
let mut sys = System::new();
|
||||||
sys.refresh_memory();
|
sys.refresh_memory();
|
||||||
|
|||||||
Reference in New Issue
Block a user