Гость
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде / 22 сообщений из 22, страница 1 из 1
20.06.2014, 02:25
    #38674843
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Ну т.е. обычно dll либо системная, либо кладется в папку с программой. Тогда достаточно указать ее имя:

Код: vbnet
1.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" (аргументы) As Long



Если dll лежит в другой, заранее известной папке C:\MyKnownPath\, то работает такой вариант:
Код: vbnet
1.
Public Declare Function CPP_MyFunction Lib "C:\MyKnownPath\cpp_my_dll.dll" (аргументы) As Long



Предположим, я заранее не знаю в какой папке лежит dll, но могу ее вычислить из кода т.е. нужно реализовать следующее:

1) Программа вычисляет SomePath (путь установки приложения, кот. может быть любым)
2) Программа знает что по пути SomePath лежит известная cpp_my_dll.dll
3) Программа знает что в этой dll есть известная ф-ция CPP_MyFunction и хочет ее вызвать.

Задекларировать заранее я не могу. Я не знаю SomePath, знаю только алгоритм его вычисления.

Как?
...
Рейтинг: 0 / 0
20.06.2014, 02:40
    #38674845
скукотища
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Дмитрий77,
LoadLibrary
...
Рейтинг: 0 / 0
20.06.2014, 03:04
    #38674850
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
скукотища,

именно по этому пути и иду.

Ну допустим

Код: vbnet
1.
2.
3.
4.
5.
6.
hMod = LoadLibrary("SomePath\cpp_my_dll.dll")
ProcAdd = GetProcAddress(hMod, "CPP_MyFunction")

??????????????????
...
FreeLibrary hMod



А как мне ее вызвать, зная ProcAdd?

В C++ такая штука декларируется (как-то так):
Код: plaintext
1.
2.
3.
4.
typedef int (__cdecl *MYPROC)();

ProcAdd = (MYPROC) GetProcAddress(hinstLib, "CPP_MyFunction"); 
(ProcAdd) (); 



А а VB чего делать?
...
Рейтинг: 0 / 0
20.06.2014, 03:45
    #38674858
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
У меня (видимо к счастью) CPP_MyFunction не имеет аргументов.
Просто возвращает указатель на Null-Terminated строку в памяти.

Код: vbnet
1.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long



Т.е. вот такой простой вариант получился:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Public Function My_MyFunction(ByVal PathToDll As String) As String
  Dim hMod As Long
  Dim ProcAdd As Long
  hMod = LoadLibrary(PathToDll)
  If hMod <> 0 Then
    ProcAdd = GetProcAddress(hMod, "CPP_MyFunction")
    If ProcAdd <> 0 Then
      My_MyFunction = PtrToString(CallWindowProc(ProcAdd, 0, 0, 0, 0))
    End If
    FreeLibrary hMod
  End If
End Function


Ничего не упустил?

PtrToString -это моя приблуда, которая вытаскивает строку по Ptr (адресу в памяти), я ее неоднократно приводил в своих топиках.
Главное, код выше этот Ptr возвращает.

... с параметрами наверно тяжело, судя по рассуждениям на разных форумах.
...
Рейтинг: 0 / 0
20.06.2014, 04:33
    #38674863
скукотища
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
> Дмитрий77,
> ... с параметрами наверно тяжело, судя по рассуждениям на разных форумах.

пример реализации для stdcall (в сообщении от 03-29-2005, 12:53 PM).
...
Рейтинг: 0 / 0
20.06.2014, 05:28
    #38674868
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
скукотища,

я именно (видимо копию) этого топика и изучал.

И вот то что в первом посте мне понравилось значительно больше, нежели заумности в проекте куда ведет ссылка внизу.
И мне к счастью CallWindowProc достаточно.

В принципе, я думаю можно сделать и с аргументами без тех заумностей что в указанном тобой примере.
Но это надо копать документацию и врубаться, и если честно не охота.
Итак уже на своего Визарда неделю потратил.
...
Рейтинг: 0 / 0
20.06.2014, 06:31
    #38674878
experience
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Посмотрите в эту сторону
http://www.script-coding.com/dynwrap.html
и возможно по ссылке в шапке на langmf http://forum.script-coding.com/
...
Рейтинг: 0 / 0
20.06.2014, 07:10
    #38674886
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
experience,

ну не знаю.

