アプリでコンテンツを受信する - Windows共有を統合する

Windows共有シートを使用すると、アプリを通じてコンテンツ (他のアプリから共有) を受け取ることができます。 このガイドでは、アプリを共有ターゲットとして登録し、パッケージ アプリ (MSIX)、プログレッシブ Web Apps (PWA)、およびパッケージ化されていない Win32 アプリ間で共有コンテンツを処理する方法について説明します。

この記事で

セクション あなたが見つけるもの
機能を宣言する前に アプリが処理するファイルの種類と形式のみを宣言する
パッケージ アプリ (UWP とパッケージ デスクトップ) の共有ターゲットを実装する UWP アプリとパッケージ デスクトップ アプリのマニフェスト宣言とアクティブ化処理
PWA の共有ターゲットを実装する share_target マニフェストと POST の処理
パッケージ化されていない Win32 アプリで共有を受信する パッケージ ID を付与し、共有ターゲットとして登録する
ベスト プラクティス 信頼できる受信フローの推奨事項
受信の進行状況を報告する 大規模または長時間実行される共有処理の状態レポート
Troubleshooting 共有ターゲットに関する一般的な問題の修正

機能を宣言する前に

ほとんどの共有ターゲット統合のバグは、 アプリが実際に処理できる以上のものを宣言することによって発生します。 アプリで <uap:SupportsAnyFileType />宣言されている場合は、処理できないファイル (たとえば、ユーザーがスプレッドシートを共有するときに表示されるフォト エディター) など、 すべての ファイルの種類の共有シートに表示されます。

常に、アプリで処理できる特定のファイルの種類とデータ形式のみを宣言します。 例えば次が挙げられます。

<!-- ✓ Correct: declare only what you support -->
<uap:SupportedFileTypes>
  <uap:FileType>.jpg</uap:FileType>
  <uap:FileType>.png</uap:FileType>
</uap:SupportedFileTypes>

<!-- ✗ Incorrect: declares everything -->
<!-- <uap:SupportsAnyFileType /> -->

汎用ファイルムーバー (クラウド ストレージ、ファイル転送アプリ) にのみ <uap:SupportsAnyFileType /> を予約します。 アプリ カテゴリ別の宣言については、 DataFormat と FileType のリファレンスを参照 してください。

パッケージ アプリ (UWP とパッケージ デスクトップ) の共有ターゲットを実装する

このセクションは、UWP アプリパッケージ デスクトップ アプリ (WinUI 3、WPF、WinForms) に適用されます。 どちらもパッケージ ID を持つ MSIX パッケージとして出荷されるため、共有ターゲットは同じ方法で宣言され、アクティブ化の処理方法のみが異なります (手順 2 を参照)。

1. マニフェストで宣言する

package.appxmanifestを編集して共有ターゲットとして登録します。 アプリが処理するファイルの種類とデータ形式 のみを 宣言します。

<Extensions>
  <uap:Extension Category="windows.shareTarget">
    <uap:ShareTarget>
      <uap:SupportedFileTypes>
        <uap:FileType>.jpg</uap:FileType>
        <uap:FileType>.jpeg</uap:FileType>
        <uap:FileType>.png</uap:FileType>
        <uap:FileType>.gif</uap:FileType>
        <uap:FileType>.bmp</uap:FileType>
      </uap:SupportedFileTypes>
      <uap:DataFormat>Bitmap</uap:DataFormat>
    </uap:ShareTarget>
  </uap:Extension>
</Extensions>

2. 共有のアクティブ化を処理する

アプリが共有ターゲットとしてアクティブ化されたら、 OnShareTargetActivated イベントを処理します。

Note

OnShareTargetActivated は、UWP アプリ (Windows.UI.Xaml.Application) のアクティブ化のオーバーライドです。 パッケージ化されたデスクトップ アプリ (WinUI 3、WPF、WinForms) は、AppInstance.GetActivatedEventArgsを介して共有のアクティブ化を受け取り、ExtendedActivationKind.ShareTargetを確認します。 パッケージ アプリのアクティブ化情報を取得するを参照してください。

protected override async void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
    ShareOperation shareOperation = args.ShareOperation;
    shareOperation.ReportStarted();

    try
    {
        if (shareOperation.Data.Contains(StandardDataFormats.StorageItems))
        {
            IReadOnlyList<IStorageItem> items = await shareOperation.Data.GetStorageItemsAsync();
            
            // Validate: check count, types, and sizes
            if (items.Count == 0)
            {
                shareOperation.ReportError("No items received.");
                return;
            }

            var file = (IStorageFile)items[0];
            
            // Process the file
            await ProcessImageAsync(file);
        }
        
        shareOperation.ReportCompleted();
    }
    catch (Exception ex)
    {
        shareOperation.ReportError($"Error: {ex.Message}");
    }
}

private async Task ProcessImageAsync(IStorageFile file)
{
    // Your processing logic here
}

