Windows 沙箱執行

先在你的電腦上建置,然後在 Windows 沙盒中執行並自動化應用程式:

winapp run . --on sandbox --detach
winapp ui inspect --on sandbox -a MyApp
winapp ui invoke --on sandbox SubmitButton -a MyApp

請將 run 替換為您的應用程式名稱,或替換為 MyApp 輸出的來賓 PID。 --detach 啟動後返回,以便下一個指令檢查應用程式;沒有它,就會 run 等應用程式退出。 沙盒在指令和重建之間會持續運行。

開始之前

  • 請在支援的版本上使用 Windows 11 24H2 或更新版本,並啟用硬體虛擬化。
  • Guest 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 不會停止已採用的實例或移除無關的應用程式。 沒有靜默回退至主機的機制:要求在 Sandbox 中執行的指令,會在 Sandbox 中執行,否則就失敗。

運行與重建

winapp run .\MyApp.csproj --on sandbox --detach --json
winapp run .\publish --on sandbox --detach
winapp run . --on sandbox --clean --detach

建立選項如 --configuration、 --arch、 --framework、 --property、 --no-build, --no-restore 並套用在主機上。 註冊、啟動與除錯皆在訪客中進行;應用程式沒有註冊在你的電腦上。

Option 沙盒模式的影響
--detach 發射後回來,而不是等退出
--no-launch 部署並註冊,無需啟動
--clean 重新安裝此部署並清除其應用程式資料
--unregister-on-exit 應用程式結束後移除此套件註冊
--with-alias 啟動訪客執行別名,並轉送串流
--debug-output 串流訪客除錯輸出; 僅限打包應用程式

未封裝的應用程式會從已部署的資料夾啟動執行檔。 他們沒有可註冊的套件。 在未封裝的 Sandbox 執行中,--debug-output 會被拒絕。

重新執行傳輸會更新已變更的檔案,並移除建置輸出中已刪除的檔案。 除非你申請 --clean,否則應用程式資料會被保留。 未完成的部署不會啟動;重新嘗試會重建其客體副本。 如果 Winapp 在準備建置檔案時有變動,請完成建置後再試一次。

溫暖的 UI 指令只會回報結果,不會重複沙盒準備訊息。 沙盒啟動和連線恢復仍然會顯示進度。 使用 --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 執行時選擇會尊重應用程式已設定的滾轉政策與架構;不要假設同一主版本中任何更新的執行時都能正常運作。

若無法支援框架、執行時設定或相依性,該指令會在啟動前明確失敗並識別需求。 追蹤該錯誤的動作。 若您的專案支援,發佈為自含式就不需要對應的共用執行階段;但這不會移除不相關的套件相依性。

自動化使用者介面

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,則會改為選取你的主機桌面。

實際輸入與錄製需要連接 且未最小化的沙盒用戶端。 即使無法輸入,唯讀檢查仍然可運作。 Winapp 可在不啟用的情況下還原自身最小化的用戶端;你必須恢復最小化的手動開啟客戶端。 如果重新連線後輸入不可用,指令會失敗,而不是聲稱已傳送輸入。 請使用錯誤中的 reconnect 指令並重試。

用 winapp target snapshot sandbox --json 來檢查桌面準備狀況,無需啟動或重新連接沙盒。 識別到終端機錯誤的視窗不算作遠端桌面。 若 winapp 因所選桌面仍在連線中或無法檢測而無法驗證該桌面,則就緒狀態仍無法使用;請稍候後再試。 多個遠端桌面仍然可能存在模糊性。 快照不會幫你關閉視窗或解決錯誤。

請參閱 UI 自動化 ,涵蓋選擇器、輸入方法與斷言。

協調沙盒中的使用者介面工作流程

用一個 WINAPP_UI_WORKFLOW_ID 來做協作指令,每個獨立工作流程用不同的值。 每次呼叫時都要設定它,尤其是在你的代理程式每次工具呼叫時都會啟動全新的 shell。 winapp 轉發一個經過雜湊、沙盒生成專用的身份;原始主機值不會傳送給訪客。

例如,在兩個終端機中使用相同值進行記錄與互動。 為每個新工作流程選擇一個新值。

第一航廈:

$env:WINAPP_UI_WORKFLOW_ID = 'myapp-checkout-01'
winapp ui record --on sandbox -a MyApp --duration-sec 20 --frames -o .\checkout.mp4

第二航廈,錄製進行時:

