100 releases (19 breaking)
Uses new Rust 2024
new 0.19.2 | May 23, 2025 |
---|---|
0.18.4 | May 16, 2025 |
0.17.3 | Mar 29, 2025 |
0.13.4 | Dec 10, 2024 |
0.0.2 | Mar 3, 2022 |
#18 in Windows APIs
4,740 downloads per month
Used in amscrapper-rs
445KB
9K
SLoC
Rust for windows uiautomation
The uiatomation-rs
crate is a wrapper for windows uiautomation. This crate can help you make windows uiautoamtion API calls conveniently.
Usages
Start by adding the dependency of this crate to your Cargo.toml file. Make use of any windows uiautomation calls as needed.
Features
Supported Features
Feature | Description | Default |
---|---|---|
process |
Support process operations and filter by process id | False |
dialog |
Enable message boxes to show message | False |
input |
Support keyboard inputs | True |
pattern |
Support Microsoft UI Automation control patterns | - |
control |
Enable to wrapper ui element as control to simplify operations | True |
event |
Support Microsoft UI Automation events | False |
log |
Use log crate to print debug message | False |
all |
Enable all the above features | False |
pattern
is a feature thatcontrol
depends on.
Default Features
input
,control
,pattern
(introduced by thecontrol
dependency)
In order to be compatible with the version before
v0.19.0
, you should addprocess
,dialog
andevent
features.
Examples
Print All UIElements
use uiautomation::Result;
use uiautomation::UIAutomation;
use uiautomation::UIElement;
use uiautomation::UITreeWalker;
fn main() {
let automation = UIAutomation::new().unwrap();
let walker = automation.get_control_view_walker().unwrap();
let root = automation.get_root_element().unwrap();
print_element(&walker, &root, 0).unwrap();
}
fn print_element(walker: &UITreeWalker, element: &UIElement, level: usize) -> Result<()> {
for _ in 0..level {
print!(" ")
}
println!("{} - {}", element.get_classname()?, element.get_name()?);
if let Ok(child) = walker.get_first_child(&element) {
print_element(walker, &child, level + 1)?;
let mut next = child;
while let Ok(sibling) = walker.get_next_sibling(&next) {
print_element(walker, &sibling, level + 1)?;
next = sibling;
}
}
Ok(())
}
Open Notepad and Input Text
use uiautomation::core::UIAutomation;
use uiautomation::processes::Process;
fn main() {
Process::create("notepad.exe").unwrap();
let automation = UIAutomation::new().unwrap();
let root = automation.get_root_element().unwrap();
let matcher = automation.create_matcher().from(root).timeout(10000).classname("Notepad");
if let Ok(notepad) = matcher.find_first() {
println!("Found: {} - {}", notepad.get_name().unwrap(), notepad.get_classname().unwrap());
notepad.send_keys("Hello,Rust UIAutomation!{enter}", 10).unwrap();
let window: WindowControl = notepad.try_into().unwrap();
window.maximize().unwrap();
}
}
Get Properties As Variant
use uiautomation::UIAutomation;
use uiautomation::types::UIProperty;
use uiautomation::variants::Variant;
fn main() {
let automation = UIAutomation::new().unwrap();
let root = automation.get_root_element().unwrap();
let name: Variant = root.get_property_value(UIProperty::Name).unwrap();
println!("name = {}", name.get_string().unwrap());
let ctrl_type: Variant = root.get_property_value(UIProperty::ControlType).unwrap();
let ctrl_type_id: i32 = ctrl_type.try_into().unwrap();
println!("control type = {}", ctrl_type_id);
let enabled: Variant = root.get_property_value(UIProperty::IsEnabled).unwrap();
let enabled_str: String = enabled.try_into().unwrap();
println!("enabled = {}", enabled_str);
}
Simulate Keyboard Input
use uiautomation::core::UIAutomation;
fn main() {
let automation = UIAutomation::new().unwrap();
let root = automation.get_root_element().unwrap();
root.send_keys("{Win}D", 10).unwrap();
}
Add Event Handler
struct MyFocusChangedEventHandler{}
impl CustomFocusChangedEventHandler for MyFocusChangedEventHandler {
fn handle(&self, sender: &uiautomation::UIElement) -> uiautomation::Result<()> {
println!("Focus changed: {}", sender);
Ok(())
}
}
fn main() {
let note_proc = Process::create("notepad.exe").unwrap();
let automation = UIAutomation::new().unwrap();
let root = automation.get_root_element().unwrap();
let matcher = automation.create_matcher().from(root).timeout(10000).classname("Notepad");
if let Ok(notepad) = matcher.find_first() {
let focus_changed_handler = MyFocusChangedEventHandler {};
let focus_changed_handler = UIFocusChangedEventHandler::from(focus_changed_handler);
automation.add_focus_changed_event_handler(None, &focus_changed_handler).unwrap();
let text_changed_handler: Box<CustomPropertyChangedEventHandlerFn> = Box::new(|sender, property, value| {
println!("Property changed: {}.{:?} = {}", sender, property, value);
Ok(())
});
let text_changed_handler = UIPropertyChangedEventHandler::from(text_changed_handler);
automation.add_property_changed_event_handler(¬epad, uiautomation::types::TreeScope::Subtree, None, &text_changed_handler, &[UIProperty::ValueValue]).unwrap();
}
println!("waiting for notepad.exe...");
note_proc.wait().unwrap();
}
Dependencies
~127MB
~2M SLoC