Как правильно реагировать на типы regvaule из winreg crate? - PullRequest
1 голос
/ 08 января 2020

Я застрял в следующей проблеме. Чтобы правильно сохранить некоторые значения, мне нужно знать, что это за значение. Строка или целое число.

В данный момент мой код не очень пригоден для повторного использования, потому что мне нужно заранее знать, какое это значение.

Было бы очень полезно получить некоторые подсказки о том, как Сделай это лучше.

extern crate winreg;

use winreg::enums::{HKEY_LOCAL_MACHINE, KEY_READ};
use std::fs::File;
use std::io::prelude::*;

fn regreadvalue_string (regpath: &str, regvalue: &str, mut inifile: &std::fs::File) {
    let hklm = winreg::RegKey::predef(HKEY_LOCAL_MACHINE);

    let subkey = hklm.open_subkey_with_flags(regpath, KEY_READ);

    match subkey {
        Ok(subkey) => {
            let thevalue: String = subkey.get_value(regvalue).unwrap_or_default();
            let iniline: String = format!("{}\\{}={}\n", regpath, regvalue, thevalue);
            let binaryiniline = iniline.as_bytes();
            inifile.write_all(binaryiniline).expect("could not write line");
            },
        Err(_error) => {
            let iniline: String = format!("{}\\{}={}\n", regpath, regvalue, "");
            let binaryiniline = iniline.as_bytes();
            inifile.write_all(binaryiniline).expect("could not write line");
            },
        };
    }
fn regreadvalue_int (regpath: &str, regvalue: &str, mut inifile: &std::fs::File) {
        let hklm = winreg::RegKey::predef(HKEY_LOCAL_MACHINE);

        let subkey = hklm.open_subkey_with_flags(regpath, KEY_READ);

        match subkey {
            Ok(subkey) => {
                let thevalue: u32 = subkey.get_value(regvalue).unwrap_or_default();
                let iniline: String = format!("{}\\{}={}\n", regpath, regvalue, thevalue);
                let binaryiniline = iniline.as_bytes();
                inifile.write_all(binaryiniline).expect("could not write line");
                },
            Err(_error) => {
                let iniline: String = format!("{}\\{}={}\n", regpath, regvalue, "");
                let binaryiniline = iniline.as_bytes();
                inifile.write_all(binaryiniline).expect("could not write line");
                },
            };
        }


fn main() -> std::io::Result<()> {

    let mut inifile = File::create("output.ini")?;
    inifile.write_all(b"[FileInfo]\n")?;
    inifile.write_all(b"Version=1\n")?;
    inifile.write_all(b"[Machine]\n")?;
    regreadvalue_string(r#"SOFTWARE\Microsoft\Windows NT\CurrentVersion"#, "ProductName", &inifile);
    regreadvalue_string(r#"SOFTWARE\Microsoft\Windows NT\CurrentVersion"#, "CurrentVersion", &inifile);
    regreadvalue_string(r#"SOFTWARE\Microsoft\Windows NT\CurrentVersion"#, "EditionID", &inifile);
    regreadvalue_string(r#"SOFTWARE\Microsoft\Windows NT\CurrentVersion"#, "ReleaseId", &inifile);
    regreadvalue_string(r#"SOFTWARE\Microsoft\Cryptography"#, "MachineGuid", &inifile);
    regreadvalue_string(r#"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName"#, "ComputerName", &inifile);
    regreadvalue_string(r#"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"#, "Domain", &inifile);
    regreadvalue_string(r#"SYSTEM\ControlSet001\Control\SystemInformation"#, "ComputerHardwareId", &inifile);
    regreadvalue_string(r#"SYSTEM\ControlSet001\Control\SystemInformation"#, "SystemManufacturer", &inifile);
    regreadvalue_string(r#"SYSTEM\ControlSet001\Control\SystemInformation"#, "SystemProductName", &inifile);
    regreadvalue_string(r#"SYSTEM\ControlSet001\Control\SystemInformation"#, "BIOSVersion", &inifile);
    regreadvalue_string(r#"SYSTEM\ControlSet001\Control\SystemInformation"#, "BIOSReleaseDate", &inifile);
    regreadvalue_int(r#"SYSTEM\HardwareConfig\Current"#, "EnclosureType", &inifile);

    Ok(())
}

1 Ответ

0 голосов
/ 08 января 2020

Вы можете использовать winreg::RegKey::get_raw_value API, чтобы получить необработанное значение реестра и отформатировать его самостоятельно в соответствии с его типом:

use std::io::prelude::*;
use winreg::{
    enums::{RegType, HKEY_LOCAL_MACHINE, KEY_READ},
    types::FromRegValue,
    RegValue,
};

fn display_reg_value(rv: &RegValue) -> String {
    match rv.vtype {
        RegType::REG_SZ | RegType::REG_EXPAND_SZ | RegType::REG_MULTI_SZ => {
            String::from_reg_value(rv).unwrap_or_default()
        }
        RegType::REG_DWORD => u32::from_reg_value(rv).unwrap_or_default().to_string(),
        RegType::REG_QWORD => u64::from_reg_value(rv).unwrap_or_default().to_string(),
        _ => panic!("can only process reg value of type string, u32 or u64"),
    }
}

fn regreadvalue(regpath: &str, regvalue: &str, mut inifile: &std::fs::File) {
    let hklm = winreg::RegKey::predef(HKEY_LOCAL_MACHINE);
    let subkey = hklm.open_subkey_with_flags(regpath, KEY_READ);
    let thevalue = match subkey {
        Ok(subkey) => {
            let v = subkey.get_raw_value(regvalue).unwrap();
            display_reg_value(&v)
        }
        Err(_) => "".to_string(),
    };
    let iniline = format!("{}\\{}={}\n", regpath, regvalue, thevalue);
    let binaryiniline = iniline.as_bytes();
    inifile
        .write_all(binaryiniline)
        .expect("could not write line");
}

Обратите внимание, что я не делаю Windows. Таким образом, код может содержать небольшие ошибки, но вы поняли идею. Это действительно недостаток winreg ящика: он должен был реализовать черту Display для своего типа RegValue.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...