win,linux remove desktop wallpaper

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages
2023-10-11 19:03:34 +08:00
parent 1be5f2d647
commit d3ce8203be
45 changed files with 453 additions and 45 deletions

View File

@@ -14,6 +14,7 @@ use hbb_common::{
message_proto::Resolution,
sleep, timeout, tokio,
};
use std::process::{Command, Stdio};
use std::{
collections::HashMap,
ffi::OsString,
@@ -26,6 +27,7 @@ use std::{
sync::{atomic::Ordering, Arc, Mutex},
time::{Duration, Instant},
};
use wallpaper;
use winapi::{
ctypes::c_void,
shared::{minwindef::*, ntdef::NULL, windef::*, winerror::*},
@@ -2335,3 +2337,98 @@ fn get_license() -> Option<License> {
}
Some(lic)
}
fn get_sid_of_user(username: &str) -> ResultType<String> {
let mut output = Command::new("wmic")
.args(&[
"useraccount",
"where",
&format!("name='{}'", username),
"get",
"sid",
"/value",
])
.creation_flags(CREATE_NO_WINDOW)
.stdout(Stdio::piped())
.spawn()?
.stdout
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to open stdout"))?;
let mut result = String::new();
output.read_to_string(&mut result)?;
let sid_start_index = result
.find('=')
.map(|i| i + 1)
.ok_or(anyhow!("bad output format"))?;
if sid_start_index > 0 && sid_start_index < result.len() + 1 {
Ok(result[sid_start_index..].trim().to_string())
} else {
bail!("bad output format");
}
}
pub struct WallPaperRemover {
old_path: String,
}
impl WallPaperRemover {
pub fn new() -> ResultType<Self> {
let start = std::time::Instant::now();
if !Self::need_remove() {
bail!("already solid color");
}
let old_path = match Self::get_recent_wallpaper() {
Ok(old_path) => old_path,
Err(e) => {
log::info!("Failed to get recent wallpaper:{:?}, use fallback", e);
wallpaper::get().map_err(|e| anyhow!(e.to_string()))?
}
};
Self::set_wallpaper(None)?;
log::info!(
"created wallpaper remover, old_path:{:?}, elapsed:{:?}",
old_path,
start.elapsed(),
);
Ok(Self { old_path })
}
fn get_recent_wallpaper() -> ResultType<String> {
// SystemParametersInfoW may return %appdata%\Microsoft\Windows\Themes\TranscodedWallpaper, not real path and may not real cache
// https://www.makeuseof.com/find-desktop-wallpapers-file-location-windows-11/
// https://superuser.com/questions/1218413/write-to-current-users-registry-through-a-different-admin-account
let (hkcu, sid) = if is_root() {
let username = get_active_username();
let sid = get_sid_of_user(&username)?;
log::info!("username:{username}, sid:{sid}");
(RegKey::predef(HKEY_USERS), format!("{}\\", sid))
} else {
(RegKey::predef(HKEY_CURRENT_USER), "".to_string())
};
let explorer_key = hkcu.open_subkey_with_flags(
&format!(
"{}Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Wallpapers",
sid
),
KEY_READ,
)?;
Ok(explorer_key.get_value("BackgroundHistoryPath0")?)
}
fn need_remove() -> bool {
if let Ok(wallpaper) = wallpaper::get() {
return !wallpaper.is_empty();
}
false
}
fn set_wallpaper(path: Option<String>) -> ResultType<()> {
wallpaper::set_from_path(&path.unwrap_or_default()).map_err(|e| anyhow!(e.to_string()))
}
}
impl Drop for WallPaperRemover {
fn drop(&mut self) {
// If the old background is a slideshow, it will be converted into an image. AnyDesk does the same.
allow_err!(Self::set_wallpaper(Some(self.old_path.clone())));
}
}