Add MinGW build config, remove console window, Chinese font support
This commit is contained in:
4
.env.example
Normal file
4
.env.example
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
PROXMOX_HOST=proxmox.example.com
|
||||||
|
PROXMOX_USER=root@pam
|
||||||
|
PROXMOX_TOKEN=your-api-token-here
|
||||||
|
VM_ID=100
|
||||||
@@ -18,7 +18,8 @@ opt-level = 3
|
|||||||
lto = true
|
lto = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
strip = true
|
strip = true
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
# MinGW target config
|
|
||||||
[target.x86_64-pc-windows-gnu]
|
[target.x86_64-pc-windows-gnu]
|
||||||
linker = "x86_64-w64-mingw32-gcc"
|
linker = "x86_64-w64-mingw32-gcc"
|
||||||
|
rustflags = ["-C", "link-args=-static-libgcc"]
|
||||||
66
microsoft-feedback.md
Normal file
66
microsoft-feedback.md
Normal file
@@ -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 警告界面点击"详细信息"链接提交反馈。
|
||||||
14
sign.ps1
Normal file
14
sign.ps1
Normal file
@@ -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"
|
||||||
@@ -260,7 +260,7 @@ impl ProxmoxClient {
|
|||||||
.post(&url)
|
.post(&url)
|
||||||
.header("Authorization", self.auth_header())
|
.header("Authorization", self.auth_header())
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.json(&serde_json::json!({"action": "shutdown"}))
|
.json(&serde_json::json!({"command": "shutdown"}))
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
|||||||
44
src/gui.rs
44
src/gui.rs
@@ -145,7 +145,9 @@ pub fn gui_run() {
|
|||||||
viewport: egui::ViewportBuilder::default()
|
viewport: egui::ViewportBuilder::default()
|
||||||
.with_inner_size([520.0, 480.0])
|
.with_inner_size([520.0, 480.0])
|
||||||
.with_min_inner_size([450.0, 400.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()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -274,6 +276,46 @@ impl eframe::App for App {
|
|||||||
});
|
});
|
||||||
ui.add_space(4.0);
|
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("虚拟机列表:");
|
ui.label("虚拟机列表:");
|
||||||
egui::ScrollArea::vertical().max_height(120.0).stick_to_bottom(true).show(ui, |ui| {
|
egui::ScrollArea::vertical().max_height(120.0).stick_to_bottom(true).show(ui, |ui| {
|
||||||
|
|||||||
Reference in New Issue
Block a user