开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 172|回复: 8
打印 上一主题 下一主题
收起左侧

[其它源码] Windows系统下载工具开源Python源码

[复制链接]
结帖率:100% (1/1)
跳转到指定楼层
楼主
发表于 前天 20:01 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式   四川省绵阳市
分享源码
界面截图:
是否带模块: 纯源码
备注说明: -
Python源码 Windows系统下载工具支持最新,下载好自动挂载虚拟光驱打开!不限速下载!
系统下载工具.7z (45.88 KB, 下载次数: 11, 售价: 1 枚 精币)

代码预览


#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#![allow(dead_code)]


mod app;
mod core;
mod download;
mod ui;
mod utils;


use eframe::egui;
use std::sync::Arc;


/// 预加载的配置数据
pub struct PreloadedConfig {
    pub remote_config: Option<download::server_config::RemoteConfig>,
    pub system_info: Option<core::system_info::SystemInfo>,
    pub hardware_info: Option<core::hardware_info::HardwareInfo>,
    pub partitions: Vec<core::disk::Partition>,
}


fn main() -> eframe::Result<()> {
    // 加载应用配置(用于获取日志设置)
    let app_config = core::app_config::AppConfig::load();
   
    // 初始化日志系统
    if let Err(e) = utils::logger::LogManager::init(app_config.log_enabled) {
        eprintln!("日志系统初始化失败: {}", e);
        // 即使日志初始化失败,程序也应该继续运行
    }
   
    // 清理旧日志文件
    if app_config.log_enabled {
        if let Err(e) = utils::logger::LogManager::cleanup_old_logs(app_config.log_retention_days) {
            log::warn!("清理旧日志失败: {}", e);
        }
    }


    // 初始化国际化系统
    utils::i18n::init(&app_config.language);


    log::info!("神龙科技-小弧师兄一键装机 启动中...");


    // 检查命令行参数,处理PE环境下的自动安装/备份
    let args: Vec<String> = std::env::args().collect();
   
    if args.contains(&"/PEINSTALL".to_string()) || args.contains(&"--pe-install".to_string()) {
        log::info!("检测到PE安装模式,执行自动安装...");
        return run_pe_install();
    }
   
    if args.contains(&"/PEBACKUP".to_string()) || args.contains(&"--pe-backup".to_string()) {
        log::info!("检测到PE备份模式,执行自动备份...");
        return run_pe_backup();
    }


    // 检查管理员权限
    if !utils::privilege::is_admin() {
        log::warn!("需要管理员权限,正在尝试提升权限...");
        if let Err(e) = utils::privilege::restart_as_admin() {
            log::error!("提升权限失败: {}", e);
            eprintln!("需要管理员权限运行此程序");
        }
        return Ok(());
    }


    log::info!("已获得管理员权限");


    // 检查是否为64位系统
    if !cfg!(target_arch = "x86_64") {
        log::error!("本程序仅支持64位系统");
        eprintln!("本程序仅支持64位系统");
        return Ok(());
    }


    // 检查依赖文件完整性
    if let Err(missing_files) = check_dependencies() {
        log::error!("依赖文件缺失: {:?}", missing_files);
        let message = format!(
            "程序文件不完整,无法正常运行。\n\n\
            缺少以下文件:\n{}\n\n\
            请重新下载完整安装包或修复程序文件。",
            missing_files.join("\n")
        );
        show_error_message(&message);
        return Ok(());
    }


    log::info!("依赖文件检查通过");


    // 检查系统核心组件(极限精简系统检测)
    if let Err(missing_components) = check_system_components() {
        log::error!("系统组件缺失: {:?}", missing_components);
        let message = format!(
            "很抱歉,该软件目前暂时不支持您所使用的极限精简系统使用。\n\n\
            缺少以下系统组件:\n{}",
            missing_components.join("\n")
        );
        show_error_message(&message);
        return Ok(());
    }


    log::info!("系统组件检查通过");


    // 防止重复运行
    let _mutex = match single_instance::SingleInstance::new("神龙科技Windows系统下载工具") {
        Ok(m) => {
            if !m.is_single() {
                log::warn!("程序已在运行中");
                return Ok(());
            }
            m
        }
        Err(e) => {
            log::error!("创建互斥锁失败: {}", e);
            return Ok(());
        }
    };


    log::info!("正在预加载配置和系统信息...");


    // 在显示窗口前先加载服务器配置和系统信息
    let preloaded_config = preload_all_config();
    let preloaded_config = Arc::new(preloaded_config);


    log::info!("预加载完成,初始化 GUI...");


    // 加载图标
    log::info!("加载图标...");
    let icon = load_icon();


    // 设置窗口选项
    log::info!("创建窗口选项...");
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default()
            .with_inner_size([950.0, 680.0])
            .with_min_inner_size([800.0, 600.0])
            .with_icon(icon),
        ..Default::default()
    };


    // 运行应用,传入预加载的配置
    log::info!("启动 eframe 窗口...");
    let config_clone = preloaded_config.clone();
    eframe::run_native(
        "神龙科技-小弧师兄一键装机 - Windows系统一键重装工具",
        options,
        Box::new(move |cc| {
            log::info!("eframe 回调开始创建 App...");
            Ok(Box::new(app::App::new_with_preloaded(cc, &config_clone)))
        }),
    )
}


