From 66e6ef2e8c12e77a231a9291bc03c595c0e13dfb Mon Sep 17 00:00:00 2001 From: zqm Date: Tue, 7 Apr 2026 13:21:31 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=9C=8D=E5=8A=A1=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Updater/AppData/Updater/config.json | 2 +- Windows/CS/Framework4.0/Updater/Cargo.lock | 543 ++++++++++++++++++ Windows/CS/Framework4.0/Updater/Cargo.toml | 5 + Windows/CS/Framework4.0/Updater/build.rs | 8 + Windows/CS/Framework4.0/Updater/src/main.rs | 186 ++++-- 5 files changed, 703 insertions(+), 41 deletions(-) create mode 100644 Windows/CS/Framework4.0/Updater/build.rs diff --git a/Windows/CS/Framework4.0/Updater/AppData/Updater/config.json b/Windows/CS/Framework4.0/Updater/AppData/Updater/config.json index 949fe2b..8676a3d 100644 --- a/Windows/CS/Framework4.0/Updater/AppData/Updater/config.json +++ b/Windows/CS/Framework4.0/Updater/AppData/Updater/config.json @@ -1,3 +1,3 @@ { "debug_mode": false -} \ No newline at end of file +} diff --git a/Windows/CS/Framework4.0/Updater/Cargo.lock b/Windows/CS/Framework4.0/Updater/Cargo.lock index 3dc7ffb..0524ede 100644 --- a/Windows/CS/Framework4.0/Updater/Cargo.lock +++ b/Windows/CS/Framework4.0/Updater/Cargo.lock @@ -7,10 +7,13 @@ name = "Updater" version = "0.1.0" dependencies = [ "dirs", + "futures-util", "serde", "serde_json", "tokio", + "tokio-tungstenite", "windows", + "winres", ] [[package]] @@ -19,6 +22,21 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.11.1" @@ -31,6 +49,41 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "data-encoding" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dirs" version = "5.0.1" @@ -52,6 +105,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "errno" version = "0.3.14" @@ -62,6 +126,68 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -73,6 +199,125 @@ dependencies = [ "wasi", ] +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "itoa" version = "1.0.18" @@ -94,6 +339,12 @@ dependencies = [ "libc", ] +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + [[package]] name = "lock_api" version = "0.4.14" @@ -103,6 +354,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + [[package]] name = "memchr" version = "2.8.0" @@ -149,12 +406,36 @@ dependencies = [ "windows-link", ] +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + [[package]] name = "pin-project-lite" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -173,6 +454,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -242,6 +553,17 @@ dependencies = [ "zmij", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -252,6 +574,12 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + [[package]] name = "smallvec" version = "1.15.1" @@ -268,6 +596,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "syn" version = "2.0.117" @@ -279,6 +613,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -299,6 +644,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tokio" version = "1.51.0" @@ -327,12 +682,88 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "sha1", + "thiserror", + "url", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -537,6 +968,118 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winres" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" +dependencies = [ + "toml", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zmij" version = "1.0.21" diff --git a/Windows/CS/Framework4.0/Updater/Cargo.toml b/Windows/CS/Framework4.0/Updater/Cargo.toml index 329c9cd..4c1d409 100644 --- a/Windows/CS/Framework4.0/Updater/Cargo.toml +++ b/Windows/CS/Framework4.0/Updater/Cargo.toml @@ -9,3 +9,8 @@ serde_json = "1.0" dirs = "5.0" tokio = { version = "1.37", features = ["full"] } windows = { version = "0.56", features = ["Win32_System_Console"] } +tokio-tungstenite = "0.21.0" +futures-util = "0.3.32" + +[build-dependencies] +winres = "0.1.12" diff --git a/Windows/CS/Framework4.0/Updater/build.rs b/Windows/CS/Framework4.0/Updater/build.rs new file mode 100644 index 0000000..8e875a2 --- /dev/null +++ b/Windows/CS/Framework4.0/Updater/build.rs @@ -0,0 +1,8 @@ +extern crate winres; + +fn main() { + let mut res = winres::WindowsResource::new(); + res.set("FileVersion", "0.0.0.1"); + res.set("ProductVersion", "0.0.0.1"); + res.compile().unwrap(); +} \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Updater/src/main.rs b/Windows/CS/Framework4.0/Updater/src/main.rs index 3fc5d50..67b18ea 100644 --- a/Windows/CS/Framework4.0/Updater/src/main.rs +++ b/Windows/CS/Framework4.0/Updater/src/main.rs @@ -1,71 +1,174 @@ use serde::{Deserialize, Serialize}; use std::fs; use std::path::PathBuf; +use std::process::Command; use tokio::signal; use tokio::time; +use futures_util::sink::SinkExt; +use futures_util::stream::StreamExt; +/// Updater 自身配置(AppData/Updater/config.json) +/// 只负责 Updater 自己的行为参数,连接地址从公共 config.json 加载 #[derive(Debug, Serialize, Deserialize)] struct Config { + /// 调试模式:true 时保留控制台窗口并输出日志 debug_mode: bool, } impl Default for Config { fn default() -> Self { - Self { - debug_mode: false, - } + Self { debug_mode: false } } } -fn get_config_path() -> PathBuf { +/// 获取 Updater 自身配置路径 AppData/Updater/config.json +fn get_updater_config_path() -> PathBuf { let exe_path = std::env::current_exe().expect("Failed to get executable path"); - let drive = if let Some(parent) = exe_path.parent() { - let drive = parent.as_os_str().to_str().unwrap_or("C:/").split('\\').next().unwrap_or("C:"); - std::path::Path::new(&format!("{}/", drive)).to_path_buf() - } else { - std::path::Path::new("C:/").to_path_buf() - }; - let appdata = drive.join("AppData").join("Updater"); - fs::create_dir_all(&appdata).expect("Failed to create config directory"); - appdata.join("config.json") + let drive = exe_path + .parent() + .and_then(|p| p.as_os_str().to_str()) + .and_then(|s| s.split('\\').next()) + .unwrap_or("C:"); + let appdata = PathBuf::from(format!("{}/AppData", drive)); + let updater_dir = appdata.join("Updater"); + let _ = fs::create_dir_all(&updater_dir); + updater_dir.join("config.json") } -fn load_config() -> Config { - let config_path = get_config_path(); +/// 获取公共配置路径 AppData/config.json(与 BootLoader 同级) +fn get_public_config_path() -> PathBuf { + let exe_path = std::env::current_exe().expect("Failed to get executable path"); + let drive = exe_path + .parent() + .and_then(|p| p.as_os_str().to_str()) + .and_then(|s| s.split('\\').next()) + .unwrap_or("C:"); + PathBuf::from(format!("{}/AppData/config.json", drive)) +} + +/// 加载 Updater 自身配置;若文件不存在则写入默认值 +fn load_updater_config() -> Config { + let config_path = get_updater_config_path(); if config_path.exists() { - match fs::read_to_string(&config_path) { - Ok(content) => { - match serde_json::from_str(&content) { - Ok(config) => config, - Err(_) => Config::default(), - } + if let Ok(content) = fs::read_to_string(&config_path) { + if let Ok(config) = serde_json::from_str::(&content) { + return config; } - Err(_) => Config::default(), - } - } else { - let default_config = Config::default(); - match serde_json::to_string_pretty(&default_config) { - Ok(content) => { - match fs::write(&config_path, content) { - Ok(_) => default_config, - Err(_) => default_config, - } - } - Err(_) => default_config, } } + // 文件不存在或解析失败 → 写入默认值 + let default_config = Config::default(); + if let Ok(content) = serde_json::to_string_pretty(&default_config) { + let _ = fs::write(&config_path, content); + } + default_config } -async fn upgrade(debug_mode: bool) { +/// 从公共 config.json 读取 ServerUrl 字段 +fn resolve_ws_url() -> String { + let config_path = get_public_config_path(); + if let Ok(content) = fs::read_to_string(&config_path) { + if let Ok(json) = serde_json::from_str::(&content) { + if let Some(url) = json.get("ServerUrl").and_then(|v| v.as_str()) { + return url.to_string(); + } + } + } + // 读取失败 → 降级到默认值 + "ws://127.0.0.1:8087/ws".to_string() +} + +fn is_process_running(process_name: &str) -> bool { + use std::process::id; + + let current_pid = id().to_string(); + let output = Command::new("tasklist") + .args(["/FI", &format!("IMAGENAME eq {}", process_name), "/FO", "CSV"]) + .output() + .expect("Failed to execute tasklist"); + + let output_str = String::from_utf8_lossy(&output.stdout); + let lines: Vec<&str> = output_str.lines().collect(); + let mut count = 0; + + for line in lines { + if line.contains(&format!("\"{}\"", process_name)) && !line.contains(¤t_pid) { + count += 1; + } + } + + count > 0 +} + +async fn upgrade(server_url: &str, debug_mode: bool) { if debug_mode { - println!("开始升级"); + println!("开始升级检查,连接服务端..."); + } + connect_to_websocket(server_url, debug_mode).await; +} + +async fn connect_to_websocket(server_url: &str, debug_mode: bool) { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::{connect_async, tungstenite::Message}; + + if debug_mode { + println!("Connecting to WebSocket server: {}", server_url); + } + + if let Ok(request) = server_url.into_client_request() { + match connect_async(request).await { + Ok((mut ws_stream, _)) => { + if debug_mode { + println!("Connected to WebSocket server"); + } + + // 注册身份 + let app_info = serde_json::json!({ + "type": "Updater", + "action": "register" + }); + + if let Err(e) = ws_stream.send(Message::Text(app_info.to_string())).await { + eprintln!("Failed to send register info: {:?}", e); + } else { + match ws_stream.next().await { + Some(Ok(message)) => { + if debug_mode { + println!("Server response: {:?}", message); + } + } + Some(Err(e)) => { + eprintln!("WebSocket error: {:?}", e); + } + None => { + eprintln!("WebSocket connection closed by server"); + } + } + } + } + Err(e) => { + eprintln!("Failed to connect to WebSocket server: {:?}", e); + } + } + } else { + eprintln!("Invalid WebSocket URL: {}", server_url); } } #[tokio::main] async fn main() { - let config = load_config(); - + // 检查是否已有 Updater 进程在运行 + if is_process_running("Updater.exe") { + return; + } + + // 加载 Updater 自身配置(debug_mode) + let config = load_updater_config(); + + // 从公共 config.json 解析 WebSocket 连接地址 + let server_url = resolve_ws_url(); + + // 非 debug 模式下释放控制台,后台静默运行 if !config.debug_mode { #[cfg(windows)] { @@ -79,13 +182,16 @@ async fn main() { } } } - + if config.debug_mode { + println!("Updater started in debug mode"); + println!("Server URL: {}", server_url); + let mut interval = time::interval(time::Duration::from_secs(300)); loop { tokio::select! { _ = interval.tick() => { - upgrade(config.debug_mode).await; + upgrade(&server_url, config.debug_mode).await; } _ = signal::ctrl_c() => { println!("Received Ctrl+C, exiting..."); @@ -97,7 +203,7 @@ async fn main() { let mut interval = time::interval(time::Duration::from_secs(300)); loop { interval.tick().await; - upgrade(config.debug_mode).await; + upgrade(&server_url, config.debug_mode).await; } } }