本文规定了将第一方和第三方应用程序与Windows截屏工具集成的协议,使用ms-screenclip: URI(统一资源标识符)方案。 该协议支持通过截图工具捕获图像和视频(含音频),应用调用方可以选择其应用将显示的截图工具功能。
Important
此协议需要打包Windows应用(MSIX)。 打包应用后,操作系统会自动向 Snipping 工具提供应用的标识,该工具使用它安全地将捕获响应路由回应用。 未打包的(Win32)调用方无法通过 redirect-uri接收响应。 如果解压缩的应用提供了一个 redirect-uri,则 Snipping 工具不会提供响应,并且可能会在不显示捕获 UI 的情况下退出。
注释
此协议取代了 “启动”屏幕截图(已弃用)中记录的体验,该体验现已弃用。
支持的功能
截图工具协议支持以下功能:
- 矩形捕获
- 自由捕获
- 窗口捕获
- 屏幕录制
- 自定义可用的捕获模式
- 自动保存(可选)
协议规范
URI 格式:ms-screenclip://{host}/{path}?{query parameters}
| 组件 | Description | 价值观 |
|---|---|---|
| Scheme | Snipping Tool 的自定义配置 | ms-screenclip |
| 主机 | 要执行的截图工具操作 |
capture 或 discover |
| 路径 | 要捕获的媒体类型(仅限于capture主机;discover主机不包含路径) |
/image 或 /video |
| 查询 | 操作的参数 | 请参阅下表 |
注释
路径和查询参数名称不区分大小写。 例如,ms-screenclip://capture/Image?Redirect-Uri=my-app://response 的行为与 ms-screenclip://capture/image?redirect-uri=my-app://response 相同。
捕获主机
使用 capture 主机启动截图工具的捕获界面。
路径
| 路径 | Description |
|---|---|
/image |
启动图像捕获(屏幕截图)。 需要模式参数。 |
/video |
启动视频捕获(屏幕录制)。 始终使用矩形模式。 |
模式参数 (捕获模式/图像模式)
必须为/image路径准确指定恰好一个模式参数。 模式参数是 没有值的空查询参数。
| 参数 | Description |
|---|---|
rectangle |
交互式矩形捕获模式。 |
freeform |
交互式自由抓取模式。 |
window |
交互式窗口捕获模式。 |
Important
必须指定模式参数而不指定值。 例如,使用 &rectangle, 而不是&rectangle=value。 提供值将导致错误响应。
对于 /image,必须指定一个模式参数。 指定零个或多个模式将导致 400 Bad Request 错误响应。 对于 /video,将忽略任何模式参数。
查询参数(捕获参数)
注释
可以按任意顺序提供查询参数。
| 参数 | 类型 | 必需 | Description | 违约 |
|---|---|---|---|---|
redirect-uri |
URI | 是的 | 截取工具发送捕获响应的回调 URI。 应用必须为此 URI 方案注册协议处理程序。 如果省略,则截图工具不会显示捕获用户界面,也不会返回响应。 | n/a |
user-agent |
字符串 | 不(强烈建议) | 用于日志记录和分析的调用应用程序的标识符。 需要通过支持渠道诊断问题;省略你自己的风险。 | n/a |
api-version |
字符串 | 否 | 要使用的协议版本,例如 "1.2"。 如果省略,则请求将作为版本 1.2进行处理。 |
1.2 |
x-request-correlation-id |
字符串 | 否 | 请求的唯一标识符,允许引用特定的事务或事件链。 | 自动生成的 GUID |
enabledModes |
字符串(列表) | 否 | 控制 UI 中可用的捕获模式。 请参阅下面的 EnabledModes 。 | 仅 URI 中指定的模式 |
auto-save |
标志 | 否 | 出现时,捕获的屏幕截图或录制会自动保存到用户的设备。 | 不存在(无自动保存) |
注释
发布较新的协议版本时,api-version的默认值在1.2中不会更改。 始终将忽略 api-version 的请求处理为 1.2。 若要使用更新版本中添加的功能,请将 api-version 设置为该版本。 我们建议在每个请求中显式指定 api-version ,以便应用与已知协议版本保持关联,而不是隐式默认值。
注释
提供api-version时,它必须与响应/discover数组(当前supportedVersions、1.0和1.1)中的1.2一个值完全匹配。 任何其他值(包括类似 1.15 的中间值或格式不正确的值,如 1.0abc),都会返回 400 Bad Request 响应。 若要发现特定 Snipping 工具版本接受的版本集,请调用 发现主机。
注释
该 auto-save 标志尊重用户的“截图工具”设置。 如果用户在“截图工具”中禁用了自动保存功能,即使请求包含 auto-save,捕获也不会保存到设备。
发现主机
使用 discover 主机在运行时查询 Snipping 工具支持的功能、模式和协议版本。 这对于在发出捕获请求之前检查兼容性非常有用。
查询参数 (发现功能)
| 参数 | 类型 | 必需 | Description | 违约 |
|---|---|---|---|---|
redirect-uri |
URI | 是的 | 截取工具发送功能响应的回调 URI。 应用必须为此 URI 方案注册协议处理程序。 如果省略,则截图工具不会返回响应。 | n/a |
user-agent |
字符串 | 不(强烈建议) | 用于日志记录和分析的调用应用程序的标识符。 | n/a |
x-request-correlation-id |
字符串 | 否 | 请求的唯一标识符。 | 自动生成的 GUID |
发现示例
ms-screenclip://discover?user-agent=MyApp&redirect-uri=my-app://response
发现响应格式
响应是作为查询参数追加到重定向 URI 的 discover JSON 对象。 该结构包含:
-
version:此 Snipping 工具版本支持的最新协议版本。 -
defaultVersion:请求省略时假定的api-version协议版本。 阅读此内容,了解未固定的请求是如何解析的。 -
supportedVersions:此截图工具版本接受的协议版本的数组。 -
capabilities:支持的捕获操作数组,其中每个操作包括:-
path:捕获终结点(例如,capture/imagecapture/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 参数允许你控制在“截图工具”UI 中可用的捕获模式。 使用它来限制或扩展用户的选择,以满足应用程序的要求。
支持的模式
| 模式 | Description |
|---|---|
RectangleSnip |
矩形捕获模式。 |
WindowSnip |
窗口捕获模式。 |
FreeformSnip |
自由捕获模式。 |
FullscreenSnip |
全屏捕获模式。 |
SnippingAllModes |
所有图像捕获模式:RectangleSnip、、WindowSnipFreeformSnipFullscreenSnip。 |
RectangleRecord |
矩形录制模式。 |
RecordAllModes |
所有录制模式:目前仅有RectangleRecord。 |
All |
所有受支持的模式:SnippingAllModes 和 RecordAllModes 的并集。 |
Tip
All、 SnippingAllModes和 RecordAllModes 聚合值。 它们包含的模式可能会在“截图工具”版本中变化。 使用这些值之一的应用会自动选取将来版本中添加的模式。 若要使可用模式集在更新之间保持固定,请显式列出特定模式(例如, RectangleSnip,FreeformSnip)。
Important
- 对于
/image,在 URI 中即使指定了enabledModes,也需要模式参数(例如rectangle、freeform、window)。 模式参数确定最初选择的模式。 - URI 中指定的模式始终在 UI 中可用,即使未在 UI 中
enabledModes列出。 例如,?freeform&enabledModes=RectangleSnip同时提供自由格式(来自 URI)和矩形截图功能,其中自由格式已被预先选择。 - 如果
enabledModes省略,则只有 URI 中指定的模式在 UI 中可用。 - 对于
/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 中指定了自由形式,因此将预先选择它。 用户可以在自由形式截图、矩形截图和矩形录制之间切换。
Responses
用户完成或取消捕获后,Snipping 工具会通过 redirect-uri 将响应发送回您的应用程序。 响应结构为 URI 查询参数附加到您的重定向 URI。
redirect-uri如果已包含查询参数(例如my-app://response?sessionId=abc),则保留这些参数,并追加&响应参数。 可以使用此方法通过回调来往返调用者特定的状态,该值 sessionId=abc 会和 code、reason、x-request-correlation-id 一起在响应 URI 中回显,并且对于成功的捕获还包括 file-access-token。
响应参数
| 参数 | 类型 | 现在 | Description |
|---|---|---|---|
code |
int | 始终 | 指示结果的 HTTP 样式状态代码。 |
reason |
字符串 | 始终 | 结果的可读说明。 |
x-request-correlation-id |
字符串 | 始终 | 原始请求(或自动生成的请求)中的关联 ID。 |
file-access-token |
字符串 | 仅限成功 | 表示 SharedStorageAccessManager 捕获媒体的令牌。 使用此来检索文件。 |
discover |
字符串 | 仅发现 | 包含功能响应的 URL 编码 JSON。 |
状态代码
| Code | 原因 | Description |
|---|---|---|
| 200 | 成功 | 捕获成功完成。 响应中包含file-access-token。 |
| 400 | 错误请求 - 参数无效或缺失 | 无法处理请求。 检查是否存在所有必需的参数并有效。 |
| 408 | 请求超时 - 操作耗时过长 | 操作在完成前超时。 |
| 499 | 客户端关闭请求 - 用户取消了 Snip | 用户通过按下 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 |
矩形捕获为预先选择的模式,所有模式均可在 UI 中使用。 |
从应用启动
必须使用 Launcher.LaunchUriAsync 从已打包的应用程序启动 Snipping Tool。 其他启动方法(例如 Process.Start 或 shell 执行)不会提供应用的标识,并且 Snipping 工具不会提供响应。
步骤 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);
步骤 3:处理响应
捕获完成后(或用户取消),Snipping Tool 会通过你的 redirect-uri,附加查询字符串形式的结果参数来激活应用。 响应到达时,大多数集成都已在运行(调用方启动 Snipping 工具,然后等待回调),因此你的应用必须处理冷启动激活(应用未运行)和热重新激活(应用已运行)。 在 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,请验证响应是否回显相同的值,以便您可以将该响应与正确的正在进行的请求匹配。 如果允许 Snipping 工具自动生成一个值,则响应将携带生成的值 - 将其视为与最近正在传输的请求匹配。
使用令牌检索捕获的媒体
使用 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 应用调用方:当你的应用是打包的 Windows 应用(MSIX)时,操作系统会将捕获的响应安全地路由回你的应用,确保只有你的应用能接收它。 这是建议的集成路径。
- 输入验证:截图工具不接受包含 UNC 路径、前导/尾随空格或控制字符的重定向 URI。
-
无片段:拒绝包含 URL 片段(例如)
my-app://response#section的重定向 URI。 狙击工具将响应参数追加为查询字符串,片段会吞下它们。 - 自我引用保护:阻止导致截图工具递归激活的重定向 URI。
Important
对于调用应用程序:
- 为重定向 URI 方案注册协议处理程序,以便应用可以接收响应。
- 在处理这些参数之前,验证并清理响应中收到的所有参数。
- 验证响应的
x-request-correlation-id是否与您的正在传输的请求匹配,以避免处理过时的响应或混淆并发请求。 Correlation-id 防止混淆,而不是建立令牌的来源 — 安全的令牌路由依赖于打包应用的回调通道。