Windows アプリ SDKでビルドされたパッケージ デスクトップ アプリ (WinUI 3、WPF、WinForms) の場合、OnShareTargetActivatedオーバーライドはありません。 代わりに、 Main メソッドでアクティブ化を検査し、 ExtendedActivationKind.ShareTargetを確認します。

using Microsoft.Windows.AppLifecycle;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.DataTransfer;

[STAThread]
static void Main(string[] args)
{
    AppActivationArguments activatedArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
    if (activatedArgs.Kind == ExtendedActivationKind.ShareTarget)
    {
        HandleShareAsync(activatedArgs.Data as ShareTargetActivatedEventArgs);
    }
    else
    {
        // Normal launch path
    }
}

static async void HandleShareAsync(ShareTargetActivatedEventArgs args)
{
    ShareOperation shareOperation = args.ShareOperation;
    shareOperation.ReportStarted();

    if (shareOperation.Data.Contains(StandardDataFormats.StorageItems))
    {
        IReadOnlyList<IStorageItem> items = await shareOperation.Data.GetStorageItemsAsync();
        // Process the shared items.
    }

    shareOperation.ReportCompleted();
}

3. 宣言するデータ形式を選択する

この参照を使用して、宣言する内容を決定します。

Format いつ使用するか アプリの例
StorageItems アプリがファイルを受信する フォト エディター、ドキュメント リーダー
Bitmap アプリが画像を受け取る 画像ビューアー、アプリの設計
Text アプリがプレーン テキストを受け取る ノート アプリ、テキスト エディター
Html アプリがリッチ テキスト コンテンツを受け取る 電子メール クライアント、リッチ エディター
Uri / WebLink アプリがリンクを処理する ブラウザー、リンク マネージャー
Rtf アプリが書式設定されたテキストを受け取る Word プロセッサ

詳細については、「 DataFormat と FileType のリファレンス」を参照してください

プログレッシブ Web Apps (PWA) の共有ターゲットを実装する

Windows上の PWA は、Web アプリ マニフェストを使用して共有ターゲットとして登録されます。 share_target エントリを追加します。

{
  "name": "My PWA",
  "short_name": "MyPWA",
  "share_target": {
    "action": "/share",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url",
      "files": [
        {
          "name": "media",
          "accept": ["image/*", "video/*"]
        }
      ]
    }
  }
}

/share ルートで、POST 要求を処理します。

app.post('/share', async (req, res) => {
  const { title, text, url, files } = req.body;

  // Validate and process
  if (files && files.length > 0) {
    const file = files[0];
    // Process the file
    console.log('Received file:', file.originalname);
  }

  if (text) {
    console.log('Received text:', text);
  }

  res.redirect('/');
});

PWA で処理できるファイルの種類のみを宣言します。 たとえば、アプリが本当にすべてのファイルを処理しない限り、 * を受け入れ型として宣言しないでください。

パッケージ化されていない Win32 アプリで共有を受信する

共有ターゲットとして登録するには、アプリに パッケージ ID が必要です。 Win32 アプリがパッケージ化されていない場合は、次の 2 つの方法のいずれかでパッケージ ID を付与します。

  • MSIX を使用して再パッケージ化する (推奨): Visual Studioの Windows Application Packaging Project テンプレートを使用して、クリーンで信頼されたインストールを行います。 MSIX パッケージ用のデスクトップ アプリケーションを設定するを参照してください。
  • 外部の場所を含むパッケージ (スパース パッケージ): 既存のインストーラーがアプリ バイナリを管理し続けている間、ID、共有ターゲットの登録、およびビジュアル資産を含む空の MSIX パッケージを追加します。 これは、MSIX に移行できないインストーラーがある場合にのみ使用します。

このセクションの残りの部分では、外部の場所のアプローチについて説明します。

1. パッケージ マニフェストを作成する

AppxManifest.xmlを設定し、ID と機能を宣言し、共有ターゲットを登録する<uap10:AllowExternalContent>を作成します。 PublisherPackageName、およびApplicationId.exe.manifestおよび署名証明書と同期したままにしておきます。

<Identity Name="PhotoStoreDemo" ProcessorArchitecture="neutral" Publisher="CN=YourPubNameHere" Version="1.0.0.0" />
<Properties>
  <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
</Properties>
<Dependencies>
  <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Capabilities>
  <rescap:Capability Name="runFullTrust" />
  <rescap:Capability Name="unvirtualizedResources" />
</Capabilities>
<Applications>
  <Application Id="PhotoStoreDemo" Executable="PhotoStoreDemo.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App">
    <Extensions>
      <uap:Extension Category="windows.shareTarget">
        <uap:ShareTarget Description="Send to PhotoStoreDemo">
          <uap:SupportedFileTypes>
            <uap:FileType>.jpg</uap:FileType>
            <uap:FileType>.png</uap:FileType>
          </uap:SupportedFileTypes>
          <uap:DataFormat>StorageItems</uap:DataFormat>
          <uap:DataFormat>Bitmap</uap:DataFormat>
        </uap:ShareTarget>
      </uap:Extension>
    </Extensions>
  </Application>
</Applications>