/// 预加载所有配置和系统信息
fn preload_all_config() -> PreloadedConfig {
    use std::time::{Duration, Instant};
   
    // 只等待远程配置和分区信息(这两个比较快且重要)
    // 系统信息和硬件信息改为异步加载,不阻塞窗口显示
   
    let remote_config_handle = std::thread::spawn(|| {
        log::info!("开始加载远程配置...");
        let config = download::server_config::RemoteConfig::load_from_server();
        log::info!("远程配置加载完成: loaded={}", config.loaded);
        config
    });


    let partitions_handle = std::thread::spawn(|| {
        log::info!("开始获取分区信息...");
        let partitions = core::disk::DiskManager::get_partitions().unwrap_or_default();
        log::info!("分区信息获取完成: {} 个分区", partitions.len());
        partitions
    });


    // 等待远程配置(带超时)
    let start = Instant::now();
    let timeout = Duration::from_secs(5);
   
    log::info!("等待远程配置...");
    let remote_config = loop {
        if remote_config_handle.is_finished() {
            break remote_config_handle.join().ok();
        }
        if start.elapsed() > timeout {
            log::warn!("远程配置加载超时,跳过");
            break None;
        }
        std::thread::sleep(Duration::from_millis(50));
    };
   
    // 等待分区信息(这个通常很快)
    log::info!("等待分区信息...");
    let partitions = partitions_handle.join().ok().unwrap_or_default();


    log::info!("预加载完成,耗时: {:?}", start.elapsed());
   
    // 系统信息和硬件信息不在这里等待,改为在 App 中异步加载
    PreloadedConfig {
        remote_config,
        system_info: None,      // 稍后异步加载
        hardware_info: None,    // 稍后异步加载
        partitions,
    }
}


fn load_icon() -> egui::IconData {
    // 使用内嵌的图标数据(编译时嵌入)
    const ICON_BYTES: &[u8] = include_bytes!("../assets/icon.png");
   
    // 从内嵌的PNG数据加载图标
    if let Ok(image) = image::load_from_memory(ICON_BYTES) {
        let image = image.to_rgba8();
        let (width, height) = image.dimensions();
        return egui::IconData {
            rgba: image.into_raw(),
            width,
            height,
        };
    }


    // 如果解析失败,返回默认图标
    egui::IconData::default()
}