Чего я точно не люблю, так это всякие wrap-перы.
Их и в самом VB, да и в любом нете кривых-косых хватает.
...
Рейтинг: 0 / 0
20.06.2014, 07:44
    #38674901
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
http://books.google.ru/books?id=q9_Y_dRnslgC&pg=PA348&lpg=PA348&dq=LoadLibrary GetProcAddress vb6&source=bl&ots=X_ARPcdvD1&sig=ZdcIQ9ycAX5rXE96KOu5SAfUGq0&hl=ru&sa=X&ei=LqijU7vdE4Op4gShy4CYBA&ved=0CEgQ6AEwCDgK#v=onepage&q=LoadLibrary GetProcAddress vb6&f=false

Листинг 8.3 и 8.4

Любое "грамотное решение" по ходу сводится к запихиванию Array() из параметров в первый параметр ф-ции CallWindowProc ассамблеровскими методами (либо побайтно, либо с использованием API работы с памятью).

У меня, повторюсь, параметров у ф-ции нет.
Единственное, чего чуть беспокоит (как человека съевшего не одну собаку), это вызов
Код: vbnet
1.
CallWindowProc(ProcAdd, 0, 0, 0, 0)


Ну т.е. не мусорится ли чего.
Автор упомянутой статьи настаивает на безобидности прямого вызова только для случая "ровно 4 параметра",
у меня же их нуль.

Хотя в принципе, код такой невинный, что работает да и ладно.
...
Рейтинг: 0 / 0
20.06.2014, 08:37
    #38674931
ZVI
ZVI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Обычно делал так:
1. Декларировал DLL без пути
2. Запоминал текущий диск и папку (не обязательно)
3. Устанавливал текущую папку с DLL при помощи ChDrive SomePath и ChDir SomePath
4. Вызвал какую нибудь (dummy) функцию из этой DLL
5. Восстанавливал то, что менялось в п.2 (не обязательно)
После этого при любой текущей папке можно вызывать и другие функции этой DLL
...
Рейтинг: 0 / 0
20.06.2014, 10:39
    #38675066
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
ZVI,

я понял твою идею.

Короче, это все лишнее
ZVI2. Запоминал текущий диск и папку (не обязательно)
3. Устанавливал текущую папку с DLL при помощи ChDrive SomePath и ChDir SomePath
4. Вызвал какую нибудь (dummy) функцию из этой DLL
5. Восстанавливал то, что менялось в п.2 (не обязательно)

Вариант 1:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long

Public Function MyLoad_MyFunction_1(ByVal PathOnlyToDll As String) As String
  'PathOnlyToDll -только Folder ее нахождения
  SetDllDirectory PathOnlyToDll '!!!SetDllDirectory не проверяет даже существование папки
  MyLoad_MyFunction_1= PtrToString(CPP_MyFunction)
End Function


Но если блин промахнулись с папкой (проверять SetDllDirectory бесполезно, она и несуществующую забабахает и вернет True)
или файла dll в ней нет (в моем случае не гарантировано)
то будет ошибка

Вариант 2:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long

Public Function MyLoad_MyFunction_2(ByVal PathToDll As String) As String
  Dim hMod As Long
  hMod = LoadLibrary(PathToDll)
  If hMod <> 0 Then
    MyLoad_MyFunction_2= PtrToString(CPP_MyFunction)
    Dim FreeResult As Long
    FreeResult = 1
    Do Until FreeResult = 0 ' OK, library reference count is 0, and library is therefore unloadable
      FreeResult = FreeLibrary(hMod)
      Debug.Print FreeResult
    Loop
  End If
End Function



Но опять же, если промахнулись с наличием ф-ции (в старой версии cpp_my_dll.dll одна из ф-ций отсутствует, а априори не знаю версию клиента), то будет ошибка.

Посему грамотный вариант без использования вызова по ProcAdd такой:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long 'путь не указываем

Public Function MyLoad_MyFunction(ByVal PathToDll As String) As String
  Dim hMod As Long
  Dim ProcAdd As Long
  hMod = LoadLibrary(PathToDll)
  If hMod <> 0 Then
    ProcAdd = GetProcAddress(hMod, "CPP_MyFunction")
    If ProcAdd <> 0 Then
      MyLoad_MyFunction= PtrToString(CPP_MyFunction) 'а не по ProcAdd!!!
    End If
    Dim FreeResult As Long
    FreeResult = 1
    Do Until FreeResult = 0 ' OK, library reference count is 0, and library is therefore unloadable
      FreeResult = FreeLibrary(hMod)
      Debug.Print FreeResult
    Loop
  End If
End Function



Честно говоря, я не уверен в эффективности и необходимости FreeLibrary, да еще и с циклом (по MSDN извините).
Очевидно, что при обычном задекларированном вызове VB всегда делает LoadLibrary, но ни фига и никогда не делает FreeLibrary
(а иначе как он путь продолжает видеть после вызова твоего dummy и реверсной смены папки назад).

