Запуск Ножниц

В этой статье описывается протокол интеграции встроенных и сторонних приложений со Средством обрезки в Windows, используя схему ms-screenclip: URI (универсальный идентификатор ресурса). Протокол поддерживает запись изображений и видео (с аудио) с помощью средства Snipping Tool, и разработчики приложений могут выбрать, какие функции Snipping Tool будут отображаться в их приложении.

Important

Для этого протокола требуется приложение packaged Windows (MSIX). Когда приложение упаковывается, операционная система автоматически предоставляет идентификатор приложения программе Snipping Tool, которая использует его для безопасной передачи ответа на захват обратно в приложение. Неупакованные абоненты (Win32) не могут получать ответы через redirect-uri. Если неупакованное приложение предоставляет redirect-uri, средство захвата фрагментов не выдаст ответ и может завершиться, не отображая интерфейс захвата.

Note

Этот протокол заменяет интерфейс, описанный в фрагменте экрана запуска (не рекомендуется), который теперь устарел.

Поддерживаемые функции

Протокол Snipping Tool поддерживает следующие функции:

  • Захват прямоугольника
  • Запись freeform
  • Запись окна
  • Запись экрана
  • Настройка доступных режимов захвата
  • Автоматическое сохранение (необязательно)

Спецификация протокола

Формат URI:ms-screenclip://{host}/{path}?{query parameters}

Компонент Description Ценности
Схема Пользовательская схема для программы Snipping Tool ms-screenclip
Хост Операция с фрагментами инструментов для выполнения capture или discover
Путь Тип носителя для записи (применяется только к capture узлу; discover узел не имеет пути) /image или /video
Query Параметры для операции См. таблицы ниже

Note

Пути и имена параметров запроса не чувствительны к регистру. Например, ms-screenclip://capture/Image?Redirect-Uri=my-app://response ведет себя так же, как ms-screenclip://capture/image?redirect-uri=my-app://response.

Захват узла

Используйте хост capture, чтобы запустить экран захвата Инструмента обрезки.

Путь

Путь Description
/image Запускает запись изображений (снимок экрана). Требуется параметр режима.
/video Запускает видеозахват (запись экрана). Всегда используется режим прямоугольника.

Параметры режима (запись и изображение)

/image Для /image пути требуется указать только один параметр режима. Параметры режима — это параметры запроса без значения.

Parameter Description
rectangle Интерактивный режим захвата прямоугольной области.
freeform Интерактивный режим записи freeform.
window Режим интерактивного захвата окон.

Important

Параметры режима должны быть указаны без значения. Например, используйте &rectangle, а не&rectangle=value. Предоставление значения приведет к ошибочному ответу.

Для /image необходимо указать ровно один параметр режима. Указание нуля или нескольких режимов приведет к ответу на ошибку 400 Bad Request . Для /video параметр режима любого типа игнорируется.

Параметры запроса (запись)

Note

Параметры запроса могут быть предоставлены в любом порядке.

Parameter Тип Обязательный Description По умолчанию
redirect-uri URI Да Универсальный код ресурса (URI) обратного вызова, куда Средство захвата экрана отправляет ответ на захват. Приложение должно зарегистрировать обработчик протокола для этой схемы URI. Если параметр отсутствует, Snipping Tool не отображает интерфейс захвата и не возвращает ответ. n/a
user-agent струна Нет (настоятельно рекомендуется) Идентификатор вызывающего приложения, используемого для ведения журнала и аналитики. Требуется для диагностики проблем через каналы технической поддержки; в противном случае на свой собственный риск. n/a
api-version струна Нет Версия протокола, используемая, например "1.2". Если опущен, запрос обрабатывается как версия 1.2. 1.2
x-request-correlation-id струна Нет Уникальный идентификатор запроса, позволяющий ссылаться на определенную транзакцию или цепочку событий. Автоматически созданный GUID
enabledModes строка (список) Нет Определяет, какие режимы захвата доступны в пользовательском интерфейсе. См. статью EnabledModes ниже. Только режим, указанный в URI
auto-save flag Нет При наличии захваченный снимок экрана или запись автоматически сохраняется на устройстве пользователя. Отсутствует (автоматическое сохранение не существует)

