Hi All,
As I know, when I declare functions from DLL, like this:
Code:
Private Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long
If refer to system dll
When I declare function like this:
Code:
Private Declare Function MyFunc Lib "test.dll" Alias "DLLMyFunc" (ByVal lpText As String) As Long
I refer to test.dll file which may be located in app folder or in system folders (windows, windows\system32 etc.)
If test.dll located in app folder and system folder too, to which dll VB would refer?
How can I refer to specfic dll? For example, only for DLL, which located in app folder, event such dll is located in system folder too
Thanks all
Ah yes, this is really the interesting question. I do not know. LOL . I vaguely remember reading a post about it, i believe it checks the System32 folder first. Anyway, I guess you can try to "break" you app by changing the current directory via:
vb Code:
Private Declare Function GetCurrentDirectory Lib "kernel32.dll" Alias "GetCurrentDirectoryA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Private Declare Function SetCurrentDirectory Lib "kernel32.dll" Alias "SetCurrentDirectoryA" (ByVal lpPathName As String) As Long
VB delay loads DLLs in most cases and when this is the case, the delay-loaded DLL is not loaded until it is first called. I think that if you ensure the DLL you want to use is in your app's path then it will be used since that is the first path searched. If you want to use the system folder (3rd path in search order), you may want to rename the DLL in your app.path if it exists there.
Another option could be to explicitly load the DLL via LoadLibrary API. If done, you probably should call FreeLibrary API when your app unloads. I don't know if VB calls FreeLibrary if it didn't load the DLL.
Insomnia is just a byproduct of, "It can't be done"
With both implicit and explicit linking, Windows first searches for "known DLLs", such as Kernel32.dll and User32.dll. Windows then searches for the DLLs in the following sequence:
The directory where the executable module for the current process is located.
The current directory.
The Windows system directory. The GetSystemDirectory function retrieves the path of this directory.
The Windows directory. The GetWindowsDirectory function retrieves the path of this directory.
The directories listed in the PATH environment variable.
It mean's that at first system try to find it in app folder, isn't it?
Renaming is not correct way.
Because I'm using special dll which contains functions for protecting app from copying
Pro Users may replace this dll with another dll, without protecting functions
Of course, I'm also checking MD5 or CRC of this dll, before checking protection
That is exactly how I interpret it. App.path is the first folder searched.
If someone deleted your DLL from the app.path then that is easy enough to check and you can abort your app. If it is there, you can crc and abort if crc is not the same. I guess those would be valid options.
When I suggested maybe renaming. What I meant is that if you wanted to prevent the one in your app.path from running, renaming it would prevent it from being the 1st found, then the other paths would be searched and, if found in those other paths, that one would be used instead.
To prevent potential problems, I'd suggest that the DLL always be installed in the exe's folder. But what if someone moved the exe to another folder?
Insomnia is just a byproduct of, "It can't be done"
It mean's that at first system try to find it in app folder, isn't it?
As LaVolpe said, App.Path is good enough for VB programmers.
On a technical level though, the "Executable Module Directory" and the "Current Directory" can differ. This is for people who manually link to DLLs/EXEs themselves for operations like Resource management (Ex: extracting Icons and converting them to GDIPlus Images ) and [Un]Registering ActiveX controls at runtime via:
vb Code:
LoadLibrary
GetProcAddress ("DllRegisterServer" or "DllUnregisterServer")
CallWindowProc
FreeLibrary
If you want to see the mod dir and current dir differ, run this:
vb Code:
Option Explicit
Private Declare Function Module32First Lib "kernel32.dll" (ByVal hSnapshot As Long, ByRef lppe As MODULEENTRY32) As Long
Private Declare Function GetCurrentDirectory Lib "kernel32.dll" Alias "GetCurrentDirectoryA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Private Declare Function SetCurrentDirectory Lib "kernel32.dll" Alias "SetCurrentDirectoryA" (ByVal lpPathName As String) As Long
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32.dll" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function GetCurrentProcessId Lib "kernel32.dll" () As Long
Private Const MAX_PATH As Long = 260
Private Const TH32CS_SNAPMODULE As Long = &H8
Private Const MAX_MODULE_NAME32 As Long = 256
Private Type MODULEENTRY32
dwSize As Long
th32ModuleID As Long
th32ProcessID As Long
GlblcntUsage As Long
ProccntUsage As Long
modBaseAddr As Long
modBaseSize As Long
hModule As Long
szModule As String * MAX_MODULE_NAME32
szExeFile As String * MAX_PATH
End Type
Private Sub Form_Load()
Dim udtME32 As MODULEENTRY32, lRet As Long, hTH32SS As Long, szCurrentDir As String, szModDir As String
' Change the current directory for this process to the parent folder
lRet = SetCurrentDirectory("..")
' Get a snapshot of the Modules for the current application
ok, thanks a lot
but another question
How can I detect path of registered ActiveX control, which used in app
I wan't to do it, 'cause
Before using ActiveX control, I would detect path, then check MD5 or CRC of control's file
then continue running
It's control used for protecting app from illegal copying
Advanced users way replace original ActiveX control for unoriginal ActiveX control
2Xiphias3:
Thank u, I can get file wich binded to ActiveX control in your code
But may be user from which name the app is started, can't have access for registry
Therefore I search another way
Option Explicit
Dim objWMIService, objCOMClassItems, objCOMClassItem
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set objCOMClassItems = objWMIService.ExecQuery("Select * from Win32_ClassicCOMClassSetting where Caption LIKE '%ActiveLock%'",,48)
For Each objCOMClassItem In objCOMClassItems
WScript.Echo "Caption: " & objCOMClassItem.Caption
WScript.Echo "ComponentId: " & objCOMClassItem.ComponentId
WScript.Echo "Description: " & objCOMClassItem.Description
WScript.Echo "InprocServer (file): " & objCOMClassItem.InprocServer32
Next
Set objCOMClassItem = Nothing
Set objCOMClassItems = Nothing
Set objWMIService = Nothing
But may be user from which name the app is started, can't have access for registry
I doubt this. All you're doing is reading the registry. If the user cant read the registry, when the app is running how would it know what Object to instantiate when it can't get the relevant GUID/CLSID and the path (usually from InprocServer32). Remember, ActiveX controls are only required to be registered at the point before of instantiation, hence why registering controls at run-time will work (though not recommended). The information about COM is stored in the registry. So, as far as I know, whatever route you take, you need to read from the registry. Correct me if I'm wrong.
Reasons like this is why I always try to find or make my own type library and utilize the Watch window as much as I can. I made a somewhat long rant about the HTML Type library in another thread, and told the guy to reference they HTML Obj lib and declare his variables properly using the relevant DataTypes rather than Varianting everything.
I decided to look into this "WMI" and no surprise found a TypeLib and pumped out all the properties. Gotta love it when dot-notation shows something. For anyone interested in using WMI in VB6, then check out: http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx
Also, here's how to use VB6 to get ALL the information by enumerating the properties and not missing out because you don't know the actual property name (as seen above, it was InprocServer32).
TypeLibrary:
Code:
Microsoft WMI Scripting V1.2 Library
System32\wbem\wbemdisp.tlb
Code:
vb Code:
Option Explicit
Private Sub Form_Load()
Dim oWMIService As WbemScripting.SWbemServices, oCOMSet As SWbemObjectSet, oCOM As SWbemObjectEx, _
oProp As SWbemProperty
Set oWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set oCOMSet = oWMIService.ExecQuery("Select * from Win32_ClassicCOMClassSetting where CAPTION LIKE '%X3Button%'")