use std::process::{Command, Stdio};
use std::thread::sleep;
use std::time::Duration;
use dbgscope::dbgeng::DebugEngine;
const LAUNCH_CMD: &str = "cmd.exe /c exit 42";
fn show(e: &DebugEngine, cmd: &str) {
match e.execute_command(cmd) {
Ok(out) => print!("{out}"),
Err(err) => println!("ERR: {err}"),
}
}
fn main() {
let e = DebugEngine::new();
println!("=== 1. launch_process_begin / wait (the split path) ===");
match e.launch_process_begin(LAUNCH_CMD) {
Ok(pending) => {
println!("[commit] side effect OK — handle would be committed now");
match pending.wait() {
Ok(()) => println!("wait OK — target stopped at the loader breakpoint"),
Err(err) => println!("wait ERR: {err} (target may still exist!)"),
}
}
Err(err) => println!("begin ERR: {err} (nothing was created; retry is clean)"),
}
show(&e, "|");
let _ = e.end_session();
println!("\n=== 2. launch_process (the fused wrapper, now begin+wait) ===");
match e.launch_process(LAUNCH_CMD) {
Ok(()) => println!("launch_process OK"),
Err(err) => println!("launch_process ERR: {err}"),
}
show(&e, "|");
let _ = e.end_session();
println!("\n=== 3. attach_process_begin / wait ===");
let mut victim = Command::new("cmd.exe")
.args(["/c", "ping", "-n", "30", "127.0.0.1"])
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.expect("failed to spawn victim process");
let pid = victim.id();
println!("spawned victim pid {pid}");
sleep(Duration::from_millis(500));
match e.attach_process_begin(pid) {
Ok(pending) => {
println!("[commit] attached to {pid} — handle would be committed now");
match pending.wait() {
Ok(()) => println!("wait OK — target broken in"),
Err(err) => println!("wait ERR: {err} (still attached!)"),
}
}
Err(err) => println!("begin ERR: {err} (not attached; retry is clean)"),
}
show(&e, "|");
let _ = e.end_session();
let _ = victim.kill();
let _ = victim.wait();
println!("\n=== 4. drop the guard, THEN pump the engine ===");
match e.launch_process_begin(LAUNCH_CMD) {
Ok(pending) => {
drop(pending);
println!("guard dropped without wait(); nothing has spawned yet");
}
Err(err) => println!("begin ERR: {err}"),
}
match e.wait_for_event(30_000) {
Ok(()) => println!("post-drop wait OK — deferred spawn completed"),
Err(err) => println!("post-drop wait ERR: {err}"),
}
show(&e, "|");
show(&e, "r rip");
let _ = e.end_session();
println!("\ndone — expect cmd.exe as the current process in 1, 2, 3 and 4");
}