#![windows_subsystem = "windows"] use std::{ fmt::Display, io::prelude::*, time::{Duration, Instant}, }; use conpty::io::PipeReader; fn main() { let mut p = conpty::spawn("cmd").unwrap(); to_file(format!("Process PID={:?}", p.pid())); let mut input = p.input().unwrap(); let mut output = p.output().unwrap(); output.blocking(false); to_file(format!( "{:?}", wait_for(&mut output, "All rights reserved") )); input .write_all("echo \"This is a test string 😁\"\r\n".as_bytes()) .unwrap(); to_file(format!("{:?}", wait_for(&mut output, "😁"))); input.write_all(b"powershell\r\n").unwrap(); to_file(format!( "{:?}", wait_for(&mut output, "https://aka.ms/PSWindows") )); input.write_all(b"cat examples/cat.rs\r\n").unwrap(); to_file(format!("{:?}", wait_for(&mut output, "main"))); } fn wait_for(output: &mut PipeReader, s: &str) -> String { let treashhold = Duration::from_secs(2); let now = Instant::now(); let mut out = vec![0; 1000]; let mut buf = String::new(); loop { try_read(output, &mut out, &mut buf); if buf.contains(s) { return buf; } if now.elapsed() > treashhold { panic!("TIMEOUT REACHED") } } } fn try_read(o: &mut PipeReader, out: &mut Vec, buf: &mut String) { match o.read(out) { Ok(n) => { let s = String::from_utf8_lossy(&out[..n]); buf.push_str(&s); } Err(err) => { if err.kind() == std::io::ErrorKind::WouldBlock { return; } panic!("{:?}", err); } } } fn to_file(text: impl Display) { let mut f = std::fs::File::options() .append(true) .create(true) .write(true) .open("info.txt") .unwrap(); f.write_all(format!("{}\n", text).as_bytes()).unwrap(); f.flush().unwrap(); }