.NET MAUI CLI(maui 命令)设计指南:统一 Android/iOS 环境配置、设备发现与应用检查
2026/9/13 5:28:53 网站建设 项目流程

.NET MAUI CLI(maui 命令)设计指南:统一 Android/iOS 环境配置、设备发现与应用检查

【免费下载链接】maui.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.项目地址: https://gitcode.com/GitHub_Trending/ma/maui

maui是 .NET MAUI 仓库设计文档(docs/design/cli.md)所规划的官方命令行工具,目标是为跨 Android、iOS、macOS、Windows、Mac Catalyst 的 MAUI 开发提供统一的设备管理与环境配置接口。本文以其设计文档为主体,结合仓库 CI 流水线中的实际使用方式(eng/pipelines/common/provision.yml),完整介绍安装调用、全部子命令、设备发现策略、IDE 集成架构与未来规划,让读者既能直接上手使用,也能理解其底层设计取舍。

背景与动机:为什么要为 MAUI 单独做一个 CLI

.NET MAUI 横跨多个平台,而各平台的原生工具链各自为政。文档以截图为例指出平台差异之痛:

  • 在 iOS 上截屏需要xcrun simctl io booted screenshot
  • 在 Android 上则需要adb exec-out screencap

日志访问、可视树检查、设备管理同样存在各自的平台专属实现。这种碎片化对两类用户尤其不友好:

  1. 人类开发者:需要在记忆多套平台命令之间来回切换;
  2. AI Agent:源于仓库作者此前用 WPF 进行的 "vibe coding" 实验(vibe-wpf),实验证明:只要给 AI Agent 合适的工具,它就能高效开发应用;而 MAUI 跨平台命令的碎片化,恰恰是 Agent 自动化开发的最大障碍。

mauiCLI 的定位,就是用一个统一的接口覆盖这些平台专属操作,同时保持与现有dotnet工作流(dotnet rundotnet watch)的兼容。

设计原则

文档为 CLI 确立了五条设计原则:

  1. 委托给原生工具链——maui自身不重新实现底层能力,而是封装sdkmanageradbxcrun simctl等现成工具;
  2. 复用共享库——Android 侧复用dotnet/android-toolsXamarin.Android.Tools.AndroidSdk)做 SDK/JDK 发现,并把 JDK 安装、SDK 引导、许可接受等新能力回馈给该库;
  3. 机器优先输出——每个命令都支持--json结构化输出;
  4. 无状态——每个命令"读状态、执行、退出",不维护会话;
  5. 补充dotnet run——沿用dotnet run对 .NET MAUI 定义的设备标识符与框架选项,二者互补而非竞争。

五大目标

  • 环境设置:用单一工具管理 Android SDK/JDK、Xcode 运行时、模拟器与仿真器;
  • 截图捕获:让 AI Agent 能对运行中的 .NET MAUI 应用截图,用于验证视觉变更;
  • 日志访问:统一访问各平台设备日志(logcat、Console 等);
  • 可视树检查:让 Agent 能检查运行时可视树的结构与属性(.NET MAUI 可视树);
  • 开发者体验:无缝融入现有dotnetCLI 工作流,与dotnet rundotnet watch等协同。

安装与调用方式

CLI 支持三种调用形态:

# 1. 直接调用(安装后) maui screenshot -o screenshot.png # 2. 通过 .NET CLI dotnet maui screenshot -o screenshot.png # 3. 内联安装并调用(无需预先安装) dotnet tool exec -y Microsoft.Maui.Cli screenshot -o screenshot.png

安装方式则分全局与本地两种:

# 作为全局工具 dotnet tool install --global Microsoft.Maui.Cli # 作为本地工具(推荐用于项目) dotnet tool install Microsoft.Maui.Cli # 还原本地工具 dotnet tool restore

工具安装后以maui命令出现在 PATH 上,本文档中所有命令均使用maui形式。

关于自动安装的规划:.NET workload 规范中的tools-packs特性支持从 workload 自动安装工具,但该特性目前尚未实现。一旦可用,Microsoft.Maui.Cli有望在mauiworkload 安装时自动装上,省去手动安装步骤;在那之前,dotnet tool install仍是标准途径。

全局选项

所有命令都支持以下全局选项:

