PDA

View Full Version : Converting Guid to _GUID using C#.NET


cyourth
20 Feb 2007, 19:20
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; }

DocMoriarty
21 Feb 2007, 00:45
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.


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

cyourth
21 Feb 2007, 12:31
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.


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

lc0277
21 Feb 2007, 15:53
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.


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|Bind ingFlags.Instance, null,
mySimconnectInstance, new object[] { myGuid } );




Another solution would be to wait for an hypothetical bugfix in the hypothetical simconnect update. ;)

ziporama
22 Feb 2007, 08:18
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.


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

cyourth
16 Jun 2007, 15:18
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... :(

FlapsOut
16 Jun 2007, 20:03
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

cyourth
17 Jun 2007, 15:11
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...

treeTops
28 Jun 2007, 09:26
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

FlapsOut
30 Jun 2007, 23:20
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 :)

Geoff_D
05 Jul 2007, 11:56
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:

cyourth
05 Jul 2007, 12:33
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

treeTops
05 Jul 2007, 16:02
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)

FlapsOut
13 Jul 2007, 18:56
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

voltage
08 Oct 2007, 12:51
Hi,

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


[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.AddrOfPinnedObje ct(), myGuidPtr, (uint)0x10);
Marshal.FreeHGlobal(myGuidPtr);
nativeGuidHandle.Free();

return nativeGuid;
}
}