11-14-2018 02:15 PM
In a library node function call, a dll (i2cfa.dll) is called and I can't see the path. Clicking browse will get me to the desktop. During execution the dll opens a window and in that window I can see that the dll revision is equal to 1.
In the PC I have 4 instances of this dll. And all of the are revision 2 when being opened. There is no revision 1 dll as I have searched the whole PC, and LabVIEW search paths.
How can I find out the path of this ghost dll labview is calling? I tried tasklist in cmd but since the dll is in the LabVIEW application context I can't see any task with a similar name i.e. i2c.
Solved! Go to Solution.
11-14-2018 04:47 PM
I've used process monitor to track down where applications are trying to load DLLs from but I'm not sure I understand the question you are asking.
Is the issue that the call library function node is calling a DLL and you are not sure where that DLL is being loaded or is the CLFN calling a function that requires another DLL to be loaded into memory and that DLL isn't being found?
11-15-2018 03:05 AM - edited 11-15-2018 03:11 AM
I'd use LoadLibraryA, and then a GetModuleFileNameA. Give the LoadLibrary just the name, and it should return a reference to the loaded module. Then GetModuleFileNameA will return it's path.
Of course use FreeLibrary to release the module reference.
In LabVIEW 2013...
11-16-2018 04:50 AM
Hey Wiebe,
That's a really good contribution!
I have a small addition: As you wrote, GetModuleFileNameA will return the path for a module that was loaded. However, this means loaded by the current process (as you are doing in your example). There is also GetModuleFileNameExA, which locates the file of a module that was loaded by another process.
And a remark: I don't know if these functions are aware of Windows 64-bit's transparent path redirection, that is 64-bit dlls being stored in %windir%\system32, 32-bit dlls in %windir%\syswow64. In case the function returns a path that seems to be non-existent, check the other path as well.
11-16-2018 08:13 AM
@ikaiser wrote:
Hey Wiebe,
That's a really good contribution!
Thanks, surprisingly simply. Hope it works for OP.
@ikaiser wrote:
I have a small addition: As you wrote, GetModuleFileNameA will return the path for a module that was loaded. However, this means loaded by the current process (as you are doing in your example). There is also GetModuleFileNameExA, which locates the file of a module that was loaded by another process.
Yes, but you'll need privileges to be allowed to do that. That could make things really complex. I think dlls loaded by dlls in LabVIEW, count as the same process. Not sure, someone should do an experiment.
@ikaiser wrote:
And a remark: I don't know if these functions are aware of Windows 64-bit's transparent path redirection, that is 64-bit dlls being stored in %windir%\system32, 32-bit dlls in %windir%\syswow64. In case the function returns a path that seems to be non-existent, check the other path as well.
At some point I'll undergo the transition to 64 bit. At the moment, I have no reason...
11-16-2018 09:24 AM - edited 11-16-2018 09:38 AM
wiebe@CARYA wrote:
At some point I'll undergo the transition to 64 bit. At the moment, I have no reason...
Just change the HINSTANCE parameter for each of the three functions from Numeric->(U)Int32 to Numeric->Pointer Sized (Unsigned) Integer. That way it will still work in 32-bit but you will be prepared when (rather than if) you ever move to 64-bit.
11-16-2018 09:43 AM
@rolfk wrote:
wiebe@CARYA wrote:
At some point I'll undergo the transition to 64 bit. At the moment, I have no reason...
Just change the HINSTANCE parameter for each of the three functions from Numeric->(U)Int32 to Numeric->Pointer Sized (Unsigned) Integer. That way it will still work in 32-bit but you will be prepared when (rather than if) you ever move to 64-bit.
Your probably right, but how can you tell from the spec if a handle is a pointer? Are all handles pointer sized? I think you've mentioned something about this somewhere a while ago.
11-16-2018 03:38 PM - edited 11-16-2018 03:44 PM
You can't tell what is the internal implementation. But a Windows HANDLE is defined as
typedef void *HANDLE;
And all H-something variables in Windows are defined as being of type
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
Which is a pointer to a struct containing an opaque int value. What this int value means, if anything, is up to the resource manager handling the according type of handle, for some the handle itself is a pointer to some internal data structures, for others the int value is an index of some sorts into a table of resources, and for some it's probably something else.
So all Windows API functions accepting a handle of some sorts (HWND, HDC, HBRUSH, HBITMAP, HKEY, HENHMETAFILE, HFONT, HICON, HMENU, etc) expect here a pointer sized value even if some might not use the upper 32 bit of the value on 64 bit platforms.
11-19-2018 02:08 AM
Rolf, OK thanks. I thought there were exceptions.
Attached is the same VI with a pointer sized integer. I also changed the CLFN to run in any thread. No need to stall the UI thread. I also added error in\error out and connected the inputs and outputs to the CP. And I put the configuration to show 'names' (that could be more descriptive).
11-19-2018 02:37 AM
Nice work, but my eyes hurt when I see the module name wire not lining up to the arg1 parameter (which could be named more descriptively too).