标志说明
--json结构化 JSON 输出
--verbose详细日志
--interactive控制交互提示(默认:终端中为true;CI 环境或输出被重定向时为false
--dry-run预演动作,不真正执行
--platform <p>按平台过滤:androidiosmaccatalystwindows

交互检测机制dotnetCLI 保持一致:自动识别 CI 环境变量(TF_BUILDGITHUB_ACTIONSCI等),并检测Console.IsOutputRedirected,据此决定是否弹出交互提示。这意味着在 CI 中不加参数也能安全地非交互执行。

环境设置命令

Android

命令说明
maui android install安装 JDK + SDK + 推荐包
maui android install --accept-licenses非交互安装
maui android install --packages <list>安装指定包
maui android jdk check检查 JDK 状态
maui android jdk install安装 OpenJDK 21
maui android jdk list列出已安装的 JDK
maui android sdk list列出已安装的包
maui android sdk list --available显示可安装的包
maui android sdk install <packages>安装指定包
maui android sdk accept-licenses接受所有许可
maui android sdk uninstall <package>卸载指定包
maui android emulator list列出仿真器
maui android emulator create <name>创建仿真器(自动探测系统镜像)
maui android emulator start <name>启动仿真器
maui android emulator stop <name>停止仿真器
maui android emulator delete <name>删除仿真器

安装路径与默认值由dotnet/android-tools处理。

Apple(仅 macOS)

命令说明
maui apple install [--accept-license] [--runtime <version>]可选接受 Xcode 许可并安装模拟器运行时;未来可能提示用户安装 Xcode
maui apple check检查 Xcode、运行时与环境状态
maui apple xcode check检查 Xcode 安装与许可
maui apple xcode list列出 Xcode 安装
maui apple xcode select <path>切换当前 Xcode
maui apple xcode accept-license接受 Xcode 许可
maui apple simulator list列出模拟器
maui apple simulator create <name> <type> <runtime>创建模拟器
maui apple simulator start <id>启动模拟器
maui apple simulator stop <id>停止模拟器
maui apple simulator delete <id>删除模拟器
maui apple runtime check检查运行时状态
maui apple runtime list列出已安装的运行时
maui apple runtime list --all列出所有运行时(已安装 + 可下载)
maui apple runtime install <version>安装 iOS 运行时

许可标志命名差异:Android 用accept-licenses(复数),因为sdkmanager要求接受多个 SDK 组件的许可;Apple 用accept-license(单数),因为xcodebuild -license accept接受的是统一的 Xcode 许可协议。

底层实现参考

Android 侧委托给dotnet/android-toolsXamarin.Android.Tools.AndroidSdk):

功能实现
SDK 发现、引导与许可接受SdkManager
JDK 发现与安装JdkInstaller
ADB 设备管理AdbRunner
AVD / 仿真器管理AvdManagerRunnerEmulatorRunner

Apple 侧直接封装原生工具链:

功能原生工具
模拟器管理xcrun simctl(list、create、boot、shutdown、delete)
运行时管理xcrun simctl runtime(list、add)
Xcode 管理xcode-selectxcodebuild -license
设备检测xcrun devicectl list devices(真机)、xcrun simctl list(模拟器)

Apple 操作通过 AppleDev.Tools 封装simctldevicectl

退出码约定

所有命令使用统一的退出码:

代码含义
0成功
1一般错误
2环境/配置错误
3权限被拒绝(需要提权)
4网络错误(下载失败)
5资源未找到

仓库中的实际落地:CI 已经用起来了

这份设计并非纸上谈兵——.NET MAUI 仓库自己的 CI 流水线已经实际使用了mauiCLI。在 eng/pipelines/common/provision.yml 中:

  • 环境准备阶段通过dotnet build -t:ProvisionJdk ...-t:ProvisionAndroidSdkCommonPackages ...等 MSBuild target 调用 CLI 安装 JDK 与 SDK,任务显示名直接标注为 "(maui cli)";
  • 随后用dotnet maui android sdk check --ci --json做非交互检查,并解析其 JSON 输出:读取status字段判断 SDK 是否可用,读取details.path得到首选 SDK 路径,进而设置ANDROID_SDK_ROOTANDROID_HOME两个环境变量。

这恰好印证了设计文档的两点:--json机器优先输出真的被 CI 消费;--ci之类隐式关闭交互的标志让流水线可以安全地非交互执行。同时说明 Android 侧还存在文档命令表之外的maui android sdk check检查命令(返回含statusdetails.path的 JSON 结构)。

设备发现:maui device list

maui device list用一条命令列出所有平台的已连接设备、运行中的仿真器和可用模拟器:

maui device list [--platform <p>] [--json]

选项:

  • --platform <PLATFORM>:按平台过滤(androidiosmaccatalyst);省略则列出所有平台;
  • --json:结构化 JSON 输出,供机器消费。

