2017-01-03 2 views
11

Я хочу получить доступ к секционированным приложениям COM + на удаленном сервере. Я попытался это:COM + активация на удаленном сервере с разделами в C#

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+ object activation in a different partition

+0

Вы уверены, что это не дизайн? Сообщение об ошибке соответствует вашим настройкам. Вы должны связаться с Microsoft, я думаю. Также проверьте это: https://social.technet.microsoft.com/Forums/windows/en-US/a601d45a-10c0-4da9-a424-d35afef22161/how-to-enable-windows-7-windows-8-com- partitions-function –

+0

Думаю, вам почему-то нужно включить имя сервера в прозвище. Прямо сейчас вы используете только имя сервера для подключения к каталогу на сервере. Вы не используете его для создания объекта так же, как в случае, если вы не используете разделы. Таким образом, вы на самом деле пытаетесь создать объект на своем локальном компьютере, на котором у вас нет разрешенных разделов. Решение, вероятно, не должно включать локальные разделы, как предложено ссылкой, предоставленной @SimonMourier, потому что это позволит вам создать объект локально, и это, вероятно, не то, что вы хотите здесь. –

+1

@MikaelEriksson В теории возможно возможно. На самом деле, похоже, в настоящее время может не поддерживаться. BindToMoniker реализуется с вызовом CreateBindCtx (получает IBindCtx), MkParseDisplayName и, наконец, BindMoniker. Вы можете реализовать последовательность самостоятельно, и вместо того, чтобы использовать BindCtx по умолчанию (который имеет структуру BIND_OPTS), вы можете создать его самостоятельно с помощью структуры BIND_OPTS2. У этого есть pServerInfo с информацией о сервере. Теперь это хорошая часть. Плохая часть документации: class moniker в настоящее время не соблюдает флаг pServerInfo. Похоже, что сейчас это не сработает. – Uwe

ответ

3

Т.Л., д-р
Согласно MS документации есть способ сделать это путем установки pServerInfo в структуре BIND_OPTS2 для привязки прозвища. К сожалению, это не, работающий для прозвища 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; 
    } 

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

Как уже говорилось, к сожалению, этот код не представляется возможным написать в 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

0

Удаленный COM должен быть доступен по очереди или DCOM. При доступе к DCOM вам необходимо экспортировать прокси-сервер приложения. И установите прокси-сервер на клиентский ПК.

Тип активации COM должен быть настроен как «Серверное приложение» для экспорта прокси-сервера приложения.

После установки прокси-сервера приложений, клиент может непосредственно вызывать

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

Для раздела, он предназначен, чтобы показать каждый пользователь собственного набора приложений. Если текущий раздел связан с пользователем, раздел не должен записываться в коды.

Смежные вопросы