Open6
Rust初心者がRustでWindowsレジストリを操作するまで
レジストリ操作までの第一歩
Windows APIをコールできるクレートがあるようだ。
まずは、このクレートを追加する。
クレートを追加したが、windows::Win32::System::Registry以下、そもそもWin32すらインポートできない状況が続いた。
調べてみると、ビルド時間を短縮するために使用するfeaturesフラグを選択し、条件付きコンパイルを行うようだ。
必要なfeaturesはwindows-docs-rsには書いておらず、以下のぺージで検索できる。
今回は、Registry周りをいじりたいので、以下のようにした。
Cargo.toml
[dependencies.windows]
version = "0.59.*"
features = [
"Win32_System_Registry",
]
無事赤線が消えた。ヤッター
実際に使用する関数・定数等を探すため、ドキュメントを読んでいたが、説明が全く書かれていない。
適当な関数名でWeb検索をかけるとC++でのドキュメントを見つけた。
恐らくここを参考にすればいけるんじゃないかな...
C++でのレジストリ操作を行うチュートリアルを見つけた。助かる。
まずはレジストリの値(パス)を読み取る。
registry値読み取りに使用したwindowsクレートの関数はRegOpenKeyExA
とRegQueryValueExA
(RegGetValue
でもよかったっぽい)
こんなコードになった
read
use windows::{
core::PCSTR,
Win32::System::Registry::*,
Win32::Foundation::ERROR_SUCCESS
};
use std::ffi::CString;
fn get_registry_val(subkey_puth:String, value_name:String) -> Option<String> {
let hkey: HKEY = HKEY_CURRENT_USER;
let subkey_cstring = CString::new(subkey_puth).unwrap(); // NULL 終端が必要
let subkey = PCSTR(subkey_cstring.as_ptr() as _);
let valuename_cstring = CString::new(value_name).unwrap();
let valuename = PCSTR(valuename_cstring.as_ptr() as _);
let mut buffer = [0u8; 256];
let mut bufsize = buffer.len() as u32;
unsafe {
let mut hsubkey = HKEY::default();
let open_result = RegOpenKeyExA(hkey, subkey, Some(0), KEY_READ, &mut hsubkey);
if open_result == ERROR_SUCCESS {
let query_result = RegQueryValueExA(hsubkey, valuename, None, None, Some(buffer.as_mut_ptr()), Some(&mut bufsize));
if query_result == ERROR_SUCCESS {
let value = String::from_utf8_lossy(&buffer[..(bufsize as usize - 1)]);
let value_string = value.to_string();
println!("InstallPath: {}", value_string);
return Some(value_string);
} else {
eprintln!("RegQueryValueExA failed with error code: {:?}", query_result);
}
let close_result = RegCloseKey(hsubkey);
if close_result != ERROR_SUCCESS {
eprintln!("Failed to close registry key: {:?}", close_result);
}
} else {
eprintln!("RegOpenKeyExA failed with error code: {:?}", open_result);
}
}
return None;
}
読み取りの問題で、日本語は文字化けしてしまう。とはいえ、英語のみのパスを使用すればよいので一旦はこれで良し。(文字化け対処できるのであれば教えて欲しいです!)
同様に、書き込みを行う関数を作成する。
使用するwindowsクレートの関数はRegSetKeyValueA
write
#[tauri::command]
fn get_registry_val(subkey_puth:String, value_name:String) -> Option<String> {
let hkey: HKEY = HKEY_CURRENT_USER; // HKEY_CURRENT_USER(0x80000001) ユーザーのルートキー
let subkey_cstring = CString::new(subkey_puth).unwrap(); // NULL 終端が必要
let subkey = PCSTR(subkey_cstring.as_ptr() as _); // PCSTR に変換 指定のキーへのパス
let valuename_cstring = CString::new(value_name).unwrap(); // NULL 終端が必要
let valuename = PCSTR(valuename_cstring.as_ptr() as _); // PCSTR に変換 指定の値の名前
let mut buffer = [0u8; 256]; // バッファ
let mut bufsize = buffer.len() as u32;
unsafe {
let mut hsubkey = HKEY::default(); // サブキーのハンドル
// サブキーを開く
let open_result = RegOpenKeyExA(hkey, subkey, Some(0), KEY_READ, &mut hsubkey);
if open_result == ERROR_SUCCESS {
// サブキーが開けたら値を取得
let query_result = RegQueryValueExA(hsubkey, valuename, None, None, Some(buffer.as_mut_ptr()), Some(&mut bufsize));
if query_result == ERROR_SUCCESS {
// バッファから文字列を取得
let value = String::from_utf8_lossy(&buffer[..(bufsize as usize - 1)]);
let value_string = value.to_string();
println!("InstallPath: {}", value_string);
return Some(value_string);
} else {
eprintln!("RegQueryValueExA failed with error code: {:?}", query_result);
}
// サブキーを閉じる(重要)
let close_result = RegCloseKey(hsubkey);
if close_result != ERROR_SUCCESS {
eprintln!("Failed to close registry key: {:?}", close_result);
}
} else {
eprintln!("RegOpenKeyExA failed with error code: {:?}", open_result);
}
}
return None;
}