Если неграмотно вызывать dll, которую VB не найдет то будет "Dll not found".

А вот если вызвать dll сначала грамотно любым из 4-х методов включая твой и 3 моих,
потом выполнить грамотный цикл из FreeLibrary,
а потом вызвать dll "неграмотно", то будет не "Dll not found", а просто crash VB-приложения,
почему ХЗ и я с Opal так однажды уже игрался и так и не докопался почему.

Вот поэтому думаю, может и не стоит вообще FreeLibrary делать.
Ну накрутит прога несколько рефренсов, хуже то от этого не будет.
А вот не будет ли хуже от FreeLibrary, честно говоря не уверен.
...
Рейтинг: 0 / 0
20.06.2014, 11:00
    #38675103
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Модуль класса FunctionPtr
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
Option Explicit

Private Declare Function GetProcAddress Lib "kernel32" ( _
   ByVal hModule As Long, ByVal lpProcName As String) As Long

Private Const DISPATCH_METHOD = &H1&
Private Const LOCALE_SYSTEM_DEFAULT = &H800&
Private Const DISPID_VALUE = 0&
Private Const S_OK = 0&

Public Enum CALLCONV
   CC_FASTCALL = 0
   CC_CDECL = 1
   CC_MSCPASCAL = CC_CDECL + 1
   CC_PASCAL = CC_MSCPASCAL
   CC_MACPASCAL = CC_PASCAL + 1
   CC_STDCALL = CC_MACPASCAL + 1
   CC_FPFASTCALL = CC_STDCALL + 1
   CC_SYSCALL = CC_FPFASTCALL + 1
   CC_MPWCDECL = CC_SYSCALL + 1
   CC_MPWPASCAL = CC_MPWCDECL + 1
   CC_MAX = CC_MPWPASCAL + 1
End Enum

Public Enum VARENUM
   VT_EMPTY = 0
   VT_NULL = 1
   VT_I2 = 2
   VT_I4 = 3
   VT_R4 = 4
   VT_R8 = 5
   VT_CY = 6
   VT_DATE = 7
   VT_BSTR = 8
   VT_DISPATCH = 9
   VT_ERROR = 10
   VT_BOOL = 11
   VT_VARIANT = 12
   VT_UNKNOWN = 13
   VT_DECIMAL = 14
   VT_I1 = 16
   VT_UI1 = 17
   VT_UI2 = 18
   VT_UI4 = 19
   VT_INT = 22
   VT_UINT = 23
   VT_VOID = 24
   VT_ARRAY = &H2000
   VT_BYREF = &H4000
End Enum

Private Type PARAMDATA
   szName As String
   vt As Integer 'VARENUM
End Type

Private Type METHODDATA
   szName As String
   ppdata As Long       ' pointer to an array of PARAMDATAs
   dispid As Long       ' method ID
   iMeth As Long        ' method index
   cc As CALLCONV       ' calling convention
   cArgs As Long        ' count of arguments
   wFlags As Integer    ' same wFlags as on IDispatch::Invoke()
   vtReturn As Integer
End Type

Private Type INTERFACEDATA
   pmethdata As Long    ' pointer to an array of METHODDATAs
   cMembers As Long
End Type

Private Declare Function CreateDispTypeInfo Lib "oleaut32" ( _
   pidata As INTERFACEDATA, ByVal lcid As Long, pptinfo As IUnknown) As Long
Private Declare Function CreateStdDispatch Lib "oleaut32" ( _
   ByVal punkOuter As IUnknown, pvThis As Delegator, _
   ByVal ptinfo As IUnknown, ppunkStdDisp As IUnknown) As Long

Private Type VTable
   pThunk As Long
End Type

Private Type Delegator
   pVtbl As Long
   pFunc As Long
End Type

Private Type Thunk
   b0 As Byte
   b1 As Byte
   b2 As Byte
   b3 As Byte
   b4 As Byte
   b5 As Byte
End Type
'Private m_Thunk(0 To 5) As Long
Private m_Thunk As Thunk

Private m_VTable As VTable
Private m_Delegator As Delegator
Private m_InterfaceData As INTERFACEDATA
Private m_MethodData As METHODDATA
Private m_ParamData() As PARAMDATA
Private m_FunctionPtr As Object
Private m_fInternalCall As Boolean


Private Sub Class_Initialize()
 'nop = 90h
