Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 42 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ A universal event automation system for Windows built in Rust. Monitor file syst

```bash
# Clone the repository
git clone https://github.com/yourusername/win_event_engine.git
git clone https://github.com/stylebending/win_event_engine.git
cd win_event_engine

# Build in release mode
Expand Down Expand Up @@ -78,9 +78,15 @@ cargo run -p engine -- --dry-run

# Disable hot-reloading (enabled by default)
cargo run -p engine -- --no-watch

# Install as Windows Service (requires admin)
cargo run -p engine -- --install

# Uninstall Windows Service (requires admin)
cargo run -p engine -- --uninstall
```

## Configuration
## Windows Service

Create a `config.toml` file in the project root:

Expand Down Expand Up @@ -168,11 +174,44 @@ Options:
--dry-run Run in dry-run mode (don't execute actions)
-l, --log-level <LEVEL> Log level (debug, info, warn, error) [default: info]
--no-watch Disable hot-reloading of configuration
--install Install as Windows Service (requires admin)
--uninstall Uninstall Windows Service (requires admin)
--run-service Internal: run as Windows Service
--status Show engine status and exit
-h, --help Print help
-V, --version Print version
```

## Windows Service

The engine can run as a Windows Service for production deployments.

### Installation

```bash
# Install the service (requires admin)
engine.exe --install

# Start the service
sc start WinEventEngine
```

### Configuration

When running as a service:
- Config location: `%PROGRAMDATA%\win_event_engine\config\config.toml`
- Log location: `%PROGRAMDATA%\win_event_engine\logs\service.log`

### Uninstallation

```bash
# Stop the service first
sc stop WinEventEngine

# Uninstall the service
engine.exe --uninstall
```

## Architecture

```
Expand Down Expand Up @@ -372,7 +411,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
- [x] CLI interface
- [x] Rule engine
- [x] Configuration hot-reloading
- [ ] Windows service wrapper
- [x] Windows service wrapper
- [ ] Web dashboard
- [ ] Metrics and monitoring
- [ ] Plugin system for custom actions
Expand Down
9 changes: 7 additions & 2 deletions engine/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
[package]
name = "engine"
version = "0.1.1"
version = "0.1.2"
edition = "2024"

[[bin]]
name = "engine"
path = "src/main.rs"

[dependencies]
tokio = { version = "1", features = ["full"] }
uuid = { version = "1", features = ["v4"] }
Expand All @@ -14,7 +18,8 @@ tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["fmt"] }
notify = "6"
clap = { version = "4", features = ["derive"] }
windows = { version = "0.52", features = ["Win32_Foundation", "Win32_UI_WindowsAndMessaging", "Win32_UI_Accessibility", "Win32_System_Threading", "Win32_System_ProcessStatus", "Win32_System_Registry", "Win32_Security"] }
windows = { version = "0.52", features = ["Win32_Foundation", "Win32_UI_WindowsAndMessaging", "Win32_UI_Accessibility", "Win32_System_Threading", "Win32_System_ProcessStatus", "Win32_System_Registry", "Win32_System_Services", "Win32_Security"] }
windows-service = "0.8"

engine_core = { path = "../engine_core" }
bus = { path = "../bus" }
Expand Down
62 changes: 62 additions & 0 deletions engine/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod config;
mod engine;
mod plugins;
mod service;

#[cfg(test)]
mod integration_tests;
Expand Down Expand Up @@ -38,6 +39,18 @@ struct Cli {
/// Disable hot-reloading of configuration
#[arg(long)]
no_watch: bool,

/// Install as Windows Service (requires admin)
#[arg(long)]
install: bool,

/// Uninstall Windows Service (requires admin)
#[arg(long)]
uninstall: bool,

/// Run as Windows Service (internal - called by SCM)
#[arg(long)]
run_service: bool,
}

#[tokio::main]
Expand All @@ -63,6 +76,55 @@ async fn main() {
env!("CARGO_PKG_VERSION")
);

// Handle service install/uninstall commands
if cli.install || cli.uninstall {
match service::ServiceManagerHandle::new() {
Ok(manager) => {
if cli.install {
let exe_path = std::env::current_exe()
.map_err(|e| format!("Failed to get executable path: {}", e))
.unwrap_or_else(|e| {
error!("{}", e);
std::process::exit(1);
});
match manager.install(exe_path.to_str().unwrap_or("")) {
Ok(_) => {
println!("Service installed successfully.");
println!(
"Use 'sc start WinEventEngine' or the Services control panel to start."
);
}
Err(e) => {
error!("Failed to install service: {}", e);
std::process::exit(1);
}
}
} else if cli.uninstall {
match manager.uninstall() {
Ok(_) => {
println!("Service uninstalled successfully.");
}
Err(e) => {
error!("Failed to uninstall service: {}", e);
std::process::exit(1);
}
}
}
}
Err(e) => {
error!("Failed to connect to Service Control Manager: {}", e);
std::process::exit(1);
}
}
return;
}

// Run as Windows Service if --run-service flag is provided
if cli.run_service {
service::run_service();
return;
}

// Determine config path for hot-reloading
let config_path = if let Some(ref path) = cli.config {
Some(path.clone())
Expand Down
Loading