在计算机上生成,然后在Windows沙盒中运行并自动执行应用:
winapp run . --on sandbox --detach
winapp ui inspect --on sandbox -a MyApp
winapp ui invoke --on sandbox SubmitButton -a MyApp
将 MyApp 替换为你的应用名称或由 run 打印的来宾 PID。
--detach 在启动后返回,以便下一个命令可以检查应用;如果没有它, run 请等待应用退出。 沙盒在执行命令和重新构建之间会持续运行。
在您开始之前
- 在受支持的版本中使用 Windows 11 24H2 或更高版本,并启用硬件虚拟化。
- 来宾 winapp 支持 x64 和 Arm64。 x86 应用需要来宾环境支持才能运行,并且其依赖项也必须与 x86 匹配;x64 运行时不能满足 x86 应用的要求。
- 保持主机会话处于未锁定状态,以便进行实际输入和屏幕捕获。
在打开或关闭Windows功能中启用Windows沙盒,或者从管理员终端运行此功能:
dism.exe /Online /Enable-Feature /FeatureName:Containers-DisposableClientVM /All /NoRestart
保存工作并在准备就绪时重启Windows。 然后从“开始”菜单打开Windows沙盒,并完成任何客户端安装或更新。 winapp 不启用该功能、安装客户端、请求提升或重启Windows。 如果缺少先决条件,则会停止运行并提供设置说明;检测到的 Windows 挂起重启将单独报告。
冷连接或重新连接可以短暂地集中注意力。 连接后,winapp 会保持自己的客户端窗口屏幕外,而无需激活它。 由你手动打开的沙盒窗口将保留在原处。
Important
构建仍在你的计算机上运行。 项目评估、还原和编译不是彼此独立的。
--on sandbox 并不会使不受信任的项目可以安全构建。
一个沙盒是一个共享环境。 其中的应用和工作流共享用户、桌面、注册表、包、运行时和网络访问权限。 它们可以观察或相互干扰。 将单独的计算机用于互不受信任的工作流。
Windows 同一时间只允许使用一个沙盒。 winapp 重复使用正在运行的实例,包括你自己打开的实例。 进行准备后,会添加 winapp 的共享引导文件夹、来宾代理、开发人员模式以及一条入站防火墙规则。 winapp 不会停止采用的实例或删除不相关的应用。 不存在静默回退到主机环境的情况:请求在沙盒中运行的命令要么在那里运行,要么失败。
运行和重新构建
winapp run .\MyApp.csproj --on sandbox --detach --json
winapp run .\publish --on sandbox --detach
winapp run . --on sandbox --clean --detach
生成选项,例如--configuration,、--framework--arch、--property和--no-build--no-restore应用于主机上。 注册、启动和调试都在来宾系统中进行;应用不会注册到你的计算机上。
| 选项 | 沙盒中的效果 |
|---|---|
--detach |
启动后即返回,而非等待退出 |
--no-launch |
在不启动的情况下部署和注册 |
--clean |
重新安装此部署并清除其应用程序数据 |
--unregister-on-exit |
在应用退出后删除此包注册 |
--with-alias |
通过转发流启动其来宾执行别名 |
--debug-output |
流式传输来宾系统调试输出;仅限打包应用 |
解压缩的应用从已部署的文件夹启动其可执行文件。 他们没有可注册的软件包。
--debug-output 在未打包的沙盒运行中会被拒绝。
重新运行传输会传输已更改的文件,并删除构建输出中已删除的文件。
除非您请求--clean,否则应用数据会被保留。 未完成的部署无法启动;重试后会重新生成其客户机副本。 如果在 winapp 准备生成文件时生成文件发生更改,请完成生成并重试。
预热后的 UI 命令仅报告其结果,不会重复显示 Sandbox 准备消息。 沙盒启动和连接恢复仍会显示进度。 使用 --verbose 显示连接计时信息和诊断详细信息;--quiet 和 --json 不显示进度信息。
JSON 运行记录包括来宾进程 ID 和目标范围:
{
"ProcessId": 4212,
"Sandbox": true,
"ProcessScope": "sandbox",
"UiTargetArgs": "--on sandbox -a 4212",
"ExecutionTarget": {
"Kind": "sandbox",
"Id": "default",
"Architecture": "arm64",
"Epoch": "..."
}
}
这些字段是运行结果中的其他字段,而不是单独的文档。 检查应用时复制整个 UiTargetArgs 值: winapp ui inspect --on sandbox -a 4212。
在沙盒重新创建后,重新发现 PID 和窗口句柄;它们属于该沙盒代际,而不属于主机或未来的来宾。
独立应用和代理的生命周期
分离式未打包应用会在来宾代理程序停止时结束运行,包括在修复代理程序期间。
如果它在两条命令之间消失了,请使用 --detach 重新运行,并重新识别其 UI 目标。
等待应用退出而不是将其分离,这样可以观察到它何时退出;但这并不能让应用在代理丢失后继续存活。 打包应用使用 Windows 激活机制,而不是代理进程的生命周期。 关闭或重启沙盒将结束其中的所有应用。
共享运行时
winapp 会在启动前检查应用的包依赖项、Windows 应用 SDK 要求以及 *.runtimeconfig.json。 它会使用主机缓存或下载所需的有效负载,然后在 客户机中安装缺失的受支持运行时,而不是安装在您的计算机上。
包要求包括发布者、版本和体系结构。 共享.NET运行时选择遵循应用程序的配置的前滚策略和体系结构;不要假定同一主版本中的任何较新的运行时都适用。
如果不支持框架、运行时配置或依赖项,则命令在启动之前显式失败并标识要求。 执行该错误对应的操作。 在项目支持的情况下,以自包含方式发布后将无需相应的共享运行时;但这不会移除不相关的包依赖项。
自动化 UI
winapp ui list-windows --on sandbox
winapp ui inspect --on sandbox -a MyApp
winapp ui invoke --on sandbox SubmitButton -a MyApp
winapp ui screenshot --on sandbox -a MyApp -o .\result.png
每个 ui 动词都接受 --on sandbox。 应用名称、PID、窗口句柄和选择器均在客户机内部解析。 使用 -a/--app 或 -w/--window 用于应用目标命令;winapp 不会猜测上次启动的应用。 省略 --on sandbox 则会改为选择主机桌面。
真实输入和录制需要 已连接且未最小化的 Sandbox 客户端。 输入不能时,只读检查仍可正常工作。 winapp 可以在不激活它的情况下恢复其自身已最小化的客户端;手动打开并最小化的客户端必须由你来恢复。 如果重新连接后无法获得输入,命令将会失败,而不是声称已传递输入。 在错误中使用重新连接命令,然后重试。
使用 winapp target snapshot sandbox --json 检查桌面是否已就绪,而无需启动或重新连接沙盒。 识别的终端错误窗口不算作远程桌面。 如果 winapp 因仍在连接中或无法被检查而无法验证所选桌面,则就绪状态仍不可用;请等待后重试。 多个远程桌面仍然可能会造成混淆。 快照不会替你关闭这些窗口,也不会解决其中的错误。
有关选择器、输入方法和断言,请参阅 UI 自动化 。
协调沙盒中的 UI 工作流
使用一个 WINAPP_UI_WORKFLOW_ID 用于协作命令,对于每个独立工作流使用不同的值。
在每个调用上设置它,尤其是在代理为每个工具调用启动新的 shell 时。 winapp 会转发一个特定于沙盒代际的哈希标识;原始主机值不会被发送给来宾。
例如,使用相同值在两个终端中记录和交互。 为每个新工作流选择一个新值。
终端 1:
$env:WINAPP_UI_WORKFLOW_ID = 'myapp-checkout-01'
winapp ui record --on sandbox -a MyApp --duration-sec 20 --frames -o .\checkout.mp4
终端 2,录制进行时:
$env:WINAPP_UI_WORKFLOW_ID = 'myapp-checkout-01'
winapp ui invoke --on sandbox SubmitButton -a MyApp
$env:WINAPP_UI_WORKFLOW_ID = 'myapp-checkout-01'
winapp ui inspect --on sandbox -a MyApp
当录制和操作均完成后:
$env:WINAPP_UI_WORKFLOW_ID = 'myapp-checkout-01'
winapp ui yield --on sandbox
命名工作流在其最后一条命令之后会继续保留其 UI 控制权四秒钟;yield 会立即释放该控制权。 如果未指定 ID,则每个命令在完成后都会释放其轮次。
因此,一次无 ID 录制会在其持续期间阻止其他更改桌面的工作流。
只读检查无需等待。 主机和来宾的 UI 交互轮次彼此独立。
暂停后,再次检查并重新打开所需的任何菜单或对话框:另一个工作流可能已使用来宾桌面。 协作轮次不会将各个应用彼此隔离开来。
屏幕截图和录制
使用 ui 捕获应用窗口,或使用 target 捕获 整个原生来宾桌面,包括系统 shell 和安装程序对话框:
winapp ui record --on sandbox -a MyApp --duration-sec 10 --frames -o .\app.mp4
winapp target screenshot sandbox -o .\sandbox.png
winapp target record sandbox --duration-sec 20 --frames -o .\sandbox.mp4
输出会落在主机上,即使省略 -o 也是如此。 屏幕截图默认使用 screenshot.png;录制使用 recording-<timestamp>-<guid>.mp4。
对于录制内容,--frames 还会提供 <output-name>.frames 目录,其中包含 JPEG、frames.ndjson 和 manifest.json。 结果报告主机路径。 目标录制在来宾中运行;其主机文件会在录制结束且交付完成后可用。
target screenshot 等待来宾的 UI 轮次,而不激活任何窗口。
它排除主机沙盒窗口的标题栏和边框。 其 PNG 图像未经过缩放:以来宾屏幕原点 (0,0) 为基准时,图像坐标可直接用于 ui drag 或 ui touch --at 等坐标输入命令,配合使用 --on sandbox。
为具有负原点的桌面添加报告原点。
使用 --json 读取 coordinates.sourceBounds 和 coordinates.contentRect;二者都使用物理像素,且右边缘和下边缘为排他性边界。
目标录制在 JSON 和帧清单中报告相同的字段。 MP4 和 JPEG 帧共享映射,包括 --max-edge 缩放和编码器填充。 若要映射图像像素 (x,y),请先拒绝外部 contentRect的点,然后计算每个源坐标作为 sourceStart + floor((pixel - contentStart + 0.5) * sourceSize / contentSize)。
向下缩放会丢失精度;需要精确坐标时,请使用原生 PNG。 来宾桌面边界发生更改时,会通过 display_changed 停止录制,仅保留更改发生前的帧,并将帧清单标记为不完整。
默认情况下,现有 MP4 或配对 .frames 目录被拒绝。 使用新路径,或在新的录制完成后传递 --overwrite 来替换它们。 先前的帧捆绑会保留为 <output-name>.frames.previous-<id>,即使替换内容中省略了 --frames 也是如此。 失败的捕获使旧记录保持不变。
对于脚本和代理,首选正 --duration-sec 值。 npm 的 uiRecord 和 targetRecord 帮助程序需要 durationSec;它们的中止信号会强制取消,而不是正常停止。 有关支持的值,请参阅 ui record。
如果未通过 CLI 指定录制时长,录制将等待停止信号。
开始捕获后,按 Ctrl+C 可成功完成录制并返回 stopReason: cancelled。 其他中断可以保留有用的视频或帧。 读取 stopReason、partialOutput 和 recoveryHint(存在时),并使用所报告的证据路径,而不是假定正常完成。 如果在拍摄过程中整个桌面捕获变得不可用,它会以 capture_unavailable 停止,而不是继续捕获不可用的桌面。 它不会将沙盒切换到前台来挽救某一帧。 在提供任何可用证据之前,捕获可能会失败。
对于失败的来宾录制,恢复的证据会放在主机上唯一的 <output>.partial-<id> 目录中。 如果传送失败,已接收的文件将保留在所报告的恢复路径下(例如 <output>.recovery-<id>),且来宾原始文件会被保留。 在重试或关闭沙盒之前,请保持沙盒继续运行,并按照该错误提供的恢复操作执行。 保留的部分文件不一定是可播放的视频。
屏幕截图和视频可能包含敏感信息。 像对待 MP4 一样谨慎地处理帧目录。 有关记录选项和结果字段,请参阅 ui record。
检查沙盒
winapp target snapshot sandbox
winapp target snapshot sandbox --json
这会报告就绪情况、当前部署和来宾窗口,而无需创建 VM、重新连接客户端或修复代理。 如果当前没有 Sandbox 在运行,它会报告这一情况并成功退出。 若要启动一个,请使用 winapp run . --on sandbox --detach。
报告区分来宾支持的内容与当前客户端可以执行的操作;最小化的客户端可以阻止输入或捕获,即使来宾支持这两者。
使用来宾窗口列表获取 UI PID,而不是使用部署所跟踪的启动器进程。
JSON workRoot 字段(如 Work root 文本输出中所示)是相对文件传输路径的绝对基数,通常 C:\WinApp\work。 它独立于 C:\WinApp,通常为 capabilities.managedRoot;当客户机未报告其托管根时,则会省略。
如果多个客户端窗口导致无法明确捕获,错误信息会列出候选项;请先确定要关闭哪个窗口,然后再重试。
运行命令和复制文件
winapp target exec sandbox -- dotnet --info
$copy = winapp target push sandbox .\setup.ps1 Setup\setup.ps1 --json | ConvertFrom-Json
winapp target exec sandbox --cwd (Split-Path -Parent $copy.targetPath) -- powershell -ExecutionPolicy Bypass -File .\setup.ps1
winapp target pull sandbox Results .\results
使用 target exec 进行设置和诊断。 它作为来宾用户运行,转发标准流,并返回命令的退出代码。 它不是完整的交互式终端;控制台应用程序会看到重定向的管道。
--json 格式化的是 winapp 的错误信息,而不是子命令的标准输出(stdout)。
对于 push 和 pull,目标路径相对于由 target snapshot 报告的 workRoot。 绝对路径、根路径和 UNC 目标路径被拒绝。 单个文件会准确放到你指定的目标位置;目录则会在该目标位置下保留其原有结构。 使用推送后输出的解析后的来宾路径(JSON targetPath)来确定下一条命令的 --cwd;对于单个文件,请使用其父目录。 如果客户机未报告其受管根目录,则推送会在复制前失败;应遵循该错误信息中的更新指引,而不要自行假定默认路径。
仅运行你信任的安装程序脚本。 该示例使用进程作用域的 -ExecutionPolicy Bypass,因为新建的沙盒通常会根据其 Restricted 策略拒绝脚本。
传输会跳过未更改的文件,并在发布之前验证替换项。 符号链接和交汇点不会被跟随:部署会拒绝使用它们,而在复制目录时则会跳过链接项。 直接命名的链接源或通过链接访问的目标路径被拒绝。 请改为复制真实文件或目录。
删除应用并关闭沙盒
winapp unregister --on sandbox --manifest .\Package.appxmanifest
如果当前目录中有清单文件,就可以省略 --manifest。 这只会删除当前沙盒中由 winapp 注册的相应开发包。
外部安装的包会保持原样,即使其标识匹配。
--force 不支持 --on;它不能绕过所有权检查。
这是基于清单的包清理,而不是用于未打包应用的取消注册命令,也不是 .cs 输入。
沙盒仍保持运行状态。 使用Windows沙盒自己的 CLI 管理其生存期:
wsb list
wsb connect --id <id>
wsb stop --id <id>
停止丢弃来宾及其工作。 首先保存所需的证据,并在停止他们可能正在使用的实例之前获取用户的同意。 以后的 winapp 命令可以创建新的沙盒;之后重新发现所有应用目标。
故障排除
请按照错误中的 userAction 处理;nextCommand 只是建议,并不表示可以自动运行它。 在自动化中,检查结构化的 error.code。
基础结构故障可能会退出 70,但任意应用程序也可以返回 70;仅数值退出状态不区分它们。
由路由式 UI 操作建议的恢复命令会保留 --on <target>,因此复制该建议后,仍会保持在同一执行目标上。
| 错误或症状 | 怎么办 |
|---|---|
sandbox_unsupported |
检查 Windows 版本和版次以及固件虚拟化支持 |
sandbox_setup_required |
使用上述说明启用Windows沙盒,然后在准备就绪时重启 |
sandbox_setup_requires_restart |
Windows 报告需要重新启动;请保存当前工作,并在准备好后重新启动,然后重试 |
sandbox_setup_incomplete |
从“开始”菜单打开 Windows 沙盒并完成客户端设置/更新,然后重试 |
sandbox_unmanaged_instance、sandbox_target_ambiguous |
检查报告实例/窗口;不要停止不相关的工作来解决歧义 |
sandbox_input_not_ready、sandbox_no_interactive_session |
还原现有客户端或按定向重新连接,然后重试 |
sandbox_agent_incompatible |
根据版本错误提示操作;如有要求,请按照该 CLI 的安装方式升级已安装的 CLI,然后仅在获得同意后再关闭或重试 |
sandbox_agent_busy |
等待另一个命令完成,然后重试 |
sandbox_terminated、sandbox_target_stale、sandbox_stale_handle |
重新运行应用程序并重新识别客户机 PID/窗口 |
sandbox_state_unavailable |
确保%USERPROFILE%\.winapp\state可写,或者如果已设置了WINAPP_TARGET_STATE_ROOT,请更正它 |
sandbox_deployment_dirty、sandbox_transfer_interrupted |
重试部署或传输 |
sandbox_runtime_provision_failed |
解决命名依赖项或不受支持的运行时配置;请参阅 共享运行时 |
sandbox_package_conflict、sandbox_provisioned_package_conflict |
遵循针对相应软件包的操作;请勿删除不相关的软件包或收件箱中的软件包 |
sandbox_artifact_failed |
检查报告的输出和客户端就绪情况;保留任何部分证据 |
target_invalid、target_invalid_arguments |
更正错误中显示的目标或选项 |
winapp update 更新 项目 SDK 依赖项,而不是已安装的 CLI。 这不是用于解决主机/客户机 CLI 不兼容问题的修复措施。
在 build 28000 沙盒中共享目标
经测试,28000 版本的 Sandbox 无法枚举共享目标。 在沙盒中测试其他应用功能,但要在沙盒外验证共享从源应用到目标应用的流程。