実行可能ファイルをパッケージ ID にリンクするアプリケーション マニフェスト (YourApp.exe.manifest) を追加します。

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="PhotoStoreDemo.app" />
  <msix xmlns="urn:schemas-microsoft-com:msix.v1"
        publisher="CN=YourPubNameHere"
        packageName="PhotoStoreDemo"
        applicationId="PhotoStoreDemo" />
</assembly>

2. パッケージを作成して署名する

MakeAppx.exe スイッチで/nvを使用してマニフェストのみを含むパッケージをビルドし、SignTool.exeを使用して信頼された証明書で署名します。

MakeAppx.exe pack /d <folder with AppxManifest.xml> /p <output>\mypackage.msix /nv
SignTool.exe sign /fd SHA256 /a /f <path to cert> /p <cert key> <path to package>

署名証明書をコンピューター上の信頼できる場所にインストールします。

3. 初回実行時にパッケージを登録する

最初の実行時に、アプリが ID で再起動されるように、外部の場所パッケージを登録します。 外部の場所と署名された .msixへの絶対パスを指定します。

[STAThread]
public static void Main(string[] cmdArgs)
{
    if (!ExecutionMode.IsRunningWithIdentity())
    {
        string externalLocation = Environment.CurrentDirectory;
        string externalPkgPath = externalLocation + @"\PhotoStoreDemo.package.msix";

        if (registerPackageWithExternalLocation(externalLocation, externalPkgPath))
        {
            // Registration succeeded - restart so the app runs with identity.
            // Join the arguments into a single string; cmdArgs.ToString() would
            // return the array type name ("System.String[]"), not the arguments.
            string forwardedArgs = cmdArgs is null ? string.Empty : string.Join(" ", cmdArgs);
            Process.Start(Application.ResourceAssembly.Location, arguments: forwardedArgs);
        }
        else
        {
            // Registration failed - run without identity.
            new SingleInstanceManager().Run(cmdArgs);
        }
    }
}

4. 共有のアクティブ化を処理する

ID を使用してアプリを再起動した後、「ExtendedActivationKind.ShareTargetを処理する」に示すようにを処理します。

完全な例については、 PhotoStoreDemo サンプル (外部の場所と共にパッケージ化)WinUI 共有ターゲットのサンプルを参照してください。

ソース側のデスクトップ共有の場合は、「IDataTransferManagerInteropする」の説明に従ってを使用します。

ベスト プラクティス

受信フローを構築する場合は、このチェックリストを使用します。

推奨 避ける 共同作業の重要性
特定のファイル拡張子とデータ形式のみを宣言する ファイルムーバー以外のアプリ向けの <uap:SupportsAnyFileType /> の宣言 共有シートに不要な共有先が表示されないようにします
処理する前に、形式、カウント、ファイルの種類、およびファイル サイズを検証する 受信データが常に期待値と一致すると仮定する 実行時のエラーと共有エクスペリエンスの破損を防ぎます
リンク ハンドラーの Uri とイメージ ハンドラーの Bitmap + StorageItems を宣言する 共通共有ペイロードの部分宣言 実際にサポートされているコンテンツに対してアプリが表示されるようにします
実行時間の長い受信フローで ReportStartedReportDataRetrieved、および ReportCompleted を使用する 進行状況レポートなしで実行時間の長い受信作業を実行する 共有操作の信頼性を維持し、システムに正しい状態を提供します

大きなペイロードまたは長い処理の場合は、共有ターゲットから状態を報告します。

protected override async void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
  ShareOperation shareOperation = args.ShareOperation;
  shareOperation.ReportStarted();

  try
  {
    // Acquire the data your app needs.
    var items = await shareOperation.Data.GetStorageItemsAsync();
    shareOperation.ReportDataRetrieved();

    // Process data.
    await ProcessAsync(items);

    shareOperation.ReportCompleted();
  }
  catch (Exception ex)
  {
    shareOperation.ReportError($"Share failed: {ex.Message}");
  }
}

将来の共有用に QuickLink を返す場合は、 ReportCompleted(QuickLink) を使用します。

Troubleshooting

アプリが共有シートに表示されない:

  • マニフェスト宣言が共有されているコンテンツと一致するかどうかを確認します (ファイルの種類とデータ形式を確認します)。
  • パッケージ アプリの場合は、パッケージ ID を使用してアプリを実行していることを確認します。
  • アプリ カテゴリの DataFormat と FileType のリファレンス を確認します。

処理できないコンテンツに対してアプリが表示されます。

  • SupportedFileTypesリストとDataFormatリストを、サポート対象のみに絞り込む。

共有シートは、次のエラーで閉じます。

  • 非同期作業の前に ReportStarted() を呼び出し、完了したら ReportCompleted() してください。
  • 例外を処理し、説明メッセージを使用して ReportError() を呼び出します。

私が期待するファイルを受け取っていません:

  • ファイル形式が宣言された FileType または DataFormatと一致することを確認します。
  • アクティブ化ハンドラーに検証ロジックを追加して、実際に到着しているものを調べます。