我遇到基于COM的客户端 - 服务器设置问题。 COM服务器使用C#(.NET 4.0)编写,并作为(已注册的)本地服务器运行。
根据连接到服务器的应用程序,其他客户端将收到服务器执行失败(HRESULT异常:0x80080005(CO_E_SERVER_EXEC_FAILURE)
解释了潜在问题here (in the section COM is integrity aware)。我理解它的方式,是由于提升的应用程序创建具有更高完整性级别的服务器这一事实。当另一个未提升的应用程序连接时,不允许连接到同一个实例。当非提升的应用程序创建进程时,会发生同样的情况,然后是提升的应用程序连接。
我尝试实现page中描述的解决方案:修改注册表以设置应允许所有客户端连接的安全描述符。在C ++中有code sample,但这在.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服务器的单独实例,但服务器会阻止两个实例作为同一用户运行。鉴于我设置的权限,我不希望第一个实例首先启动。
由于其中一个客户端应用程序在Medium IL中运行,另一个在High IL中运行,我还在mandatory label上尝试了变体,如:
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
工具设置相同的密钥时,我可以通过拒绝启动权限来强制服务器加载失败。
我想指出我的服务器进程不需要提升。如何使提升和非提升的进程都能够连接到单个服务器实例?
答案 0 :(得分:1)
根据Windows Vista Security Model Analysis,您需要使用共享对象(如命名管道)在不同的IL之间进行操作。此外,共享对象的IL应等于您使用的最低IL。
答案 1 :(得分:0)
你必须将Debug选项设置为VS中的Any cpu。