Ham*_*rin 11 c# activation com+ moniker remote-server
我想访问远程服务器上的分区COM +应用程序.我试过这个:
using COMAdmin
using System.Runtime.InteropServices;
_serverName = myRemoteServer;
_partionName = myPartionName;
_message = myMessage;
ICOMAdminCatalog2 catalog = new COMAdminCatalog();
catalog.Connect(_serverName);
string moniker = string.Empty;
string MsgInClassId = "E3BD1489-30DD-4380-856A-12B959502BFD";
//we are using partitions
if (!string.IsNullOrEmpty(_partitionName))
{
COMAdminCatalogCollection partitions = catalog.GetCollection("Partitions");
partitions.Populate();
string partitionId = string.Empty;
foreach (ICatalogObject item in partitions)
{
if (item.Name == _partitionName)
{
partitionId = item.Key;
break;
}
}
if (!string.IsNullOrEmpty(partitionId) )
{
moniker = $"partition:{partitionId}/new:{new Guid(MsgInClassId)}";
try
{
var M = (IMsgInManager)Marshal.BindToMoniker(moniker);
M.AddMsg(_message);
}
catch (Exception ex)
{
throw new Exception($"We can not use: {_partitionName} with Id {partitionId}. {ex.ToString()}");
}
}
else
{
throw;
}
}
else
//we don't have partitions and this will work
{
Type T = Type.GetTypeFromCLSID(new Guid(MsgInClassId), _serverName, true);
var M = (IMsgInManager)Activator.CreateInstance(T);
M.AddMsg(_message);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,当我们在(远程)机器上本地时,分区正在使用名字对象和Marshal.BindToMoniker.但是,当我尝试从我的机器远程执行相同的操作时,我从Marshal.BindToMoniker收到错误,即未启用Partitons.因为我的机器分区未启用.
Message = "COM+ partitions are currently disabled. (Exception from HRESULT: 0x80110824)"
Run Code Online (Sandbox Code Playgroud)
如何使用Marshal.BindToMoniker在远程服务器上运行.这是我可以添加到名字字符串的东西,即
moniker = $"server:_server/partition:{partitionId}/new:{new Guid(MsgInClassId)}"
Run Code Online (Sandbox Code Playgroud)
我的问题非常类似于: 在另一个分区中激活COM +对象
tl;dr
根据 MS 文档,有一种方法可以通过在 BIND_OPTS2 结构中设置 pServerInfo 来绑定名字来实现此目的。不幸的是,这不适用于 COM 类名称。
请参阅: https: //msdn.microsoft.com/en-us/library/windows/desktop/ms694513 (v=vs.85).aspx,其中显示 *pServerInfo:
COM 的新类名称当前不支持 pServerInfo 标志。
但也许只是尝试你的场景,在将来的某个时候它可能会受到支持(或者已经是并且文档是错误的)。
另请参阅:
http: //thrysoee.dk/InsideCOM+/ch11c.htm
,其中还在脚注中说它不适用于类名称:http://thrysoee.dk/InsideCOM+/footnotes.htm#CH1104
理论和建议的解决方案(如果 c# 支持)
免责声明:我无法测试代码,因为我没有测试设置。这超出了我的想象。一点伪代码。
为此,您必须自己编写 COM/Moniker 调用的代码。为此,您可以查看微软实施的来源作为起点。BindToMoniker 的实现如下:
public static Object BindToMoniker(String monikerName)
{
Object obj = null;
IBindCtx bindctx = null;
CreateBindCtx(0, out bindctx);
UInt32 cbEaten;
IMoniker pmoniker = null;
MkParseDisplayName(bindctx, monikerName, out cbEaten, out pmoniker);
BindMoniker(pmoniker, 0, ref IID_IUnknown, out obj);
return obj;
}
Run Code Online (Sandbox Code Playgroud)
CreateBindCtx、MkParseDisplayName和BindMoniker是 OLE32.dll 函数。
IBindCtx有更改绑定上下文的方法。为此,您可以致电IBindCtx.GetBindContext(out BIND_OPTS2)并将设置更改为您需要的设置。然后使用 设置新的绑定上下文IBindCtx.SetBindContext(BIND_OPTS2)。所以本质上你自己的代码版本看起来像这样(伪代码):
public static Object BindToMoniker(String monikerName)
{
Object obj = null;
IBindCtx bindctx = null;
CreateBindCtx(0, out bindctx);
BIND_OPTS2 bindOpts;
bindOpts.cbStruct = Marshal.SizeOf(BIND_OPTS2);
bindctx.GetBindOptions(ref bindOpts);
// Make your settings that you need. For example:
bindOpts.dwClassContext = CLSCTX_REMOTE_SERVER;
// Anything else ?
bindOpts.pServerInfo = new COSERVERINFO{pwszName = "serverName"};
bindctx.SetBindOptions(ref bindOpts);
UInt32 cbEaten;
IMoniker pmoniker = null;
MkParseDisplayName(bindctx, monikerName, out cbEaten, out pmoniker);
BindMoniker(pmoniker, 0, ref IID_IUnknown, out obj);
return obj;
}
Run Code Online (Sandbox Code Playgroud)
如前所述,不幸的是,该代码无法直接用 C# 编写。甚至 OLE32.dll 方法声明 CreateBindCtx、MkParseDisplayName 和 BindMoniker 也在 Marshal.cs 中私有声明,因此您必须在项目中再次声明它们。
但幸运的是,我们IBindCtx使用了 a 声明BIND_OPTS2和 BIND_OPTS2 结构定义本身。它们是在Microsoft.VisualStudio.OLE.Interop(无论如何在这个命名空间中有趣的声明)中声明的。因此您可以尝试使用它们,因为在 Marshal 对象和 marshal.cs 中仅使用了 BIND_OPTS 结构。我不知道这是否是框架的一部分并且可重新分发(我对此表示怀疑),但对于测试来说这应该足够好了。如果有效,可以在您自己的解决方案中再次声明这些内容。
有关所用函数的一些信息:
BindMoniker
CreateBindCtx
MkParseDisplayName
BIND_OPTS2