1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Dynamic Loading of SimConnect Versions

Discussion in 'SimConnect' started by scruffyduck, 13/2/08.

  1. scruffyduck

    scruffyduck Administrator Staff Member FSDevConf team Resource contributor

    Joined:
    17/9/05
    Messages:
    23,308
    Country:
    wales
    The recent problem with ADE and Pete's comments on FSUIPC lead me to think about dynamically loading the version of SimConnect that matches the users version of FSX. I have no idea how to do this :eek: If anyone can offer some pointers as to how I might handle this in the managed environment (I am using C# but understand VB.Net) I would be most appreciative :)
  2. Pete Dowson

    Pete Dowson

    Joined:
    25/9/06
    Messages:
    315
    Country:
    unitedkingdom
    See this thread over in the Avsim Simconnect forum:

    http://forums.avsim.net/dcboard.php?az=show_topic&forum=255&topic_id=969

    I can answer questions if you like. But only really in C/C++. No idea about managed languages I'm afraid.

    Regards

    Pete
  3. Daniel

    Daniel

    Joined:
    21/12/06
    Messages:
    139
    Country:
    netherlands
    I've been thinking about this for some time. The problem is that what you can do in C# is tied to the SimConnect version you are referencing and you can't reference multiple SimConnect version within one project.

    You can within a solution though... so as a very rough outline:

    - Define an Interface that contains methods that should deliver SimConnect functionality you require, say: IMySimConnect

    - Create three DLL projects (sc_rtm.dll, sc_sp1.dll, sc_sp2.dll), each one referencing one specific SimConnect version

    - Inside each of the DLL's create a class (MyScRTM, MyScSP1 or MySCSP2) that implements the IMySimConnect interface using the available SimConnect calls in the specific version.

    - Have the constructor for these classes try 'new SimConnect' and throw an exception if the 'new SimConnect' throws an exception.


    Then in your main application:

    Code:
    IMySimConnect mySimConnect = null;
    
    try
    {
      mySimConnect = (IMySimConnect)new MySCSP2();
    }
    catch (Exception)
    {
      Log("SimConnect SP2 not available");
    }
    
    if ( mySimConnect == null )
    {
     try
     {
      mySimConnect = (IMySimConnect)new MySCSP1();
     }
     catch (Exception)
     {
       Log("SimConnect SP1 not available");
     }
    }
    
    if ( mySimConnect == null )
    {
     try
     {
      mySimConnect = (IMySimConnect)new MySCRTM();
     }
     catch (Exception)
     {
       Log("No SimConnect available");
     }
    }
    
    if ( mySimConnect != null )
    {
     mySimConnect.RecvResponse += new ........
     mySimConnect.RequestSomething()
    }
    

    Daniel
  4. scruffyduck

    scruffyduck Administrator Staff Member FSDevConf team Resource contributor

    Joined:
    17/9/05
    Messages:
    23,308
    Country:
    wales
    Thanks Daniel, I can see how that could work. It is pretty similar to the way that ADE checks up front to see if SimConnect is present. Obviously it is only looking for the RTM version since that is what is referenced by the main application.
  5. Pete Dowson

    Pete Dowson

    Joined:
    25/9/06
    Messages:
    315
    Country:
    unitedkingdom
    Doesn't C# provide for run-time dynamic linking? i.e. the method which, in C/C++ uses the Windows API calls like LoadLibrary and GetProcAddress?

    If it doesn't, it seems it is impossible to use such a language for projects involving "plug-ins", as plug-ins are generally just DLLs which are used if they are present and not if they are not.

    Regards
    Pete
  6. Daniel

    Daniel

    Joined:
    21/12/06
    Messages:
    139
    Country:
    netherlands
    I don't think so.

    For instance, if I reference the RTM version of SimConnect, there's no way I can add code like:

    s = new SimConnect(....);
    s.Text(....);

    Because the Text method does not exist in the RTM version.

    You can do this for example:

    [DllImport("winmm.dll")]
    static extern Int32 mixerGetLineControls(IntPtr hmxobj, ref MIXERLINECONTROLS pmxlc, UInt32 fdwControls);

    But I don't htink you can influence which winmm.dll gets loaded runtime.

    Daniel
    Last edited: 13/2/08
  7. scruffyduck

    scruffyduck Administrator Staff Member FSDevConf team Resource contributor

    Joined:
    17/9/05
    Messages:
    23,308
    Country:
    wales
    Pete

    There are methods to dynamically load plugins. SBuilderX uses them to load the different tile servers. That is written in VB.Net which is has essentially the same abilites as C#.

    I have got some notes on dynamic loading of libraries somewhere but had not connected that to this problem :eek: Works on Interfaces as per Daniel's suggestion if I remember rightly.

    I will have to dig back through my notes and stuff to see what I can find.
  8. Pete Dowson

    Pete Dowson

    Joined:
    25/9/06
    Messages:
    315
    Country:
    unitedkingdom
    If you can do it, that's the SECOND part of the solution. The FIRST part is more complicated as you can see if you refer to that AVSIM thread I referred to above (the one started by a question from Jean-Luc).

    In order to determine which DLL to link to, and get Windows' side-by-side library system to select it for you, you have to do manifest probing. That involves accessing a few rather arcane (to me) routines in obscure parts of Windows.

    It all works fine with C and C++ programming, but I would never have figured it out without some help from the MS guy responsible for SimConnect.

    Regards

    Pete
  9. beatle

    beatle

    Joined:
    28/9/06
    Messages:
    324
    Country:
    us-virginia
    The Managed SimConnect DLLs aren't in the WinSxS but instead are in the Global Assembly Cache (GAC). They are versioned within the GAC similar to the WinSxS though.

    Instead of looking for specific DLLs, you instead provide an AssemblyName class object with the various bits of info about the assembly you want to load (name, version, public key, etc). You can get a list of the installed managed SimConnect libraries and the info needed to fill the AssemblyName object with the following DOS command:

    gacutil /l | findstr /i simconnect

    if you have RTM, SP1, and SP2/XPack installed, that will give you the info for all the available public versions.

    As Jon mentioned, doing dynamic assembly loading works best when the objects within the assembly are based on an Interface definition, which unfortunately the current SimConnect stuff isn't. Without Interfaces, you have to do a lot of Reflection based stuff to get the needed types, instantiate objects of those types, and get method delegates to functions within those types, and then call the methods via the delegates.

    The multi DLL method mentioned earlier might be easier to deal with, as each version specific DLL could use the normal ways of dealing with a class object within the DLL itself and provide a known Interface based API to the calling app.
  10. Pete Dowson

    Pete Dowson

    Joined:
    25/9/06
    Messages:
    315
    Country:
    unitedkingdom
    Ugh. As if life wasn't complicated enough!

    Thanks Tim. I'm really really glad I avoided all those horrible languages. C is really a bit too high level for me already. I used to revel in assembly language programming before Windies made it so damned long-winded! ;-)

    Best Regards

    Pete
  11. beatle

    beatle

    Joined:
    28/9/06
    Messages:
    324
    Country:
    us-virginia
    It's not that bad, the GAC is just another set of subdirs under Windows like the WinSxS, except that it contains managed assemblies instead of native libraries :->

    I like the managed stuff (C# at least, I could live without VB.Net :-> ). Granted you run into the occasional thing that's real hard to do that used to be easy, but there's lots more stuff that's now easy that used to be hard(er) :->.

    We just got rid of the last little bits of assembler in the tree a couple of weeks ago (couple of utility routines).
  12. scruffyduck

    scruffyduck Administrator Staff Member FSDevConf team Resource contributor

    Joined:
    17/9/05
    Messages:
    23,308
    Country:
    wales
    Hi Tim

    Thanks for the explanation. I think a call to gacutil could be very useful from an application like ADE even if it is only used to log the versions the user actually has in GAC. At least it makes it easier to investigate problems that users get. I am going to add that to my startup code and log the versions found.

    The other thing about plugin schemes is that they are generally loading different libraries for different add in functions and not trying to select between a group of versions of the same library with the same name.

    From what you say it looks like the approach suggested by Daniel might be best. Without a common interface the individual dlls would have to me wrapped in some way in any case I think.
    Last edited: 14/2/08

Share This Page