Welcome Guest,Register Now
Log In

ANT Forum

Welcome guest, please Login or Register

   

Problem with ANT library loading (FIT SDK)

Avatar
RankRankRankRank

Total Posts: 296

Joined 0

PM

Hello experts,

I'm using the FIT SDK 1.2 for a Windows .NET application in C# which has a plugin architecture:
- a core application (.EXE)
- several plugins (.DLLs)

The plugin DLLs need to be installed in different directories, not the install directory of the main .EXE which is taboo for plugin related installs.

The FIT SDK libraries are only used from one plugin.

I've tried to install the FIT DLLs (ANT_WrappedLib.dll, DSI_CP210xManufacturing_3_1.dll, DSI_SiUSBXp_3_1.dll) in the plugin DLL install directory. This results in an exception "ANTLibrary Exception: ANT_WrappedLib.dll not found in working directory", upon the call of "new ANT_Managed_Library.ANT_Device()".
I tried to use System.IO.Directory.SetCurrentDirectory(...) to appropriately set the cwd but to no avail.
In a second approach I added the DLL install path to the "Path" Environment Variable - to no avail as well.
So it looks as if the ANT_NET.dll stubbornly expects the 3 referenced DLLs in the directory of the main assembly (i.e. .EXE)!??

Question: Is there any way to let ANT_NET.dll load the native FIT SDK DLLs from one of these places (preferably its own install path and/or the Path env. var)?

If not I'd suggest a SDK enhancement like ANT_Managed_Library.ANT_Common.setUnmanagedLibrary Path(String path) and ANT_Managed_Library.ANT_Common.setUSBLibraryPath(S tring path).
Of course one method like setLibraryPath would be ok as well.

Thanks in advance,
OMB

PS: Posted in parallel to https://forums.garmin.com/showthread.php?p=93253#post93253      
Avatar
RankRankRankRank

Total Posts: 662

Joined 2012-10-09

PM

Just to clarify, the files you refer to (ANT_WrappedLib.dll, DSI_CP210xManufacturing_3_1.dll, DSI_SiUSBXp_3_1.dll), are part of the ANT Library package, not the FIT SDK. You can find the FIT SDK here
http://www.thisisant.com/pages/developer-zone/fit-sdk

No, the ANT library does not support specifying the path of all these DLLs. Since a big part of the library is actually implemented in unmanaged C++, this is not as straightforward. The full source code of the library is available in the ANT+ Adopter Zone in case you wanted to add such functionality.      
Avatar
RankRankRankRank

Total Posts: 296

Joined 0

PM

Thanks a lot for your reply which helped a lot. I wasn't aware that the source code of the libraries is publicly available.

So I found a solution.
1. place the libraries in an arbitrary directory DLL_DIR
2. before calling the ANT_Device() constructor perform either of these:
2.a Directory.SetCurrentDirectory(DLL_DIR)
2.b SetDllDirectory(DLL_DIR), where SetDllDirectory is a native Windows method that can be imported like this:
[DllImport("kernel32.dll"CharSet CharSet.UnicodeSetLastError true)]
        [return
MarshalAs(UnmanagedType.Bool)]
        
static extern bool SetDllDirectory(string lpPathName); 


3. Unfortunately the ANT_Managed_Library.ANT_Common class methods to check for presence of library are code slightly too simple. So I patched them like this and created my own copy of ANT_NET.dll:
public static void checkUnmanagedLibrary()
        
{
            
// Check the unmanaged wrapper is present
            // if (!System.IO.File.Exists(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ANT_UNMANAGED_WRAPPER)))
            // OMB
            
if (!ExistsInSearchPath(ANT_UNMANAGED_WRAPPER))
                throw new 
ANT_Exception(ANT_UNMANAGED_WRAPPER " not found in working directory");            
        
}

        
// see http://msdn.microsoft.com/en-us/library/ms682586.aspx
        // If SafeDllSearchMode is enabled, the search order is as follows:
        // 
        //    1. The directory from which the application loaded.
        //    2. The system directory. Use the GetSystemDirectory function to get the path of this directory.
        //    3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
        //    4. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
        //    5. The current directory.
        //    6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
        // 
        // If SafeDllSearchMode is disabled, the search order is as follows:
        // 
        //    1. The directory from which the application loaded.
        //    2. The current directory.
        //    3. The system directory. Use the GetSystemDirectory function to get the path of this directory.
        //    4. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
        //    5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
        //    6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
        // 
        
[DllImport("Kernel32.dll")]
        
public static extern uint GetDllDirectory(uint lengthStringBuilder buffer);

        private static 
IList<StringMyDLLSearchPath null;
        private static 
IList<StringDLLSearchPath
        {
            get
            {
                
if (MyDLLSearchPath == null)
                
{
                    MyDLLSearchPath 
= new List<String>();
                    
MyDLLSearchPath.Add(AppDomain.CurrentDomain.BaseDirectory);
                    
MyDLLSearchPath.Add(Environment.GetFolderPath(Environment.SpecialFolder.System));
                    
MyDLLSearchPath.Add(Directory.GetCurrentDirectory());
                    const 
int sbCapacity 512;
                    
StringBuilder sb = new StringBuilder(sbCapacity);
                    
GetDllDirectory(sbCapacitysb);
                    if (
sb.Length 0)
                        
MyDLLSearchPath.Add(sb.ToString());
                
}
                
return MyDLLSearchPath;
            
}
        }
        
private static bool ExistsInSearchPath(string fileName)
        
{
            
foreach (String folderName in DLLSearchPath)
                if (
File.Exists(Path.Combine(folderNamefileName)))
                    return 
true;
            return 
false;
        


That's it. Works like a charm.
Note that method checkUSBLibraries() should be changed as well.

Maybe you can adopt these changes to your standard library code. I'm happy to donate them free of royalties wink

Thanks again for your quick and helpful response.

OMB

EDITED: I forgot to check for the folders listed in the %PATH env. variable, but you should be able to add this easily.      
Avatar
RankRankRankRank

Total Posts: 662

Joined 2012-10-09

PM

Thanks for posting back with your solution!