Toon posts:

[vb6] (Zelfgemaakte) DLL aanroepen en 'vrijlaten'?

Pagina: 1
Acties:

Verwijderd

Topicstarter
Euj iedereen.

Ik heb een probleem. Ik heb een programma gemaakt waarin je grafieken kunt maken, en dat is in de vorm van een DLL. Hoe het precies werkt doet er niet zo toe, het probleem is alsvolgt:

Om de dll aan te roepen heb ik een mini-projectje gemaakt 'standalone'. Deze bevat 1 form, 1 timer en de volgende code:
code:
1
2
3
4
5
6
7
8
9
Private mpgraph As Object
Private Sub Form_Load()
Set mpgraph = CreateObject("MPGraphDLL.dll")
mpgraph.start 
End Sub

Private Sub Timer1_Timer()

End Sub

Ik heb al een beetje lopen met die timer, zodat om de zoveel tijd gechecked werd of de DLL nog wel 'bestond', maar bij elke actie die ik daarvoor uitvoerde werd de DLL opnieuw geladen, etc etc...
Dus hoe laat ik de 'DLL' nadat ik 'set mpgraph...' heb gedaan weer vrij, zodat ik gewoon kan zeggen 'end', en dat het proggie dan weg is?
De vraagstelling is misschien een beetje vaag, maar er moet toch iemand zijn die het begrijpt :P?

Verwijderd

Je kan in vb object "vrij" maken met
code:
1
 set <objectname> = nothing

Verwijderd

Topicstarter
Nadeel is wel dat je dan ook meteen de DLL killt! In de DLL zitten een aantal vensters (gewoon modal forms) en die worden weergegeven (een wizard grafieken, een venster met de uiteindelijke grafiek, printschermpje, etc...). Ik wil dus dat de DLL gestart wordt, en standalone verder gaat, totdat uiteindelijk het hoofdvenster afgesloten wordt (event frm_grafiek_unload). Dan mag het over en uit zijn. Als ik nu doe:
code:
1
2
3
4
Set mpgraph = CreateObject("MPGraphDLL.dll")
mpgraph.start
Set mpgraph = Nothing
End

Dan zie ik in een flits een venstertje voorbijkomen (het eerste venster van de DLL: de wizard), maar die is net zo snel weer verdwenen, en alles is afgesloten! Dit is niet wat ik zocht, maar bedankt voor de snelle reactie!

  • pistole
  • Registratie: Juli 2000
  • Laatst online: 21:40

pistole

Frutter

en idealiter doe je het als volgt (vervang connection met jouw classname:
code:
1
2
3
4
5
6
7
8
9
10
11
12
Dim conn As Connection

Sub test()
    On Error GoTo foutje
      Set conn = New Connection
    On Error GoTo 0
    Set conn = Nothing
    Exit Sub
    
foutje:
    MsgBox "error, object kon niet gemaakt worden ofzo"
End Sub

EDIT
heh?
Waarom wil je dan checken of die dll nog bestaat, tijdens het executeren ervan?!

Ik frut, dus ik epibreer


  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Op donderdag 11 juli 2002 09:59 schreef CyberKnutselaar het volgende:
Nadeel is wel dat je dan ook meteen de DLL killt! In de DLL zitten een aantal vensters (gewoon modal forms) en die worden weergegeven (een wizard grafieken, een venster met de uiteindelijke grafiek, printschermpje, etc...). Ik wil dus dat de DLL gestart wordt, en standalone verder gaat, totdat uiteindelijk het hoofdvenster afgesloten wordt (event frm_grafiek_unload). Dan mag het over en uit zijn. Als ik nu doe:
code:
1
2
3
4
Set mpgraph = CreateObject("MPGraphDLL.dll")
mpgraph.start
Set mpgraph = Nothing
End

Dan zie ik in een flits een venstertje voorbijkomen (het eerste venster van de DLL: de wizard), maar die is net zo snel weer verdwenen, en alles is afgesloten! Dit is niet wat ik zocht, maar bedankt voor de snelle reactie!
Als je wil wachten totdat het gebeuren in de DLL klaar is zou je met WaitForSingleObject erop kunnen wachten. Je eigen progsel moet dan verder niks meer hoeven te doen (en ook geen vensters open hebben staan) want die blijft dan natuurlijk in een wait state totdat de DLL klaar is.

Als je in de executable nog wel andere dingen wilt doen zou je een dedicated thread kunnen starten die het object maakt en erop wacht... Maar dat moet je dan wel ff netjes aanpakken, want zelf threads bouwen in VB kan in bepaalde gevallen onverwachte )en onbedoelde) side effects hebben...

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


