On the subject, I wanted to add:
a) you can detect what simconnect client is installed (or not), by scanning the WinSxS folder and look for simclient folder names.
The folder name in the side by side looks like this in XP or Vista:
x86_Microsoft.FlightSimulator.SimConnect_67c7c14424d61b5b_10.0.61259.0_x-ww_fb842f5a
Microsoft.FlightSimulator.SimConnect = the string to look for.
10.0.61259.0 = the version to look for.
Strings to look for:
Microsoft.ESP.SimConnect - for ESP
Microsoft.FlightSimulator.SimConnect - for FSX (all versions)
Versions to look for:
1.0.20.0 - ESP RTM
10.0.61259.0 - FSX SP2 or Acceleration
10.0.60905.0 - FSX RTM
b) Specifying which version to use by your client
C/C++
When you include the simconnect.h file, it has a #pragma comment(lib, "") directive that points to a particular version of simconnect.
The directive in simconnect.h to reference SimConnect RTM is this:
Code:
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" "Microsoft.FlightSimulator.SimConnect " "' " \
"version='" "10.0.60905.0" "' " \
"processorArchitecture='x86' " \
"publicKeyToken='" "67c7c14424d61b5b" "'\"")
For SP2:
Code:
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" "Microsoft.FlightSimulator.SimConnect" "' " \
"version='" "10.0.61259.0" "' " \
"processorArchitecture='x86' " \
"publicKeyToken='" "67c7c14424d61b5b" "'\"")
In C++, you can disable this reference by defining the SIMCONNECT_H_NOMANIFEST compiler symbol
Code:
#define SIMCONNECT_H_NOMANIFEST
before including the simconnect header file. This will require you to add it yourself to the manifest.
You can remove or change that in two ways:
b.1 - modify the simconnect.h header to the version you want, so you point to the right lib file
b.2 - provide a manual manifest that will tell the loader to use the right side by side assembly when your .DLL or .EXE loads.
In Visual Studio 2005, you have to use the MT.EXE tool in the VC/BIN folder to do this (that tool is also part of the Windows SDK).
In Visual Studio 2008, you add a manifest reference directly to your project (you can also use MT.EXE but it is not distributed with VS2008).
C# / VB.NET
The interop DLL assembly provided by ACES that you reference in your .NET project makes that reference for you. There are few options here outside of writing your own interop assembly and link it to the native simconnect.lib (been there, get ready for very interesting marshalling problems given that most simconnect structures are in fact unions with variable length). You can also use the MT tool if needed to change that, but that would mean your interop DLL will likely not work because the library will not match up.
c) Another way to detect what a client has installed:
Create two dummy DLLs, one referencing RTM SimConnect, the other SP2 SimConnect in their respective manifest. Use LoadLibrary() from your code (.NET or C++) to load the library. It will fail is the corresponding version of SimConnect is not found on the client. The returned handle (C++) or IntPtr (.NET) is 0, the GetLastError will tell you usually error 2, "file not found".
What does a manifest look like?
Here's an example for a C++ dll in VS 2008:
Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.DebugCRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.FlightSimulator.SimConnect" version="10.0.61259.0" processorArchitecture="x86" publicKeyToken="67c7c14424d61b5b"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
The first dependency looks for the shared runtime library version 9 (VS2008), the second looks for Simconnect SP2.
By incorporating a manifest in your file (either during linking or using the MT tool), you can control what version of Simconnect you compile against.
What creates the manifest incorporated in my file?
The manifest is usually automatically generated based on the include files (#pragma), linked libraries or assemblies at link time. Additional dependencies can be added in the project as well in VS2008. The linker looks through all the dependencies and generates the manifest resource for you. You can also modify it and manually add your own lines. There are tools (MGEN) you can also use for this, but you will not need this. In most cases, let the linker do this for you.
How is the manifest incorporated in my file?
The linker does this for you, and inserts a special resource entry in your DLL or RES. The O/S loader looks for this special entry and takes over from there, before you even get to run your entry point routine.
A few quirks with manifests: I found that using LoadLibrary() or LoadLibraryEx() will not work if you are referencing the same assembly in the manifest AND a separate standalone DLL. If you get a dll load error, look to your manifest first.
How do I know if my file will load and the computer is configured with the right client?
A handy troubleshooting utility to use is DependencyWalker (
www.dependencywalker.com), which loads your gauge or DLL and looks at the entire manifest tree. Anything missing will pop up there.
If you get an error, your file won't load. A side by side is missing, or if not in side by side, a dll is missing in your application's folder or the search path.
If you get a warning and the dependency has an hourglass next to it, it's an optional dependency (delay loaded) that you probably don't need, but will be used if present by something you referenced somewhere. Vista and XP have different load delay dlls you will see.
One gotcha: If you load dlls manually via the windows API LoadLibrary calls, for example, to specify a folder where the dll you need is located, it will blow up during the load if the same library is in the side by side folder. This is by design. In this case, you will have no errors in dependency walker, but a big problem at runtime.
The tool is amazing to find out why your stuff doesn't load on a client, and will ensure your side by side configuration is also correct.
From code, look for the WinSxS contents and see what's installed there.
Hope this helps,
Etienne