Note

Значение по умолчанию api-version1.2 не изменяется при выпуске более новых версий протокола. Запросы, в которых опущено api-version, всегда обрабатываются как 1.2. Чтобы использовать функции, добавленные в более позднюю версию, установите api-version на эту версию. Рекомендуется явно указывать api-version в каждом запросе, чтобы приложение оставалось привязанным к известной версии протокола, а не неявной по умолчанию.

Note

При предоставлении api-version он должен точно соответствовать одному из значений в массиве ответа supportedVersions (1.0, 1.1, и 1.2 в настоящее время). Любое другое значение, включая промежуточные значения, например 1.151.0abc или неправильно сформированные значения, возвращает 400 Bad Request ответ. Чтобы узнать, какие версии совместимы с определенной сборкой средства Snipping Tool, вызовите discover host.

Note

Флаг auto-save учитывает параметры пользователя для Snipping Tool. Если пользователь отключил автоматическое сохранение в Инструменте обрезки, запись не сохраняется на устройстве, даже если в запросе указано auto-save.

Обнаружение хоста

discover Используйте хост для запроса поддерживаемых возможностей, режимов и версии протокола Snipping Tool во время выполнения. Это полезно для проверки совместимости перед выполнением запроса на запись.

Параметры запроса (обнаружение)

Parameter Тип Обязательный Description По умолчанию
redirect-uri URI Да Универсальный код ресурса (URI) обратного вызова, на который Snipping Tool отправляет ответ о возможностях. Приложение должно зарегистрировать обработчик протокола для этой схемы URI. Если не указано, инструмент Snipping Tool не возвращает ответ. n/a
user-agent струна Нет (настоятельно рекомендуется) Идентификатор вызывающего приложения, используемого для ведения журнала и аналитики. n/a
x-request-correlation-id струна Нет Уникальный идентификатор запроса. Автоматически созданный GUID

Пример обнаружения

ms-screenclip://discover?user-agent=MyApp&redirect-uri=my-app://response

Поиск формата ответа

Ответ — это объект JSON, добавленный к URI перенаправления в качестве discover параметра запроса. Она содержит:

  • version: Последняя версия протокола, которую поддерживает эта сборка средства Snipping Tool.
  • defaultVersion: версия протокола предполагается, когда запрос опускает api-version. Ознакомьтесь с этим, чтобы понять, как интерпретируются незакреченные запросы.
  • supportedVersions: массив версий протокола, которые принимает эта сборка средства Snipping.
  • 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 позволяет управлять режимами захвата, доступными в пользовательском интерфейсе средства Snipping. Используйте его, чтобы ограничить или расширить выбор пользователя для соответствия требованиям приложения.

Поддерживаемые режимы

Режим Description
RectangleSnip Режим захвата прямоугольника.
WindowSnip Режим захвата окна.
FreeformSnip Режим записи freeform.
FullscreenSnip Режим полноэкранного захвата.
SnippingAllModes Все режимы захвата изображений: RectangleSnip, WindowSnip, FreeformSnip. FullscreenSnip
RectangleRecord Режим записи в формате прямоугольника.
RecordAllModes Все режимы записи: в настоящее время только RectangleRecord.
All Все поддерживаемые режимы: объединение SnippingAllModes и RecordAllModes.

Tip

All, SnippingAllModesи RecordAllModes являются статистическими значениями. Режимы, которые они включают, могут изменяться в новых версиях Snipping Tool. Приложение, использующее одно из этих значений, автоматически выбирает режимы, добавленные в будущие выпуски. Чтобы сохранить набор доступных режимов фиксированного между обновлениями, выведите явный список определенных режимов (например, RectangleSnip,FreeformSnip).

Important

  • Для /image в URI требуется параметр режима (например, rectangle, freeform, window), даже если enabledModes указано. Параметр режима определяет изначально выбранный режим.
  • Режим, указанный в URI, всегда доступен в пользовательском интерфейсе, даже если он не указан.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

