1#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
2
3#[cfg(target_os = "windows")]
4mod dialog;
5#[cfg(target_os = "windows")]
6mod updater;
7
8#[cfg(target_os = "windows")]
9fn main() {
10 if let Err(e) = windows_impl::run() {
11 log::error!("Error: Zed update failed, {:?}", e);
12 windows_impl::show_error(format!("Error: {:?}", e));
13 }
14}
15
16#[cfg(not(target_os = "windows"))]
17fn main() {}
18
19#[cfg(target_os = "windows")]
20mod windows_impl {
21 use std::path::Path;
22
23 use super::dialog::create_dialog_window;
24 use super::updater::perform_update;
25 use anyhow::{Context as _, Result};
26 use windows::{
27 Win32::{
28 Foundation::{HWND, LPARAM, WPARAM},
29 UI::WindowsAndMessaging::{
30 DispatchMessageW, GetMessageW, MB_ICONERROR, MB_SYSTEMMODAL, MSG, MessageBoxW,
31 PostMessageW, WM_USER,
32 },
33 },
34 core::HSTRING,
35 };
36
37 pub(crate) const WM_JOB_UPDATED: u32 = WM_USER + 1;
38 pub(crate) const WM_TERMINATE: u32 = WM_USER + 2;
39
40 pub(crate) fn run() -> Result<()> {
41 let helper_dir = std::env::current_exe()?
42 .parent()
43 .context("No parent directory")?
44 .to_path_buf();
45 init_log(&helper_dir)?;
46 let app_dir = helper_dir
47 .parent()
48 .context("No parent directory")?
49 .to_path_buf();
50
51 log::info!("======= Starting Zed update =======");
52 let (tx, rx) = std::sync::mpsc::channel();
53 let hwnd = create_dialog_window(rx)?.0 as isize;
54 std::thread::spawn(move || {
55 let result = perform_update(app_dir.as_path(), Some(hwnd));
56 tx.send(result).ok();
57 unsafe { PostMessageW(Some(HWND(hwnd as _)), WM_TERMINATE, WPARAM(0), LPARAM(0)) }.ok();
58 });
59 unsafe {
60 let mut message = MSG::default();
61 while GetMessageW(&mut message, None, 0, 0).as_bool() {
62 DispatchMessageW(&message);
63 }
64 }
65 Ok(())
66 }
67
68 fn init_log(helper_dir: &Path) -> Result<()> {
69 simplelog::WriteLogger::init(
70 simplelog::LevelFilter::Info,
71 simplelog::Config::default(),
72 std::fs::File::options()
73 .append(true)
74 .create(true)
75 .open(helper_dir.join("auto_update_helper.log"))?,
76 )?;
77 Ok(())
78 }
79
80 pub(crate) fn show_error(mut content: String) {
81 if content.len() > 600 {
82 content.truncate(600);
83 content.push_str("...\n");
84 }
85 let _ = unsafe {
86 MessageBoxW(
87 None,
88 &HSTRING::from(content),
89 windows::core::w!("Error: Zed update failed."),
90 MB_ICONERROR | MB_SYSTEMMODAL,
91 )
92 };
93 }
94}