failed attempt at making a single binary for CLI and GUI on Windows

This commit is contained in:
2023-05-12 21:34:32 -07:00
parent 5b9c711008
commit 4ee1d543f7
7 changed files with 166 additions and 61 deletions

View File

@ -13,7 +13,6 @@ use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
};
use crate::app;
use crate::config::AppConfig;
use crate::credentials::{BaseCredentials, SessionCredentials};
@ -23,6 +22,16 @@ use crate::errors::*;
pub fn parser() -> Command<'static> {
Command::new("creddy")
.about("A friendly AWS credentials manager")
// we don't want the default help handling because it early-exits,
// and on Windows we need to setup the console before we can output
.disable_help_flag(true)
.arg(
Arg::new("help")
.short('h')
.long("help")
.action(ArgAction::SetTrue)
.help("Print this message or the help of the given subcommand(s)")
)
.subcommand(
Command::new("run")
.about("Launch Creddy")

View File

@ -2,7 +2,6 @@ use std::net::Ipv4Addr;
use std::path::PathBuf;
use auto_launch::AutoLaunchBuilder;
use is_terminal::IsTerminal;
use serde::{Serialize, Deserialize};
use sqlx::SqlitePool;
@ -96,7 +95,7 @@ pub fn get_or_create_db_path() -> Result<PathBuf, DataDirError> {
path.push("Creddy");
std::fs::create_dir_all(&path)?;
if cfg!(debug_assertions) && std::io::stdout().is_terminal() {
if cfg!(debug_assertions) {
path.push("creddy.dev.db");
}
else {

View File

@ -3,6 +3,20 @@
windows_subsystem = "windows"
)]
#[cfg(windows)]
use {
std::fs::File,
std::os::windows::io::FromRawHandle,
std::os::raw::c_void,
gag::Redirect,
windows::Win32::System::Console::{
AllocConsole,
AttachConsole,
GetStdHandle,
STD_OUTPUT_HANDLE,
STD_ERROR_HANDLE,
}
};
mod app;
mod cli;
@ -15,18 +29,40 @@ mod state;
mod server;
mod tray;
use crate::errors::ErrorPopup;
use std::io::Write;
fn main() {
let res = match cli::parser().get_matches().subcommand() {
None | Some(("run", _)) => {
let args = cli::parser().get_matches();
let help = matches!(args.get_one::<bool>("help"), Some(true));
// This is the only case that doesn't need a console
if let None | Some(("run", _)) = args.subcommand() {
if !help {
app::run().error_popup("Creddy failed to start");
Ok(())
},
return;
}
}
// on Windows, need to do the whole allocate-a-console thing
#[cfg(windows)]
attach_console();
// let (out, err) = setup_console();
println!("Testing stdout");
// writeln!(&mut out, "Testing allocated file");
if help {
// if we can't print help, we can't print an error, so just panic
dbg!(args.get_one::<bool>("help"));
cli::parser().print_help().unwrap();
std::thread::sleep(std::time::Duration::from_secs(3));
return;
}
let res = match args.subcommand() {
Some(("show", m)) => cli::show(m),
Some(("exec", m)) => cli::exec(m),
// clap ensures that subcommand is either None or run/show/exec
_ => unreachable!(),
};
@ -34,3 +70,43 @@ fn main() {
eprintln!("Error: {e}");
}
}
fn attach_console() {
unsafe { AttachConsole(u32::MAX); }
}
fn setup_console() -> (Redirect<File>, Redirect<File>) {
let (mut stdout, stderr) = unsafe {
AllocConsole();
// if we can't get handles to stdout/err, we can't display these errors,
// so there's no point in doing anything other than panicking
let stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE).unwrap();
let stderr_handle = GetStdHandle(STD_ERROR_HANDLE).unwrap();
let mut f = File::create("C:\\Users\\Joe\\Downloads\\debug.txt").unwrap();
writeln!(&mut f, "{stdout_handle:?}\n{:?}", stdout_handle.0 as *mut c_void).unwrap();
(
File::from_raw_handle(stdout_handle.0 as *mut c_void),
File::from_raw_handle(stderr_handle.0 as *mut c_void),
)
};
writeln!(&mut stdout, "Testing stdout before redirect")
.map_err(|e| log_err(e))
.unwrap();
(
Redirect::stdout(stdout).unwrap(),
Redirect::stderr(stderr).unwrap()
)
}
fn log_err(e: impl std::error::Error) {
let mut f = File::create("C:\\Users\\Joe\\Downloads\\log.txt").unwrap();
writeln!(&mut f, "{e}").unwrap();
}