• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

Converting Guid to _GUID using C#.NET

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

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:
 
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. ;)
 
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:
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... :(
 
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
 
Custom Action

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

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:
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
 
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 :)
 
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 :)

That's my boy -- thinking out of the "FSX" box again :rolleyes:
 
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
 
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:
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:
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;
        }
    }
 
Back
Top