' m_Thunk(0) = &H4244C8B      'mov ecx, [esp+4]               ;this pointer
' m_Thunk(1) = &H9004418B     'mov eax, [ecx+4]   nop         ;m_pFunc address
' m_Thunk(2) = &H90240C8B     'mov ecx, [esp]     nop
' m_Thunk(3) = &H4244C89      'mov [esp+4], ecx
' m_Thunk(4) = &H9004C483     'add esp, 4         nop
' m_Thunk(5) = &H9090E0FF     'jmp eax            nop nop     ;jump m_pFunc
 With m_Thunk
    .b0 = &H59 'pop  ecx                ;59
    .b1 = &H58 'pop  eax                ;58
    .b2 = &H51 'push ecx                ;51
    .b3 = &HFF 'jmp DWORD PTR [eax + 4] ;FF 60 04
    .b4 = &H60
    .b5 = &H4
 End With
' m_Thunk(0) = &HFF515859
' m_Thunk(1) = &H90900460
End Sub


Public Function Create( _
   ByVal pFunc As Long, ByVal Conv As CALLCONV, ByVal RetType As VARENUM, _
   ParamArray ParamTypes() As Variant) As Object
 If Not m_FunctionPtr Is Nothing Then
    Set Create = m_FunctionPtr
    Exit Function
 End If
 
 Dim i As Long
 Dim cParam As Long
 If m_fInternalCall Then
    cParam = UBound(ParamTypes(0)) + 1
 Else
    cParam = UBound(ParamTypes) + 1
 End If
 
 If cParam Then
    ReDim m_ParamData(0 To cParam - 1) As PARAMDATA
    For i = 0 To cParam - 1
       If m_fInternalCall Then
          m_ParamData(i).vt = ParamTypes(0)(i)
       Else
          m_ParamData(i).vt = ParamTypes(i)
       End If
       m_ParamData(i).szName = "Arg" & i
    Next
    m_MethodData.ppdata = VarPtr(m_ParamData(0))
 End If
 m_MethodData.szName = "Call"
 m_MethodData.dispid = DISPID_VALUE
 m_MethodData.iMeth = 0
 m_MethodData.cc = Conv
 m_MethodData.cArgs = cParam
 m_MethodData.wFlags = DISPATCH_METHOD
 m_MethodData.vtReturn = RetType
 
 m_InterfaceData.pmethdata = VarPtr(m_MethodData)
 m_InterfaceData.cMembers = 1

 Dim ti As IUnknown
 Dim Result As IUnknown
 i = CreateDispTypeInfo(m_InterfaceData, LOCALE_SYSTEM_DEFAULT, ti)
 If i = S_OK Then
    m_VTable.pThunk = VarPtr(m_Thunk) 'VarPtr(m_Thunk(0))
    
    m_Delegator.pVtbl = VarPtr(m_VTable)
    m_Delegator.pFunc = pFunc
    i = CreateStdDispatch(Nothing, m_Delegator, ti, Result)
    If i = S_OK Then
       Set m_FunctionPtr = Result
       Set Create = m_FunctionPtr
    End If
 End If
End Function

Public Function CreateFromDLL( _
   ByVal hModule As Long, ByVal FuncName As String, ByVal Conv As CALLCONV, _
   ByVal RetType As VARENUM, ParamArray ParamTypes() As Variant) As Object
 Dim pfn As Long
 pfn = GetProcAddress(hModule, FuncName)
 If pfn Then
    m_fInternalCall = True
    Set CreateFromDLL = Create(pfn, Conv, RetType, ParamTypes())
    m_fInternalCall = False
 End If
End Function


Public Property Get Func() As Object
 Set Func = m_FunctionPtr
End Property


'Public Function Invoke(ParamArray Args() As Variant) As Variant
' If IsMissing(Args) Then
'    Invoke = m_FunctionPtr.Invoke
' Else
'    Select Case UBound(Args)
'    Case 0:
'       Invoke = m_FunctionPtr.Call(Args(0))
'    Case 1:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1))
'    Case 2:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1), Args(2))
'    Case 3:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1), Args(2), Args(3))
'    Case 4:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1), Args(2), Args(3), _
'                                   Args(4))
'    Case 5:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1), Args(2), Args(3), _
'                                   Args(4), Args(5))
'    Case 6:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1), Args(2), Args(3), _
'                                   Args(4), Args(5), Args(6))
'    Case 7:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1), Args(2), Args(3), _
'                                   Args(4), Args(5), Args(6), Args(7))
'    Case 8:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1), Args(2), Args(3), _
'                                   Args(4), Args(5), Args(6), Args(7), _
'                                   Args(8))
'    Case 9:
'       Invoke = m_FunctionPtr.Call(Args(0), Args(1), Args(2), Args(3), _
'                                   Args(4), Args(5), Args(6), Args(7), _
'                                   Args(8), Args(9))
'    Case Else:
'       MsgBox "Слишком много параметров!", vbExclamation
'       Stop
'    End Select
' End If
'End Function