/// 检查程序依赖文件完整性
/// 返回 Ok(()) 表示所有文件存在,Err(Vec<String>) 包含缺失的文件列表
fn check_dependencies() -> Result<(), Vec<String>> {
    let exe_dir = utils::path::get_exe_dir();
   
    // 必需的依赖文件列表
    let required_files = [
        // bin 目录 - 核心工具
        "bin/bcdedit.exe",
        "bin/bcdboot.exe",
        "bin/bootsect.exe",
        "bin/format.com",
        "bin/aria2c.exe",
    ];
   
    let mut missing_files = Vec::new();
   
    for file in &required_files {
        let file_path = exe_dir.join(file);
        if !file_path.exists() {
            log::warn!("依赖文件缺失: {}", file);
            missing_files.push(file.to_string());
        }
    }
   
    if missing_files.is_empty() {
        Ok(())
    } else {
        Err(missing_files)
    }
}


/// 检查系统核心组件完整性(用于检测极限精简系统)
/// 返回 Ok(()) 表示所有组件存在,Err(Vec<String>) 包含缺失的组件列表
fn check_system_components() -> Result<(), Vec<String>> {
    // 获取系统盘路径 (通过 SYSTEMROOT 环境变量,通常为 C:\Windows)
    let system_root = std::env::var("SYSTEMROOT")
        .or_else(|_| std::env::var("WINDIR"))
        .unwrap_or_else(|_| "C:\\Windows".to_string());
   
    let system32_path = std::path::Path::new(&system_root).join("System32");
   
    // 必需的系统组件列表
    let required_components = [
        ("diskpart.exe", "磁盘分区工具"),
        ("wimgapi.dll", "WIM 镜像处理库"),
        ("advapi32.dll", "高级 Windows API 库"),
    ];
   
    let mut missing_components = Vec::new();
   
    for (file, description) in &required_components {
        let file_path = system32_path.join(file);
        if !file_path.exists() {
            log::warn!("系统组件缺失: {} ({})", file, description);
            missing_components.push(format!("{} - {}", file, description));
        }
    }
   
    if missing_components.is_empty() {
        Ok(())
    } else {
        Err(missing_components)
    }
}


/// PE环境下自动执行安装
fn run_pe_install() -> eframe::Result<()> {
    use core::install_config::ConfigFileManager;
   
    println!("[PE INSTALL] ========== PE自动安装模式 ==========");
   
    // 查找配置文件所在分区
    let data_partition = match ConfigFileManager::find_data_partition() {
        Some(p) => p,
        None => {
            eprintln!("[PE INSTALL] 错误: 未找到安装配置文件");
            show_error_message("未找到安装配置文件,无法继续安装。");
            return Ok(());
        }
    };
   
    println!("[PE INSTALL] 数据分区: {}", data_partition);
   
    // 读取安装配置
    let config = match ConfigFileManager::read_install_config(&data_partition) {
        Ok(c) => c,
        Err(e) => {
            eprintln!("[PE INSTALL] 错误: 读取配置失败: {}", e);
            show_error_message(&format!("读取安装配置失败: {}", e));
            return Ok(());
        }
    };
   
    println!("[PE INSTALL] 目标分区: {}", config.target_partition);
    println!("[PE INSTALL] 镜像文件: {}", config.image_path);
   
    // 查找安装标记分区
    let target_partition = match ConfigFileManager::find_install_marker_partition() {
        Some(p) => p,
        None => config.target_partition.clone(),
    };
   
    // 构建完整镜像路径
    let data_dir = ConfigFileManager::get_data_dir(&data_partition);
    let image_path = format!("{}\\{}", data_dir, config.image_path);
   
    if !std::path::Path::new(&image_path).exists() {
        eprintln!("[PE INSTALL] 错误: 镜像文件不存在: {}", image_path);
        show_error_message(&format!("镜像文件不存在: {}", image_path));
        return Ok(());
    }
   
    println!("[PE INSTALL] 完整镜像路径: {}", image_path);
   
    // 执行安装
    let result = execute_pe_install(&target_partition, &image_path, &config, &data_dir);
   
    // 清理标记文件
    ConfigFileManager::cleanup_partition_markers(&target_partition);
   
    match result {
        Ok(_) => {
            println!("[PE INSTALL] 安装完成!");
            if config.auto_reboot {
                println!("[PE INSTALL] 即将重启...");
                let _ = utils::cmd::create_command("shutdown")
                    .args(["/r", "/t", "10", "/c", "神龙科技-小弧师兄一键装机 系统安装完成,即将重启..."])
                    .spawn();
            } else {
                show_success_message("系统安装完成!请手动重启计算机。");
            }
        }
        Err(e) => {
            eprintln!("[PE INSTALL] 安装失败: {}", e);
            show_error_message(&format!("系统安装失败: {}", e));
        }
    }
   
    Ok(())
}


