繁体   English   中英

使用C#中的分区在远程服务器上进行COM +激活

[英]COM+ activation on a remote server with partitions in C#

我想访问远程服务器上的分区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);
            }

        }

因此,当我们在(远程)机器上本地时,分区正在使用名字对象和Marshal.BindToMoniker。 但是,当我尝试从我的机​​器远程执行相同的操作时,我从Marshal.BindToMoniker收到错误,即未启用Partitons。 因为我的机器分区未启用。

Message = "COM+ partitions are currently disabled. (Exception from HRESULT: 0x80110824)"

如何使用Marshal.BindToMoniker在远程服务器上运行。 这是我可以添加到名字字符串的东西,即

moniker = $"server:_server/partition:{partitionId}/new:{new Guid(MsgInClassId)}"

我的问题非常类似于: 在另一个分区中激活COM +对象

TL;博士
根据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; 
    } 

CreateBindCtxMkParseDisplayNameBindMoniker是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; 
    } 

如上所述,遗憾的是,此代码无法用C#开箱即用。 甚至OLE32.dll方法声明CreateBindCtx,MkParseDisplayName和BindMoniker都是在Marshal.cs中私下声明的,因此您必须再次在项目中声明它们。

但我们很幸运, IBindCtx声明使用BIND_OPTS2和BIND_OPTS2结构定义本身。 它们在Microsoft.VisualStudio.OLE.Interop中声明(无论如何都在此命名空间中有趣的声明)。 所以你可以尝试使用它们,因为在Marshal对象和marshal.cs中只使用了BIND_OPTS结构。 我不知道这是否是框架的一部分和可再分发(我对此表示怀疑),但对于测试,这应该足够好了。 如果它有效,可以在您自己的解决方案中再次声明这些内容。

有关使用功能的一些信息:
BindMoniker
CreateBindCtx
MkParseDisplayName
BIND_OPTS2

Queue或DCOM需要访问远程COM。 在通过DCOM访问时,您需要在服务器上导出应用程序代理。 并在客户端PC中安装代理。

必须将COM激活类型配置为“服务器应用程序”才能导出应用程序代理。

安装应用程序代理后,客户端可以直接调用

moniker = $"new:{new Guid(MsgInClassId)}";
try
{
    var M = Marshal.BindToMoniker(moniker);
}

对于分区,它旨在向每个用户显示自己的应用程序集。 如果当前分区与用户关联,则不需要将代码写入代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM