2012-01-30 79 views
0

我已經能夠使用CreateToolWindow2以編程方式從F#Interactive創建一個VS2010 AddIn工具窗口,該工具窗口本身是一個工具窗口。我傳給CreateToolWindow2的參數AssemblyClass對應於組成工具窗口的Panel(WinForms)。對創建的面板的引用通過參考ControlObject「ref」參數「返回」。插件間通信

已經打上我的面板的與ComVisible(true)屬性我得到恢復,實例除了當我嘗試訪問該實例的任何成員(從F#互動的上下文中)組裝我得到一個RemotingException:「這個遠程代理具有沒有通道接收器,這意味着服務器沒有正在監聽的註冊服務器通道,或者這個應用程序沒有合適的客戶端通道與服務器交談。「

任何想法如何避開這個障礙?

+0

確實[這](http://stackoverflow.com/questions/1657863/remoting-and-missing-channel-sinks)幫助? – Daniel 2012-01-30 05:41:33

+0

@丹尼爾 - 謝謝,我已經看到了,它看起來很相關,但沒有看到答案可以幫助我(我幾乎沒有使用過Remoting API)。我的一部分麻煩可能是我的面板控件已經從'Panel'繼承,不能從MarshalByRefObject繼承。此外,'CreateToolWindow2'實際上創建了我的面板實例並將其交給我......不確定是否缺少對象的所有權會使事情變得困難(指的是「......兩端創建通道」)。 。 – 2012-01-30 05:52:51

+0

@Daniel - 實際上,'Panel'確實最終從MarshalByRefObject繼承,所以我想我已經有一些東西在我身邊了...... – 2012-01-30 06:02:48

回答

1

這有點原始,我個人認爲它很髒,但始終存在使用文件系統來管理通信的後備。指定一個可由兩個插件訪問的臨時文件並管理它們之間的鎖定,並且突然間您有一個跨插件通信系統。這當然假設你很容易改變兩個插件來使用這個方法(我不確定你會考慮其中一個插件是否被預先包裝好)。

+0

對於一個古怪的,可信的想法+1!但我堅持一個更清潔的方法! – 2012-01-30 05:32:14

1

WCF service使用named pipes。我現在正在這樣做,以在一些WF4活動的設計界面和Visual Studio擴展之間進行溝通。

它很簡單。我無法顯示所有的代碼,因爲它的一些代碼封裝在控制打開和關閉通道的幫助程序中,但定義非常簡單,並且全部以代碼完成。

你只需要定義一個綁定

var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport); 
binding.ReceiveTimeout = TimeSpan.FromMinutes(1); 

建立頻道

var channelFactory = new ChannelFactory<IServiceInterface>(binding, endpointAddress); 

,你必須確保端點地址是保證在客戶端和服務器相同,它們共享相同的進程,但存在於不同的AppDomain中。一個簡單的方法做,這是作用域的地址進程ID ...

private const string AddressFormatString = 
    "net.pipe://localhost/Company/App/HostType/{0}"; 
private static string _hostAddress; 

public static string HostAddress() 
{ 
    if (_hostAddress == null) 
     _hostAddress = string.Format(
          AddressFormatString, 
          Process.GetCurrentProcess().Id); 
    return _hostAddress; 
} 

你有這個(,一個客戶端應用程序域一個在插件的AppDomain)兩個實際的副本,但由於它們都在同一個進程中,主機地址保證在兩者中都是相同的,並且你不會遇到VS同時加載多個VS實例的問題(不要擔心Running Object Table,謝謝)。

我將這個地址代碼保存在基本主機類中。打開主機通道也很容易:

Host = new ServiceHost(this, new Uri(HostAddress())); 

var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);  
Host.AddServiceEndpoint(typeof(IServiceInterface), binding, HostAddress()); 
Host.Open();