From c60e4b5cd4d09b20bc2be6475de1c3b6cda00a70 Mon Sep 17 00:00:00 2001 From: jbjf6666 Date: Fri, 16 Oct 2026 01:51:50 +0800 Subject: [PATCH] =?UTF-8?q?chore(release):=20v1.1.0=20=E2=80=94=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=201.0.0=20=E2=86=92=201.1.0?= =?UTF-8?q?=EF=BC=8CREADME=20=E5=8F=8C=E8=AF=AD=E5=8C=96=EF=BC=8C=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E8=84=9A=E6=9C=AC=E7=BC=96=E7=A0=81=E8=87=AA=E6=A3=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 版本号 1.1.0(Windows 支持是新功能) - core/protocol.py APP_VERSION、installer/version_info.txt、installer/iosloc.iss MyAppVersion、Location.spec(mac BUNDLE)、tools/make_dmg.py VERSION 全部同步到 1.1.0 - 产物命名规范:Windows 用 _win、macOS 用 _mac 后缀,Release 页面一眼分清平台 · iOSLocationTrack-1.1.0_win-setup.exe · iOSLocationTrack-1.1.0_win-portable.zip · iOSLocationTrack-1.1.0_mac.dmg README 双语化(默认中文) - docs/README-WINDOWS.en.md 新增(Windows 文档全文英文版) - docs/README-WINDOWS.md 顶部加 [中文] | [English] 语言切换 - README.md / README.en.md 的下载章节改成平台表格,说明 _win / _mac 命名 构建脚本编码自检 - scripts/build.ps1 新增第 0.5 步:检查 scripts/*.ps1 是否为 UTF-8 with BOM, 缺失则自动补回。Windows PowerShell 5.1 没有 BOM 时会按 ANSI(GBK) 解析, 中文乱码且直接语法报错(改个注释就构建不了,本项目实际踩过两次) - 本次修复:build.ps1 的 BOM 在编辑后被工具静默丢弃,已补回 验收(Windows 11 x64 / iPhone 11 iOS 26.6.1) - selftest 83/83、drift_sim 40/40、offline_tiles 13/13 - 打包版 exe 清单含 requireAdministrator,FileVersion 1.1.0.0 --- Location.spec | 6 +- README.en.md | 17 +- README.md | 16 +- core/protocol.py | 2 +- docs/README-WINDOWS.en.md | 313 +++++++++++++++++++++++++++++++++++++ docs/README-WINDOWS.md | 6 +- installer/iosloc.iss | 7 +- installer/version_info.txt | 8 +- scripts/build.ps1 | 22 ++- tools/make_dmg.py | 8 +- 10 files changed, 380 insertions(+), 25 deletions(-) create mode 100644 docs/README-WINDOWS.en.md diff --git a/Location.spec b/Location.spec index 4bba0f9..445019a 100644 --- a/Location.spec +++ b/Location.spec @@ -207,12 +207,12 @@ else: name="虚拟定位轨迹.app", icon=str(ROOT / "resources" / "AppIcon.icns"), bundle_identifier="com.local.ios-location-track", - version="1.0.0", + version="1.1.0", info_plist={ "CFBundleName": "虚拟定位轨迹", "CFBundleDisplayName": "虚拟定位轨迹", - "CFBundleShortVersionString": "1.0.0", - "CFBundleVersion": "1.0.0", + "CFBundleShortVersionString": "1.1.0", + "CFBundleVersion": "1.1.0", "CFBundlePackageType": "APPL", "CFBundleIconFile": "AppIcon", "CFBundleIconName": "AppIcon", diff --git a/README.en.md b/README.en.md index b48ae01..179a537 100644 --- a/README.en.md +++ b/README.en.md @@ -13,7 +13,7 @@ The UI is a local web app opened in a Chrome / Edge app window (no address bar > userspace stack — no Wintun driver needed), detects and auto-installs Apple Mobile Device > Support on first launch, and shows an environment self-check window. > Build outputs: `dist\iOSLocationTrack\iOSLocationTrack.exe` and -> `dist\installer\iOSLocationTrack-1.0.0-setup.exe`. +> `dist\installer\iOSLocationTrack-1.1.0_win-setup.exe`. --- @@ -21,10 +21,19 @@ The UI is a local web app opened in a Chrome / Edge app window (no address bar ### Option A — Download the installer (recommended) -Grab `iOSLocationTrack-1.0.0.dmg` from [Releases](https://github.com/jbjf6666/ios-location-track/releases): +Grab the build for your platform from [Releases](https://github.com/jbjf6666/ios-location-track/releases): -1. Open the DMG and drag `虚拟定位轨迹.app` into `Applications` -2. If macOS says *"unidentified developer"* on first launch → **right-click → Open → Open** +| Platform | Filename | Notes | +| --- | --- | --- | +| **Windows** | `iOSLocationTrack-_win-setup.exe` | Installer. A portable ZIP is also provided — just unzip and run | +| **macOS** | `iOSLocationTrack-_mac.dmg` | Open the DMG and drag the app into `Applications` | + +On Windows the first launch asks for administrator rights and shows an environment +self-check window that installs anything missing — see +[docs/README-WINDOWS.md](docs/README-WINDOWS.md). + +macOS: open the DMG and drag `虚拟定位轨迹.app` into `Applications`. If macOS says +*"unidentified developer"* on first launch → **right-click → Open → Open**. **No Python, no dependencies** — the Python runtime and every dependency are bundled inside the app (~80 MB). Config and tile cache are written to `~/Library/Application Support/iOSLocationTrack/`. diff --git a/README.md b/README.md index 168f60b..92a8918 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ > Windows 版:免管理员建立隧道(纯 Python 用户态协议栈,不需要 Wintun 驱动)、 > 启动时自动检测并安装 Apple Mobile Device Support、带「环境准备」自检窗口。 > 构建产物:`dist\iOSLocationTrack\iOSLocationTrack.exe` 与 -> `dist\installer\iOSLocationTrack-1.0.0-setup.exe`。 +> `dist\installer\iOSLocationTrack-1.1.0_win-setup.exe`。 --- @@ -20,10 +20,18 @@ ### 方式一:直接下载安装包(推荐) -从 [Releases](https://github.com/jbjf6666/ios-location-track/releases) 下载 `iOSLocationTrack-1.0.0.dmg`: +从 [Releases](https://github.com/jbjf6666/ios-location-track/releases) 下载对应平台的安装包: -1. 打开 DMG,把 `虚拟定位轨迹.app` 拖进 `Applications` -2. 首次打开若提示「来自身份不明的开发者」→ 右键 → 打开 → 再点「打开」 +| 平台 | 文件名 | 说明 | +| --- | --- | --- | +| **Windows** | `iOSLocationTrack-<版本>_win-setup.exe` | 安装包。也可用绿色版压缩包,解压即用 | +| **macOS** | `iOSLocationTrack-<版本>_mac.dmg` | 打开 DMG,把 App 拖进 `Applications` | + +Windows 版首次启动会请求管理员权限并弹出「环境准备」窗口自动补齐依赖, +详见 [docs/README-WINDOWS.md](docs/README-WINDOWS.md)。 + +macOS 版:打开 DMG,把 `虚拟定位轨迹.app` 拖进 `Applications`;首次打开若提示 +「来自身份不明的开发者」→ 右键 → 打开 → 再点「打开」。 **不需要安装 Python、不需要任何依赖**,Python 运行时与全部依赖都已打包在应用内(约 80 MB)。 数据(配置、瓦片缓存)写到 `~/Library/Application Support/iOSLocationTrack/`。 diff --git a/core/protocol.py b/core/protocol.py index 2ad58d4..cc4a883 100644 --- a/core/protocol.py +++ b/core/protocol.py @@ -11,7 +11,7 @@ import uuid from typing import Any APP_NAME = "iOS 虚拟定位轨迹工具" -APP_VERSION = "1.0.0" +APP_VERSION = "1.1.0" PROTOCOL_VERSION = "v1" DEFAULT_HOST = "127.0.0.1" diff --git a/docs/README-WINDOWS.en.md b/docs/README-WINDOWS.en.md new file mode 100644 index 0000000..8f70bae --- /dev/null +++ b/docs/README-WINDOWS.en.md @@ -0,0 +1,313 @@ +# Windows Guide — iOS Virtual Location & Route Simulator + +[**中文**](README-WINDOWS.md) | [English](README-WINDOWS.en.md) + +> This document is for Windows users and maintainers. +> macOS instructions live in [README.md](../README.md); the porting rationale and +> lessons learned are in [WINDOWS_PORT.md](WINDOWS_PORT.md). + +--- + +## 1. Quick start (3 minutes) + +1. Run `iOSLocationTrack-1.1.0_win-setup.exe`, or unzip the portable build and + double-click `iOSLocationTrack.exe`. +2. **The app requests administrator rights** — click *Yes* on the UAC prompt. + This is only needed so it can auto-install the Apple driver on first run. +3. An **Environment Check** window appears, listing every required component: + - Ready items show a green ✓ and their button reads *已就绪* (disabled) + - Missing items show a red ✗ with a clickable **Install / Download** button + - **The "进入程序" (Enter) button only becomes clickable once every required item is ready** +4. Click **进入程序** — the UI opens in a Chrome/Edge app window (no address bar). +5. Connect your iPhone by cable → unlock it → tap *Trust* → click **连接设备** in the UI. + +> Running from source: `.\scripts\run.ps1` (creates the venv, installs dependencies +> and fetches the disk-image assets automatically). + +--- + +## 2. What the Environment Check verifies + +| Item | Required | How it is checked | What "Install" does | +| --- | --- | --- | --- | +| Python runtime | ✅ | version string | — (bundled in the exe) | +| pymobiledevice3 | ✅ | import + version | — (bundled) | +| **Apple Mobile Device Support** | ✅ | service state + a protocol round-trip on port 27015 | downloads and installs it (~40–200 MB) | +| RSD tunnel deps | ✅ | imports `pytun_pmd3` / `pmd_pytcp` etc. | — (bundled) | +| Developer disk image | ✅ | three files under `resources/ddi/personalized/` | downloads the personalized image (~15 MB) | +| Administrator rights | ✅ | `IsUserAnAdmin` | right-click → *Run as administrator* | +| iPhone connection | ➖ optional | usbmuxd `ListDevices` | — (just plug the phone in) | +| Network reachability | ➖ optional | TCP to `gs.apple.com:443` | — (Apple signs the image online) | + +**The only authoritative signal that usbmuxd actually works is a protocol round-trip +on `127.0.0.1:27015`** — not merely that the port accepts a connection. +`ReadBUID` needs no device attached, so the service can be validated with no phone present. + +### Text-mode self check + +```powershell +# portable build +.\dist\iOSLocationTrack\iOSLocationTrack.exe --check-driver +# from source +.venv\Scripts\python.exe main.py --check-driver +``` + +Sample output: + +``` +平台:Windows(管理员:是) +服务:RUNNING(Apple Mobile Device Service) +版本:Apple Mobile Device Support 20.0.0.35 +usbmuxd(127.0.0.1:27015):可通信 +设备:1 台 + · 00008030-001551840A02402E(USB) +结论:Apple Mobile Device Service 正在运行,usbmuxd 可通信 +``` + +--- + +## 3. Automatic Apple Mobile Device Support installation + +Click **Install** on the Apple row in the Environment Check window, or run: + +```powershell +main.py --install-driver # from source +iOSLocationTrack.exe --install-driver # portable build +``` + +Strategies are tried in order and fall through automatically (`core/apple_driver.py`): + +| # | Strategy | Notes | +| --- | --- | --- | +| 0 | Start the existing service | If it is installed but stopped, `sc start` is all that is needed (cheapest, most common fix) | +| 1 | Standalone AMDS MSI | `AppleMobileDeviceSupport64.msi` from Apple's CDN (~38 MB) | +| 2 | Full iTunes bundle | `https://www.apple.com/itunes/download/win64` (~193 MB) | +| 3 | winget | `Apple.AppleMobileDeviceSupport` / `Apple.iTunes` | + +Success exit codes: `0`, `3010`, `1641`, `1638` (MSI semantics; 3010/1641 mean a reboot is needed). + +### Traps you must know about (all verified on real hardware) + +1. **The service name contains spaces: `Apple Mobile Device Service`.** + `AppleMobileDeviceService` is only the exe basename — `sc query AppleMobileDeviceService` + fails with error 1060. +2. **There is no `\\.\pipe\usbmuxd` on Windows.** usbmuxd is exposed purely as TCP + `127.0.0.1:27015`. +3. **Do not detect the driver by looking for `usbaapl64`.** The AMDS MSI contains + **zero `.inf`/`.sys`/`.cat` files** — it does **not** ship the USB driver. On a modern + machine the iPhone actually binds to `appleusb.inf` (service `WINUSB` / `usbccgp`). + A `usbaapl64` check produces false "missing driver" reports on perfectly healthy systems. +4. **The AMDS ProductCode changes with every version.** The stable identifier is the + UpgradeCode `{5CF0656E-F3B8-11DB-BA81-804E56D89593}` (shared by x86 and x64). +5. **Apple publishes no stable "latest" direct link** — the `iTunes64Setup.exe` URL embeds + a build number. This project therefore pins a SHA256 where one is available and fails + loudly rather than installing something unverifiable. +6. **Microsoft Store iTunes and the classic installer are mutually exclusive**: the classic + installer's `LaunchCondition` hard-codes `NOT ITUNES_STORE_APP_INSTALLED`. Separately, + the Store daemon **cannot discover devices over Wi-Fi**. pymobiledevice3's own docs + recommend the classic installer for exactly this reason. + +--- + +## 4. How Windows differs from macOS (**important**) + +The single biggest porting trap: **the two platforms build the RSD tunnel in fundamentally +different ways**, so `core/tunnel.py` has two entirely separate code paths. + +| | macOS | Windows | +| --- | --- | --- | +| Tunnel | `remote start-tunnel --native` (piggybacks Apple's `remoted`) | `UserspaceRsdTunnel` (pure-Python PyTCP userspace stack) | +| Needs root/admin | No | **No** | +| Needs a third-party driver | No | **No** (Wintun not required) | +| RSD address reachable from | any process (kernel-routable) | **this process only** (userspace stack) | +| Implementation | subprocess + parse `HOST PORT` from stdout | build and hold the RSD object on the app's event loop | +| Measured time | — | **~0.3 s** | + +### Why Windows cannot use the "tunnel helper subprocess" design + +On macOS the tunnel runs in a child process that prints `HOST PORT`, and the main process +connects over ordinary TCP. That does not work on Windows: + +- The userspace tunnel's device address **only exists inside the protocol stack of the + process that created it**; +- pymobiledevice3 injects a relay dialer into the `RemoteServiceDiscoveryService` object it + returns (`open_connection=dial_plane.dial`); +- Building a *new* RSD from `(host, port)` falls back to the stdlib dialer, which goes to the + OS network stack and fails with `OSError [WinError 1231] The network location cannot be + reached` (reproduced during this port). + +**The correct approach**: inject the **rsd object itself** into the DVT layer. +`RealLocationProvider` already had an `rsd=` injection seam (`core/location_provider.py`), +and `core/server.py:provider_for()` now uses it on Windows. + +### About Wintun + +`docs/WINDOWS_PORT.md` originally said to install Wintun first. **Measurement says it is not +needed:** + +- The userspace tunnel runs a pure-Python PyTCP stack and creates no kernel adapter; +- Moreover the `pytun_pmd3` dependency **already bundles** `wintun.dll` for every + architecture (`pytun_pmd3/wintun/bin/amd64/wintun.dll`), so there was never anything to + download. + +### Verified environment + +| Item | Value | +| --- | --- | +| OS | Windows 11 Home (Chinese), 10.0.26200, x64 | +| Python | 3.12.14 | +| pymobiledevice3 | 11.31.0 | +| Device | iPhone 11 (`iPhone12,1`), **iOS 26.6.1** | +| Apple Mobile Device Support | 20.0.0.35 | +| iTunes | 12.13.11.1 (classic) | + +Measured connect time: **0.8 s** (0.3 s tunnel + image/DVT session). + +--- + +## 5. Where data and logs live + +| Content | Path | +| --- | --- | +| Config / tile cache / logs | `%LOCALAPPDATA%\iOSLocationTrack\` | +| Application log | `%LOCALAPPDATA%\iOSLocationTrack\logs\app.log` | +| MSI install logs | `%LOCALAPPDATA%\iOSLocationTrack\logs\msi-*.log` | +| Downloaded installers | `%LOCALAPPDATA%\iOSLocationTrack\installers\` | +| Developer image cache | `%USERPROFILE%\.pymobiledevice3\Xcode_iOS_DDI_Personalized\` | + +`app.log` is UTF-8, tab-separated: `timestamp \t level \t message`. +Open it in Notepad or use `Get-Content -Encoding UTF8` (Windows PowerShell 5.1 defaults to +ANSI and will show mojibake). + +--- + +## 6. Building + +```powershell +# One shot: icon → image assets → tests → PyInstaller → Inno Setup +.\scripts\build.ps1 + +# exe only +.\scripts\build.ps1 -NoInstaller + +# Fast rebuild, skip tests +.\scripts\build.ps1 -SkipTests -SkipIcon -SkipDdi +``` + +Outputs: + +| File | Notes | +| --- | --- | +| `dist\iOSLocationTrack\iOSLocationTrack.exe` | Portable onedir build — copy the whole folder | +| `dist\installer\iOSLocationTrack-1.1.0_win-setup.exe` | Installer (Inno Setup 6) | + +**Prerequisites:** + +```powershell +python -m venv .venv +.venv\Scripts\python.exe -m pip install -i https://mirrors.aliyun.com/pypi/simple/ pymobiledevice3 pillow pyinstaller +winget install -e --id JRSoftware.InnoSetup # optional, installer only +``` + +### Packaging traps (all fixed — do not reintroduce them) + +1. **Do not exclude `distutils` / `setuptools` / `wheel` / `pip`.** PyInstaller and + setuptools hooks force-import or alias them, and the build dies immediately: + ``` + ValueError: Target module "distutils" already imported as ExcludedModule('distutils',) + ValueError: Target module "wheel" already imported as ExcludedModule('wheel',) + ``` +2. **Do not exclude `tkinter`** — the Environment Check window is built with it. +3. **`copy_metadata` must include** `apple_compress` and friends, otherwise mounting fails + with `No package metadata was found for apple_compress`. +4. **Do not exclude `questionary` / `prompt_toolkit` / `pygments`** — pymobiledevice3 imports + them at runtime; excluding them silently breaks real-device support (device discovery + degrades to the libimobiledevice fallback). +5. **With `--windowed`, `sys.stdout` is `None`** — check before printing. +6. **`.ps1` files must be UTF-8 *with BOM*.** Windows PowerShell 5.1 only parses a script as + UTF-8 when it sees a BOM; otherwise it uses the system ANSI code page (GBK on Chinese + Windows), which turns every Chinese character into mojibake and **breaks the script with a + syntax error** (`The string is missing the terminator`). + Both `scripts\run.ps1` and `scripts\build.ps1` are stored as UTF-8 with BOM, and + `build.ps1` re-adds a missing BOM automatically as step 0.5. + +### Requesting administrator rights at launch + +The Windows branch of `Location.spec` sets `uac_admin=True`, which makes PyInstaller write +`requestedExecutionLevel level="requireAdministrator"` into the exe manifest. +You can verify it by searching the exe for `requireAdministrator`. + +> Note: the userspace tunnel itself does **not** need administrator rights. Elevation exists +> purely so the first run can auto-install Apple Mobile Device Support without asking the user +> to right-click and elevate manually. + +--- + +## 7. Acceptance tests + +```powershell +# No device needed (136 checks) +.venv\Scripts\python.exe tests\selftest.py # 83: protocol/geometry/playback/config/tiles/e2e +.venv\Scripts\python.exe tests\drift_sim.py # 40: realism model +.venv\Scripts\python.exe tests\offline_tiles.py # 13: offline tile cache + +# Platform feasibility (real device, 7 checks) +.venv\Scripts\python.exe tests\win_e2e.py --confirm + +# Application layer (real device, 9 checks; uses App's real wiring) +.venv\Scripts\python.exe tests\win_app_e2e.py --confirm + +# UI without a device +.venv\Scripts\python.exe main.py --mock +``` + +Real-device acceptance, the 6 steps from §7 of `WINDOWS_PORT.md`: + +1. `pymobiledevice3 usbmux list` sees the device ✅ +2. Developer disk image mounts ✅ +3. "Connect device" → tunnel up → DVT session ready ✅ +4. Play a route → the phone's location actually moves ✅ +5. "Stop" → the phone returns to its real location ✅ +6. App layer 9/9 and platform layer 7/7 ✅ + +--- + +## 8. Known limitations + +| Limitation | Detail | +| --- | --- | +| **One userspace tunnel per process** | PyTCP's stack is a process-global singleton. Do not run two instances. | +| **Only one tool may hold the RSD connection** | 爱思助手 / i4Tools / Xcode will evict each other. Close them first. | +| **iOS 16 and earlier unsupported** | Classic images must be signed by Apple per build; third-party images are rejected by the device. This project targets iOS 17+. | +| **DVT can only change latitude/longitude** | `simulateLocationWithLatitude:longitude:` takes only two arguments; altitude, accuracy and sensor data are synthesized by iOS and cannot be injected. | +| **Mounting the image needs network access** | The personalized image is signed online by Apple TSS per device. | +| **The tunnel can drop silently** | The Windows userspace stack occasionally disconnects, after which the device quietly reverts to its real location while the UI still looks fine. A **keepalive** re-sends the last point every 15 s when a location is set but playback is stopped (`core/location_provider.py:KEEPALIVE_INTERVAL`). | +| **DDI mounting may disturb DVT on iOS 26.4.x** | One peer project reports that uploading the image on 26.4.1 kills the tunnel, poisoning later DVT calls with `InvalidService`. Verified fine on 26.6.1 here. If you hit it, mount the image in another tool first. | +| **Unsigned exe triggers SmartScreen** | There is no code-signing certificate. Click *More info → Run anyway*. | +| **Windows 10 1809 or later** | The installer sets `MinVersion=10.0`. | + +--- + +## 9. File map (Windows-related changes) + +| File | Notes | +| --- | --- | +| `core/platform.py` | **New.** Platform abstraction: data dir, browser probing, process management, elevation, signals | +| `core/apple_driver.py` | **New.** Apple Mobile Device Support detection/install + developer image download | +| `core/setup_window.py` | **New.** The Environment Check window (tkinter) | +| `core/tunnel.py` | **Rewritten.** Windows uses an in-process userspace tunnel; macOS keeps the native subprocess tunnel | +| `core/server.py` | Injects the runner into TunnelManager; `provider_for()` injects the rsd object; file logging; resources dir split from data dir | +| `core/location_provider.py` | Platform-aware error messages; **keepalive added** (`_keepalive_loop`) | +| `main.py` | Environment Check window, background Apple driver check, `--check-driver` / `--install-driver`, cross-platform browser and signals | +| `Location.spec` | Platform branches; Windows uses `.ico` + `uac_admin=True` + `version_info.txt`; **one spec, no fork** | +| `tools/make_ico.py` | **New.** Builds a multi-size `.ico` from the existing PNG iconset | +| `tools/probe_tunnel_win.py` | **New.** Tunnel feasibility diagnostic | +| `scripts/run.ps1` / `build.ps1` | **New.** Windows run/build scripts | +| `installer/iosloc.iss` | **New.** Inno Setup installer script | +| `installer/version_info.txt` | **New.** exe version resource | +| `installer/languages/ChineseSimplified.isl` | **New.** Inno Setup 6.7 no longer bundles Chinese, so it ships with the repo | +| `tests/win_e2e.py` / `win_app_e2e.py` | **New.** Real-device acceptance (platform layer / application layer) | + +The macOS build chain (`tools/make_dmg.py`, `scripts/run.sh`, `build_app.sh`, and the +`BUNDLE` branch of `Location.spec`) is **fully retained** — a single codebase builds on both +platforms. diff --git a/docs/README-WINDOWS.md b/docs/README-WINDOWS.md index 8011916..cb8b54e 100644 --- a/docs/README-WINDOWS.md +++ b/docs/README-WINDOWS.md @@ -1,5 +1,7 @@ # Windows 版说明(iOS 虚拟定位轨迹工具) +[**中文**](README-WINDOWS.md) | [English](README-WINDOWS.en.md) + > 本文档面向 Windows 用户与维护者。 > macOS 侧说明见 [README.md](../README.md);移植决策与背景见 [WINDOWS_PORT.md](WINDOWS_PORT.md)。 @@ -7,7 +9,7 @@ ## 1. 三分钟上手 -1. 运行 `iOSLocationTrack-1.0.0-setup.exe` 安装,或直接双击绿色版 +1. 运行 `iOSLocationTrack-1.1.0_win-setup.exe` 安装,或直接双击绿色版 `dist\iOSLocationTrack\iOSLocationTrack.exe`。 2. **程序会请求管理员权限**(UAC 弹窗点「是」)—— 用于首次自动安装 Apple 驱动。 3. 弹出**「环境准备」**窗口,逐项列出所需组件: @@ -183,7 +185,7 @@ Windows 上这样行不通: | 文件 | 说明 | | --- | --- | | `dist\iOSLocationTrack\iOSLocationTrack.exe` | 绿色版 onedir,整个目录一起拷走 | -| `dist\installer\iOSLocationTrack-1.0.0-setup.exe` | 安装包(Inno Setup 6) | +| `dist\installer\iOSLocationTrack-1.1.0_win-setup.exe` | 安装包(Inno Setup 6) | **前置条件:** diff --git a/installer/iosloc.iss b/installer/iosloc.iss index bce0be8..304f286 100644 --- a/installer/iosloc.iss +++ b/installer/iosloc.iss @@ -4,7 +4,7 @@ ; 1) .venv\Scripts\python.exe -m PyInstaller --clean --noconfirm Location.spec ; 2) "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" installer\iosloc.iss ; -; 产物:dist\installer\iOSLocationTrack-1.0.0-setup.exe +; 产物:dist\installer\iOSLocationTrack-1.1.0_win-setup.exe ; ; 说明: ; - 安装包**不包含** Apple 的驱动。程序首次启动时会自动检测 Apple Mobile Device @@ -14,7 +14,7 @@ #define MyAppName "iOS 虚拟定位轨迹工具" #define MyAppNameEn "iOSLocationTrack" -#define MyAppVersion "1.0.0" +#define MyAppVersion "1.1.0" #define MyAppPublisher "本地工具" #define MyAppExeName "iOSLocationTrack.exe" #define DistDir "..\dist\iOSLocationTrack" @@ -32,7 +32,8 @@ DisableProgramGroupPage=yes PrivilegesRequired=lowest PrivilegesRequiredOverridesAllowed=dialog OutputDir=..\dist\installer -OutputBaseFilename={#MyAppNameEn}-{#MyAppVersion}-setup +; 产物名带 _win 后缀,与 macOS 的 _mac 对应,Release 页面上一眼能分清平台。 +OutputBaseFilename={#MyAppNameEn}-{#MyAppVersion}_win-setup SetupIconFile=..\resources\AppIcon.ico UninstallDisplayIcon={app}\{#MyAppExeName} Compression=lzma2/max diff --git a/installer/version_info.txt b/installer/version_info.txt index c196b1c..b792db5 100644 --- a/installer/version_info.txt +++ b/installer/version_info.txt @@ -2,8 +2,8 @@ # 语法见 https://learn.microsoft.com/windows/win32/menurc/versioninfo-resource VSVersionInfo( ffi=FixedFileInfo( - filevers=(1, 0, 0, 0), - prodvers=(1, 0, 0, 0), + filevers=(1, 1, 0, 0), + prodvers=(1, 1, 0, 0), mask=0x3f, flags=0x0, OS=0x40004, @@ -18,12 +18,12 @@ VSVersionInfo( [ StringStruct('CompanyName', '本地工具'), StringStruct('FileDescription', 'iOS 虚拟定位轨迹工具'), - StringStruct('FileVersion', '1.0.0.0'), + StringStruct('FileVersion', '1.1.0.0'), StringStruct('InternalName', 'iOSLocationTrack'), StringStruct('LegalCopyright', '本地工具,用于自有 App 的定位功能测试'), StringStruct('OriginalFilename', 'iOSLocationTrack.exe'), StringStruct('ProductName', 'iOS 虚拟定位轨迹工具'), - StringStruct('ProductVersion', '1.0.0.0'), + StringStruct('ProductVersion', '1.1.0.0'), ], ) ]), diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 4ab90cc..7e58d9a 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -2,7 +2,7 @@ # # 产出: # dist\iOSLocationTrack\iOSLocationTrack.exe 绿色版(直接双击运行) -# dist\installer\iOSLocationTrack-1.0.0-setup.exe 安装包(需要 Inno Setup 6) +# dist\installer\iOSLocationTrack-1.1.0_win-setup.exe 安装包(需要 Inno Setup 6) # # 用法(在项目根目录): # .\scripts\build.ps1 # 打包 exe + 安装包(若装了 Inno Setup) @@ -49,6 +49,26 @@ if ($LASTEXITCODE -ne 0) { } Write-Ok "PyInstaller / Pillow 就绪" +# ---------- 0.5 脚本编码自检(.ps1 必须 UTF-8 with BOM)---------- +# Windows PowerShell 5.1 只有看到 BOM 才按 UTF-8 解析 .ps1;否则按系统 ANSI 代码页读, +# 结果是中文全部乱码并**直接语法报错**(The string is missing the terminator),脚本根本跑不起来。 +# 不少编辑器/工具保存时会静默丢掉 BOM,所以这里自动补回,避免"改个注释就构建不了"。 +$bomFixed = @() +foreach ($script in Get-ChildItem (Join-Path $PSScriptRoot '*.ps1')) { + $bytes = [System.IO.File]::ReadAllBytes($script.FullName) + $hasBom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF + if (-not $hasBom) { + $text = [System.IO.File]::ReadAllText($script.FullName, [System.Text.UTF8Encoding]::new($false)) + [System.IO.File]::WriteAllText($script.FullName, $text, [System.Text.UTF8Encoding]::new($true)) + $bomFixed += $script.Name + } +} +if ($bomFixed.Count -gt 0) { + Write-Warn "已为下列脚本补回 UTF-8 BOM:$($bomFixed -join '、')(下次编辑请保留 BOM)" +} else { + Write-Ok ".ps1 编码正常(UTF-8 with BOM)" +} + # ---------- 1. 图标 ---------- if (-not $SkipIcon) { Write-Bold "1. Windows 图标(.ico)" diff --git a/tools/make_dmg.py b/tools/make_dmg.py index cef9ed7..eb5e18b 100644 --- a/tools/make_dmg.py +++ b/tools/make_dmg.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """把打包好的 .app 制作成可分发的 DMG 安装包。 -产物:dist/虚拟定位轨迹-1.0.0.dmg +产物:dist/iOSLocationTrack-1.1.0_mac.dmg 内容:应用本身 + Applications 快捷方式(拖进去即安装)+ 中文安装说明 特点: @@ -25,9 +25,11 @@ from pathlib import Path ROOT = Path(__file__).resolve().parent.parent APP_NAME = "虚拟定位轨迹" -VERSION = "1.0.0" +VERSION = "1.1.0" APP = ROOT / "dist" / f"{APP_NAME}.app" -DMG = ROOT / "dist" / f"{APP_NAME}-{VERSION}.dmg" +# 产物名带 _mac 后缀,与 Windows 的 _win 对应,Release 页面上一眼能分清平台。 +# 用 ASCII 文件名:GitHub Release 会把非 ASCII 字符剥掉(v1.0.0 首次上传时踩过)。 +DMG = ROOT / "dist" / f"iOSLocationTrack-{VERSION}_mac.dmg" VOLUME = APP_NAME BG_WIDTH, BG_HEIGHT = 600, 400