0
votes

I've got a C# application that I've been using for years to script remote desktop connections. It's always been built on the AxMsRdpClient3 (note the 3, which I guess is some kind of version number). There are features in AxMsRdpClient8 (version 8) that I want to be able to use, but as I understand it, this requires Remote Desktop version 8 to be installed. Not all users have that installed (or even can install it on Windows XP/Vista), though.

So as Sheng Jiang suggested, I am creating the control at runtime now and I have code that looks like this:

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

As expected, rdp8.EndInit() throws an exception on machines that do not have Remote Desktop version 8 installed. The problem is that after we try to create the AxMSRDPClient8, the rdp3.EndInit() fails as well (class not registered) on older machines. If I don't attempt to create the AxMSRDPClient8 first, the AxMSRDPClient3 initializes and works correctly.

1
add os detection code to avoiding trying in the first place. - Sheng Jiang 蒋晟
I could detect the OS, but the OS doesn't really tell you which AxMsRdpClient version to use. For example, Remote Desktop 8 is available for download for Windows 7, but it doesn't come installed by default. Plus, if I detected the OS, my code wouldn't function on the next version of Windows where something like above would continue to work. Is the concept above not valid for activeX controls? Why would a valid activeX control fail just because you had an invalid one before? - Jason
Each of the CLSIDs is compatible with later system versions. For example, the CLSID for the scriptable control on Windows Vista will work on later system versions, such as Windows 7. - Sheng Jiang 蒋晟

1 Answers

3
votes

each version of RDP activeX has a different clsid. You need to detect the OS version and create an activex at runtime with the class id corresponding to the lowest OS version you plan to support.

If your code depends on late binding, better rewrite your code to work with IMsRdpClient* and IMsRdpClientNonScriptable*. For example MsRdpClient8NotSafeForScripting supports the following interfaces:

  • up to version 8 of IMsRdpClient*
  • up to version 5 of IMsRdpClientNonScriptable
  • IMsTscNonScriptable
  • IMsRdpPreferredRedirectionInfo
  • IMsRdpExtendedSettings

MsRdpClient3NotSafeForScripting supports

  • version 2 of IMsRdpClient*
  • IMsRdpClientNonScriptable
  • IMsTscNonScriptable.

if you want to detect whether your activex support a particular interface version, just cast the ActiveX's instance to the interface. when a cast fails you know the interface is not supported.

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