/// PE环境下自动执行备份
fn run_pe_backup() -> eframe::Result<()> {
    use core::install_config::ConfigFileManager;
   
    println!("[PE BACKUP] ========== PE自动备份模式 ==========");
   
    // 查找配置文件所在分区
    let data_partition = match ConfigFileManager::find_data_partition() {
        Some(p) => p,
        None => {
            eprintln!("[PE BACKUP] 错误: 未找到备份配置文件");
            show_error_message("未找到备份配置文件,无法继续备份。");
            return Ok(());
        }
    };
   
    println!("[PE BACKUP] 数据分区: {}", data_partition);
   
    // 读取备份配置
    let config = match ConfigFileManager::read_backup_config(&data_partition) {
        Ok(c) => c,
        Err(e) => {
            eprintln!("[PE BACKUP] 错误: 读取配置失败: {}", e);
            show_error_message(&format!("读取备份配置失败: {}", e));
            return Ok(());
        }
    };
   
    println!("[PE BACKUP] 源分区: {}", config.source_partition);
    println!("[PE BACKUP] 保存路径: {}", config.save_path);
   
    // 查找备份标记分区
    let source_partition = match ConfigFileManager::find_backup_marker_partition() {
        Some(p) => p,
        None => config.source_partition.clone(),
    };
   
    // 执行备份
    let result = execute_pe_backup(&source_partition, &config);
   
    // 清理标记文件
    ConfigFileManager::cleanup_partition_markers(&source_partition);
   
    match result {
        Ok(_) => {
            println!("[PE BACKUP] 备份完成!");
            show_success_message(&format!("系统备份完成!\n保存位置: {}", config.save_path));
        }
        Err(e) => {
            eprintln!("[PE BACKUP] 备份失败: {}", e);
            show_error_message(&format!("系统备份失败: {}", e));
        }
    }
   
    Ok(())
}


