Sign in to follow this  
Guest JeanLuc_

SimConnect with FS9

Recommended Posts

Hi,I'm trying to achieve something and before going further, I was wondering if someone already has done it, or, someone has already experimented and know if this is possible or not. Let me try to explain in short:I build a gauge file, that runs in both FS9 and FSX. Now, for the FSX version, i.e. when the gauge at runtime detects it is running in FSX, I'd like to take advantage of some SimConnect features.The context: when I #include "SimConnect.h", and I link with SimConnect.lib, I create a static dependency to the SimConnect.dll that is loaded when the gauge loads. It is alright in FSX, and it is a no issue the DLL loads in FS9 as well. So far, so good.The issue: if the computer does not have SimConnect.dll installed, FS9 refuses to load the gauge (which is normal, one dependent DLL is missing in the system).So this goes to the question: it is possible to only dynamically load the SimConnect.dll like in using LoadLibraryEx() and GetProcAddress()(which in my case, would be loaded only if the gauge runs in FSX, and not loaded if the gauge runs in FS9)?If so, what are the steps to go by, i.e. are there any special case to do this properly because of SimConnect (compared to any other standard .DLL, the SimConnect requires the manifest depenency?!?)I thank you in advance for your help with this!

Share this post


Link to post
Share on other sites
Help AVSIM continue to serve you!
Please donate today!

So this goes to the question: it is possible to only dynamically load the SimConnect.dll like in using LoadLibraryEx() and GetProcAddress()(which in my case, would be loaded only if the gauge runs in FSX, and not loaded if the gauge runs in FS9)?
Yes it is possible. My own code, in FSUIPC4, links in that fashion, as it is designed to use the latest version of SimConnect it can find and which it knows about. In order to link to the chosen version it has to use FSUIPC4 does have a manifest dependency too, but only to get itself loaded (by the originally released SimConnect). I don't think you'll have that problem with a Gauge as it isn't SimConnect loading your code.So, leave off the Manifest dependency (there's a macro defined in SimConnect.h for you to do that without having to modify the file). Then you need the Manifest(s) for the version(s) of SimConnect you need built into your Resources, but with ID's >100 (to stop them being checked by Windows on loading). Bind them using the MT utility -- for instance I have a series of lines like this in my "Post-Build Event" section of project properties:mt.exe -manifest "$(OutDir)SimC_SP1.manifest" -outputresource:"$(OutDir)FSUIPC4.dll";^#101where the file "SimC_SP1.manifest" is simply the manifest suited to the SP1 version of SimConnect.To use this manifest and bind to that version of SimConnect you need code like this: ACTCTX act = { 0 }; HANDLE hctx; ULONG_PTR ulCookie; act.cbSize = sizeof(act); act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; act.lpSource = pszExePath; act.lpResourceName = MAKEINTRESOURCE(101); hctx = CreateActCtx (&act); if (hctx !=INVALID_HANDLE_VALUE) { if (!ActivateActCtx(hctx, &ulCookie)) { ReleaseActCtx(hctx); ... ERROR, THIS VERSION NOT WORKING! } } else ... ERROR THIS VERSION NOT INSTALLEDAssuming no failures, when you now LoadLibrary("SimConnect.DLL") you will get the version just activated. You can do all your GetProcAddress calls, and when you have done, just call DeactivateActCtx(0, ulCookie); ReleaseActCtx(hctx);Your links will remain -- you are associated with that version of SimConnect now (even if other modules in FSX are using other versions!). RegardsPete

Share this post


Link to post
Share on other sites

