2017-01-03 27 views
11

원격 서버의 파티션 된 COM + 응용 프로그램에 액세스하려고합니다. 나는이 시도했다 : 우리는 (원격) 시스템에 로컬 때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+ 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가 있습니다. 이제는 좋은 부분입니다. 문서의 나쁜 부분 : 클래스 모니 커는 현재 pServerInfo 플래그를 사용하지 않습니다. 그래서 지금은 효과가 없을 것 같습니다. – Uwe

답변

3

TL; DR
MS 문서에 할 수있는 방법이 있나요 따르면 이것은 모니 커를 바인딩하기위한 BIND_OPTS2 구조체의 pServerInfo를 설정함으로써 가능합니다. 불행하게도 이것은 이 아니며 COM 클래스 모니 커를 위해이 아닙니다.

참조 :

COM의 새로운 클래스 모니 커는 현재 pServerInfo 플래그를 준수하지 않습니다 : 그것은 * pServerInfo에 대해 말한다 https://msdn.microsoft.com/en-us/library/windows/desktop/ms694513(v=vs.85).aspx .

시나리오를 시도해보고 나중에 지원 될 수도 있습니다 (또는 이미 문서가 잘못되어 있습니다).

참조 : 는 또한 클래스 모니 커 작동하지 않습니다 각주 말한다 http://thrysoee.dk/InsideCOM+/ch11c.htm
: 그것은
면책 조항 C#에서 지원하는 경우 http://thrysoee.dk/InsideCOM+/footnotes.htm#CH1104

이론 및 제안 솔루션 : 나는 테스트 설정이 없으므로 코드를 테스트 할 수 없습니다. 이건 내 머리 꼭대기에서 떨어져있어. 약간의 의사 코드.

이렇게하려면 COM/Moniker를 직접 호출해야합니다. 이를 위해 마이크로 소프트 구현 소스를 출발점으로 볼 수 있습니다.

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, MkParseDisplayNameBindMoniker이 OLE32.DLL 기능은 다음과 같습니다 이 BindToMoniker처럼 구현된다.

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에서 개인적으로 선언되므로 프로젝트에서 다시 선언해야합니다.

BIND_OPTS2 및 BIND_OPTS2 구조 정의 자체를 사용하여 IBindCtx 선언을 사용하여 운이 좋습니다. 그들은 Microsoft.VisualStudio.OLE.Interop (어쨌든이 네임 스페이스의 흥미로운 선언)에 선언되어 있습니다. 그래서 Marshal 객체와 marshal.cs 내부에서만 BIND_OPTS 구조체가 사용되기 때문에이를 사용할 수 있습니다. 이것이 프레임 워크의 일부인지, 재배포 할 수 있는지 (나는 의심 스럽지만) 테스트하기에는 충분할 것입니다. 작동하는 경우 이러한 사항은 자체 솔루션에서 다시 선언 할 수 있습니다. 사용 된 기능에 대한

일부 정보 :
BindMoniker
CreateBindCtx
MkParseDisplayName
BIND_OPTS2

0

원격 COM 대기열 또는 DCOM에 액세스 할 필요가있다. DCOM으로 액세스 할 때 서버에서 응용 프로그램 프록시를 내 보내야합니다. 그리고 클라이언트 PC에 프록시를 설치하십시오.

응용 프로그램 프록시를 내보내려면 COM 활성화 유형을 "서버 응용 프로그램"으로 구성해야합니다.

응용 프로그램 프록시를 설치 한 후, 클라이언트가 직접 파티션에 대해

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

를 호출 할 수 있습니다, 자신의 응용 프로그램 세트를 각 사용자를 보여주기 위해 설계되었습니다. 현재 파티션이 사용자와 연결되어 있으면 파티션에 코드를 쓸 필요가 없습니다.