/// 执行PE安装
fn execute_pe_install(
    target_partition: &str,
    image_path: &str,
    config: &core::install_config::InstallConfig,
    data_dir: &str,
) -> anyhow::Result<()> {
    use anyhow::Context;
   
    println!("[PE INSTALL] Step 1: 格式化分区");
    // 格式化目标分区
    let output = utils::cmd::create_command("cmd")
        .args(["/c", &format!("format {} /FS:NTFS /Q /Y", target_partition)])
        .output()
        .context("执行格式化命令失败")?;
   
    if !output.status.success() {
        let stderr = utils::encoding::gbk_to_utf8(&output.stderr);
        anyhow::bail!("格式化分区失败: {}", stderr);
    }
   
    println!("[PE INSTALL] Step 2: 释放镜像");
    // 释放镜像
    let apply_dir = format!("{}\\", target_partition);
   
    if config.is_gho {
        // GHO镜像使用Ghost
        let ghost = core::ghost::Ghost::new();
        if !ghost.is_available() {
            anyhow::bail!("Ghost工具不可用");
        }
        
        let partitions = core::disk::DiskManager::get_partitions().unwrap_or_default();
        ghost.restore_image_to_letter(image_path, target_partition, &partitions, None)?;
    } else {
        // WIM/ESD使用DISM
        let dism = core::dism::Dism::new();
        dism.apply_image(image_path, &apply_dir, config.volume_index, None)?;
    }
   
    println!("[PE INSTALL] Step 3: 导入驱动");
    // 导入驱动
    if config.restore_drivers {
        let driver_path = format!("{}\\drivers", data_dir);
        if std::path::Path::new(&driver_path).exists() {
            let dism = core::dism::Dism::new();
            let _ = dism.add_drivers_offline(&apply_dir, &driver_path);
        }
    }
   
    println!("[PE INSTALL] Step 4: 修复引导");
    // 修复引导
    let boot_manager = core::bcdedit::BootManager::new();
    let use_uefi = detect_uefi_mode();
    boot_manager.repair_boot_advanced(target_partition, use_uefi)?;
   
    println!("[PE INSTALL] Step 5: 应用高级选项");
    // 应用高级选项
    let mut advanced_options = ui::advanced_options::AdvancedOptions::default();
    advanced_options.remove_shortcut_arrow = config.remove_shortcut_arrow;
    advanced_options.restore_classic_context_menu = config.restore_classic_context_menu;
    advanced_options.bypass_nro = config.bypass_nro;
    advanced_options.disable_windows_update = config.disable_windows_update;
    advanced_options.disable_windows_defender = config.disable_windows_defender;
    advanced_options.disable_reserved_storage = config.disable_reserved_storage;
    advanced_options.disable_uac = config.disable_uac;
    advanced_options.disable_device_encryption = config.disable_device_encryption;
    advanced_options.remove_uwp_apps = config.remove_uwp_apps;
    advanced_options.import_storage_controller_drivers = config.import_storage_controller_drivers;
    advanced_options.custom_username = !config.custom_username.is_empty();
    advanced_options.username = config.custom_username.clone();
   
    let _ = advanced_options.apply_to_system(target_partition);
   
    // 生成无人值守配置
    if config.unattended {
        let _ = generate_unattend_xml_pe(target_partition, &config.custom_username);
    }
   
    println!("[PE INSTALL] Step 6: 清理临时文件");
    // 清理数据目录
    let _ = std::fs::remove_dir_all(data_dir);
   
    Ok(())
}


/// 执行PE备份
fn execute_pe_backup(
    source_partition: &str,
    config: &core::install_config::BackupConfig,
) -> anyhow::Result<()> {
    let dism = core::dism::Dism::new();
    let capture_dir = format!("{}\\", source_partition);
   
    if config.incremental && std::path::Path::new(&config.save_path).exists() {
        dism.append_image(
            &config.save_path,
            &capture_dir,
            &config.name,
            &config.description,
            None,
        )
    } else {
        dism.capture_image(
            &config.save_path,
            &capture_dir,
            &config.name,
            &config.description,
            None,
        )
    }
}


/// 检测UEFI模式(使用 Windows API)
fn detect_uefi_mode() -> bool {
    // 检查EFI系统分区
    for letter in ['S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] {
        let efi_path = format!("{}:\\EFI\\Microsoft\\Boot", letter);
        if std::path::Path::new(&efi_path).exists() {
            return true;
        }
    }
   
    // 使用 Windows API 检测固件类型
    #[cfg(windows)]
    {
        #[link(name = "kernel32")]
        extern "system" {
            fn GetFirmwareEnvironmentVariableW(
                lpName: *const u16,
                lpGuid: *const u16,
                pBuffer: *mut u8,
                nSize: u32,
            ) -> u32;
        }


        unsafe {
            let name: Vec<u16> = "".encode_utf16().chain(std::iter::once(0)).collect();
            let guid: Vec<u16> = "{00000000-0000-0000-0000-000000000000}"
                .encode_utf16()
                .chain(std::iter::once(0))
                .collect();
            let mut buffer = [0u8; 1];


            let result = GetFirmwareEnvironmentVariableW(
                name.as_ptr(),
                guid.as_ptr(),
                buffer.as_mut_ptr(),
                buffer.len() as u32,
            );


            if result == 0 {
                let error = std::io::Error::last_os_error();
                let raw_error = error.raw_os_error().unwrap_or(0) as u32;
               
                // ERROR_INVALID_FUNCTION (1) 表示是 Legacy BIOS
                if raw_error == 1 {
                    return false;
                }
            }
            // 其他情况都认为是 UEFI
            return true;
        }
    }
   
    #[cfg(not(windows))]
    false
}