Thanks for the detailed explanations Pete. Here is the final class I've implemented to dynamically support SimConnect in my gauge.Hope this helps! ============================================================Instead of using integer to identify the resources (the manifest files included as resources), I use names. They are defined like this in the .rc:SIMC_RTM_MANIFEST RT_MANIFEST "SimC_RTM.manifest"SIMC_SP1_MANIFEST RT_MANIFEST "SimC_SP1.manifest"with SimC_RTM.manifest:<?xml version='1.0' encoding='UTF-8' standalone='yes'?>and SimC_SP1.manifest:<?xml version='1.0' encoding='UTF-8' standalone='yes'?>============================================================In order to use it, I simply do the following: g_SimConnect = new ISimConnect(); if ( g_SimConnect && g_SimConnect->Start(DllModule()) && SUCCEEDED(g_SimConnect->SubscribeToSystemEvent(EVENT_PAUSE, "Pause")) ) { g_SimConnect->CallDispatch(SimConnectDispatchProc, NULL); }============================================================and when no longer needed (gauge exits):#define SAFE_DELETE(p) { if(p) { delete (p); (p)=0; } }SAFE_DELETE(g_SimConnect);============================================================// ISimConnect class//// offers an interface to SimConnect#pragma once#define SIMCONNECT_H_NOMANIFEST#include "SimConnect.h"#include "windows.h"#include /*************************************************************************************************/class ISimConnect{ // typedef HRESULT (__stdcall *t_SimConnect_Open)(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex); typedef HRESULT (__stdcall *t_SimConnect_Close)(HANDLE hSimConnect); typedef HRESULT (__stdcall *t_SimConnect_SubscribeToSystemEvent)(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName); typedef HRESULT (__stdcall *t_SimConnect_CallDispatch)(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext); //----------------------------------------------------------------------------public: ISimConnect() : Valid(0) , hSimConnect(0) , pSimConnect_Open(0) , pSimConnect_Close(0) , pSimConnect_SubscribeToSystemEvent(0) , pSimConnect_CallDispatch(0) { } ~ISimConnect() { Stop(); } //---------------------------------------------------------------------------- bool Start(HMODULE hInst) { static LPCTSTR _manifest_name_lut [] = { "SIMC_SP1_MANIFEST", "SIMC_RTM_MANIFEST", 0 }; if (Valid) return true; if (!hInst) return false; // store the module name, used to open the SimConnect interface TCHAR* szModule = new TCHAR[_MAX_PATH]; GetModuleFileName(hInst, szModule, MAX_PATH); ModuleName = szModule; delete szModule; // try to load the latest SimConnect version long manifestidx = 0; while (!Valid && _manifest_name_lut[manifestidx]) { ACTCTX act = { 0 }; HANDLE hctx; act.cbSize = sizeof(act); act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; //|ACTCTX_FLAG_HMODULE_VALID; act.lpSource = ModuleName.c_str(); // seems it does not work with hInst only so use the module filename act.lpResourceName = _manifest_name_lut[manifestidx]; //act.hModule = hInst; hctx = CreateActCtx (&act); if (hctx != INVALID_HANDLE_VALUE) { ULONG_PTR ulCookie = 0; if (ActivateActCtx(hctx, &ulCookie)) { hSimConnectDll = LoadLibrary("SimConnect.dll"); if (hSimConnectDll) { pSimConnect_Open = (t_SimConnect_Open)GetProcAddress(hSimConnectDll,"SimConnect_Open"); pSimConnect_Close = (t_SimConnect_Close)GetProcAddress(hSimConnectDll,"SimConnect_Close"); pSimConnect_SubscribeToSystemEvent = (t_SimConnect_SubscribeToSystemEvent)GetProcAddress(hSimConnectDll,"SimConnect_SubscribeToSystemEvent"); pSimConnect_CallDispatch = (t_SimConnect_CallDispatch)GetProcAddress(hSimConnectDll,"SimConnect_CallDispatch"); Valid = (SUCCEEDED(Open(ModuleName.c_str()))) ? 1 : 0; } DeactivateActCtx(0, ulCookie); } ReleaseActCtx(hctx); } manifestidx++; } return (Valid) ? true : false; } //---------------------------------------------------------------------------- bool Stop() { if (Valid) { Close(); FreeLibrary(hSimConnectDll); hSimConnectDll = 0; pSimConnect_Open = 0; pSimConnect_Close = 0; pSimConnect_SubscribeToSystemEvent = 0; pSimConnect_CallDispatch = 0; Valid = 0; } return true; } //---------------------------------------------------------------------------- HRESULT SubscribeToSystemEvent (SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName) { return (pSimConnect_SubscribeToSystemEvent) ? pSimConnect_SubscribeToSystemEvent (hSimConnect, EventID, SystemEventName) : -1; } HRESULT CallDispatch (DispatchProc pfcnDispatch, void * pContext) { return (pSimConnect_CallDispatch) ? pSimConnect_CallDispatch (hSimConnect, pfcnDispatch, pContext) : -1; } //----------------------------------------------------------------------------private: //HRESULT Open (LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex) HRESULT Open (LPCSTR szName) { return (pSimConnect_Open) ? pSimConnect_Open (&hSimConnect, szName, NULL, 0, NULL, 0) : -1; } HRESULT Close () { HRESULT result = (pSimConnect_Close) ? pSimConnect_Close (hSimConnect) : -1; hSimConnect = 0; return result; } //----------------------------------------------------------------------------private: long Valid; HMODULE hSimConnectDll; HANDLE hSimConnect; std::string ModuleName; // t_SimConnect_Open pSimConnect_Open; t_SimConnect_Close pSimConnect_Close; t_SimConnect_SubscribeToSystemEvent pSimConnect_SubscribeToSystemEvent; t_SimConnect_CallDispatch pSimConnect_CallDispatch;};