Пример вызова
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Private Declare Function GetModuleHandleW Lib "kernel32" ( _
   ByVal lpModuleName As Long) As Long

Private Sub Command1_Click()
 Dim fpMessageBoxExW As FunctionPtr
 Dim ofpMessageBoxExW As Object
 Dim lRes As Long
 
 Set fpMessageBoxExW = New FunctionPtr
 Set ofpMessageBoxExW = fpMessageBoxExW.CreateFromDLL( _
                           GetModuleHandleW(StrPtr("USER32")), _
                           "MessageBoxExW", CC_STDCALL, _
                           VT_I4, _
                           VT_I4, VT_I4, VT_I4, VT_I4, VT_I4)
 lRes = ofpMessageBoxExW.Call(hWnd, StrPtr("Текст"), StrPtr("Заголовок"), _
                              vbOKCancel Or vbQuestion, 0)
End Sub

cdecl поддерживается.

Это не единственный способ вызова функции по адресу, но, как по мне, самый гибкий.
...
Рейтинг: 0 / 0
20.06.2014, 11:25
    #38675159
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Бенедикт,

спасибо. Давно тебя не слышал.

Ну, смотри. Тот пример который ты привел (в подробности каюсь не вдавался, но по беглому уловил) по сути повторение уже сказанного:

1. 16192859
ссылка на Zip внизу

2. 16192954

Согласен?

===
Из совета ZVI и моего топика 16193687
следует что достаточно
1) задекларировать без пути
2) cделать LoadLibrary с путем (либо SetDllDirectory )
3) вызвать задекларированную ф-цию (со всеми параметрами как положено)

Нафига извращаться? Как считаешь?
==================
В VB по сути хорошо что декларировать можно что угодно.
Например пример C-шного кода
А как установить/обновить драйвер для одного конкретного модема?
Обрати внимание что с pInstallSelectedDriver пришлось извращаться именно по принципу о кот. сейчас говорим, хотя обычно в C достаточно include <.h>,
но вот забыли нарисовать.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
typedef
BOOL
(*PINSTALLSELECTEDDRIVER)(
  HWND hwndParent,
  HDEVINFO DeviceInfoSet,
  LPCWSTR Reserved,
  BOOL Backup,
  PDWORD pReboot    
  );

    // To be more secure, make sure to load the newdev.dll file from the
    // system 32 directory.
    if (GetSystemDirectory(NewDevPath, SIZECHARS(NewDevPath)) == 0) {
      DisplayError(_T("GetSystemDirectory"));
      goto ForceInstall;
    }

    if (FAILED(StringCchCat(NewDevPath, SIZECHARS(NewDevPath), TEXT("\\NEWDEV.DLL")))) {
      SetLastError(ERROR_INSUFFICIENT_BUFFER);
      DisplayError(_T("StringCchCat"));
      goto ForceInstall;
    }

    hNewDev = LoadLibrary(NewDevPath);
    if (!hNewDev) {
      DisplayError(_T("LoadLibrary"));
      goto ForceInstall;
    }

    pInstallSelectedDriver = (PINSTALLSELECTEDDRIVER)GetProcAddress(hNewDev, "InstallSelectedDriver");
    if (!pInstallSelectedDriver) {
      DisplayError(_T("GetProcAddress"));
      goto ForceInstall;
    }

    // Call pInstallSelectedDriver to install the selected driver on
    // the selected device.
    if (!pInstallSelectedDriver(NULL,
                           DeviceInfoSet,
                           NULL,
                           FALSE,
                           &dwRebootRequired)) {
      DisplayError(_T("InstallSelectedDriver"));
      goto ForceInstall;
    } else {
      if (dwRebootRequired & (DI_NEEDREBOOT | DI_NEEDRESTART)) {
        // A reboot is required.
        * RebootRequired = TRUE;
      }
			break;
    }




А в VB оказалось проще:
16072864
Код: vbnet
1.
2.
3.
Public Declare Function InstallSelectedDriver Lib "newdev.dll" _
 (ByVal hWndParent As Long, ByVal DeviceInfoSet As Long, _
 ByVal Reserved As Long, ByVal Backup As Long, ByRef bReboot As Long) As Boolean
...
Рейтинг: 0 / 0
20.06.2014, 11:47
    #38675204
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Дмитрий77Бенедикт,

спасибо. Давно тебя не слышал.

Тоже рад тебя слышать. А то твое имя уже в качестве эталона приходится использовать )) 15961785
...
Рейтинг: 0 / 0
20.06.2014, 12:05
    #38675237