/// 生成无人值守XML (PE版本)
fn generate_unattend_xml_pe(target_partition: &str, username: &str) -> anyhow::Result<()> {
    use crate::core::system_utils::{get_file_version, get_system_architecture};
    use std::path::Path;
   
    let username = if username.is_empty() { "User" } else { username };
   
    // 检测目标系统架构
    let arch = get_system_architecture(target_partition);
    let arch_str = arch.as_unattend_str();
   
    // 通过 ntdll.dll 文件版本检测目标系统版本
    let ntdll_path = Path::new(target_partition).join("Windows").join("System32").join("ntdll.dll");
    let (is_win7, is_win8) = match get_file_version(&ntdll_path) {
        Some((major, minor, _, _)) => {
            let is_win7 = major == 6 && minor == 1;
            let is_win8 = major == 6 && (minor == 2 || minor == 3);
            (is_win7, is_win8)
        }
        None => (false, false)
    };
   
    // 根据系统版本生成不同的OOBE配置
    // Win7: 移除HideOEMRegistrationScreen(家庭版不支持)
    let oobe_section = if is_win7 {
        r#"<OOBE>
                <HideEULAPage>true</HideEULAPage>
                <ProtectYourPC>3</ProtectYourPC>
                <NetworkLocation>Home</NetworkLocation>
            </OOBE>"#
    } else if is_win8 {
        r#"<OOBE>
                <HideEULAPage>true</HideEULAPage>
                <HideLocalAccountScreen>true</HideLocalAccountScreen>
                <ProtectYourPC>3</ProtectYourPC>
                <NetworkLocation>Home</NetworkLocation>
            </OOBE>"#
    } else {
        r#"<OOBE>
                <HideEULAPage>true</HideEULAPage>
                <HideLocalAccountScreen>true</HideLocalAccountScreen>
                <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
                <ProtectYourPC>3</ProtectYourPC>
                <SkipMachineOOBE>true</SkipMachineOOBE>
                <SkipUserOOBE>true</SkipUserOOBE>
            </OOBE>"#
    };
   
    let xml_content = format!(r#"<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
    <settings pass="windowsPE">
        <component name="Microsoft-Windows-Setup" processorArchitecture="{arch}" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
            <UserData>
                <ProductKey>
                    <WillShowUI>OnError</WillShowUI>
                </ProductKey>
                <AcceptEula>true</AcceptEula>
            </UserData>
        </component>
    </settings>
    <settings pass="oobeSystem">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="{arch}" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            {oobe}
            <UserAccounts>
                <LocalAccounts>
                    <LocalAccount wcm:action="add">
                        <Password>
                            <Value></Value>
                            <PlainText>true</PlainText>
                        </Password>
                        <Description>Local User</Description>
                        <DisplayName>{user}</DisplayName>
                        <Group>Administrators</Group>
                        <n>{user}</n>
                    </LocalAccount>
                </LocalAccounts>
            </UserAccounts>
            <AutoLogon>
                <Password>
                    <Value></Value>
                    <PlainText>true</PlainText>
                </Password>
                <Enabled>true</Enabled>
                <Username>{user}</Username>
            </AutoLogon>
        </component>
    </settings>
</unattend>"#, arch = arch_str, oobe = oobe_section, user = username);


    let panther_dir = format!("{}\\Windows\\Panther", target_partition);
    std::fs::create_dir_all(&panther_dir)?;
   
    let unattend_path = format!("{}\\unattend.xml", panther_dir);
    std::fs::write(&unattend_path, &xml_content)?;
   
    Ok(())
}




/// 显示错误消息框
fn show_error_message(message: &str) {
    #[cfg(windows)]
    {
        use std::ffi::OsStr;
        use std::os::windows::ffi::OsStrExt;
        use std::ptr::null_mut;
        
        let wide_message: Vec<u16> = OsStr::new(message)
            .encode_wide()
            .chain(std::iter::once(0))
            .collect();
        let wide_title: Vec<u16> = OsStr::new("神龙科技-小弧师兄一键装机 错误")
            .encode_wide()
            .chain(std::iter::once(0))
            .collect();
        
        unsafe {
            #[link(name = "user32")]
            extern "system" {
                fn MessageBoxW(hwnd: *mut std::ffi::c_void, text: *const u16, caption: *const u16, utype: u32) -> i32;
            }
            MessageBoxW(null_mut(), wide_message.as_ptr(), wide_title.as_ptr(), 0x10); // MB_ICONERROR
        }
    }
   
    #[cfg(not(windows))]
    {
        eprintln!("错误: {}", message);
    }
}


/// 显示成功消息框
fn show_success_message(message: &str) {
    #[cfg(windows)]
    {
        use std::ffi::OsStr;
        use std::os::windows::ffi::OsStrExt;
        use std::ptr::null_mut;
        
        let wide_message: Vec<u16> = OsStr::new(message)
            .encode_wide()
            .chain(std::iter::once(0))
            .collect();
        let wide_title: Vec<u16> = OsStr::new("神龙科技-小弧师兄一键装机")
            .encode_wide()
            .chain(std::iter::once(0))
            .collect();
        
        unsafe {
            #[link(name = "user32")]
            extern "system" {
                fn MessageBoxW(hwnd: *mut std::ffi::c_void, text: *const u16, caption: *const u16, utype: u32) -> i32;
            }
            MessageBoxW(null_mut(), wide_message.as_ptr(), wide_title.as_ptr(), 0x40); // MB_ICONINFORMATION
        }
    }
   
    #[cfg(not(windows))]
    {
        println!("成功: {}", message);
    }
}


评分

参与人数 1好评 +1 精币 +2 收起 理由
andyfeifei + 1 + 2 YYDS~!

查看全部评分


结帖率:0% (0/1)

签到天数: 6 天

9
发表于 23 分钟前 | 只看该作者   江西省上饶市
这是真大神啊。
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)

