Show HN: a Rust Crate for the Modern macOS SMAppService API
4 days ago
2
A Rust wrapper for macOS's ServiceManagement framework, specifically the SMAppService API. This library provides a safe and idiomatic Rust interface for registering and managing macOS services.
The ServiceManagement framework in macOS provides a way for applications to manage system services. This library wraps the objc2-service-management API in a Rust-friendly interface, allowing to:
Register applications as login items
Register and manage launch agents and daemons from the application bundle
Check the status of registered services
Open the System Settings Login Items panel
macOS 13.0 (Ventura) or later
cargo add smappservice-rs
Register the Main Application as a Login Item
use smappservice_rs::{AppService,ServiceType};let app_service = AppService::new(ServiceType::MainApp);match app_service.register(){Ok(()) => println!("Application registered successfully as login item!"),Err(e) => eprintln!("Failed to register application: {}", e),}
Check Registration Status
use smappservice_rs::{AppService,ServiceType,ServiceStatus};let app_service = AppService::new(ServiceType::MainApp);let status = app_service.status();println!("Service status: {}", status);if status == ServiceStatus::RequiresApproval{println!("Please approve the service in System Settings");AppService::open_system_settings_login_items();}
use smappservice_rs::{AppService,ServiceType};let agent_service = AppService::new(ServiceType::Agent{plist_name:"com.example.myapp.agent.plist"});ifletErr(e) = agent_service.register(){eprintln!("Failed to register agent: {}", e);}
use smappservice_rs::{AppService,ServiceType};let daemon_service = AppService::new(ServiceType::Daemon{plist_name:"com.example.myapp.daemon.plist"});ifletErr(e) = daemon_service.register(){eprintln!("Failed to register daemon: {}", e);}
Register a Helper Application as a Login Item
use smappservice_rs::{AppService,ServiceType};let login_item = AppService::new(ServiceType::LoginItem{identifier:"com.example.helper"});ifletErr(e) = login_item.register(){eprintln!("Failed to register login item: {}", e);}
use smappservice_rs::{AppService,ServiceType};let app_service = AppService::new(ServiceType::MainApp);match app_service.unregister(){Ok(()) => println!("Application unregistered successfully!"),Err(e) => eprintln!("Failed to unregister application: {}", e),}
Due to the nature of the ServiceManagement framework, testing is primarily done through integration tests. The tests are located in the integration_tests directory and cover various service types.
This project is licensed under the MIT License - see the LICENSE.md file for details.
Contributions are welcome! Please feel free to submit a Pull Request or open an Issue.