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

Converting Guid to _GUID using C#.NET

Discussion in 'SimConnect' started by cyourth, 21/2/07.

  1. cyourth

    cyourth

    Joined:
    7/2/07
    Messages:
    7
    Country:
    canada
    Has anyone tried using the C#.NET version of SimConnect.ExecuteMissionAction(_GUID) or SimConnect.simconnect.CompleteCustomMissionAction(_GUID) methods?

    Cannot seem to convert Guid data type to _GUID???

    Found some info on Microsoft site, but code didn't work...

    Example Code:

    [StructLayout(LayoutKind.Sequential, Size = 0x10)]
    struct _GUID
    {
    public Int32 Data1;
    public Int16 Data2;
    public Int16 Data3;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] Data4;​
    };

    Guid FromGUID(_GUID guid)
    {
    return new Guid(
    guid.Data1, guid.Data2, guid.Data3,
    guid.Data4[0], guid.Data4[1], guid.Data4[2],
    guid.Data4[3], guid.Data4[4], guid.Data4[5],
    guid.Data4[6], guid.Data4[7]​
    );​
    }

    _GUID ToGUID(Guid guid)
    {
    _GUID newGuid = new _GUID();
    byte[] guidData = guid.ToByteArray();
    newGuid.Data1 = BitConverter.ToInt32(guidData, 0);
    newGuid.Data2 = BitConverter.ToInt16(guidData, 4);
    newGuid.Data3 = BitConverter.ToInt16(guidData, 6);
    newGuid.Data4 = new byte[8];
    Array.Copy(guidData, 8, newGuid.Data4, 0, 8);
    return newGuid;​
    }
  2. DocMoriarty

    DocMoriarty

    Joined:
    20/12/06
    Messages:
    64
    Country:
    germany
    Maybe if you added a

    Pack:=1

    to the structure attributes.

    Compilers tend to align structure members at fullword boundaries, that is each 16-bit int gets aligned at a 32 bit boundary unless you tell him not to do so.


    Code:
    <StructLayout(LayoutKind.Sequential, Pack:=1)>
  3. cyourth

    cyourth

    Joined:
    7/2/07
    Messages:
    7
    Country:
    canada
    This doesn't seem to work...
    [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x10)]​

    The following error is still generated:

    _GUID guid = new _GUID();
    simconnect.ExecuteMissionAction(guid);​

    Error 1: Argument '1': cannot convert from 'Managed_Client_Event.Form1._GUID' to '_GUID'​

    When _GUID isn't defined locally (commented out), the following error is generated:

    Error 2: '_GUID' is inaccessible due to its protection level​

    Why wouldn't the developers at MS internalize this data conversion, when Guid data type is used within the simconnect_OnRecvCustomAction() event handler :confused:
  4. lc0277

    lc0277

    Joined:
    25/9/06
    Messages:
    156
    Country:
    france
    Hi cyourth,

    You don't have to redefine your own _Guid struct since it's already defined in the simconnect dll.
    I already had this kind of problem with another type defined by simconnect. It seems that some of the structures and enumerations are defined with an incorrect protection level in the assembly.
    You can check with an assembly viewer (like Lutz Roeder's .NET reflector) that the _GUID struct is declared internal. It means that it cannot be accessed outside the SimConnect assembly. So unfortunately there are no clean and simple way to use this type, and all methods that depends on it, including ExecuteMissionAction()

    You may find a work-around using reflexion to instantiate a _Guid and call ExecuteMissionAction() without having a reference to the _GUID type in your code, thus without any compile-time errors. But the problem remains how to write the content of the guid. For the SIMOBJECT_TYPE enumeration, which had the same protection level bug, I used unsafe pointers to read its content. I don't think it's possible here since you need some kind of "anchor" to initialize your pointer and it cannot be the base adress of your object. I'm not an expert with such C# hacking stuff, there may be a special construct I don't know, to write in an arbitrary memory area.

    Code:
    Assembly asm = Assembly.LoadFrom("Microsoft.FlightSimulator.SimConnect.dll");
    Type guidType = asm.GetType("_GUID");
    object myGuid = Activator.CreateInstance(guidType);
    // ??? how to write the content of myGuid ???
    
    Type scType = asm.GetType("SimConnect");
    scType.InvokeMember("ExecuteMissionAction", 
          BindingFlags.Public|BindingFlags.InvokeMethod|BindingFlags.Instance, null,
          mySimconnectInstance, new object[] { myGuid } );
    
    
    
    Another solution would be to wait for an hypothetical bugfix in the hypothetical simconnect update. ;)
  5. ziporama

    ziporama

    Joined:
    28/9/06
    Messages:
    203
    Country:
    unitedstates
    Reflection is neat isn't it :)

    Try this (untested but should work) to copy the object you get from the instance and map it to your structure. You may also be able to cast it directly but the strong type checking may get in the way.

    Code:
    // using the _GUID struct as you've defined it above
    int len = Marshal.Sizeof(typeof(_GUID)); // 0x40;  size of the _GUID
    IntPtr ptr = Marshal.AllocHGlobal( len ); 
    Marshal.Copy( myGuid, 0, ptr, len ); // myGuid obtained via reflection - see above post by LC0277
    _GUID gid   = (_GUID)Marshal.PtrToStructure( ptr, typeof(_GUID) );
    Marshal.FreeHGlobal( ptr );
    
    
    Last edited: 23/2/07
  6. cyourth

    cyourth

    Joined:
    7/2/07
    Messages:
    7
    Country:
    canada
    C#.net version of ExecuteMissionAction(_GUID) still not working in SP1A release

    So it looks like the C#.net version of SimConnect.ExecuteMissionAction(_GUID) and SimConnect.simconnect.CompleteCustomMissionAction( _GUID) methods are still not working correctly in the new SP1A SDK release...

    I've tried to find a work-around using reflexion to instantiate a _Guid and call ExecuteMissionAction() without having a reference to the _GUID type in your code, but I cannot get it to work...

    Does anybody else have an idea how to get this working? :confused:

    I've tried to communicate with some of the guys on the ACES team, but they refer me back to this forum... :(
  7. FlapsOut

    FlapsOut

    Joined:
    29/5/07
    Messages:
    75
    Country:
    us-texas
    simconnect.CompleteCustomMissionAction

    cyourth,

    I'm interested in knowing if you actually created a CustomAction in one of the Missions (or a new Mission), or if were you using the _GUID of an existing MissionAction?

    Thanks,
    FlapsOut
  8. cyourth

    cyourth

    Joined:
    7/2/07
    Messages:
    7
    Country:
    canada
    Custom Action

    I created a mission based custom action, with a timed trigger. The C#.net application is receiving the custom action event, with the correct payload string. This C#.net application is now trying to call ExecuteMissionAction( _GUID ) method, with a valid GUID mission action... It's here that we are having a problem. The _GUID is protected in the SimConnect object. I've tried using reflection to instantiate _GUID (see above code) - but this didn't work...
    Last edited: 17/6/07
  9. treeTops

    treeTops

    Joined:
    28/6/07
    Messages:
    2
    Country:
    ca-ontario
    Same problem with my code

    I'm having the same problem with my C#.net code. It looks like the ACES \ Microsoft group didn't fix this problem with the new SP1A release. Have you had any luck in finding a solution :confused:

    I tried the same code in C++ and it seems to work :), but I would rather code in C#.net
  10. FlapsOut

    FlapsOut

    Joined:
    29/5/07
    Messages:
    75
    Country:
    us-texas
    Solution...

    There is no solution directly...

    Microsoft has chosen to make this 'protected' and until they are persuaded to change? Nothing we can do...I have exercised this ad-nauseum...

    However? Microsoft, HAS persuaded me to try other approaches ;)

    And, so it goes? FSUIPC->FS6->FS7->FS8->FS9->FSX->New Tricks :p

    Flaps :)
  11. Geoff_D

    Geoff_D

    Joined:
    5/2/07
    Messages:
    359
    Country:
    unitedstates
    That's my boy -- thinking out of the "FSX" box again :rolleyes:
  12. cyourth

    cyourth

    Joined:
    7/2/07
    Messages:
    7
    Country:
    canada
    Good Old Microsoft

    If Microsoft didn't want the developers to use these methods, then don't include them in the API, or document the methods that do not work as of release dates...

    Maybe we should invoice Microsoft for wasting our development time :D
  13. treeTops

    treeTops

    Joined:
    28/6/07
    Messages:
    2
    Country:
    ca-ontario
    Any other Methods that do not work under C#

    Does anyone have a list of C# SimConnect methods that currently do not work under the SP1a release... :confused:

    Current C# SimConnect methods are:

    1. ExecuteMissionAction(_GUID)
    2. CompleteCustomMissionAction(_GUID)
    Last edited: 5/7/07
  14. FlapsOut

    FlapsOut

    Joined:
    29/5/07
    Messages:
    75
    Country:
    us-texas
    Good Point!

    Hi TreeTops,

    I've been posting my own analysis in menu posts here...Maybe some are useful?

    As you know, the new SDK has many, many areas, and I have been attempting to go thru and try them in turn.

    Some work, many do not...

    Search on posts by FlapsOut, and you will obtain, not only what works, but also the code to see for yourself?

    Thanks,
    Flaps
    Last edited: 15/8/07
  15. voltage

    voltage

    Joined:
    8/10/07
    Messages:
    2
    Country:
    germany
    Some tricky workaround

    Hi,

    i've written some tricky reflection/native code mix to workaround the missing _GUID structure.. following code should work:

    Code:
        [StructLayout(LayoutKind.Sequential, Size = 0x10)]
        struct _GUID
        {
            public Int32 Data1;
            public Int16 Data2;
            public Int16 Data3;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public byte[] Data4;
    
            [DllImport("kernel32.dll", EntryPoint = "CopyMemory", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
            private static extern void NativeCopyMemory(IntPtr dest, IntPtr source, uint length);
    
            public static _GUID ToGUID(Guid guid)
            {
                _GUID newGuid = new _GUID();
                byte[] guidData = guid.ToByteArray();
                newGuid.Data1 = BitConverter.ToInt32(guidData, 0);
                newGuid.Data2 = BitConverter.ToInt16(guidData, 4);
                newGuid.Data3 = BitConverter.ToInt16(guidData, 6);
                newGuid.Data4 = new byte[8];
                Array.Copy(guidData, 8, newGuid.Data4, 0, 8);
                return newGuid;
            }
    
            public static object ToSimConnectGUID(Guid guid)
            {
                Assembly asm = Assembly.GetAssembly(typeof(SimConnect));
                //Assembly asm = Assembly.LoadFrom("Microsoft.FlightSimulator.SimConnect.dll");
                Type guidType = asm.GetType("_GUID");
                object nativeGuid = Activator.CreateInstance(guidType);
                GCHandle nativeGuidHandle = GCHandle.Alloc(nativeGuid, GCHandleType.Pinned);
                _GUID myGuid = ToGUID(guid);
                IntPtr myGuidPtr = Marshal.AllocHGlobal(0x10);
                Marshal.StructureToPtr(myGuid, myGuidPtr, true);
                NativeCopyMemory(nativeGuidHandle.AddrOfPinnedObject(), myGuidPtr, (uint)0x10);
                Marshal.FreeHGlobal(myGuidPtr);
                nativeGuidHandle.Free();
    
                return nativeGuid;
            }
        } 
    

Share This Page