У меня возникла проблема с настройкой клиент-сервер на базе COM. COM-сервер написан на С# (.NET 4.0) и работает как (зарегистрированный) локальный сервер.
В зависимости от того, какое приложение подключается к серверу, другие клиенты получат Выполнение сервера не выполнено (Исключение из HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)
Основная проблема объясняется здесь (в разделе COM известно о целостности). То, как я это понимаю, связано с тем, что повышенное приложение создает сервер с более высоким уровнем целостности. Когда подключается другое приложение без добавления, ему не разрешено подключаться к одному экземпляру. То же самое происходит, когда не-приподнятое приложение создает этот процесс, после чего соединение с повышенным приложением.
Я попытался реализовать решение, описанное на странице : изменение реестра для установки дескриптора безопасности, который должен позволять всем клиентам подключаться, В С++ есть пример кода, но это делает то же самое в .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);
}
Однако это не имеет желаемого эффекта. Когда второй клиент пытается создать экземпляр объекта, о котором идет речь, Windows пытается запустить отдельный экземпляр моего COM-сервера, но сервер предотвращает запуск двух экземпляров в качестве одного и того же пользователя. Учитывая установленные мной разрешения, я бы не ожидал, что второй экземпляр будет запущен в первую очередь.
Поскольку одно из клиентских приложений работает в среде IL, а другое в 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
для установки того же ключа, я могу заставить сервер потерпеть неудачу при загрузке, отказав разрешениям на запуск.
Я хотел бы указать, что мой серверный процесс не требует повышения. Как сделать как повышенные, так и невыполненные процессы способными подключиться к экземпляру одного сервера?