ZVI
ZVI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Промахнулись ли папкой с DLL определяется однократно Dir-ом перед обращением к dummy-функции DLL.
Начинку DLL можно косвенно вычислить по размеру/контрольной сумме/версии файла
...
Рейтинг: 0 / 0
20.06.2014, 12:24
    #38675261
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
ZVIПромахнулись ли папкой с DLL определяется однократно Dir-ом перед обращением к dummy-функции DLL.


Не надо Dir-ов, тем более однократных.
Dir -плохо, PathFileExists-хорошо. Только писал об этом недавно.
Как узнать, существует ли файл?

ZVIНачинку DLL можно косвенно вычислить по размеру/контрольной сумме/версии файла
md5 этой dll я обычно проверяю, но не в данном конкретном случае.
md5 зависит от версии dll, а они у меня в разных версиях проги могут отличаться.
Утилита кот. пишу, должна работать с любой версией, а также допускать отсутствие dll.

Вариант который я привел Declare -> Load(FullPath) > GetProc -> Run (то что в Declare) -думаю оптимальный.
При любом промахе ф-ция вернет пустую строку, и в этом случае я перейду к след. методу определения искомого.
...
Рейтинг: 0 / 0
20.06.2014, 12:44
    #38675302
ZVI
ZVI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Дмитрий77Вариант который я привел Declare -> Load(FullPath) > GetProc -> Run (то что в Declare) -думаю оптимальный.
При любом промахе ф-ция вернет пустую строку, и в этом случае я перейду к след. методу определения искомого.
Вроде да, оптимально.
Как работает Declare после первого вызова любой функции DLL и почему очень быстро еще и потом,
хорошо расписано у Владислава Петровского (Хакер) - Magic Pointers («красивые» указатели на функции, вызов)
...
Рейтинг: 0 / 0
20.06.2014, 23:00
    #38676023
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
ZVIхорошо расписано у Владислава Петровского (Хакер) - Magic Pointers («красивые» указатели на функции, вызов)
Да уж, расписано. Все что расписано, не противоречит сказанному.

Но я вот на что обратил внимание,
авторVB(A) устроен так:
Для всех существующих в проекте Declare-функций имеется одна таблица, в которой хранятся адреса вызываемых функций. Это VB-специфичная таблица, и для каждой Declare-функции имеется ячейка, которая хранит адрес соответствующей Declare-функции.
Изначально эта таблица вся заполнена нулями.
Как только какая-либо из Declare-функций вызывается в первый раз, в её ячейке содержится 0, что означает, что адрес функции ещё не известен. ( в первый раз )определяет адрес вызываемой сейчас функции и заносит его в таблицу.
Последующие вызовы некоторой Declare-функции берут адрес прямо из таблицы и делают переход по нему.

А теперь то что мне не нравится и что я не могу допонять:
I.
ДимаЕсли неграмотно вызывать dll, которую VB не найдет то будет "Dll not found".
Имеется в виду следующий код:
Код: vbnet
1.
2.
3.
4.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long 'путь не указываем, и dll по дефолту не найдется

'вызов
CPP_MyFunction 


Run-time error '53'
File not found: cpp_my_dll.dll

II.
ДимаА вот если вызвать dll сначала грамотно любым из 4-х методов включая твой и 3 моих,
потом выполнить грамотный цикл из FreeLibrary,
а потом вызвать dll "неграмотно", то будет не "Dll not found", а просто crash VB-приложения,
почему ХЗ и я с Opal так однажды уже игрался и так и не докопался почему.

Имеется в виду следующий код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long 'путь не указываем, и dll по дефолту не найдется

  Dim hMod As Long
  Dim ProcAdd As Long
  hMod = LoadLibrary("PathToDll\cpp_my_dll.dll") 'загрузили, указав путь
  If hMod <> 0 Then
    ProcAdd = GetProcAddress(hMod, "CPP_MyFunction Lib ") 
    If ProcAdd <> 0 Then
      'вызов
      CPP_MyFunction 'вызов сработал
    End If
    'Делаем  FreeLibrary -все законно, убираем ВСЕ reference, все по MSDN
    Dim FreeResult As Long
    FreeResult = 1
    Do Until FreeResult = 0 ' OK, library reference count is 0, and library is therefore unloadable
      FreeResult = FreeLibrary(hMod)
      Debug.Print FreeResult
    Loop
  End If
  'еще вызов
  CPP_MyFunction '< и вот здесь будет crash!!! а не Run-time error '53' 


Причем если не делать первый вызов (который успешный - между LoadLibrary и FreeLibrary),
то будет Run-time error '53' not found как и в верхнем примере.