Verwijderd

Topicstarter
whuh? Dit is toch precies hetzelfde als die andere oplossing? Correct me if I'm wrong... (Ik bedoel de oplossing van pistole)

Verwijderd

Topicstarter
Waitforsingleobject? Klinkt groovie, maar hoe werkt het? heb je een voorbeeldje, want van m'n MSDN CD word ik niet veel wijzer (8>

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Op donderdag 11 juli 2002 10:06 schreef CyberKnutselaar het volgende:
Waitforsingleobject? Klinkt groovie, maar hoe werkt het? heb je een voorbeeldje, want van m'n MSDN CD word ik niet veel wijzer (8>
Je hebt dan een thread handle nodig van die DLL thread, die kan je opvragen in de DLL-class zelf (gewoon een public of friend methode GetThreadHandle maken). De exacte API call om de thread handle op te vragen weet ik zo niet uit mn hoofd. Als je die handle dan eenmaal hebt pass je die door aan WaitForSingleObject, en die call zal dan blocken totdat de thread signalled is (ofwel: totdat ie klaar is :P ). Je kan er btw ook een timeout bij opgeven, misschien makkelijk als je in je executable ook de mogelijkheid wil inbouwen om het wachten al eerder af te breken...

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


  • pistole
  • Registratie: Juli 2000
  • Laatst online: 21:40

pistole

Frutter

Op donderdag 11 juli 2002 10:06 schreef CyberKnutselaar het volgende:
Waitforsingleobject? Klinkt groovie, maar hoe werkt het? heb je een voorbeeldje, want van m'n MSDN CD word ik niet veel wijzer (8>
nogmaals

Waarom wil je dan checken of die dll nog bestaat, tijdens het executeren ervan?
Wil je checken of het ding nog in geheugen is, of dat ie uberhaupt nog bestaat?

[edit]
van bovengenoemd gedoe heb ik nog wel een stukje code liggen

Ik frut, dus ik epibreer


Verwijderd

Is een
code:
1
Set mpgraph = nothing


bij de unload van je form niet genoeg dan? :?

Tijdens je programma kun je blijven controleren of de dll nog bestaat met:
code:
1
if not mpgraph is nothing then

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Op donderdag 11 juli 2002 10:09 schreef pistole het volgende:

[..]

nogmaals

Waarom wil je dan checken of die dll nog bestaat, tijdens het executeren ervan?
Wil je checken of het ding nog in geheugen is, of dat ie uberhaupt nog bestaat?

[edit]
van bovengenoemd gedoe heb ik nog wel een stukje code liggen
My guess: hij wil een executable als 'launcher' gebruiken om zn DLL te 'booten', die vervolgens al het werk doet. Alleen hij heeft het probleem dat, zodra de executable stopt, de DLL er ook mee ophoudt :P

Am I right?

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


  • pistole
  • Registratie: Juli 2000
  • Laatst online: 21:40

pistole

Frutter

Op donderdag 11 juli 2002 10:13 schreef johnwoo het volgende:

[..]

My guess: hij wil een executable als 'launcher' gebruiken om zn DLL te 'booten', die vervolgens al het werk doet. Alleen hij heeft het probleem dat, zodra de executable stopt, de DLL er ook mee ophoudt :P

Am I right?
als dat zo is dan zou ik toch denken om ervoor te zorgen dat die "launcher" hidden blijft en dat je alleen "die dll" te zien krijgt

Ik frut, dus ik epibreer


  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Op donderdag 11 juli 2002 10:14 schreef pistole het volgende:

[..]

