mirror of
https://github.com/Xevion/smart-rgb.git
synced 2025-12-05 23:16:23 -06:00
Initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
14
.vscode/settings.json
vendored
Normal file
14
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"APMQUERYSUSPEND",
|
||||||
|
"appender",
|
||||||
|
"HWND",
|
||||||
|
"LPARAM",
|
||||||
|
"LRESULT",
|
||||||
|
"POWERBROADCAST",
|
||||||
|
"simplelog",
|
||||||
|
"USEDEFAULT",
|
||||||
|
"wndproc",
|
||||||
|
"WPARAM"
|
||||||
|
]
|
||||||
|
}
|
||||||
1302
Cargo.lock
generated
Normal file
1302
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
57
Cargo.toml
Normal file
57
Cargo.toml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
[package]
|
||||||
|
name = "smart-rgb"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
|
chrono = "0.4.38"
|
||||||
|
log = "0.4.21"
|
||||||
|
log4rs = "1.3.0"
|
||||||
|
openrgb = "0.1.2"
|
||||||
|
tokio = { version = "1.25.0", features = ["rt", "macros", "rt-multi-thread"] }
|
||||||
|
tokio-stream = "0.1.12"
|
||||||
|
tracing-appender = "0.2.3"
|
||||||
|
tracing-subscriber = { version = "0.2.16", features = ["env-filter"]}
|
||||||
|
windows-service = "0.7.0"
|
||||||
|
|
||||||
|
[dependencies.windows]
|
||||||
|
version = "0.56"
|
||||||
|
features = [
|
||||||
|
"Win32_System_LibraryLoader",
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_UI_WindowsAndMessaging",
|
||||||
|
"Win32_System_Power",
|
||||||
|
"Win32_System_RemoteDesktop",
|
||||||
|
"Win32_UI_Input_KeyboardAndMouse",
|
||||||
|
"Win32_Graphics_Gdi",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
"Win32_System_SystemInformation",
|
||||||
|
"Win32_System_Com",
|
||||||
|
"Win32_Security",
|
||||||
|
"Win32_System_TaskScheduler",
|
||||||
|
"Win32_System_Ole",
|
||||||
|
"Win32_System_Variant",
|
||||||
|
"Win32_System_Console",
|
||||||
|
"Win32_Security",
|
||||||
|
"UI"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies.windows-sys]
|
||||||
|
version = "0.52.0"
|
||||||
|
features = [
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_Security",
|
||||||
|
"Win32_System_Console",
|
||||||
|
"Win32_System",
|
||||||
|
"Win32_System_IO",
|
||||||
|
"Win32_Storage_FileSystem",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
"Win32_UI_WindowsAndMessaging",
|
||||||
|
"Win32_UI",
|
||||||
|
"Win32",
|
||||||
|
"Win32_Graphics_Gdi",
|
||||||
|
]
|
||||||
14
README.md
Normal file
14
README.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# smart-rgb
|
||||||
|
|
||||||
|
A personal script solution to ensure my computer's RGB lights go off when I need them to be.
|
||||||
|
|
||||||
|
- Off
|
||||||
|
- After idling during the day for more than 3 hours.
|
||||||
|
- After idling at night (past 11PM) for more than 25 minutes.
|
||||||
|
- Immediately once put into 'sleep' mode.
|
||||||
|
- On
|
||||||
|
- Upon unlock.
|
||||||
|
|
||||||
|
This script is intended to be cross-platform for **Windows 10** and **Ubuntu 22.04**.
|
||||||
|
|
||||||
|
It uses OpenRGB's server to enable/disable LEDs locally.
|
||||||
32
STORY.md
Normal file
32
STORY.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# story
|
||||||
|
|
||||||
|
I like to write a short story of a repository's development sometimes.
|
||||||
|
|
||||||
|
## Sketching and Testing
|
||||||
|
|
||||||
|
Right now, I have a rough sketch of what my software is going to need, and what it's going to do.
|
||||||
|
|
||||||
|
- I might use this Tokio framework for idling and receiving notices while processing events. It seems like overkill,
|
||||||
|
but if I plan to use an automatic configuration reader, than it'd be useful.
|
||||||
|
- I am unsure at this time how to process and log events.
|
||||||
|
- Currently, creating a Windows service might be fast, but it also seems to make development slow.
|
||||||
|
- Would supporting a separate stage Windows process be difficult? It seems like creating a service is just a bunch of boilerplate for running a process.
|
||||||
|
- The process shows up in Task Manager like normal anyways.
|
||||||
|
- I'm unsure right now how to properly abstract the sleep/lock/idle states in both Windows and Linux. This might be really hard and annoying. Uggg.
|
||||||
|
|
||||||
|
Resources:
|
||||||
|
- [Minosse - Windows Service in Rust for setting Process Affinities automatically](https://github.com/artumino/minosse/tree/master)
|
||||||
|
- windows_service [Crates.io](https://crates.io/crates/windows-service/) [Docs](https://docs.rs/windows-service/latest/windows_service/)
|
||||||
|
- [windows_rs/samples](https://github.com/microsoft/windows-rs/tree/master/crates/samples)
|
||||||
|
- [Service Control Handler Function](https://learn.microsoft.com/en-us/windows/win32/services/service-control-handler-function?redirectedfrom=MSDN)
|
||||||
|
- [Event Logging using Rust in Windows](https://www.reddit.com/r/rust/comments/15cq9qp/event_logging_using_rust_in_windows/)
|
||||||
|
- daemonize [Crates.io](https://docs.rs/daemonize/latest/daemonize/)
|
||||||
|
- [SO - How to Programatically Detect When the OS Windows Is Waking Up or Going to Sleep](https://stackoverflow.com/questions/4693689/how-to-programmatically-detect-when-the-os-windows-is-waking-up-or-going-to-sl)
|
||||||
|
- [Tauri Discussion - Power Monitor api or plugin like in electron](https://github.com/tauri-apps/tauri/issues/8968)
|
||||||
|
- [Using WinAPI in Rust to Manage Windows Services](https://friendlyuser.github.io/posts/tech/rust/Using_WinAPI_in_Rust_to_Manage_Windows_Services/)
|
||||||
|
|
||||||
|
## Service vs Window
|
||||||
|
|
||||||
|
So initial studies were pretty confusing as most of the solutions for detecting changes in lock screen or sleep mode used `Wndproc`, which is a callback installed when creating a Window; a solution that I really wasn't interested in.
|
||||||
|
|
||||||
|
On top of being complex as hell, it required hiding the window manually using special `SW_HIDE` magic, and it sounded wrong. Also, I don't think services should have windows at all.
|
||||||
196
src/main.rs
Normal file
196
src/main.rs
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
use std::ffi::OsString;
|
||||||
|
|
||||||
|
use windows_service::{
|
||||||
|
service::{ServiceAccess, ServiceErrorControl, ServiceInfo, ServiceStartType, ServiceType},
|
||||||
|
service_manager::{ServiceManager, ServiceManagerAccess},
|
||||||
|
service_control_handler::{self, ServiceControlHandlerResult},
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::{runtime::Runtime, sync::mpsc};
|
||||||
|
|
||||||
|
use tokio::sync::mpsc::UnboundedReceiver;
|
||||||
|
use windows_service::{define_windows_service, service_dispatcher};
|
||||||
|
|
||||||
|
const SERVICE_NAME: &str = "Easy RGB - Background Scheduler";
|
||||||
|
const SERVICE_DESCRIPTION: &str = "Service to apply rules to background processes";
|
||||||
|
|
||||||
|
define_windows_service!(ffi_service_main, service_main);
|
||||||
|
|
||||||
|
pub(crate) async fn rule_applier(
|
||||||
|
rule_file_path: &str,
|
||||||
|
shutdown_recv: &mut UnboundedReceiver<()>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
// let wmi_con = WMIConnection::new(COMLibrary::new()?)?;
|
||||||
|
|
||||||
|
// Apply rules to all running processes
|
||||||
|
// let running_process: Vec<WinProcess> = wmi_con.async_query().await?;
|
||||||
|
// running_process.into_iter().for_each(|process| {
|
||||||
|
// let process_info: ProcessInfo = process.into();
|
||||||
|
// rule_set.apply(&process_info)
|
||||||
|
// });
|
||||||
|
|
||||||
|
tokio::select! {
|
||||||
|
// Apply rules to new processes
|
||||||
|
// output = monitor_new_processes(&rule_set, &wmi_con) => output,
|
||||||
|
// Or wait for shutdown signal
|
||||||
|
_ = shutdown_recv.recv() => {
|
||||||
|
println!("Shutting down process monitor");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn service_main(_: Vec<OsString>) {
|
||||||
|
use windows_service::service::{ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
let (shutdown_send, mut shutdown_recv) = mpsc::unbounded_channel();
|
||||||
|
|
||||||
|
let event_handler = move |control_event| -> ServiceControlHandlerResult {
|
||||||
|
match control_event {
|
||||||
|
ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
|
||||||
|
ServiceControl::Stop => {
|
||||||
|
shutdown_send.send(()).unwrap();
|
||||||
|
ServiceControlHandlerResult::NoError
|
||||||
|
}
|
||||||
|
_ => ServiceControlHandlerResult::NotImplemented,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let status_handle = service_control_handler::register(SERVICE_NAME, event_handler).unwrap();
|
||||||
|
status_handle
|
||||||
|
.set_service_status(ServiceStatus {
|
||||||
|
service_type: ServiceType::OWN_PROCESS,
|
||||||
|
current_state: ServiceState::Running,
|
||||||
|
controls_accepted: ServiceControlAccept::STOP,
|
||||||
|
exit_code: ServiceExitCode::Win32(0),
|
||||||
|
checkpoint: 0,
|
||||||
|
wait_hint: Duration::default(),
|
||||||
|
process_id: None,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
let rules_path = args.get(2).map(|s| s.as_str()).unwrap_or("rules.json");
|
||||||
|
|
||||||
|
let error_code = if rt
|
||||||
|
.block_on(rule_applier(rules_path, &mut shutdown_recv))
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
status_handle
|
||||||
|
.set_service_status(ServiceStatus {
|
||||||
|
service_type: ServiceType::OWN_PROCESS,
|
||||||
|
current_state: ServiceState::Stopped,
|
||||||
|
controls_accepted: ServiceControlAccept::empty(),
|
||||||
|
exit_code: ServiceExitCode::Win32(error_code),
|
||||||
|
checkpoint: 0,
|
||||||
|
wait_hint: Duration::default(),
|
||||||
|
process_id: None,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn main() -> anyhow::Result<(), windows_service::Error> {
|
||||||
|
use log::{debug, info, LevelFilter};
|
||||||
|
use log4rs::{append::{console::ConsoleAppender, file::FileAppender}, config::{Appender, Logger, Root}, encode::pattern::PatternEncoder, Config};
|
||||||
|
|
||||||
|
let stdout = ConsoleAppender::builder().build();
|
||||||
|
|
||||||
|
let log_file_path = std::env::current_exe().unwrap().with_file_name("service.log");
|
||||||
|
|
||||||
|
let requests = FileAppender::builder()
|
||||||
|
.encoder(Box::new(PatternEncoder::default()))
|
||||||
|
.build(log_file_path)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let config = Config::builder()
|
||||||
|
.appender(Appender::builder().build("stdout", Box::new(stdout)))
|
||||||
|
.appender(Appender::builder().build("requests", Box::new(requests)))
|
||||||
|
.logger(Logger::builder().build("app::backend::db", LevelFilter::Debug))
|
||||||
|
.logger(Logger::builder()
|
||||||
|
.appender("requests")
|
||||||
|
.additive(false)
|
||||||
|
.build("app::requests", LevelFilter::Info))
|
||||||
|
.build(Root::builder().appender("stdout").appender("requests").build(LevelFilter::Trace))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let handle = log4rs::init_config(config).unwrap();
|
||||||
|
|
||||||
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
let command = args.get(1);
|
||||||
|
|
||||||
|
debug!("Service control executed with args: {:?}", args);
|
||||||
|
|
||||||
|
if let Some(command) = command {
|
||||||
|
match command.as_str() {
|
||||||
|
"install" => {
|
||||||
|
install_service(args.get(2).map(|s| s.as_str()))?;
|
||||||
|
info!("Service installed");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
"uninstall" => {
|
||||||
|
uninstall_service()?;
|
||||||
|
info!("Service uninstalled");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
"run" => {
|
||||||
|
info!("Running service (nil)");
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
info!("Unknown command");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Starting service");
|
||||||
|
match service_dispatcher::start(SERVICE_NAME, ffi_service_main) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error starting service: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn install_service(rules_path: Option<&str>) -> windows_service::Result<()> {
|
||||||
|
let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE;
|
||||||
|
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
|
||||||
|
let service_binary_path = ::std::env::current_exe().unwrap();
|
||||||
|
|
||||||
|
let service_info = ServiceInfo {
|
||||||
|
name: SERVICE_NAME.into(),
|
||||||
|
display_name: SERVICE_NAME.into(),
|
||||||
|
service_type: ServiceType::OWN_PROCESS,
|
||||||
|
start_type: ServiceStartType::AutoStart,
|
||||||
|
error_control: ServiceErrorControl::Normal,
|
||||||
|
executable_path: service_binary_path,
|
||||||
|
launch_arguments: vec!["run".into()],
|
||||||
|
dependencies: vec![],
|
||||||
|
account_name: None, // run as System
|
||||||
|
account_password: None,
|
||||||
|
};
|
||||||
|
let service = service_manager.create_service(&service_info, ServiceAccess::CHANGE_CONFIG)?;
|
||||||
|
service.set_description(SERVICE_DESCRIPTION)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn uninstall_service() -> windows_service::Result<()> {
|
||||||
|
let manager_access = ServiceManagerAccess::CONNECT;
|
||||||
|
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
|
||||||
|
let service = service_manager.open_service(SERVICE_NAME, ServiceAccess::DELETE)?;
|
||||||
|
service.delete()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
88
src/main.rs.bad
Normal file
88
src/main.rs.bad
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#![windows_subsystem = "windows"]
|
||||||
|
|
||||||
|
use windows_sys::Win32::{
|
||||||
|
Foundation::{HWND, LRESULT},
|
||||||
|
Graphics::Gdi::{BeginPaint, EndPaint, FillRect, COLOR_WINDOW, HBRUSH, PAINTSTRUCT},
|
||||||
|
UI::WindowsAndMessaging::{
|
||||||
|
CreateWindowExA, DefWindowProcA, DispatchMessageA, GetMessageA, PostQuitMessage,
|
||||||
|
RegisterClassA, ShowWindow, TranslateMessage, CW_USEDEFAULT, MSG, SW_NORMAL, WM_DESTROY,
|
||||||
|
WM_PAINT, WNDCLASSA, WS_OVERLAPPED,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// use windows::Win32::{
|
||||||
|
// Foundation::{HWND, LRESULT},
|
||||||
|
// Graphics::Gdi::{BeginPaint, EndPaint, FillRect, COLOR_WINDOW, PAINTSTRUCT},
|
||||||
|
// UI::WindowsAndMessaging::{
|
||||||
|
// CreateWindowExA, DefWindowProcA, DispatchMessageA, GetMessageA, PostQuitMessage,
|
||||||
|
// RegisterClassA, ShowWindow, TranslateMessage, CW_USEDEFAULT, SW_NORMAL, WS_OVERLAPPED,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
unsafe extern "system" fn wndproc(hwnd: HWND, msg: u32, wparam: usize, lparam: isize) -> LRESULT {
|
||||||
|
match msg {
|
||||||
|
WM_DESTROY => {
|
||||||
|
PostQuitMessage(0);
|
||||||
|
0
|
||||||
|
}
|
||||||
|
WM_PAINT => {
|
||||||
|
let mut ps: PAINTSTRUCT = std::mem::zeroed();
|
||||||
|
let hdc = BeginPaint(hwnd, &mut ps);
|
||||||
|
FillRect(hdc, &ps.rcPaint, (COLOR_WINDOW + 1) as HBRUSH);
|
||||||
|
EndPaint(hwnd, &ps);
|
||||||
|
0
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("msg: {}", msg);
|
||||||
|
DefWindowProcA(hwnd, msg, wparam, lparam)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn create_window() -> HWND {
|
||||||
|
let class_name = b"gdi\0";
|
||||||
|
let wc = WNDCLASSA {
|
||||||
|
style: 0,
|
||||||
|
lpfnWndProc: Some(wndproc),
|
||||||
|
cbClsExtra: 0,
|
||||||
|
cbWndExtra: 0,
|
||||||
|
hInstance: 0,
|
||||||
|
hIcon: 0,
|
||||||
|
hCursor: 0,
|
||||||
|
hbrBackground: 0,
|
||||||
|
lpszMenuName: std::ptr::null(),
|
||||||
|
lpszClassName: class_name.as_ptr(),
|
||||||
|
};
|
||||||
|
RegisterClassA(&wc);
|
||||||
|
|
||||||
|
let hwnd = CreateWindowExA(
|
||||||
|
0,
|
||||||
|
class_name.as_ptr(),
|
||||||
|
b"title\0".as_ptr(),
|
||||||
|
WS_OVERLAPPED,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
400,
|
||||||
|
300,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
std::ptr::null(),
|
||||||
|
);
|
||||||
|
if hwnd == 0 {
|
||||||
|
panic!("create failed");
|
||||||
|
}
|
||||||
|
ShowWindow(hwnd, windows_sys::Win32::UI::WindowsAndMessaging::SW_HIDE);
|
||||||
|
hwnd
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
create_window();
|
||||||
|
let mut msg: MSG = std::mem::zeroed();
|
||||||
|
while GetMessageA(&mut msg, 0, 0, 0) > 0 {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessageA(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
93
src/main.rs.disabled2
Normal file
93
src/main.rs.disabled2
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
use windows::Win32::Foundation::LRESULT;
|
||||||
|
use windows::Win32::{
|
||||||
|
Foundation::{HWND, LPARAM, WPARAM},
|
||||||
|
System::Power::POWERBROADCAST_SETTING,
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::LevelFilter;
|
||||||
|
use log4rs::append::console::ConsoleAppender;
|
||||||
|
use log4rs::append::file::FileAppender;
|
||||||
|
use log4rs::encode::pattern::PatternEncoder;
|
||||||
|
use log4rs::config::{Appender, Config, Logger, Root};
|
||||||
|
use std::{thread::sleep, time::Duration};
|
||||||
|
use windows::Win32::UI::WindowsAndMessaging::DefWindowProcA;
|
||||||
|
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
unsafe extern "system" fn wndproc(
|
||||||
|
window: HWND,
|
||||||
|
message: u32,
|
||||||
|
wparam: WPARAM,
|
||||||
|
lparam: LPARAM,
|
||||||
|
) -> LRESULT {
|
||||||
|
|
||||||
|
match message {
|
||||||
|
PBT_APMQUERYSUSPEND => {
|
||||||
|
debug!("PBT_APMQUERYSUSPEND");
|
||||||
|
LRESULT(0)
|
||||||
|
}
|
||||||
|
WM_POWERBROADCAST => {
|
||||||
|
debug!("WM_POWERBROADCAST: {:?} - {:?}", wparam, lparam);
|
||||||
|
if wparam == WPARAM(32787) {
|
||||||
|
let st: &mut POWERBROADCAST_SETTING =
|
||||||
|
&mut *(lparam.0 as *mut POWERBROADCAST_SETTING);
|
||||||
|
|
||||||
|
debug!("Power Setting: {:?}", st.PowerSetting);
|
||||||
|
// let guid = GUID::from(MONITOR_GUID);
|
||||||
|
// if st.PowerSetting == guid && st.Data == [0] {
|
||||||
|
// thread::spawn(|| send_mixed_input);
|
||||||
|
// let _ = registry_ops::RegistrySetting::new(
|
||||||
|
// ®istry_ops::RegistryEntries::LastRobotInput,
|
||||||
|
// )
|
||||||
|
// .set_registry_data(®istry_ops::get_current_time());
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
LRESULT(0)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
debug!("{} - {:?} - {:?}", message, wparam, lparam);
|
||||||
|
DefWindowProcA(window, message, wparam, lparam)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn main() -> () {
|
||||||
|
// Wait forever
|
||||||
|
let stdout = ConsoleAppender::builder().build();
|
||||||
|
|
||||||
|
let requests = FileAppender::builder()
|
||||||
|
.encoder(Box::new(PatternEncoder::new("{d} - {m}{n}")))
|
||||||
|
.build("log/requests.log")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let config = Config::builder()
|
||||||
|
.appender(Appender::builder().build("stdout", Box::new(stdout)))
|
||||||
|
.appender(Appender::builder().build("requests", Box::new(requests)))
|
||||||
|
.logger(Logger::builder().build("app::backend::db", LevelFilter::Debug))
|
||||||
|
.logger(Logger::builder()
|
||||||
|
.appender("requests")
|
||||||
|
.additive(false)
|
||||||
|
.build("app::requests", LevelFilter::Info))
|
||||||
|
.build(Root::builder().appender("stdout").build(LevelFilter::Trace))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let handle = log4rs::init_config(config).unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
loop {
|
||||||
|
sleep(Duration::from_secs(1000));
|
||||||
|
debug!("Hello, Windows!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// use windows::Win32::UI::WindowsAndMessaging::{MessageBoxA, MB_OK};
|
||||||
|
// let _ = unsafe { MessageBoxA(
|
||||||
|
// None,
|
||||||
|
// "Hello, Windows!",
|
||||||
|
// "Hello, Windows!",
|
||||||
|
// MB_OK,
|
||||||
|
// ) };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user