SDK Discussion: How to retrieve a string from SimConnect in C#?

Reading everything except strings in c#, How to retrieve a string from SimConnect in C#?

I’m on my phone so a bit hard to explain. Look at my github project. I have string retrievals in there. GitHub - SAHorowitz/MSFS2020-PilotPathRecorder: Record your flight path with key flight information archived during the Microsoft Flight Simulator 2020 flights. Then export that data to a KML file to use with Google Earth for 3 dimensional flight analysis

2 Likes

Here’s a more direct snippet:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct GENERIC_DATA
{
    // ...
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string title;
    // ...
}

And when you register it use the string type instead of SIMCONNECT_DATATYPE.FLOAT64:

m_simConnect.AddToDataDefinition(definition, "Title", null, 
    SIMCONNECT_DATATYPE.STRING256, 0.0f, SimConnect.SIMCONNECT_UNUSED);

Also, you may edit your post and change the category to just “SDK Discussion” - this isn’t a tutorial. :slight_smile:

1 Like

Thanks, useful , but I’m missing something …

I create simconnect and assign
simconnect.OnRecvSimobjectData += new SimConnect.RecvSimobjectDataEventHandler(SimConnect_OnRecvSimobjectData);

set structure for the Aircraft title (like in the previous post “title”

simconnect.RegisterDataDefineStruct<SimEnvironmentDataStructure> (DEFINITIONS.SimEnvironmentDataStructure);

then request data (the OBJ_ID_USER == 0)
simconnect.RequestDataOnSimObject(DATA_REQUESTS.SimEnvironmentReq, DEFINITIONS.SimEnvironmentDataStructure, SimConnect.SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD.ONCE, SIMCONNECT_DATA_REQUEST_FLAG.DEFAULT, 0, 0, 0);

then the handler does not fire but I get an exception #3 << ERROR

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SimEnvironmentDataStructure
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string title;
}

everything is working in this app (connection, getting data, sending values)
but I can’t get this string data to work

please help

I think that exception (unknown ID) is referring to something else, the above minimal code doesn’t look like it’d produce that error. You can share more code maybe.

1 Like

thanks, I’ll paste in more cdde, but if I comment out the RequestDataOnSimObject I don’t get an exception (and the other data arrives on (all numeric))

Do you have the problem if you remove CharSet = CharSet.Ansi ?

1 Like

When I removed the Ansi reference , the Exception didn’t occur but I had a cast error getting the string
in

SimConnect_OnRecvSimobjectData(,

SimEnvironmentDataStructure s1 = (SimEnvironmentDataStructure) data.dwData[0];

You’re missing: m_simConnect.RegisterDataDefineStruct<TData>(definition);

Don’t remove the <TData> part. TData is what you want to cast to.

1 Like

I have

simconnect.RegisterDataDefineStruct

<SimEnvironmentDataStructure>

(DEFINITIONS.SimEnvironmentDataStructure);

((The TData part was not showing in these posts because I needed to add a backshash before the “<”))

My SimConnect application is working … sending and receiving data … except for receiving strings.

Here’s my code C# for the attempt to get TITLE

  1. DEFINE STRUCTURE

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AircraftTitleDataStructure
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string title;
}

  1. AFTER CONNECTED setup the HANDLER

simconnect.OnRecvSimobjectData += new SimConnect.RecvSimobjectDataEventHandler(SimConnect_OnRecvSimobjectData);

3a. THEN Add the column to the DataDefinition

simconnect.AddToDataDefinition(DEFINITIONS.AircraftTitleDataStructure, “TITLE”, null, SIMCONNECT_DATATYPE.STRING256, 0.0f, SimConnect.SIMCONNECT_UNUSED);

3b. next REGISTERED the DataStructure

simconnect.RegisterDataDefineStruct(DEFINITIONS.AircraftTitleDataStructure);

  1. THEN REQUESTED TITLE

simconnect.RequestDataOnSimObject(DATA_REQUESTS.AircraftTitleRequest, DEFINITIONS.AircraftTitleDataStructure,

SimConnect.SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD.ONCE, SIMCONNECT_DATA_REQUEST_FLAG.DEFAULT, 0, 0, 0);

  1. THIS correctly GENERATES A CALL Back TO THE RECEIVE FUNCTION THAT ALMOST WORKS

void SimConnect_OnRecvSimobjectData(SimConnect sender, SIMCONNECT_RECV_SIMOBJECT_DATA data)
{
switch ((DATA_REQUESTS)data.dwRequestID)
{
case DATA_REQUESTS.DataRequest:
SimPlaneDataStructure s1 = (SimPlaneDataStructure) data.dwData[0];
UseData(s1);
break;

            case DATA_REQUESTS.AircraftTitleRequest:   // this is the case entered  
                uint a = data.dwRequestID; //ok
                uint b = data.dwID; //ok
                var t1 = data.GetType(); //ok
                var x = data.dwData[0]; //       
                string test = x.ToString();
                try
                {
                    AircraftTitleDataStructure s2 = (AircraftTitleDataStructure) data.dwData[0];    //note this GENERATES CAST EXCEPTION

                    DisplayAircraftTitle(s2.title);
                }
                catch (Exception ex)
                {
                    this.Title = ex.Message;
                }
                break;

///

///

///

also tried (in the data structure)

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]

the error is

ex.Message = “Specified cast is not valid.”

_data = {System.Collections.ListDictionaryInternal}

So I assume the structure and request are ok since it generates the callback … All the data in the callback looks ok except the cast

thanks to GeekyGameDad

I just verified all this works. You are changing lots of things and not understanding how you are breaking the interop, and that is making this more confusing.

The thing that is wrong is your struct:

[StructLayout(LayoutKind.Sequential, Pack = 1)]

You need Pack=1. You must not have CharSet=Ansi.

I think that’s your only problem.

1 Like

The solution I posted here works with strings, it may provide some assistance.

Below are snippets from that code, relevant to your problem.

I submit the initial request using:

    var unit = request.Unit;
    if (unit?.IndexOf("string") > -1)
    {
        unit = null;
    }
    // Fetch the values suitable for transmission to SimConnect
    var simReq = new SimVarRequest
    {
        ID = RequestID++,
        Request = request
    };
    // Submit the SimVar request to SimConnect
    simConnect.AddToDataDefinition(simReq.DefID, request.Name, unit, simReq.SimType, 0.0f, SimConnect.SIMCONNECT_UNUSED);

I submit the Data Structure using:

simConnect.RegisterDataDefineStruct<SimVarString>(simReq.DefID);

Finally, below is my model class for SimVarString above:

internal struct SimVarString
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string Value;
}

Note: I have not declared the structure with [StructLayout…], only the [MarshalAs…] is required.

Hope this helps…

2 Likes

thanks. What I’m trying to figure out now is how to get/set Approach Mode on A320 (tried many vars) … and how to get a list of Waypoints. I found the Waypoint rquest and callback function, I created a waypoint struct and make the request but never get a callback.

I’d suggest making another post for that, so it doesn’t get lost in this thread, otherwise others won’t know to answer, as the subject of this thread is unrelated.

1 Like