2014-02-26 204 views
0

我有一个C#应用程序,我已经使用多年来脚本远程桌面连接。它总是建立在AxMsRdpClient3上(注意3,我猜是某种版本号)。我希望能够使用AxMsRdpClient8(版本8)中的功能,但据我了解,这需要安装远程桌面版本8。但并非所有用户都已安装(甚至可以在Windows XP/Vista上安装它)。远程桌面ActiveX控件

因此,作为盛强建议,我现在在运行时创建的控制和我有一些代码,看起来像这样:

try 
{ 
    AxMsRdpClient8 rdp8 = new AxMsRdpClient8(); 
    rdp8.BeginInit(); 
    // set some properties here 
    rdp8.EndInit(); // throws Exception on machines without version 8 installed 
} 
catch (Exception ex) 
{ 
    AxMsRdpClient3 rdp3 = new AxMsRdpClient3(); 
    rdp3.BeginInit(); 
    // set some properties here 
    rdp3.EndInit(); 
} 

正如预期的那样,rdp8.EndInit()抛出一个异常,在不机器安装了远程桌面版本8。问题是,在我们尝试创建AxMSRDPClient8之后,rdp3.EndInit()在旧机器上也会失败(类未注册)。如果我不试图先创建AxMSRDPClient8,则AxMSRDPClient3将初始化并正常工作。

+0

添加os检测代码以避免尝试摆在首位。 –

+0

我可以检测操作系统,但操作系统并没有真正告诉你使用哪个AxMsRdpClient版本。例如,远程桌面8可供Windows 7下载,但默认情况下不会安装。另外,如果我检测到操作系统,我的代码将无法在下一版本的Windows上运行,其中类似上面的内容会继续工作。上述概念对于activeX控件无效吗?为什么一个有效的ActiveX控件会因为之前有一个无效控件而失败? – Jason

+0

每个CLSID都与更高版本的系统兼容。例如,Windows Vista上可编写脚本控件的CLSID可用于更高版本的系统,如Windows 7. –

回答

2

each version of RDP activeX has a different clsid。您需要检测操作系统版本并创建an activex at runtime with the class id corresponding to the lowest OS version you plan to support

如果您的代码依赖于后期绑定,请更好地重写您的代码以使用IMsRdpClient *和IMsRdpClientNonScriptable *。例如MsRdpClient8NotSafeForScripting支持以下接口:

  • 高达IMsRdpClient *
  • 版本8高达IMsRdpClientNonScriptable的版本5
  • IMsTscNonScriptable
  • IMsRdpPreferredRedirectionInfo
  • IMsRdpExtendedSettings

MsRdpClient3NotSafeForScripting支撑

  • 版本IMsRdpClient *
  • IMsRdpClientNonScriptable
  • IMsTscNonScriptable 2。

如果要检测您的activex是否支持特定的接口版本,只需将该ActiveX的实例 转换为接口即可。当一个强制转换失败时,您知道该接口不受支持。

protected void CreateRdpActiveX() 
{ 
    try 
    { 
     string clsid=GetRdpActiveXClsIdByOSVersion(); 
     Type type = Type.GetTypeFromCLSID(clsid, true); 
     this.axRdp = new AxHost (type.GUID.ToString()); 
     ((ISupportInitialize)(axRdp)).BeginInit(); 
     SuspendLayout(); 
     this.panel1.Controls.Add(axRdp);  
     ((ISupportInitialize)(axRdp)).EndInit(); 
     ResumeLayout(false); 
     var msRdpClient8 = axRdp.GetOcx() as IMsRdpClient8; 
     if(msRdpClient8!=null) 
     { 
      var advancedSettings9 =msRdpClient8.AdvancedSettings9 as IMsRdpClientAdvancedSettings8; 
      if(advancedSettings9!=null) 
       advancedSettings9.BandwidthDetection=true; 

     } 
    } 
    catch (System.Exception ex) 
    { 
     System.Console.WriteLine(ex.Message); 
    } 
} 
+0

您能否提供接口版本检测的示例? –

+0

我终于尝试了这个建议。第一个问题是Type.GetTypeFromCLSID采用GUID,而不是String。我假设我只是传递一个新的GUID(clsid)而不是clsid。我无法解决的问题是AxHost是一个抽象类,不能在第7行创建。你知道解决方法吗? – Jason

+0

我做了一个AxHost的具体子类,似乎让我过去不能创建AxHost,现在我可以编译我的类并通过它运行而不会出错。我的新问题是我在AxMsRdpClient对象上有一些事件处理程序。我如何将这些事件处理程序(OnConnected等)附加到对象,现在它是AxHost而不是AxMsRdpClient对象? – Jason