人类可读输出:

ID Description Type Platform Status emulator-5554 Pixel 7 - API 35 Emulator android Online 0A041FDD400327 Pixel 7 Pro Device android Online 94E71AE5-8040-4DB2-8A9C-6CD24EF4E7DE iPhone 16 - iOS 26.0 Simulator ios Shutdown FBF5DCE8-EE2B-4215-8118-3A2190DE1AD7 iPhone 14 - iOS 26.0 Simulator ios Booted AF40CC64-2CDB-5F16-9651-86BCDF380881 My iPhone 15 Device ios Paired

JSON 输出(--json):

{ "devices": [ { "id": "emulator-5554", "description": "Pixel 7 - API 35", "type": "Emulator", "platform": "android", "status": "Online" }, { "id": "FBF5DCE8-EE2B-4215-8118-3A2190DE1AD7", "description": "iPhone 14 - iOS 26.0", "type": "Simulator", "platform": "ios", "status": "Booted" } ] }

关键兼容性设计:输出中的id字段与dotnet run --device <id>接受的标识符完全一致,因此maui device list的结果可以直接管道给运行命令使用。

设备枚举的两种途径

途径 A:通过dotnet run --list-devices(基于项目)

.NET SDK(≥ .NET 11)提供dotnet run --list-devices,它会调用各平台 workload 定义的ComputeAvailableDevicesMSBuild target:

  • Android:调用adb devices,返回序列号、描述、类型(Device/Emulator)、状态、型号;
  • Apple:调用simctl listdevicectl list,返回 UDID、描述、类型(Device/Simulator)、OS 版本、RuntimeIdentifier。

该途径必须存在项目文件——MSBuild 需要评估.csproj才能定位正确的 workload targets;同时它是按框架工作的:先选一个目标框架,再获取该平台下的设备。

途径 B:直接调用原生工具(无需项目)

mauiCLI 直接调用adb devicesxcrun simctl list devicesxcrun devicectl list devices,不评估任何 MSBuild 项目,一次调用即可拿到统一、跨平台的设备列表。