als dat zo is dan zou ik toch denken om ervoor te zorgen dat die "launcher" hidden blijft en dat je alleen "die dll" te zien krijgt
Precies, en dat is dus ook wat ik voorstel: zorgen dat de app zelf geen forms meer in beeld heeft en dan lekker wachten op de DLL :)

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


Verwijderd

Op donderdag 11 juli 2002 10:13 schreef johnwoo het volgende:
My guess: hij wil een executable als 'launcher' gebruiken om zn DLL te 'booten', die vervolgens al het werk doet. Alleen hij heeft het probleem dat, zodra de executable stopt, de DLL er ook mee ophoudt :P

Am I right?
Dan gebruikt ie later toch weer
code:
1
Set mpgraph = GetObject("MPGraphDLL.dll")

om de actieve instance van die dll weer terug te halen 8-)

Verwijderd

Topicstarter
Op donderdag 11 juli 2002 10:14 schreef pistole het volgende:

[..]

als dat zo is dan zou ik toch denken om ervoor te zorgen dat die "launcher" hidden blijft en dat je alleen "die dll" te zien krijgt
Jep, daarom zal ik uiteindelijk bij de form_load, als het hele project werkt, de regel
code:
1
me.hide

invoegen! Jullie snappen um! Maar heeft er niemand een voorbeeld van die waitforsingleobject?

  • pistole
  • Registratie: Juli 2000
  • Laatst online: 21:40

pistole

Frutter

die heb je dan niet meer nodig, denk ik
hij wacht na object.start (of whatever) toch dat je dll klaar is

Ik frut, dus ik epibreer


Verwijderd

Op donderdag 11 juli 2002 10:17 schreef CyberKnutselaar het volgende:

Maar heeft er niemand een voorbeeld van die waitforsingleobject?
Heb je dan toch niet nodig? :?

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Op donderdag 11 juli 2002 10:19 schreef pistole het volgende:
die heb je dan niet meer nodig, denk ik
hij wacht na object.start (of whatever) toch dat je dll klaar is
Ligt eraan, ik kan me goed voorstellen dat die Start methode in dat object zn eigen worker threads aan gaat zitten maken. En liep een ActiveX DLL niet sowieso in zn eigen thread?

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


Verwijderd

Op donderdag 11 juli 2002 10:19 schreef pistole het volgende:
die heb je dan niet meer nodig, denk ik
hij wacht na object.start (of whatever) toch dat je dll klaar is
Of gebruik een property/event maarmee de dll aangeeft dat ie klaar is.

  • pistole
  • Registratie: Juli 2000
  • Laatst online: 21:40

pistole

Frutter

Op donderdag 11 juli 2002 10:21 schreef johnwoo het volgende:

[..]

Ligt eraan, ik kan me goed voorstellen dat die Start methode in dat object zn eigen worker threads aan gaat zitten maken. En liep een ActiveX object niet sowieso in zn eigen thread?
niet standaard (is gewoon inprocess)

Heeg, ik ben mijn hele (backup)archief kwijt dus ik kan je niet helpen aan een voorbeeld...

Ik frut, dus ik epibreer


Verwijderd

Topicstarter
Je kunt toch niet vanuit die dll een event aanroepen in een andere thread?

Volgensmij is die oplossing van die waitfordinges de enige goeie. Het is namelijk niet zo dat ie na 'mpgraph.start' wacht totdat de DLL helemaal afgelopen is. De DLL krijgt z'n eigen thread, en de aanroepende app gaat verder. Dus dit
code:
1
2
mpgraph.start
end

gaat niet werken, want dan killt ie meteen die DLL mee. Hij moet gewoon wachten tot die DLL klaar is!

Verwijderd

Op donderdag 11 juli 2002 10:27 schreef CyberKnutselaar het volgende:
Je kunt toch niet vanuit die dll een event aanroepen in een andere thread?
Hmmmm.... dus echt in een andere thread laten lopen...
2 mogelijkheden:

1) Knoeien met API's voor threads (CreateThread, etc.), die je alleen wel goed moet gebruiken anders krijg je een zooitje leuke crashes >:)

