2017-01-03 15 views
11

Tôi muốn truy cập các ứng dụng COM + được phân đoạn trên máy chủ từ xa. Tôi đã thử này:COM + kích hoạt trên máy chủ từ xa có phân vùng trong 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); 
      } 

     } 

Vì vậy, khi chúng tôi là địa phương trên (remote) máy, phân vùng đang làm việc với biệt danh và Marshal.BindToMoniker. Nhưng khi tôi thử làm điều tương tự từ xa từ máy của mình, tôi gặp lỗi từ Marshal.BindToMoniker rằng Partitons không được bật. Bởi vì trên phân vùng máy của tôi không được kích hoạt.

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

Tôi có thể sử dụng Marshal.BindToMoniker để chạy trên máy chủ từ xa. Có điều gì đó tôi có thể thêm vào chuỗi biệt danh nghĩa

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

Câu hỏi của tôi là rất simular này: COM+ object activation in a different partition

+0

Bạn có chắc chắn điều này không theo thiết kế? Thông báo lỗi có vẻ phù hợp với cài đặt của bạn. Bạn nên liên hệ với Microsoft tôi đoán. Ngoài ra, hãy kiểm tra điều này: https://social.technet.microsoft.com/Forums/windows/en-US/a601d45a-10c0-4da9-a424-d35afef22161/how-to-enable-windows-7-windows-8-com- phân vùng chức năng –

+0

Tôi đoán bạn bằng cách nào đó phải kết hợp tên máy chủ vào biệt danh. Ngay bây giờ bạn chỉ sử dụng tên máy chủ để kết nối với danh mục trên máy chủ. Bạn không sử dụng nó để tạo đối tượng như bạn làm trong trường hợp bạn không sử dụng phân vùng. Vì vậy, bạn đang thực sự cố gắng tạo đối tượng trên máy cục bộ của mình nơi bạn không bật phân vùng. Giải pháp có lẽ không cho phép phân vùng cục bộ như được đề xuất bởi liên kết được cung cấp bởi @SimonMourier vì điều đó sẽ chỉ cho phép bạn tạo đối tượng cục bộ và đó có lẽ không phải là những gì bạn muốn ở đây. –

+1

@MikaelEriksson Về lý thuyết có thể có. Trong thực tế, có vẻ như hiện tại có thể không được hỗ trợ. BindToMoniker được thực hiện với một cuộc gọi đến CreateBindCtx (nhận được một IBindCtx), MkParseDisplayName và cuối cùng là một BindMoniker. Bạn có thể tự thực hiện trình tự và thay vì sử dụng BindCtx mặc định (có cấu trúc BIND_OPTS), bạn có thể tự tạo một cấu trúc với cấu trúc BIND_OPTS2. Điều đó có một pServerInfo với thông tin máy chủ. Bây giờ thats phần tốt. Phần xấu từ tài liệu: class moniker hiện không tôn vinh cờ pServerInfo. Vì vậy, có vẻ như nó sẽ không hoạt động ngay bây giờ. – Uwe

Trả lời

3

tl; dr
Theo MS tài liệu có một cách để làm điều này bằng cách thiết lập pServerInfo trong cấu trúc BIND_OPTS2 để ràng buộc biệt danh. Rất tiếc, đây là không phải làm việc cho biệt danh lớp COM.

see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms694513(v=vs.85).aspx nơi nó nói cho * pServerInfo: lớp biệt danh mới

COM của hiện không tôn trọng lá cờ pServerInfo.

Nhưng có thể chỉ cần thử kịch bản của bạn và trong một thời gian tương lai, nó có thể được hỗ trợ (hoặc đã và tài liệu sai).

also see: http://thrysoee.dk/InsideCOM+/ch11c.htm
nơi nó cũng nói trong chú thích nó không hoạt động cho lớp biệt danh: http://thrysoee.dk/InsideCOM+/footnotes.htm#CH1104

Lý thuyết và giải pháp gợi ý nếu nó được hỗ trợ trong C#
Disclaimer: Tôi không thể kiểm tra mã khi tôi không có thiết lập thử nghiệm. Đây là đầu của tôi. Một mã giả bit.

Để thực hiện việc này, bạn phải tự mã hóa các cuộc gọi COM/Moniker. Đối với điều này, bạn có thể xem xét nguồn gốc của việc triển khai microsoft như là một điểm khởi đầu. Có BindToMoniker được thực hiện như:

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 là chức năng OLE32.dll.

IBindCtx có các phương pháp để thay đổi ngữ cảnh ràng buộc. Đối với điều này bạn gọi IBindCtx.GetBindContext(out BIND_OPTS2) và thay đổi cài đặt cho những gì bạn cần. Sau đó, đặt bối cảnh ràng buộc mới với IBindCtx.SetBindContext(BIND_OPTS2).Vì vậy, về cơ bản phiên bản mã của riêng bạn sẽ trông giống như thế này (mã giả):

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

Như đã nói, rất tiếc, mã này không thể viết trong C# ra khỏi hộp. Ngay cả các khai báo phương thức OLE32.dll CreateBindCtx, MkParseDisplayName và BindMoniker được khai báo riêng trong Marshal.cs, do đó bạn sẽ phải khai báo chúng trong dự án của bạn một lần nữa.

Nhưng chúng tôi may mắn với tuyên bố IBindCtx sử dụng số BIND_OPTS2 và định nghĩa cấu trúc BIND_OPTS2. Chúng được khai báo trong Microsoft.VisualStudio.OLE.Interop (các khai báo thú vị trong không gian tên này). Vì vậy, bạn có thể thử sử dụng chúng bởi vì bên trong đối tượng Marshal và marshal.cs chỉ sử dụng cấu trúc BIND_OPTS. Tôi không biết nếu điều này là một phần của khuôn khổ và redistributable (tôi nghi ngờ nó), nhưng để thử nghiệm này nên là đủ tốt. Nếu nó hoạt động những điều này có thể được tuyên bố một lần nữa trong giải pháp của riêng bạn.

Một số thông tin về chức năng sử dụng:
BindMoniker
CreateBindCtx
MkParseDisplayName
BIND_OPTS2

0

COM từ xa cần phải được truy cập bởi Queue hoặc DCOM. Bạn cần xuất proxy ứng dụng trên máy chủ khi truy cập bằng DCOM. Và cài đặt proxy trong máy khách.

Loại kích hoạt COM phải được định cấu hình là "Ứng dụng máy chủ" để xuất proxy ứng dụng.

Sau khi cài đặt ứng dụng proxy, khách hàng có thể trực tiếp gọi

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

Đối với phân vùng, nó được thiết kế để hiển thị mỗi người dùng với bộ ứng dụng riêng. Nếu phân vùng hiện tại được liên kết với người dùng, phân vùng không cần phải được viết bằng mã.

Các vấn đề liên quan