COMベースのクライアントサーバーセットアップに問題があります。COMサーバーはC#(.NET 4.0)で記述されており、(登録済みの)ローカルサーバーとして実行されます。
サーバーに接続するアプリケーションに応じて、他のクライアントはサーバーの実行に失敗します(HRESULTからの例外:0x80080005(CO_E_SERVER_EXEC_FAILURE))
根本的な問題はここで説明されています(セクションCOMは整合性を認識しています)。私の理解では、昇格したアプリケーションがより高い整合性レベルでサーバーを作成するという事実が原因です。次に、昇格されていない別のアプリケーションが接続する場合、同じインスタンスに接続することはできません。昇格されていないアプリケーションがプロセスを作成し、昇格されたアプリケーションが接続した場合も同じことが起こります。
このページで説明されている解決策を実装しようとしました。レジストリを変更して、すべてのクライアントが接続できるようにするセキュリティ記述子を設定します。C ++にはコードサンプルがありますが、これは.NETでも事実上同じことを行います。
// Security Descriptor with NO_EXECUTE_UP
var sd = new RawSecurityDescriptor("O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)");
byte[] securityDescriptor = new Byte[sd.BinaryLength];
sd.GetBinaryForm(securityDescriptor, 0);
RegistryKey key = Registry.ClassesRoot.OpenSubKey("AppID\\{APP-ID-GUID}", true);
if (key == null)
{
key = Registry.ClassesRoot.CreateSubKey("AppID\\{APP-ID-GUID}");
}
using (key)
{
key.SetValue("LaunchPermission", securityDescriptor, RegistryValueKind.Binary);
}
ただし、これには望ましい効果はありません。2番目のクライアントが問題のオブジェクトのインスタンスを作成しようとすると、WindowsはCOMサーバーの別のインスタンスを起動しようとしますが、サーバーは2つのインスタンスが同じユーザーとして実行されるのを防ぎます。私が設定した権限を考えると、最初に2番目のインスタンスが起動することは期待できません。
クライアントアプリケーションの1つはMediumILで実行されており、もう1つはHigh ILで実行されているため、次のような必須ラベルのバリアントも試してみました。
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;ME)
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)(ML;;NX;;;ME)(ML;;NX;;;HI)
ROTFlags
また、ページで提案されているように、レジストリキーを0x1(ROTFLAGS_ALLOWANYCLIENT)に設定しようとしましたが、動作に変化はありません。
LaunchPermissionレジストリ値が何らかの方法で使用されていることを確認しました。Process Monitorを使用して読み取られている場所を見つけることはできませんが、dcomcnfg.exe
ツールを使用して同じキーを設定すると、起動権限を拒否することでサーバーの読み込みに失敗させることができます。
私のサーバープロセスは昇格を必要としないことを指摘したいと思います。昇格されたプロセスと昇格されていないプロセスの両方を単一のサーバーインスタンスに接続できるようにするにはどうすればよいですか?