2) VB.NET downen en daarmee werken :)

Verwijderd

Topicstarter
Ondertussen weet ik een beetje hoe dat waitforsingleobject werkt... Punt is nu alleen nog: hoe kom ik achter de threadid van de dll (de hHandle)?

  • henkleerssen
  • Registratie: December 2000
  • Niet online

henkleerssen

Your life is as you narrate it

Waitforsingleobject voorbeeldje..
code:
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
    Private Type STARTUPINFO
      cb As Long
      lpReserved As String

      lpDesktop As String
      lpTitle As String
      dwX As Long
      dwY As Long
      dwXSize As Long
      dwYSize As Long
      dwXCountChars As Long
      dwYCountChars As Long
      dwFillAttribute As Long
      dwFlags As Long
      wShowWindow As Integer
      cbReserved2 As Integer
      lpReserved2 As Long
      hStdInput As Long
      hStdOutput As Long
      hStdError As Long
     End Type

    Private Type PROCESS_INFORMATION
      hProcess As Long

      hThread As Long
      dwProcessID As Long
      dwThreadID As Long
    End Type

    Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As Long, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Const NORMAL_PRIORITY_CLASS = &H20&
    Private Const INFINITE = -1&

    Public Sub ExecCmd(cmdline$)
      Dim proc As PROCESS_INFORMATION
      Dim start As STARTUPINFO

      start.cb = Len(start)

      ' Shell the Application:
      ret& = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

      ' Wait for the shelled application to finish:
      ret& = WaitForSingleObject(proc.hProcess, INFINITE)
      ret& = CloseHandle(proc.hProcess)
    End Sub

dat CreateProcessA API functie genereert de handle... en WaitForSingleObject API functie wacht er dus op..

Verwijderd

Topicstarter
Probleem is alleen dat ik niet
code:
1
ret& = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

Want dat is toch wel een essentieel onderdeel van bovenstaande functie. Ik moet de handle hebben van een DLL gestart met
code:
1
Set mpgraph = CreateObject("MPGraphDLL.dll")

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

In het voorbeeldje hierboven creeer je dus zelf ook die handle, maar dat hoeft in dit geval niet; je kunt met een API functie de handle van de calling thread opvragen. Die moet je dus aanroepen in je GetThreadHandle methode in je klasse. Daarmee kun je dan in je app de handle krijgen en gebruiken in WaitForSingleObject :)

[edit]
De API heet: GetCurrentThread
Zie http://msdn.microsoft.com/library/en-us/dllproc/prothred_8mn8.asp

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


  • henkleerssen
  • Registratie: December 2000
  • Niet online

henkleerssen

Your life is as you narrate it

Je zou eens kunnen kijken onder MSDN naar CreateProcessA hoe je kan spelen met parameters voor je DLL...

Verwijderd

Topicstarter
Ik denk dat dit een beetje te geavanceerd wordt. De functie getcurrentthread wordt niet herkend. Ik heb het trouwens wel voor elkaar om de hwnd te vangen, hebben we daar wat aan?

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Op donderdag 11 juli 2002 11:08 schreef CyberKnutselaar het volgende:
Ik denk dat dit een beetje te geavanceerd wordt. De functie getcurrentthread wordt niet herkend. Ik heb het trouwens wel voor elkaar om de hwnd te vangen, hebben we daar wat aan?
Ach, dat valt best mee.. Voor VB misschien, als je Win32 C(++) progt dan doe je niet anders dan Bill's API's gebruiken ;)
Anyway, je moet de functies natuurlijk wel declareren:
code:
1
2
3
Declare Function GetCurrentThread Lib "kernel32" () As Long
Declare Function WaitForSingleObject Lib "kernel32" (ByVal Handle As Long, _
  ByVal TimeOut As Long) As Long