对比
维度途径 A(MSBuild)途径 B(原生 CLI)
需要项目是——需要.csproj
跨平台每次调用一个平台(按 TFM)一次调用覆盖所有平台
元数据丰富(RuntimeIdentifier、workload 专属字段)标准(id、description、type、status)
速度较慢(MSBuild 评估 + restore)快(<2s,直接进程调用)
ID 兼容性dotnet run --device的权威来源相同的原生 ID——兼容
需要 workload是(必须安装平台 workload)否(只需原生工具adbsimctl
可扩展性workload 自动添加新设备类型每平台需单独添加支持

没有项目时的真实场景

以下工作流在项目创建前或项目上下文之外就需要设备枚举:

  1. AI Agent 引导——Agent 启动 "vibe coding" 会话时,要在脚手架项目之前先发现可用目标,此时还没有.csproj,无法调用dotnet run --list-devices
  2. IDE 启动——VS Code 打开的工作区尚未加载 MAUI 项目,扩展需要填充设备选择器向用户展示可用设备,无项目查询是唯一选择;
  3. 环境验证——开发者在任意目录运行maui device list回答"能不能看到我的手机",这是诊断步骤而非构建步骤;
  4. CI 流水线设置——CI 脚本在调用dotnet run之前检查预期仿真器/模拟器是否在运行,检查不应依赖具体项目文件;
  5. 多项目解决方案——解决方案同时含 Android 与 iOS 项目,开发者想要一个统一的设备列表,而不是逐项目跑--list-devices
  6. 跨平台总览——dotnet run --list-devices一次只显示一个 TFM 的设备,而同时切 Android/iOS 的开发者想一眼看全。

推荐方案

maui device list途径 B(直接调用原生工具)为主实现,理由:

  • 随处可用——不需要项目、workload targets,也没有 MSBuild 评估开销;
  • 设备标识符与ComputeAvailableDevices产出的原生 ID 相同,与dotnet run --device完全兼容;
  • mauiCLI 本来就要为其他命令(环境设置、仿真器管理)封装这些原生工具,设备列表是自然延伸。

而当项目可用且需要框架级设备过滤时,dotnet run --list-devices仍是正确工具——它提供更丰富的元数据(RuntimeIdentifier)且受益于 workload 专属逻辑。两者互补:

maui device list → "这台机器上存在哪些设备?" dotnet run --list-devices → "哪些设备能运行这个项目?"

各平台枚举实现:

平台原生工具枚举内容
Androidadb devices -l真机与运行中的仿真器
iOS(模拟器)xcrun simctl list devices --json所有模拟器(已启动 + 已关机)
iOS(真机)xcrun devicectl list devices已连接的真机
Mac Catalyst(宿主机器)Mac 本身

应用检查命令(规划中)

应用检查命令计划在后续版本发布;首个版本聚焦环境设置与设备管理。

设备选择选项

应用检查命令将沿用dotnet run对 .NET MAUI 约定的设备选择与框架选项:

-f|--framework <FRAMEWORK> Target framework (e.g., net10.0-android, net10.0-ios) -d|--device <DEVICE_ID> Target device identifier (from --list-devices) --list-devices List available devices/emulators/simulators -p|--project <PATH> Path to the .NET MAUI project (default: current directory) -h|--help Show help information --version Show version information

交互提示行为:

  • 未指定-f|--framework时:
    • 若存在项目文件且含多个目标框架,CLI 提示选择一个;
    • 若无项目文件,CLI 从已知 .NET MAUI 目标框架中提示(如net10.0-androidnet10.0-iosnet10.0-maccatalystnet10.0-windows)。
  • 已选框架但未指定-d|--device时:
    • CLI 提示从该平台可用的设备/仿真器/模拟器中选择;
    • 设备列表来自与dotnet run相同的ComputeAvailableDevicesMSBuild target。

注意:-d|--device使用的设备标识符与dotnet run --list-devices返回的一致。

screenshot命令

捕获正在运行的 .NET MAUI 应用的截图。

用法:

maui screenshot [options]

选项:

  • -o|--output <PATH>:输出文件路径(默认:screenshot_{timestamp}.png);
  • -w|--wait <SECONDS>:捕获前等待秒数(默认:0)。

平台实现:

首个版本覆盖 Android 与 iOS/Mac Catalyst,Windows 与 macOS 支持按规划随后跟进。

  • Android:使用adb exec-out screencap -p
  • iOS/Mac Catalyst:模拟器用xcrun simctl io booted screenshot <file>;真机捕获走 Xcode 工具链(未来);
  • Windows(规划):用 Windows 屏幕捕获 API 捕获活动应用窗口或全屏;
  • macOS(规划):用 macOS 屏幕捕获 API 或命令行工具捕获活动应用窗口或全屏。

未来命令清单

  • maui screenshot—— 捕获运行中应用的截图;
  • maui logs—— 流式输出设备日志;
  • maui tree—— 检查可视树。

dotnet rundotnet watch的集成

CLI 被设计为与现有 .NET 工作流无缝协同:

常规工作流示例

# 终端 1:带热重载运行应用 dotnet watch run # 终端 2:检查应用 maui screenshot --output iteration1.png maui logs --follow --filter "MyApp" # 未来 maui tree --json # 未来

AI Agent 工作流

# 0. 发现可用设备(无需项目) maui device list --json # 1. 修改代码 # ... agent modifies MainPage.xaml ... # 2. 等待热重载完成 sleep 2 # 3. 捕获截图 maui screenshot -o current.png # 4. 分析可视树(未来) maui tree --json # 5. 检查日志错误(未来) maui logs --level error # 6. Agent 分析输出并决定下一步

这个闭环——改代码 → 热重载 → 截图 → 分析可视树 → 查日志——正是为 AI Agent 的"感知-行动"循环设计的,也是"vibe coding"在 MAUI 上得以成立的基础设施。

平台专属考量

Android

  • 设备检测adb devices
  • 截图adb exec-out screencap -p或 UI Automator;
  • 日志:带包过滤的adb logcat

iOS / Mac Catalyst

  • 设备检测xcrun simctl list devices(模拟器)、xcrun devicectl list devices(真机)——经 AppleDev.Tools 封装;
  • 截图xcrun simctl io booted screenshot <file>(模拟器),iOS 真机(未来);
  • 日志xcrun simctl spawn booted log stream或 Console.app(模拟器)、mlaunch --logdev(真机)。

安全与隐私

CLI 仅面向开发与调试场景,设计上有三重约束:

  1. 仅调试构建:功能应在Release构建中通过 trimmer 特性标志或#if DEBUG条件禁用;
  2. 复用现有基础设施:优先复用调试器、Hot Reload 等既有传输机制,不创建新的通信通道;
  3. 不暴露给生产环境:除使用操作系统标准能力(如截图、日志)外,CLI 不应能作用于生产应用。

IDE 集成

mauiCLI 及其底层库被设计为 IDE 扩展的共享后端,消除各工具间重复的环境检测与设置逻辑。

架构

┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ VS Code ext │ │ Visual Studio │ │ AI Agent │ │ (vscode-maui) │ │ extension │ │ (Copilot, etc.) │ └────────┬─────────┘ └────────┬──────────┘ └────────┬─────────┘ │ │ │ spawns CLI references NuGet spawns CLI │ library directly │ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌────────────────────┐ ┌──────────────┐ │ maui CLI │ │ android-tools │ │ maui CLI │ │ (process) │ │ (in-process) │ │ (--json) │ └──────┬───────┘ └────────┬───────────┘ └──────┬───────┘ │ │ │ └─────────┬───────────┴───────────────────────┘ │ spawns native tools ┌───────────┼───────────┐ ▼ ▼ ▼ ┌───────────┐ ┌──────────┐ ┌──────────┐ │ adb │ │ xcrun │ │ Windows │ │ sdkmanager│ │ simctl │ │ SDK │ └───────────┘ └──────────┘ └──────────┘

集成模式

消费方集成方式理由
Visual Studio扩展直接引用android-toolsNuGet 包(进程内).NET 扩展——无序列化开销,直接 API 访问
VS Codevscode-maui派生mauiCLI 进程,解析--jsonstdoutTypeScript 扩展——CLI 是自然的进程边界
AI Agent / CI--json调用mauiCLI基于进程、语言无关
终端(人类)直接调用mauiCLI默认人类可读输出,需要时用--json

Visual Studio 直接消费dotnet/android-tools中的Xamarin.Android.Tools.AndroidSdkNuGet 包——与 CLI 内部用的是同一个库,既避免了进程开销,又给 VS 扩展完整的 API 访问权;非 .NET 消费方(VS Code、AI Agent、CI)则以 CLI 为规范接口。

IDE 如何使用

工作流CLI 命令IDE 行为
工作区打开maui apple check --jsonmaui android jdk check --json在状态栏 / 问题面板显示环境状态
环境修复maui android install --json显示进度条,流式处理type: "progress"消息
设备选择器maui device list --json填充设备下拉框 / 选择 UI
仿真器启动maui android emulator start <name> --json显示通知,完成后更新设备列表

收益

  • 行为一致——VS、VS Code、CLI 通过共享库使用同一套检测与设置逻辑;
  • 单一维护点——android-tools的缺陷修复自动传播到所有消费方;
  • AI 就绪——Agent 消费与 VS Code 相同的--json输出;
  • 集成灵活——.NET 消费方进程内集成,其余走 CLI。

当前状态

集成状态
VS Code 扩展(vscode-maui✅ 进行中
Visual Studio 扩展规划中(vNext)
GitHub Copilot / AI Agent✅ 通过--json输出支持

未来目标

MCP Server 的取舍

CLI 设计过程中曾考虑提供 MCP(Model Context Protocol)服务器,但最终结论是:先做 CLI。AI Agent 可以通过copilot-instructions.md中的示例直接使用 CLI 命令,无需自定义 MCP 服务器。若 CLI 完成后确实证明 MCP 服务器有价值,届时再以薄封装形式把 CLI 操作暴露为 MCP 协议——Visual Studio 与 VS Code 扩展都提供分发 MCP 服务器的选项,大概率会通过 .NET MAUI 工具链实现。

更多子命令

环境设置命令(Android SDK/JDK、Xcode、仿真器、模拟器)灵感来自既有社区项目:

  • .NET MAUI "Check" / "Doctor" 类工具(如dotnet-maui-checkmaui-cli);
  • Android SDK 管理工具(如AndroidSdk.Tools)。

规划中的命令:maui logs(查看控制台输出)、maui tree(显示可视树)、maui screenshot(捕获截图)。

决策:环境设置与设备列表先发布,应用检查命令在后续版本跟进。

总结

mauiCLI 的设计体现了清晰的取舍:委托原生工具链保证能力与生态兼容,--json机器优先输出让 AI Agent 与 CI 成为一等公民,复用共享库让 Visual Studio、VS Code 与 CLI 保持行为一致且单一维护。它不以替代dotnet run为目标,而是补齐后者在"无项目场景"下的设备发现与"运行中应用"的检查能力。对本文档与设计细节感兴趣的读者,可进一步阅读仓库中的 docs/design/cli.md 原文,并在 eng/pipelines/common/provision.yml 中看到它在真实 CI 流水线中的落地用法。

【免费下载链接】maui.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.项目地址: https://gitcode.com/GitHub_Trending/ma/maui

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询