Поскольку freeform указан в URI, он будет предварительно выделен. Пользователи могут переключаться между свободной формой, прямоугольным снимком и записи прямоугольной области.

Responses

После завершения или отмены захвата инструмент Snipping Tool отправляет ответ в ваше приложение через redirect-uri. Ответ структурирован как параметры запроса URI, которые присоединяются к вашему URI перенаправления.

Если параметры запроса уже включены (например, my-app://response?sessionId=abc), эти параметры сохраняются, а параметры ответа добавляются с помощью &. Это можно использовать для передачи состояния, специфичного для вызывающего объекта, через обратный вызов — значение sessionId=abc повторяется в URI ответа вместе с code, reason, x-request-correlation-id, и (для успешного захвата) file-access-token.

Параметры ответа

Parameter Тип Присутствующий Description
code int Всегда Код состояния HTTP-формата, указывающий результат.
reason струна Всегда Читаемое человеком описание результата.
x-request-correlation-id струна Всегда Идентификатор корреляции из исходного запроса (или автоматически созданный).
file-access-token струна Только успех Маркер SharedStorageAccessManager , представляющий захваченный носитель. Используйте это для извлечения файла.
discover струна Только обнаружение URL-кодированный JSON, содержащий ответ о возможностях.

Коды состояния

Code Причина 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 Режим захвата прямоугольника предварительно выбран, все режимы доступны в пользовательском интерфейсе.

Запуск из приложения

Для запуска средства Snipping из упаковаемого приложения необходимо использовать Launcher.LaunchUriAsync . Другие методы запуска (например Process.Start , выполнение оболочки) не предоставляют удостоверение вашего приложения, а средство фрагментирования не доставляет ответ.

Шаг 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. Обработка ответа

Когда запись завершается (или пользователь отменяет), средство фрагментов кода активирует приложение с помощью параметров результатов, добавленных в redirect-uri качестве строк запроса. Большинство интеграций уже выполняется при поступлении ответа — вызывающий объект запустил инструмент обрезки, затем ожидал обратный вызов, поэтому ваше приложение должно обрабатывать активацию холодного запуска (приложение не запущено) и повторную активацию теплого запуска (приложение уже запущено). Подпишитесь на оба потока в 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 Tool автоматически его сгенерировать, ответ будет содержать это значение — рассмотрите его как соответствующее вашему самому последнему запросу, находящемуся в процессе выполнения.

Получение захваченного носителя с помощью токена

Используйте класс 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 параметры перед их запуском. Применяются следующие защиты:

  • Вызывающие упакованных приложений: когда ваше приложение является упакованным Windows приложением (MSIX), операционная система безопасно перенаправляет ответ захвата обратно в ваше приложение, гарантируя, что только ваше приложение может его получать. Это рекомендуемый путь интеграции.
  • Проверка входных данных: средство фрагментирования отклоняет URI перенаправления, содержащие UNC-пути, начальные или конечные пробелы или управляющие символы.
  • Нет фрагментов: URI перенаправления, содержащие фрагмент URL-адреса (например, my-app://response#section), отклоняются. Средство фрагмента добавляет параметры ответа в виде строки запроса, а фрагмент будет проглотить их.
  • Защита от самоссылок : URI перенаправления, которые могут вызвать рекурсивную активацию средства фрагментирования, блокируются.

Important

Для вызова приложений:

  • Зарегистрируйте обработчик протокола для схемы перенаправления URI, чтобы ваше приложение могло получить ответ.
  • Перед обработкой проверяйте и очищайте все параметры, полученные в ответе.
  • Убедитесь, что ответ x-request-correlation-id соответствует запросу во время полета, чтобы избежать обработки устаревших ответов или смешивания одновременных запросов. Идентификатор корреляции предотвращает смешения; он не устанавливает происхождение маркеров — безопасная маршрутизация маркеров поступает из канала обратного вызова упакованного приложения.