このトピックでは、パッケージ化されたデスクトップ アプリ (MSIX でパッケージ化されたWindows アプリ SDK アプリを含む) とパッケージ化されていない Win32 アプリケーション間で名前付きオブジェクトを共有する方法について説明します。
パッケージ アプリケーション内の名前付きオブジェクト
名前付きオブジェクト は、プロセスがオブジェクト ハンドルを共有するための簡単な方法を提供します。 プロセスが名前付きオブジェクトを作成した後、他のプロセスは名前を使用して適切な関数を呼び出してオブジェクトのハンドルを開くことができます。 名前付きオブジェクトは、 スレッド同期 と プロセス間通信でよく使用されます。
AppContainer (UWP アプリなど) で実行されるアプリケーションには、既定で分離された名前付きオブジェクト名前空間があり、作成した名前付きオブジェクトにのみアクセスできます。 完全に信頼されたパッケージ 化されたデスクトップ アプリ (Windows アプリ SDK アプリを含む) には、この分離がないため、グローバル名前空間に名前付きオブジェクトが作成されます。 詳細については、Windows アプリ SDKに関する考慮事項を参照してください。
名前付きオブジェクトを AppContainer アプリと共有するには、オブジェクトの作成時にアクセス許可を設定し、オブジェクトを開くときに名前を修飾する必要があります。 この記事の手法は、パッケージ化に関係なく、プロセス間のアクセスを制限する場合にも役立ちます。
名前付きオブジェクトの作成
名前付きオブジェクトは、対応する Create API を使用して作成されます。
これらの API はすべて、 LPSECURITY_ATTRIBUTES パラメーターを共有します。これにより、呼び出し元は アクセス制御リスト (ACL) を 指定して、オブジェクトにアクセスできるプロセスを制御できます。 パッケージ アプリケーションと名前付きオブジェクトを共有するには、名前付きオブジェクトの作成時に ACL 内でアクセス許可を付与する必要があります。
セキュリティ識別子 (SID) は、ACL 内の ID を表します。 パッケージ化されたアプリケーションには、パッケージ ファミリ名に基づいて独自の SID があります。 パッケージ アプリケーションの SID を生成するには、そのパッケージ ファミリ名を DeriveAppContainerSidFromAppContainerName に渡します。
Note
パッケージ ファミリ名は、開発時にVisual Studioのパッケージ マニフェスト エディター、Microsoft Storeで公開されたアプリケーションのパートナー センター、または既にインストールされているアプリケーションの Get-AppxPackage PowerShell コマンドを使用して確認できます。
このサンプル では、名前付きオブジェクトを ACL するために必要な基本的なパターンを示します。 パッケージ 化されたアプリケーションと名前付きオブジェクトを共有するには、アプリケーションごとに EXPLICIT_ACCESS 構造を構築します。
grfAccessMode = GRANT_ACCESS-
grfAccessPermissions =オブジェクトと使用目的に基づく適切なアクセス許可 grfInheritance = NO_INHERITANCETrustee.TrusteeForm = TRUSTEE_IS_SIDTrustee.TrusteeType = TRUSTEE_IS_USER-
Trustee.ptstrName =DeriveAppContainerSidFromAppContainerName で取得した SID
パッケージ 化されたアプリケーションのLPSECURITY_ATTRIBUTES規則をCreate呼び出しで EXPLICIT_ACCESS パラメーターに設定することで、それらのアプリケーションにアクセス権を付与して、名前付きオブジェクトを開くことができます。
Note
Win32 アプリケーションは、AppContainer アプリによって作成された名前付きオブジェクトにアクセスできます。オブジェクトの DACL でアクセスが許可されている場合は、オブジェクトを 開くときにオブジェクト名を修飾します。 ほとんどの名前付きオブジェクトの既定の DACL は、作成者と管理者にアクセス権を付与します。 制限の厳しい DACL を設定した場合、Win32 呼び出し元には明示的なアクセス エントリも必要です。
例: ACL を使用した名前付きイベントの作成 (C++)
次の例は、名前付きイベントを作成し、パッケージ 化されたアプリケーションへのアクセス権を付与する方法を示しています。
#include <windows.h>
#include <sddl.h>
#include <aclapi.h>
#include <userenv.h>
HANDLE CreateSharedEvent(PCWSTR eventName, PCWSTR packageFamilyName)
{
// Derive the SID for the target packaged application
PSID appContainerSid = nullptr;
HRESULT hr = DeriveAppContainerSidFromAppContainerName(
packageFamilyName, &appContainerSid);
if (FAILED(hr)) return nullptr;
// Build an EXPLICIT_ACCESS entry granting synchronization and signal rights
EXPLICIT_ACCESS_W explicitAccess = {};
explicitAccess.grfAccessPermissions = SYNCHRONIZE | EVENT_MODIFY_STATE;
explicitAccess.grfAccessMode = GRANT_ACCESS;
explicitAccess.grfInheritance = NO_INHERITANCE;
explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_USER;
explicitAccess.Trustee.ptstrName = reinterpret_cast<LPWSTR>(appContainerSid);
// Create the ACL
PACL acl = nullptr;
DWORD result = SetEntriesInAclW(1, &explicitAccess, nullptr, &acl);
if (result != ERROR_SUCCESS)
{
FreeSid(appContainerSid);
return nullptr;
}
// Create the security descriptor
SECURITY_DESCRIPTOR sd = {};
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ||
!SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE))
{
LocalFree(acl);
FreeSid(appContainerSid);
return nullptr;
}
SECURITY_ATTRIBUTES sa = {};
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
// Create the named event with only the rights the creator needs
HANDLE hEvent = CreateEventExW(&sa, eventName, 0,
SYNCHRONIZE | EVENT_MODIFY_STATE);
// Cleanup
LocalFree(acl);
FreeSid(appContainerSid);
return hEvent;
}
名前付きオブジェクトを開く
名前付きオブジェクトは、対応する Open API に名前を渡すことによって開かれます。
パッケージ 化されたアプリケーションによって作成された名前付きオブジェクトは、名前付きオブジェクト パスと呼ばれる、アプリケーションの名前空間内に作成されます。 パッケージ 化されたアプリケーションによって作成された名前付きオブジェクトを開く場合、オブジェクト名には、作成するアプリケーションの名前付きオブジェクト パスのプレフィックスを付ける必要があります。
GetAppContainerNamedObjectPath は、SID に基づいてパッケージ 化されたアプリケーションの名前付きオブジェクト パスを返します。 パッケージ アプリケーションの SID を生成するには、そのパッケージ ファミリ名を DeriveAppContainerSidFromAppContainerName に渡します。
Note
パッケージ ファミリ名は、開発時にVisual Studioのパッケージ マニフェスト エディター、Microsoft Storeで公開されたアプリケーションのパートナー センター、または既にインストールされているアプリケーションの Get-AppxPackage PowerShell コマンドを使用して確認できます。
パッケージ 化されたアプリケーションによって作成された名前付きオブジェクトを開く場合は、 <PATH>\<NAME>形式を使用します。
-
<PATH>を、作成するアプリケーションの名前付きオブジェクト パスに置き換えます。 -
<NAME>をオブジェクト名に置き換えます。
Note
オブジェクト名に <PATH> のプレフィックスを付けます。これは、パッケージ 化されたアプリケーションによってオブジェクトが作成された場合にのみ必要です。 Win32 アプリケーションによって作成された名前付きオブジェクトは修飾する必要はありませんが、オブジェクトの作成時には引き続きアクセス権を付与する必要があります。
Windows アプリ SDK に関する考慮事項
MSIX でパッケージ化されたデスクトップ アプリWindows アプリ SDK、パッケージ ID を持つ完全信頼プロセスとして実行されます。AppContainer では実行されません。 つまり、名前付きオブジェクトは、従来の Win32 アプリケーションと同様に、既定でグローバル名前空間に作成されます。
ただし、これらのシナリオで前述した ACL とパス修飾の手順は引き続き必要です。
-
UWP アプリとの通信 - UWP アプリは AppContainer で実行され、分離された名前付きオブジェクト名前空間を持ちます。
GetAppContainerNamedObjectPathを使用し、ACL 経由でアクセス権を付与して、UWP アプリの名前付きオブジェクトにアクセスします。 - アクセスの制限 - 完全信頼アプリ間であっても、明示的な ACL を使用して、名前付きオブジェクトを開くことができるプロセスを制限できます。
- パッケージ化されていないWindows アプリ SDK アプリ - 名前付きオブジェクトは、従来の Win32 アプリケーションと同じ特別な処理を必要とせず、グローバル名前空間にあります。
Remarks
パッケージ アプリケーションの名前付きオブジェクトは、セキュリティを維持し、中断や終了などのアプリケーション ライフサイクル イベントのサポートを確保するために、既定で分離されます。 アプリケーション間で名前付きオブジェクトを共有すると、厳密なバインドとバージョン管理の制約が生じ、各アプリケーションが他のアプリケーションのライフサイクルに対して回復性を持つ必要があります。 このような理由から、同じ発行元のアプリケーション間でのみ名前付きオブジェクトを共有することをお勧めします。
関連するコンテンツ
Windows developer