Т.е. как это увязать с рассуждениями о "VB-специфичной таблице"?
Я подозреваю что если в таблице записан 0, то имеем Run-time error '53' not found.
После первого (успешного) вызова там не 0 а валидный адрес ф-ции.
А после FreeLibrary там НЕвалидный адрес ф-ции.
Т.е. VB суко свою "таблицу" при FreeLibrary не чистит и делает вызов по НЕвалидному адресу,
отсюда краш при повторном вызове.
Так что ли?
Как увязать?

Потому что у меня были большие заморочки из-за этих непоняток.
И вопрос был скорее забит/заретушеван, нежели решен.
Как временно "отвязать" dll от VB-проги (чтобы файл "dll" можно было при этом удалить)
...
Рейтинг: 0 / 0
21.06.2014, 08:15
    #38676109
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Дмитрий77II.
Имеется в виду следующий код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long 'путь не указываем, и dll по дефолту не найдется

  Dim hMod As Long
  Dim ProcAdd As Long
  hMod = LoadLibrary("PathToDll\cpp_my_dll.dll") 'загрузили, указав путь
  If hMod <> 0 Then
    ProcAdd = GetProcAddress(hMod, "CPP_MyFunction Lib ") 
    If ProcAdd <> 0 Then
      'вызов
      CPP_MyFunction 'вызов сработал
    End If
    'Делаем  FreeLibrary -все законно, убираем ВСЕ reference, все по MSDN
    Dim FreeResult As Long
    FreeResult = 1
    Do Until FreeResult = 0 ' OK, library reference count is 0, and library is therefore unloadable
      FreeResult = FreeLibrary(hMod)
      Debug.Print FreeResult
    Loop
  End If
  'еще вызов
  CPP_MyFunction '< и вот здесь будет crash!!! а не Run-time error '53' 


Причем если не делать первый вызов (который успешный - между LoadLibrary и FreeLibrary),
то будет Run-time error '53' not found как и в верхнем примере.

Я подозреваю что если в таблице записан 0, то имеем Run-time error '53' not found.
После первого (успешного) вызова там не 0 а валидный адрес ф-ции.
А после FreeLibrary там НЕвалидный адрес ф-ции.
Т.е. VB суко свою "таблицу" при FreeLibrary не чистит и делает вызов по НЕвалидному адресу,
отсюда краш при повторном вызове.
Так что ли?


Походу так и есть.
Этот краш можно вызвать в чистом виде, тупо FreeLibrary -> CallWindowProc(по уже невалидному ProcAdd)
Вот таким кодом:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long

  Dim hMod As Long
  Dim ProcAdd As Long
  hMod = LoadLibrary("cpp_my_dll.dll")
  If hMod <> 0 Then
    ProcAdd = GetProcAddress(hMod, "CPP_MyFunction")
    If ProcAdd <> 0 Then
      '====
      Dim FreeResult As Long
      FreeResult = 1
      Do Until FreeResult = 0 ' OK, library reference count is 0, and library is therefore unloadable
        FreeResult = FreeLibrary(hMod)
        Debug.Print FreeResult
      Loop
      '====
      CallWindowProc ProcAdd, 0, 0, 0, 0
    End If
  End If


Ошибка точно такая же, то бишь в краш-окне то же самое написано.

Вот и вопрос, как этот 0 обратно в "VB-специфичную таблицу" засунуть.
И что это за таблица? И где к ней доступ?
Потому как VB это сам делать не умеет.
...
Рейтинг: 0 / 0
21.06.2014, 20:44
    #38676341
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Я тут покопался еще.
Влезть в таблицу наверно можно.
Ссылка приведенная ZVI, там есть ссылка на ZIP.

Вызов функций по указателю

В принципе автор как-то лезет в таблицу импорта через msvbvm60.dll, где он эти все ф-ции и структуры выкопал это видимо только ему известно. Я пытался, но мне не удалось получить адрес именно своей ф-ции в этой таблице. Короче, надоело, и времени жалко - пусть хакеры развлекаются.

Но что касается темы топика и грамотного решения:
Дмитрий77Посему грамотный вариант без использования вызова по ProcAdd такой:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long 'путь не указываем

Public Function MyLoad_MyFunction(ByVal PathToDll As String) As String
  Dim hMod As Long
  Dim ProcAdd As Long
  hMod = LoadLibrary(PathToDll)
  If hMod <> 0 Then
    ProcAdd = GetProcAddress(hMod, "CPP_MyFunction")
    If ProcAdd <> 0 Then
      MyLoad_MyFunction= PtrToString(CPP_MyFunction) 'а не по ProcAdd!!!
    End If
    Dim FreeResult As Long
    FreeResult = 1
    Do Until FreeResult = 0 ' OK, library reference count is 0, and library is therefore unloadable
      FreeResult = FreeLibrary(hMod)
      Debug.Print FreeResult
    Loop
  End If
