From 15334459bead975ecdb054f06b93cf1b55b14897 Mon Sep 17 00:00:00 2001 From: xiaji Date: Thu, 16 Apr 2026 21:45:14 +0800 Subject: [PATCH] Add MinGW build config, remove console window, Chinese font support --- .env.example | 4 +++ Cargo.toml | 5 ++-- microsoft-feedback.md | 66 +++++++++++++++++++++++++++++++++++++++++++ sign.ps1 | 14 +++++++++ src/api.rs | 2 +- src/gui.rs | 44 ++++++++++++++++++++++++++++- 6 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 .env.example create mode 100644 microsoft-feedback.md create mode 100644 sign.ps1 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..8d066c1 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +PROXMOX_HOST=proxmox.example.com +PROXMOX_USER=root@pam +PROXMOX_TOKEN=your-api-token-here +VM_ID=100 \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index b854932..376ea79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,8 @@ opt-level = 3 lto = true codegen-units = 1 strip = true +panic = "abort" -# MinGW target config [target.x86_64-pc-windows-gnu] -linker = "x86_64-w64-mingw32-gcc" \ No newline at end of file +linker = "x86_64-w64-mingw32-gcc" +rustflags = ["-C", "link-args=-static-libgcc"] \ No newline at end of file diff --git a/microsoft-feedback.md b/microsoft-feedback.md new file mode 100644 index 0000000..3297052 --- /dev/null +++ b/microsoft-feedback.md @@ -0,0 +1,66 @@ +# Microsoft SmartScreen 反馈 / 申诉 + +## 基本信息 + +- **文件名称**: proxmox-vm-gui.exe +- **文件大小**: ~25 MB +- **程序类型**: GUI 桌面应用程序 (Rust + egui) +- **用途**: Proxmox 虚拟机管理工具 +- **官网**: https://www.proxmox.com/ + +## 程序描述 + +这是一个**自开发的 Proxmox 虚拟机管理工具**,用于通过 Proxmox VE API 控制虚拟机(启动、停止、重启、关机等)。 + +### 功能特性 +- 连接 Proxmox API 进行身份验证 +- 获取节点列表 +- 获取虚拟机列表 +- 启动/停止/重启虚拟机 +- 图形用户界面 (GUI) + +### 技术栈 +- **编程语言**: Rust +- **GUI 框架**: egui (https://egui.rs/) +- **HTTP 客户端**: reqwest +- **目标平台**: Windows x86_64 + +### 代码开源 +- 程序代码位于本地开发环境 +- 不包含任何恶意代码 +- 不连接未知服务器 +- 不收集用户数据 + +## 为什么被拦截? + +SmartScreen 触发可能原因: +1. **无数字签名** - 自签名代码未提交微软审核 +2. **新文件** - 首次分发给用户 +3. **非知名开发者** - 个人开发者项目 + +## 申诉请求 + +本人保证: +1. 此程序为自主开发的合法工具 +2. 不包含病毒、木马、恶意代码 +3. 不收集用户敏感信息 +4. 代码仅用于管理自己的 Proxmox 虚拟机 + +**请求**:将此程序加入 SmartScreen 白名单,或指导如何完成代码签名流程。 + +## 联系方式 + +- 开发者:[your email] +- 项目地址:[如有] + +--- + +## 如何提交申诉 + +1. 访问:https://aka.ms/wdsf (Windows Defender SmartScreen 反馈) +2. 选择"文件被错误阻止" +3. 上传 proxmox-vm-gui.exe +4. 填写上述信息 +5. 提交 + +或者在 SmartScreen 警告界面点击"详细信息"链接提交反馈。 \ No newline at end of file diff --git a/sign.ps1 b/sign.ps1 new file mode 100644 index 0000000..9194baa --- /dev/null +++ b/sign.ps1 @@ -0,0 +1,14 @@ +$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=ProxmoxVMGUI" -CertStoreLocation Cert:\CurrentUser\My +Write-Host "Certificate Thumbprint: $($cert.Thumbprint)" + +$pfxPath = "D:\selftools\proxmox-task\code_signing.pfx" + +$securePassword = New-Object -TypeName System.Security.SecureString +$ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePassword) +$plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($ptr) +[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr) + +$pwd = ConvertTo-SecureString -String $plainPassword -AsPlainText -Force +Export-PfxCertificate -Cert $cert -FilePath $pfxPath -Password $pwd + +Write-Host "Certificate exported to $pfxPath" \ No newline at end of file diff --git a/src/api.rs b/src/api.rs index 1106d39..e4a10f6 100644 --- a/src/api.rs +++ b/src/api.rs @@ -260,7 +260,7 @@ impl ProxmoxClient { .post(&url) .header("Authorization", self.auth_header()) .header("Content-Type", "application/json") - .json(&serde_json::json!({"action": "shutdown"})) + .json(&serde_json::json!({"command": "shutdown"})) .send() .await .map_err(|e| { diff --git a/src/gui.rs b/src/gui.rs index 1e1ce50..7c7726c 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -145,7 +145,9 @@ pub fn gui_run() { viewport: egui::ViewportBuilder::default() .with_inner_size([520.0, 480.0]) .with_min_inner_size([450.0, 400.0]) - .with_title("Proxmox VM 控制器"), + .with_title("Proxmox VM 控制器") + .with_decorations(true) + .with_visible(true), ..Default::default() }; @@ -274,6 +276,46 @@ impl eframe::App for App { }); ui.add_space(4.0); + // VM刷新按钮 + ui.horizontal(|ui| { + if ui.button("🔄 刷新VM列表").clicked() { + if st.nodes.is_empty() { + st.add_log("请先获取节点列表"); + } else { + let node = st.node.clone(); + let client = st.client.clone(); + let state_clone = state.clone(); + st.add_log(&format!("正在获取 {} 的虚拟机列表...", node)); + ctx.request_repaint(); + thread::spawn(move || { + let rt = tokio::runtime::Runtime::new().unwrap(); + rt.block_on(async { + let client = client.lock().unwrap(); + if let Some(c) = client.as_ref() { + match c.get_vms(&node).await { + Ok(vms) => { + let mut state = state_clone.write().unwrap(); + if !vms.is_empty() { + state.vms = vms.clone(); + state.vm_id = vms[0].0; + state.add_log(&format!("✓ 找到 {} 台虚拟机", vms.len())); + } else { + state.add_log("未找到虚拟机"); + } + } + Err(e) => { + state_clone.write().unwrap().add_log(&format!("✗ 获取虚拟机失败: {}", e)); + } + } + } else { + state_clone.write().unwrap().add_log("未连接到服务器"); + } + }); + }); + } + } + }); + // 虚拟机列表(只读) ui.label("虚拟机列表:"); egui::ScrollArea::vertical().max_height(120.0).stick_to_bottom(true).show(ui, |ui| {