chore(release): v1.1.0 — 版本号 1.0.0 → 1.1.0,README 双语化,构建脚本编码自检

版本号 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
This commit is contained in:
jbjf6666 committed 2026-10-16 01:51:50 +08:00
1 parent 4d55e2415f
commit c60e4b5cd4
10 files changed
+380 -25

No files matched your search

+3 -3
View File
@@ -207,12 +207,12 @@ else:
name="虚拟定位轨迹.app", name="虚拟定位轨迹.app",
icon=str(ROOT / "resources" / "AppIcon.icns"), icon=str(ROOT / "resources" / "AppIcon.icns"),
bundle_identifier="com.local.ios-location-track", bundle_identifier="com.local.ios-location-track",
version="1.0.0", version="1.1.0",
info_plist={ info_plist={
"CFBundleName": "虚拟定位轨迹", "CFBundleName": "虚拟定位轨迹",
"CFBundleDisplayName": "虚拟定位轨迹", "CFBundleDisplayName": "虚拟定位轨迹",
"CFBundleShortVersionString": "1.0.0", "CFBundleShortVersionString": "1.1.0",
"CFBundleVersion": "1.0.0", "CFBundleVersion": "1.1.0",
"CFBundlePackageType": "APPL", "CFBundlePackageType": "APPL",
"CFBundleIconFile": "AppIcon", "CFBundleIconFile": "AppIcon",
"CFBundleIconName": "AppIcon", "CFBundleIconName": "AppIcon",
+13 -4
View File
@@ -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 > userspace stack — no Wintun driver needed), detects and auto-installs Apple Mobile Device
> Support on first launch, and shows an environment self-check window. > Support on first launch, and shows an environment self-check window.
> Build outputs: `dist\iOSLocationTrack\iOSLocationTrack.exe` and > 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) ### 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` | Platform | Filename | Notes |
2. If macOS says *"unidentified developer"* on first launch → **right-click → Open → Open** | --- | --- | --- |
| **Windows** | `iOSLocationTrack-<version>_win-setup.exe` | Installer. A portable ZIP is also provided — just unzip and run |
| **macOS** | `iOSLocationTrack-<version>_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). **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/`. Config and tile cache are written to `~/Library/Application Support/iOSLocationTrack/`.
+12 -4
View File
@@ -12,7 +12,7 @@
> Windows 版:免管理员建立隧道(纯 Python 用户态协议栈,不需要 Wintun 驱动)、 > Windows 版:免管理员建立隧道(纯 Python 用户态协议栈,不需要 Wintun 驱动)、
> 启动时自动检测并安装 Apple Mobile Device Support、带「环境准备」自检窗口。 > 启动时自动检测并安装 Apple Mobile Device Support、带「环境准备」自检窗口。
> 构建产物:`dist\iOSLocationTrack\iOSLocationTrack.exe` 与 > 构建产物:`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)。 **不需要安装 Python、不需要任何依赖**,Python 运行时与全部依赖都已打包在应用内(约 80 MB)。
数据(配置、瓦片缓存)写到 `~/Library/Application Support/iOSLocationTrack/`。 数据(配置、瓦片缓存)写到 `~/Library/Application Support/iOSLocationTrack/`。
+1 -1
View File
@@ -11,7 +11,7 @@ import uuid
from typing import Any from typing import Any
APP_NAME = "iOS 虚拟定位轨迹工具" APP_NAME = "iOS 虚拟定位轨迹工具"
APP_VERSION = "1.0.0" APP_VERSION = "1.1.0"
PROTOCOL_VERSION = "v1" PROTOCOL_VERSION = "v1"
DEFAULT_HOST = "127.0.0.1" DEFAULT_HOST = "127.0.0.1"
+313
View File
@@ -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.
+4 -2
View File
@@ -1,5 +1,7 @@
# Windows 版说明(iOS 虚拟定位轨迹工具) # Windows 版说明(iOS 虚拟定位轨迹工具)
[**中文**](README-WINDOWS.md) | [English](README-WINDOWS.en.md)
> 本文档面向 Windows 用户与维护者。 > 本文档面向 Windows 用户与维护者。
> macOS 侧说明见 [README.md](../README.md);移植决策与背景见 [WINDOWS_PORT.md](WINDOWS_PORT.md)。 > macOS 侧说明见 [README.md](../README.md);移植决策与背景见 [WINDOWS_PORT.md](WINDOWS_PORT.md)。
@@ -7,7 +9,7 @@
## 1. 三分钟上手 ## 1. 三分钟上手
1. 运行 `iOSLocationTrack-1.0.0-setup.exe` 安装,或直接双击绿色版 1. 运行 `iOSLocationTrack-1.1.0_win-setup.exe` 安装,或直接双击绿色版
`dist\iOSLocationTrack\iOSLocationTrack.exe`。 `dist\iOSLocationTrack\iOSLocationTrack.exe`。
2. **程序会请求管理员权限**(UAC 弹窗点「是」)—— 用于首次自动安装 Apple 驱动。 2. **程序会请求管理员权限**(UAC 弹窗点「是」)—— 用于首次自动安装 Apple 驱动。
3. 弹出**「环境准备」**窗口,逐项列出所需组件: 3. 弹出**「环境准备」**窗口,逐项列出所需组件:
@@ -183,7 +185,7 @@ Windows 上这样行不通:
| 文件 | 说明 | | 文件 | 说明 |
| --- | --- | | --- | --- |
| `dist\iOSLocationTrack\iOSLocationTrack.exe` | 绿色版 onedir,整个目录一起拷走 | | `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) |
**前置条件:** **前置条件:**
+4 -3
View File
@@ -4,7 +4,7 @@
; 1) .venv\Scripts\python.exe -m PyInstaller --clean --noconfirm Location.spec ; 1) .venv\Scripts\python.exe -m PyInstaller --clean --noconfirm Location.spec
; 2) "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" installer\iosloc.iss ; 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 ; - 安装包**不包含** Apple 的驱动。程序首次启动时会自动检测 Apple Mobile Device
@@ -14,7 +14,7 @@
#define MyAppName "iOS 虚拟定位轨迹工具" #define MyAppName "iOS 虚拟定位轨迹工具"
#define MyAppNameEn "iOSLocationTrack" #define MyAppNameEn "iOSLocationTrack"
#define MyAppVersion "1.0.0" #define MyAppVersion "1.1.0"
#define MyAppPublisher "本地工具" #define MyAppPublisher "本地工具"
#define MyAppExeName "iOSLocationTrack.exe" #define MyAppExeName "iOSLocationTrack.exe"
#define DistDir "..\dist\iOSLocationTrack" #define DistDir "..\dist\iOSLocationTrack"
@@ -32,7 +32,8 @@ DisableProgramGroupPage=yes
PrivilegesRequired=lowest PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog PrivilegesRequiredOverridesAllowed=dialog
OutputDir=..\dist\installer OutputDir=..\dist\installer
OutputBaseFilename={#MyAppNameEn}-{#MyAppVersion}-setup ; 产物名带 _win 后缀,与 macOS 的 _mac 对应,Release 页面上一眼能分清平台。
OutputBaseFilename={#MyAppNameEn}-{#MyAppVersion}_win-setup
SetupIconFile=..\resources\AppIcon.ico SetupIconFile=..\resources\AppIcon.ico
UninstallDisplayIcon={app}\{#MyAppExeName} UninstallDisplayIcon={app}\{#MyAppExeName}
Compression=lzma2/max Compression=lzma2/max
+4 -4
View File
@@ -2,8 +2,8 @@
# 语法见 https://learn.microsoft.com/windows/win32/menurc/versioninfo-resource # 语法见 https://learn.microsoft.com/windows/win32/menurc/versioninfo-resource
VSVersionInfo( VSVersionInfo(
ffi=FixedFileInfo( ffi=FixedFileInfo(
filevers=(1, 0, 0, 0), filevers=(1, 1, 0, 0),
prodvers=(1, 0, 0, 0), prodvers=(1, 1, 0, 0),
mask=0x3f, mask=0x3f,
flags=0x0, flags=0x0,
OS=0x40004, OS=0x40004,
@@ -18,12 +18,12 @@ VSVersionInfo(
[ [
StringStruct('CompanyName', '本地工具'), StringStruct('CompanyName', '本地工具'),
StringStruct('FileDescription', 'iOS 虚拟定位轨迹工具'), StringStruct('FileDescription', 'iOS 虚拟定位轨迹工具'),
StringStruct('FileVersion', '1.0.0.0'), StringStruct('FileVersion', '1.1.0.0'),
StringStruct('InternalName', 'iOSLocationTrack'), StringStruct('InternalName', 'iOSLocationTrack'),
StringStruct('LegalCopyright', '本地工具,用于自有 App 的定位功能测试'), StringStruct('LegalCopyright', '本地工具,用于自有 App 的定位功能测试'),
StringStruct('OriginalFilename', 'iOSLocationTrack.exe'), StringStruct('OriginalFilename', 'iOSLocationTrack.exe'),
StringStruct('ProductName', 'iOS 虚拟定位轨迹工具'), StringStruct('ProductName', 'iOS 虚拟定位轨迹工具'),
StringStruct('ProductVersion', '1.0.0.0'), StringStruct('ProductVersion', '1.1.0.0'),
], ],
) )
]), ]),
+21 -1
View File
@@ -2,7 +2,7 @@
# #
# 产出: # 产出:
# dist\iOSLocationTrack\iOSLocationTrack.exe 绿色版(直接双击运行) # 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) # .\scripts\build.ps1 # 打包 exe + 安装包(若装了 Inno Setup)
@@ -49,6 +49,26 @@ if ($LASTEXITCODE -ne 0) {
} }
Write-Ok "PyInstaller / Pillow 就绪" 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. 图标 ---------- # ---------- 1. 图标 ----------
if (-not $SkipIcon) { if (-not $SkipIcon) {
Write-Bold "1. Windows 图标(.ico)" Write-Bold "1. Windows 图标(.ico)"
+5 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""把打包好的 .app 制作成可分发的 DMG 安装包。 """把打包好的 .app 制作成可分发的 DMG 安装包。
产物:dist/虚拟定位轨迹-1.0.0.dmg 产物:dist/iOSLocationTrack-1.1.0_mac.dmg
内容:应用本身 + Applications 快捷方式(拖进去即安装)+ 中文安装说明 内容:应用本身 + Applications 快捷方式(拖进去即安装)+ 中文安装说明
特点: 特点:
@@ -25,9 +25,11 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent ROOT = Path(__file__).resolve().parent.parent
APP_NAME = "虚拟定位轨迹" APP_NAME = "虚拟定位轨迹"
VERSION = "1.0.0" VERSION = "1.1.0"
APP = ROOT / "dist" / f"{APP_NAME}.app" 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 VOLUME = APP_NAME
BG_WIDTH, BG_HEIGHT = 600, 400 BG_WIDTH, BG_HEIGHT = 600, 400