Share this post


Link to post
Share on other sites

>Thanks for the detailed explanations Pete. Here is the final>class I've implemented to dynamically support SimConnect in my>gauge.Glad you sorted it all out. Incidentally you don't really want all of that manifest stuff, only the Simconnect part. i.e.<?xml version='1.0' encoding='UTF-8' standalone='yes'?>>Hope this helps! Thanks. It is sure to help others. It doesn't help me as I'm not into C++ I'm afraid, though I can read it reasonably well. I stick to straight C with a bit of ASM here and there where I think I can do better that the compiler! ;-)But I'm happy with my code.Incidentally, this way of checking SimConnect versions (called "manifest probing") does have the unfortunate side-effect of creating three error entries in the System Event log for each version of SimConnect you probe for which isn't installed. I've been answering support calls on this for several weeks simply because I'm currently supporting (unreleased) FSX Betas as well as the released versions (RTM and SP1). I am still looking for an alternative way of checking which doesn't generate the errors.RegardsPete

Share this post


Link to post
Share on other sites

Yes correct, I've forgotten to remove the extra lines about the CRT. Thanks!Now that you mention it, I've cross checked I've errors too in the sysevent log. If ever I found something to prevent this, I'll post in here a solution.Thanks again!

Share this post


Link to post
Share on other sites

Hi Pete,further on this, I've now added the ACCELL manifest file in the list of manisfests for the class. I've done one manually from the info I grabbed in the SxS folder (don't know if there is another way to get the info). Here is the content, but I wonder if this is a good manifest for ACCELL/SP2:<?xml version='1.0' encoding='UTF-8' standalone='yes'?>??

Share this post


Link to post
Share on other sites

>further on this, I've now added the ACCELL manifest file in>the list of manisfests for the class. I've done one manually>from the info I grabbed in the SxS folder (don't know if there>is another way to get the info).The normal way is to get it from the SimConnect.h file, right near the beginning. It is the one in that file which normally generates the manifest in your program's target folder when you compile -- it actually has to be explicitly told not to by a manifest (SIMCONNECT_H_NOMANIFEST), otherwise.Don't you have the SDK relevant to the Acceleration release? The manifest in it is updated for each release, including each Beta.Anyway, the only thing that changes in that from one build to the next of SimConnect is the final build number, i.e. 61259 for Acceleration. I've never yet seen any of the other bits change (oh, excepting there was once a redundant space at the end of the "name" string -- which appeared to be important too!).So, the manifest for Acceleration SimConnect is:<?xml version='1.0' encoding='UTF-8' standalone='yes'?>which looks pretty much identical to what you derived to me! ;-)RegardsPete

Share this post


Link to post
Share on other sites

Actually no, I don't have SDK Accel/sp2. I've just installed Accel from the gold bits and have not looked for an SDK.msi (or similar). I'll look for it.Actually, what I did to build it, was to look in the SxS folder here:C:WINDOWSWinSxSManifeststhere you have the manifest files for all assemblies, and I've just taken the latest one:x86_Microsoft.FlightSimulator.SimConnect_67c7c14424d61b5b_10.0.61259.0_x-ww_fb842f5a.Manifestand edited it (to remove dependentAssembly info for example).I've not tested it actually loads this manifest, I'll try a debugger to cross-check the loaded modules.Best regards,Jean-Luc

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this