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:
1 parent
4d55e2415f
commit
c60e4b5cd4
10 files changed
+380
-25
No files matched your search
@@ -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.
|
||||
@@ -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) |
|
||||
|
||||
**前置条件:**
|
||||
|
||||
|
||||
Reference in new issue
Block a user