Over de timeout waarde in WaitForSingleObject heeft MSDN het volgende te zeggen:
[in] Time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.
Als je 0 meegeeft dan poll je dus alleen maar. Blijkbaar is INFINITE een constante, gedefinieerd in de een of andere header file van VC++. Je zult de waarde hiervan dus even moeten opzoeken om het in VB te gebruiken. Misschien dat een goede VB API viewer ook wel weet wat de waarde ervan is. (Het zou wel eens -1 ofwel 0xFFFFFFFF kunnen zijn maar dat weet ik niet zeker). Als je de waarde niet kunt vinden kan je natuurlijk ook WaitForSingleObject in een loopje aanroepen met een groot interval, en eruit springen als de call niet terugkomt met een timeout maar de thread is beeindigd (dat kun je aan de return value zien).

Veel succes :)

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


Verwijderd

Topicstarter
Had ik net ook gevonden, maar als ik die functie uitvoer (getcurrent...) dan krijg ik standaard, altijd "-2" als uitvoer!

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Op donderdag 11 juli 2002 12:01 schreef CyberKnutselaar het volgende:
Had ik net ook gevonden, maar als ik die functie uitvoer (getcurrent...) dan krijg ik standaard, altijd "-2" als uitvoer!
Klinkt als een error code... Even een API viewer opscharrelen en kijken wat het betekent :) (Of de VC++ headerfiles doorzoeken, in dezelfde file waarin GetCurrentThread is declared staan waarschijnlijk ook de constanten)
Ik ben nu nog aan het werk, als het niet lukt zal ik vanavond wel een GetCurrentThread sampletje bakken...

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


Verwijderd

Topicstarter
Hmmmm... nee, het wil niet lukken. Telkens maar weer die -2 en ik kan er niet achterkomen wat het betekent, en ik kan er ook niet achter komen hoe ik er iets anders uit kan slepen, srry.

Als je een sampletje kon maken, graag! :D

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Ah, ik zie het al... GetCurrentThread geeft geen echte handle maar een pseudohandle. Dat is een constante (-2 dus :) ) waarmee een thread tegen functies die een handle verwachten kan zeggen dat ze de aanroepende thread moeten gebruiken.
MSDN zegt over GetCurrentThread:
The function cannot be used by one thread to create a handle that can be used by other threads to refer to the first thread. The handle is always interpreted as referring to the thread that is using it. A thread can create a "real" handle to itself that can be used by other threads, or inherited by other processes, by specifying the pseudohandle as the source handle in a call to the DuplicateHandle function.
Je moet deze pseudohandle dus eerst 'vertalen' naar een echte, system-wide, handle. Ik heb een klein exampletje gemaakt. Plak dit in een project met een enkel form en een knopje, Command1:
code:
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
Option Explicit

Private Const DUPLICATE_SAME_ACCESS = &H2

Private Declare Function GetCurrentThread Lib "kernel32" () As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function DuplicateHandle Lib "kernel32" (ByVal hSourceProcessHandle As Long, _
  ByVal hSourceHandle As Long, _
  ByVal hTargetProcessHandle As Long, _
  ByRef lpTargetHandle As Long, _
  ByVal dwDesiredAccess As Long, _
  ByVal bInheritHandle As Long, _
  ByVal dwOptions As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long


Private Sub Command1_Click()
    Dim hPseudoHandle As Long, hProcess As Long, hThreadHandle As Long
    
    hPseudoHandle = GetCurrentThread
    hProcess = GetCurrentProcess
    
    DuplicateHandle hProcess, hPseudoHandle, hProcess, hThreadHandle, 0, 0, DUPLICATE_SAME_ACCESS
    
    Me.AutoRedraw = True
    Me.Print "Pseudohandle: " & CStr(hPseudoHandle)
    Me.Print "Real handle: " & CStr(hThreadHandle)
    
    CloseHandle hThreadHandle
    Command1.Enabled = False
End Sub

De vertaalde echte handle geef je door en gebruik je in WaitForSingleObject :)

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


Verwijderd

Topicstarter
WAAAAAAAAA! Het werkt! Geweldig jongens! Heel veel tnx!

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 00:25

johnwoo

3S-GTE

Op vrijdag 12 juli 2002 10:24 schreef CyberKnutselaar het volgende:
WAAAAAAAAA! Het werkt! Geweldig jongens! Heel veel tnx!
Mooi zo :)
Da's dan één bier ;)

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1

Pagina: 1