$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 的錄製在其進行期間會阻止其他變更桌面的工作流程。 唯讀檢查無須等待。 主機與訪客的使用者介面輪次是分開的。

暫停後,再檢查一次,並重新開啟你需要的選單或對話框:訪客桌面可能已經使用了其他工作流程。 合作回合不會讓應用程式彼此隔離。

截圖與錄音

對應用程式視窗使用 target 擷取,或對 整個原生訪客桌面 使用 ui 擷取,包括殼層與安裝程式對話方塊:

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 等待訪客的介面回合,卻不啟動任何視窗。 它排除了主機沙盒視窗的標題列和邊框。 其 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>,且訪客原始檔案會被保留。 讓 Sandbox 持續執行,並先依照該錯誤的復原動作進行處理,再重試或將其關閉。 保存的部分檔案不一定是可播放的影片。

截圖與影片可能包含敏感資訊。 以處理 MP4 時同樣謹慎的態度處理影格目錄。 請參見 ui record 記錄選項與結果欄位。

檢視沙箱

winapp target snapshot sandbox
winapp target snapshot sandbox --json

這會報告準備狀況、目前部署情況及訪客視窗,無需建立虛擬機、重新連接客戶端或修復代理程式。 在沒有 Sandbox 執行中的情況下,它會回報此情況並成功結束。 若要開始,請使用 winapp run . --on sandbox --detach。

報告區分來賓系統支援的功能與目前的用戶端可執行的功能;即使來賓系統同時支援輸入與擷取,已最小化的用戶端仍可能阻止輸入或擷取。 針對 UI PID,請使用訪客視窗清單,而不是部署所追蹤的啟動器程序。 JSON workRoot 欄位(如 Work root 文字輸出所示)是相對檔案傳輸路徑的絕對基底,通常為 C:\WinApp\work。 它與 capabilities.managedRoot 分開,通常為 C:\WinApp,且當訪客未回報其受管理的根時,則會被省略。 若多個用戶端視窗阻礙明確捕捉,錯誤會列出候選者;決定要關閉哪一個再重試。

執行指令與複製檔案

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 的錯誤訊息,而不是子命令的標準輸出。

對於 push 和 pull,目標路徑相對於由 workRoot 回報的 target snapshot。 絕對、以根目錄起始及 UNC 目標路徑一律拒絕。 一個檔案會落在你指定的目的地;目錄會在該目的地下方保留其結構。 使用推送後列印的解析訪客路徑(JSON targetPath)來選擇下一個指令 --cwd;對於單一檔案,則使用其父目錄。 若客體未回報其受管理的根目錄,推送會在複製前失敗;請依照該錯誤訊息中的更新指示操作,而非自行假定預設路徑。

只執行你信任的設定腳本。 範例中使用程序範圍的 -ExecutionPolicy Bypass,因為新建立的沙盒通常會在其 Restricted 策略下拒絕執行腳本。

傳輸會跳過未更改的檔案,並在發布前驗證替換檔案。 不會跟隨符號連結與交接點:部署會拒絕它們,而複製目錄時則會略過連結項目。 直接命名的連結來源或透過連結的目的地路徑會被拒絕。 改用真實檔案或目錄。

移除應用程式並結束沙盒

winapp unregister --on sandbox --manifest .\Package.appxmanifest

如果當前目錄中有 manifest 檔案,你可以省略 --manifest。 此動作僅會移除目前 Sandbox 中由 winapp 註冊的相符開發套件。 即使識別資訊相符,外部安裝的套件也不受影響。 --force 不支援與 --on 搭配使用;它無法繞過所有權檢查。 這是以資訊清單為基礎的套件清理,不是針對未封裝應用程式的取消註冊命令,也不是 .cs 輸入。

沙盒仍在運作。 用 Windows Sandbox 自家的 CLI 管理其壽命:

wsb list
wsb connect --id <id>
wsb stop --id <id>

停止則會丟棄賓客及其工作。 先儲存所需證據,並在停止使用者可能使用的實例前取得使用者同意。 後續的 winapp 指令可以建立一個全新的沙盒;之後再重新發現所有應用程式目標。

Troubleshooting

請遵循錯誤; 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 不相容的問題。

在建置 28000 沙盒中分享目標

測試版 28000 沙盒無法列舉共享目標。 在沙盒中測試其他應用程式功能,但請在沙盒外驗證 Share 從來源到目標的流程。

另請參閱