本文規範了使用ms-screenclip: URI(統一資源識別碼)方案,將第一方及第三方應用程式整合至Windows剪輯工具的協定。 該協定支援透過截圖工具擷取影像與影片(含音訊),應用程式呼叫者可選擇將顯示哪些截圖工具功能。
Important
此協定需要一個封裝的Windows應用程式(MSIX)。 當你的應用程式被打包後,作業系統會自動將應用程式的身份提供給 Snipping Tool,Snipping Tool 會利用它安全地將擷取回應導回你的應用程式。 未封裝(Win32)呼叫端無法接收透過 redirect-uri 的回應。 若未封裝的應用程式提供 redirect-uri,剪切工具將無法提供回應,且可能退出時不顯示擷取介面。
Note
此協定取代了已棄用的 啟動畫面剪輯中所記錄的經驗。
支援的功能
剪切工具協定支援以下功能:
- 矩形擷取
- 自由格式擷取
- 視窗擷取
- 屏幕錄製
- 自訂可擷取模式
- 自動存檔(可選)
協定規範
URI 格式:ms-screenclip://{host}/{path}?{query parameters}
| 組件 | Description | 價值 |
|---|---|---|
| Scheme | 剪切工具的自訂方案 | ms-screenclip |
| 主機 | 要執行的擷取工具操作 |
capture 或 discover |
| 路徑 | 要擷取的媒體類型(僅適用於 capture 主機; discover 主機沒有路徑) |
/image 或 /video |
| 查詢 | 操作參數 | 請見下表 |
Note
路徑與查詢參數名稱不區分大小寫。 例如, ms-screenclip://capture/Image?Redirect-Uri=my-app://response 行為與 相同 ms-screenclip://capture/image?redirect-uri=my-app://response。
擷取伺服器
使用 capture 主機啟動剪切工具的擷取覆蓋層。
Path
| Path | Description |
|---|---|
/image |
啟動影像擷取(截圖)。 需要一個模式參數。 |
/video |
啟動影片擷取(螢幕錄影)。 總是用矩形模式。 |
模式參數(擷取/影像)
對於路徑, /image 你必須精確指定 一個 模式參數。 模式參數是 沒有值的裸查詢參數。
| 參數 | Description |
|---|---|
rectangle |
互動矩形擷取模式。 |
freeform |
互動式自由捕捉模式。 |
window |
互動式視窗擷取模式。 |
Important
模式參數必須在不設值的情況下指定。 例如,使用 &rectangle, 不&rectangle=value。 提供值會導致錯誤回應。
對於 /image,你必須精確指定一個模態參數。 指定零模式或多於一種模式會導致 400 Bad Request 錯誤回應。 對於 /video,任何模式參數都被忽略。
查詢參數(擷取)
Note
查詢參數可任意順序提供。
| 參數 | 類型 | Required | Description | 預設值 |
|---|---|---|---|---|
redirect-uri |
URI | 是的 | 回呼 URI,剪取工具會將擷取結果傳送至該處。 你的應用程式必須為此 URI 架構註冊一個協定處理器。 如果省略,剪切工具不會顯示擷取介面,也不會回傳回應。 | n/a |
user-agent |
字串 | 沒有(強烈推薦) | 呼叫應用程式的識別碼,用於日誌與分析。 必須透過支援管道診斷問題;如果省略,需自行承擔風險。 | n/a |
api-version |
字串 | No | 要使用的協定版本,例如 "1.2"。 若省略,請求將以版本 1.2處理。 |
1.2 |
x-request-correlation-id |
字串 | No | 請求的唯一識別碼,允許參考特定交易或事件鏈。 | 自動產生的 GUID |
enabledModes |
字串(列表) | No | 控制哪些捕捉模式可在使用者介面中使用。 請參見下方的 啟用模式 。 | 只有 URI 中指定的模式 |
auto-save |
旗標 | No | 若有截圖或錄影,會自動儲存到使用者裝置中。 | 不存在(無自動存檔) |
Note
api-version預設值1.2不會在新版協議釋出時改變。 省略api-version的請求總是會被作為1.2來處理。 若要使用後續版本新增的功能,請設定 api-version 為該版本。 我們建議在每個請求中明確指定 api-version ,讓你的應用程式持續綁定在已知的協定版本,而非隱含的預設值。
Note
當你提供 api-version時,它必須完全符合回應/discover陣列中的supportedVersions其中一個值(目前 1.0、 1.1、 1.2和 )。 任何其他值——包括中間值 1.15 如 或畸形值 1.0abc 如 ——都會回傳回應 400 Bad Request 。 要查明特定剪輯工具版本所接受的版本組合,請呼叫 discover host。
Note
該 auto-save 旗標會尊重使用者的剪切工具設定。 如果使用者在剪輯工具中關閉自動儲存,即使你的請求包含 auto-save,擷取內容也不會被儲存到裝置上。
探索主機
使用 discover 主機在執行時查詢剪切工具支援的功能、模式及協定版本。 這對於在提出擷取請求前檢查相容性很有幫助。
查詢參數(發現)
| 參數 | 類型 | Required | Description | 預設值 |
|---|---|---|---|---|
redirect-uri |
URI | 是的 | 回呼 URI,Snipping Tool 會傳送功能回應。 你的應用程式必須為此 URI 方案註冊一個協定處理器。 如果省略,Snipping Tool 不會回傳回應。 | n/a |
user-agent |
字串 | 沒有(強烈推薦) | 呼叫應用程式的識別碼,用於日誌與分析。 | n/a |
x-request-correlation-id |
字串 | No | 請求的唯一識別碼。 | 自動產生的 GUID |
發現範例
ms-screenclip://discover?user-agent=MyApp&redirect-uri=my-app://response
探索回應格式
回應是一個 JSON 物件,附加在 redirect URI 後作為 discover 查詢參數。 其包含:
-
version: 此剪切工具版本支援的最新協定版本。 -
defaultVersion:當請求省略api-version時假設的協定版本。 閱讀本文以瞭解尚未置頂的請求如何被解讀。 -
supportedVersions: 此剪切工具版本可接受的協定版本陣列。 -
capabilities:支援的捕獲操作陣列,每個操作包含:-
path:捕獲端點(例如,capture/image,capture/video)。 -
methods支援類似 HTTP 的方法。 -
parameters:終點可用參數。 -
description:能力描述。
-
{
"version": 1.2,
"defaultVersion": 1.2,
"supportedVersions": [1.0, 1.1, 1.2],
"capabilities": [
{
"path": "capture/image",
"methods": ["GET"],
"parameters": ["rectangle", "freeform", "window"],
"description": "Captures an image with options for shape."
},
{
"path": "capture/video",
"methods": ["GET"],
"parameters": [],
"description": "Captures a video in a defined area."
}
]
}
啟用模式
這個 enabledModes 參數讓你能控制剪切工具介面中可用的擷取模式。 利用它來限制或擴展使用者的選擇,以符合你應用程式的需求。
支援模式
| Mode | Description |
|---|---|
RectangleSnip |
矩形捕捉模式。 |
WindowSnip |
視窗擷取模式。 |
FreeformSnip |
自由擷取模式。 |
FullscreenSnip |
全螢幕擷取模式。 |
SnippingAllModes |
所有影像擷取模式:RectangleSnip、、WindowSnipFreeformSnip、FullscreenSnip。 |
RectangleRecord |
矩形錄影模式。 |
RecordAllModes |
所有錄影模式:目前 RectangleRecord 僅限。 |
All |
所有支援的模式:SnippingAllModes和RecordAllModes的聯集。 |
Tip
All、 SnippingAllModes、 RecordAllModes 以及 是總體值。 它們所包含的模式會隨著不同版本的剪裁工具版本而有所不同。 使用這些數值的應用程式會自動擷取未來版本新增的模式。 為了讓可用模式集合在各更新間固定不變,請明確列出具體模式(例如, RectangleSnip,FreeformSnip)。
Important
- 對於
/image,即使指定了enabledModes,URI 中仍需要一個模式參數(例如rectangle、freeform、window)。 模式參數決定最初選擇的模式。 - URI 中指定的模式總是在 UI 中可用,即使它未列在
enabledModes。 例如,可以?freeform&enabledModes=RectangleSnip同時提供自由形態(來自 URI)和矩形剪切,並預先選擇自由形。 - 若
enabledModes省略,介面中只會顯示 URI 中指定的模式。 - 對於
/image,若未指定模式參數,請求即無效,無論 是否 ,enabledModes都會產生錯誤。
EnabledModes 範例
僅啟用矩形擷取:
ms-screenclip://capture/image?rectangle&enabledModes=RectangleSnip&user-agent=MyApp&redirect-uri=my-app://response
啟用矩形與視窗剪切:
ms-screenclip://capture/image?rectangle&enabledModes=RectangleSnip,WindowSnip&user-agent=MyApp&redirect-uri=my-app://response
啟用所有剪切模式:
ms-screenclip://capture/image?rectangle&enabledModes=SnippingAllModes&user-agent=MyApp&redirect-uri=my-app://response
僅啟用錄影模式:
ms-screenclip://capture/video?enabledModes=RecordAllModes&user-agent=MyApp&redirect-uri=my-app://response
啟用多種剪輯與錄影模式:
ms-screenclip://capture/image?freeform&enabledModes=RectangleSnip,RectangleRecord&user-agent=MyApp&redirect-uri=my-app://response
由於 URI 中指定了 freeform,因此會被預先選擇。 使用者可以在自由格式、矩形剪接和矩形錄音之間切換。
Responses
使用者完成或取消擷取後,剪切工具會透過redirect-uri 回應至您的應用程式。 回應的結構是以 URI 查詢參數的形式附加在你的重定向 URI 上。
如果你 redirect-uri 已經包含查詢參數(例如 my-app://response?sessionId=abc),這些參數會被保留,回應參數則會加上 &。 你可以使用此方法透過回調函式來傳遞特定的呼叫者狀態——該值 sessionId=abc 會在回應 URI 中回傳,並與 code、reason、x-request-correlation-id 和在成功擷取時的 file-access-token 一同回傳。
回應參數
| 參數 | 類型 | 存在 | Description |
|---|---|---|---|
code |
int | 永遠 | HTTP 風格的狀態碼顯示結果。 |
reason |
字串 | 永遠 | 對結果的人類易讀描述。 |
x-request-correlation-id |
字串 | 永遠 | 原始請求(或自動產生的)相關ID。 |
file-access-token |
字串 | 唯有成功 | 代表 SharedStorageAccessManager 被捕捉媒體的代幣。 用這個來取回檔案。 |
discover |
字串 | 只發掘 | 包含能力回應的 URL 編碼 JSON 文件。 |
狀態碼
| Code | Reason | Description |
|---|---|---|
| 200 | Success | 這次佔領成功完成。 回答中包含了一個file-access-token。 |
| 400 | 錯誤請求 - 參數無效或缺失 | 該請求無法被處理。 檢查所有必要的參數是否存在且有效。 |
| 408 | 請求暫停 - 操作耗時太久 | 手術在完成前就已超時。 |
| 499 | 客戶端關閉請求 - 使用者取消了剪輯 | 使用者按下 Escape 鍵或點擊離開鍵即可取消捕捉。 僅適用於/image和/video。 |
| 500 | 內部伺服器錯誤 - 處理失敗 | 捕獲過程中發生了意外錯誤。 |
範例回應
成功捕獲:
my-app://response?code=200&reason=Success&x-request-correlation-id=aaaa0000-bb11-2222-33cc-444444dddddd&file-access-token=cccc2222-dd33-4444-55ee-666666ffffff
用戶已取消:
my-app://response?code=499&reason=Client%20Closed%20Request%20-%20User%20Cancelled%20the%20Snip&x-request-correlation-id=bbbb1111-cc22-3333-44dd-555555eeeeee
無效請求(缺少模式參數):
my-app://response?code=400&reason=Bad%20Request%20-%20Invalid%20or%20Missing%20Parameters&x-request-correlation-id=bbbb1111-cc22-3333-44dd-555555eeeeee
完整的 URI 範例
| 用例 | URI | Description |
|---|---|---|
| 矩形截圖 | ms-screenclip://capture/image?rectangle&user-agent=MyApp&redirect-uri=my-app://response |
互動式矩形擷取。 結果已返回給呼叫者。 |
| 自由形式截圖 | ms-screenclip://capture/image?freeform&user-agent=MyApp&redirect-uri=my-app://response |
互動式自由擷取 結果已返回給呼叫方。 |
| 視窗截圖 | ms-screenclip://capture/image?window&user-agent=MyApp&redirect-uri=my-app://response |
互動式視窗擷取。 結果已返回給呼叫者。 |
| 螢幕錄影 | ms-screenclip://capture/video?user-agent=MyApp&redirect-uri=my-app://response |
互動式螢幕錄影。 結果已返回給呼叫者。 |
| 探索功能 | ms-screenclip://discover?user-agent=MyApp&redirect-uri=my-app://response |
查詢支援的功能。 能力 JSON 回傳給呼叫者。 |
| 帶有自動存檔功能的矩形 | ms-screenclip://capture/image?rectangle&auto-save&user-agent=MyApp&redirect-uri=my-app://response |
啟用自動存檔的矩形擷取。 |
| 包含所有模式的矩形 | ms-screenclip://capture/image?rectangle&enabledModes=All&user-agent=MyApp&redirect-uri=my-app://response |
矩形擷取已預先選擇,所有模式皆可在使用者介面中使用。 |
從你的應用程式啟動
你必須使用 Launcher.LaunchUriAsync 才能從你已打包的應用程式啟動剪切工具。 其他啟動方式(如 Process.Start shell 執行)不會提供你應用程式的身份,Snipping Tool 也無法提供回應。
步驟 1:註冊協定處理器
在你的 Package.appxmanifest 應用程式中註冊一個自訂協定,這樣你的應用程式才能接收回撥回應。 協議名稱必須與你 redirect-uri所使用的方案相符。
<Extensions>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="my-app" DesiredView="default">
<uap:DisplayName>My App Protocol</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
</Extensions>
有關註冊與處理協定啟用的更多細節,請參閱 處理 URI 啟用 。
步驟 2:啟動剪切工具
// Capture a screenshot in rectangle mode
var uri = new Uri(
"ms-screenclip://capture/image"
+ "?rectangle"
+ "&user-agent=MyApp"
+ "&redirect-uri=my-app://capture-response"
+ "&x-request-correlation-id=" + Guid.NewGuid().ToString()
);
await Launcher.LaunchUriAsync(uri);
// Record a video
var uri = new Uri(
"ms-screenclip://capture/video"
+ "?user-agent=MyApp"
+ "&redirect-uri=my-app://capture-response"
);
await Launcher.LaunchUriAsync(uri);
// Discover capabilities (returns immediately, no capture UI)
var uri = new Uri(
"ms-screenclip://discover"
+ "?user-agent=MyApp"
+ "&redirect-uri=my-app://discover-response"
);
await Launcher.LaunchUriAsync(uri);
步驟三:處理回應
當擷取完成(或使用者取消)後,Snipping Tool 會透過 redirect-uri 啟動您的應用程式,並將結果參數附加作為查詢字串。 大多數整合在回應到來時已經在執行中——呼叫者啟動了 Snipping Tool,然後等待回呼——因此你的應用程式必須同時處理冷啟動(應用程式未執行)與熱重新啟動(應用程式已在執行)。 請在App.xaml.cs中訂閱兩條路線。
處理擷取回應(影像或影片):
// In App.xaml.cs: handle protocol activation for both cold-start and warm re-activation
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
// Cold-start path: the app was launched by Snipping Tool's callback.
var activatedArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
if (activatedArgs.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.Protocol)
{
if (activatedArgs.Data is Windows.ApplicationModel.Activation.IProtocolActivatedEventArgs protocolArgs)
{
_ = HandleProtocolActivationAsync(protocolArgs.Uri);
}
}
// Warm re-activation path: the app is already running when the callback arrives.
Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().Activated += (sender, e) =>
{
if (e.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.Protocol &&
e.Data is Windows.ApplicationModel.Activation.IProtocolActivatedEventArgs protocolArgs)
{
_ = HandleProtocolActivationAsync(protocolArgs.Uri);
}
};
}
private async Task HandleProtocolActivationAsync(Uri uri)
{
var query = new WwwFormUrlDecoder(uri.Query);
var code = query.GetFirstValueByName("code");
var reason = query.GetFirstValueByName("reason");
if (code == "200")
{
var token = query.GetFirstValueByName("file-access-token");
var file = await SharedStorageAccessManager.RedeemTokenForFileAsync(token);
// Use the captured file (see "Retrieving captured media" below)
}
else
{
// Handle error (400, 408, 499, 500)
Debug.WriteLine($"Snipping Tool returned {code}: {reason}");
}
}
處理一個偵測回應:
private void HandleDiscoverResponse(Uri uri)
{
var query = new WwwFormUrlDecoder(uri.Query);
var code = query.GetFirstValueByName("code");
if (code == "200")
{
var discover = query.GetFirstValueByName("discover");
// discover contains a URL-encoded JSON capabilities payload
var capabilities = Uri.UnescapeDataString(discover);
// Parse the JSON to inspect supported capture modes
}
}
Tip
如果您在請求中寄出了 x-request-correlation-id,請確認回覆的數值是否相同,這樣您就能將回應與正在處理中的請求正確配對。 如果你讓剪切工具自動產生一個,回應會顯示該產生的值——就當作是你最近的機上請求。
使用令牌檢索擷取的媒體
使用 SharedStorageAccessManager 類別贖回 file-access-token 並存取擷取的檔案。
代幣限制:
- 代幣只能兌換 一次。 贖回後,它不再有效。
- 代幣在 14天後過期。
- 一個應用程式的有效代幣不能超過 1000 個。 代幣兌換、移除或過期後,不再計入配額。
// Redeem the token and display the captured image
var file = await SharedStorageAccessManager.RedeemTokenForFileAsync(token);
using (var stream = await file.OpenReadAsync())
{
var bitmap = new BitmapImage();
await bitmap.SetSourceAsync(stream);
MyImage.Source = bitmap;
}
// Or copy to your app's local storage
var localFolder = ApplicationData.Current.LocalFolder;
await file.CopyAsync(localFolder, file.Name, NameCollisionOption.GenerateUniqueName);
安全性考慮
剪切工具會在啟動前驗證所有 redirect-uri 值。 執行以下保護措施:
- Packaged app callers:當你的應用程式是封裝Windows應用程式(MSIX)時,作業系統會安全地將擷取回應導回你的應用程式,確保只有你的應用程式能接收。 這是推薦的整合路徑。
- 輸入驗證:擷取工具會拒絕包含 UNC 路徑、前置/後置空白或控制字元的重定向 URI。
-
無片段:包含 URL 片段(例如
my-app://response#section)的重定向 URI 會被拒絕。 剪切工具會以查詢字串的形式附加回應參數,片段會吞噬它們。 - 自我參照保護:會阻擋會導致剪切工具遞迴啟動的重定向 URI。
Important
關於呼叫應用程式:
- 為你的重定向 URI 方案註冊一個協定處理器,讓你的應用程式能接收回應。
- 在處理回應前,先驗證並淨化所有收到的參數。
- 確認回覆是否符合
x-request-correlation-id你機上請求,以避免處理陳舊的回覆或混淆同時請求。 相關識別(Correlation-id)防止混淆;它不會建立令牌來源——安全的令牌路由來自包裝的應用程式回調通道。