End Function



Честно говоря, я не уверен в эффективности и необходимости FreeLibrary, да еще и с циклом (по MSDN извините).
Очевидно, что при обычном задекларированном вызове VB всегда делает LoadLibrary, но ни фига и никогда не делает FreeLibrary
Неграмотный он, с учетом сказанного.

Я думаю так:
1) Не надо множить Referenc-ы, можно безобидно проверить ЗАГРУЖЕНА ЛИ:
Код: vbnet
1.
hMod = GetModuleHandle(PathToDll) 'проверяем загружена ли уже


И только если не загружена, то загрузить:
Код: vbnet
1.
  If hMod = 0 Then hMod = LoadLibrary(PathToDll) 'загружаем только если не загружена


2) Не надо вообще делать цикл FreeLibrary(hMod)
VB этого не понимает и не отслеживает. При следующем запуске ф-ции "обычным способом" - даже если путь к ней видим (без LoadLibrary) получим краш.

Правильно короче так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
Public Declare Function CPP_MyFunction Lib "cpp_my_dll.dll" () As Long 'путь не указываем

Public Function My_CPP_MyFunction(ByVal PathToDll As String) As String
  Dim hMod As Long
  Dim ProcAdd As Long
  hMod = GetModuleHandle(PathToDll) 'проверяем загружена ли уже
  If hMod = 0 Then hMod = LoadLibrary(PathToDll) 'загружаем только если не загружена
  If hMod <> 0 Then
    ProcAdd = GetProcAddress(hMod, "CPP_MyFunction")
    If ProcAdd <> 0 Then
      My_CPP_MyFunction= PtrToString(CPP_MyFunction)
    End If
    '!!!А вот этого делать не надо
    'Dim FreeResult As Long
    'FreeResult = 1
    'Do Until FreeResult = 0 ' OK, library reference count is 0, and library is therefore unloadable
    '  FreeResult = FreeLibrary(hMod)
    'Loop
  End If
End Function


Т.е. мы не нарушаем идеологию VB, и при этом не плодим reference count при многократном обращениям к ф-циям dll. При любом к-ве вызовов любых ф-ций dll reference count будет максимум 2 (почему иногда 2, а не всегда 1 - видимо какие-то внутренние заморочки VB, скорее всего повторный вызов LoadLibrary если не видит адрес ф-ции в своей таблице)

Если уж очень надо полностью выгрузить dll (полная выгрузка в частности означает что dll-файл можно удалить без закрытия VB-приложения), то тогда ДА, цикл с FreeLibrary.
Но при этом обязательно помнить, что перед следующим вызовом ф-ции этой dll надо обязательно делать LoadLibrary,
ибо сам VB с этой ситуацией не справится.
...
Рейтинг: 0 / 0
23.06.2014, 11:40
    #38677006
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Дмитрий77
Код: vbnet
1.
...CallWindowProc(ProcAdd, 0, 0, 0, 0))



Не надо ее вообще использовать по возможности.
Видимо хакеры переусердствовали в стараниях по запихиванию в нее всякой дряни.

Я exe-шники свои обычно авирой проверяю -охренели эти антивирусы, но казусов то не нужно.
Смотрю ругается TR/Droper.VB.Gen
Я обычно давлю: либо ресурсы тасую, либо код протектором мешаю,+ Code Signing подписываю.
А тут вцепилась гадина анти(а)вирусная и ругается - и ничего не помогает.

Короче пока не закомментировал, не слезла.
Код: vbnet
1.
2.
'Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
' ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long


И это при том, что ф-ция в коде нигде не использовалась!!! На CallWindowProcA в файле тупо смотрит скотина авировская.

А блин, без этой ф-ции сабклассинг не получится.
Но на больших exe-шниках обычно пропускает, а здесь 300-400кб - и прицепилась тварь.
Часа 3 искал.
...
Рейтинг: 0 / 0
23.06.2014, 11:46
    #38677016
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде
Можно ли компилировать проект так, чтобы API, кот. задекларированы но проект реально не использует, никоим образом не влияли/ не "упомянались" в exe-шнике?

Я последнее время подключаю свои "общие стандартные" модули к проекту.
Поэтому там естественно куча всего.
И я обратил внимание, что exe-шник несильно, но таки побольше, чем если декларировать только необходимое как я делал раньше.
...
Рейтинг: 0 / 0
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Вызвать известную ф-цию из известной dll, но путь к dll -вычисляется в коде / 22 сообщений из 22, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]