签到天数: 2 天

8
 楼主| 发表于 昨天 19:36 | 只看该作者   四川省绵阳市
lxwker 发表于 2026-6-5 15:07
没有安装派森,有没有编译好的exe?

有的 在我QQ群里这里不好发  QQ群:399298372
回复 支持 反对

使用道具 举报

结帖率:80% (4/5)
7
发表于 昨天 18:21 | 只看该作者   山东省潍坊市
已经顶贴,感谢您对论坛的支持!
回复 支持 反对

使用道具 举报

签到天数: 2 天

6
发表于 昨天 15:07 | 只看该作者   湖北省孝感市
没有安装派森,有没有编译好的exe?
回复 支持 反对

使用道具 举报

结帖率:0% (0/1)
地下
发表于 昨天 14:07 | 只看该作者   湖北省十堰市
学习看看..!....
回复 支持 反对

使用道具 举报

签到天数: 3 天

地板
发表于 昨天 13:04 | 只看该作者   北京市北京市
支持一下的哈哈哈
回复 支持 反对

使用道具 举报

结帖率:96% (482/502)

签到天数: 5 天

板凳
发表于 昨天 09:22 | 只看该作者   内蒙古自治区乌海市
谢谢分享
回复 支持 反对

使用道具 举报

结帖率:0% (0/2)

签到天数: 5 天

沙发
发表于 昨天 09:12 | 只看该作者   广西壮族自治区玉林市
感谢分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表