Newsgroup: it.comp.lang.visual-basic
Titolo: Ottenere il valore di ritorno di una funzione in un thread

Ciao a tutti.. Per registrare dei componenti creo un thread con la
CreateThread che lancia la funzione DllRegisterServer.. COme faccio a
sapere il valore che restituisce la funzione? Con quale API?
Grazie ciao.

biank...@libero.it
 wrote:

Sei sicuro che la CreateThread funzioni in Visual Basic??!?
Ho i miei dubbi!

 ha scritto nel messaggio
news:diipi2$ten$1...@newsreader.mailgate.org...

Funziona, giuro ;-).
L'API che serve è GetExitCodeThread.
Qua c'è il codice completo, senza che blanko stia tanto ad impazzire:
http://www.codeguru.com/vb/controls/vb_activex/article.php/c3479
Già abbondantemente testato ed utilizzato.
Bye
Raf

 L'API che serve è GetExitCodeThread.
Le conosco queste API, ho utilizzato le stesse ma per i processi, proprio
perchè in passato non sono riuscito a far partire in VB 6, la CreateThread
e leggendo sui news, si diceva che non funzionava anche se veniva detto il
contrario. 
Ora non so, magari provo a usare il codice da te postato per test!

 
http://www.codeguru.com/vb/controls/vb_activex/article.php/c3479
Ma questo codice è una stupida registrazione/deregistrazione automatica
di una dll!!!
Non ha nulla a che vedere con la CreateThread!!!

 ha scritto nel messaggio
news:diiqio$utf$1...@newsreader.mailgate.org...

Non so hai fatto lo sforzo di esaminare il codice nello zip, che stupido tanto
non è (almeno per me).
Per poter invocare le routine DLLRegisterServer e DLLUnregisterServer di un
modulo esterno non c'è altro modo che creare un thread.
Ed è quello che blanko credo stesse tentando di fare da solo, senza sfruttare
(come me eheh) quella sub già preconfezionata.
Te ne fornisco uno stralcio:
Private Declare Function CreateThreadForRegister Lib "KERNEL32" Alias
"CreateThread" _
(lpThreadAttributes As Any, ByVal dwStackSize As Long, ByVal lpStartAddress As
Long, _
ByVal lpparameter As Long, ByVal dwCreationFlags As Long, lpThreadID As Long) As
Long
...
   hThread = CreateThreadForRegister(ByVal 0&, 0&, ByVal lngProcAddress, ByVal
0&, 0&, lpThreadID)
   If hThread Then
        fSuccess = (WaitForSingleObject(hThread, 10000) = WAIT_OBJECT_0)
        If Not fSuccess Then
           Call GetExitCodeThread(hThread, dwExitCode)
           Call ExitThread(dwExitCode)
...
Comunque non so che dirti... senz'altro se la CreateThread non è usata con mille
attenzioni può essere rischiosa.
Un altra circostanza in cui l'ho usata è stata la realizzazione di un servizio
NT, seguendo questo articolo:
http://www.freevbcode.com/ShowCode.asp?ID=4317
Anche in questo caso problemi non ne ho avuti.
Ciao
Raf

 
http://www.freevbcode.com/ShowCode.asp?ID=4317
guarda, io ho fatto la cosa più semplice del mondo:
CreateThread(...) con i parametri della funzione da chiamare ecc...
e non funziona!
Forse usandola per chiamare altre funzioni API, compie il suo lavoro,
ma chiamarla con una propria funzione (come ho fatto su nell'esempio),
non funziona!

Anche in questo caso problemi non ne ho avuti.
Confermo, anch'io ho usato quel codice, la CreateThread funziona benissimo in VB
per creare servizi.
--
ciao
  Stefano

Ragazzi intanto grazie mille davvero per l'interesse :-)
Vi posto il codice della mia funzione.. Fidatevi delle declare che sono
un puro copia incolla :-)) Essa funziona alla grande, crea il thread
aspetta la fine del thread e effettivamente registra il componente che
gli passo in run-time.. Il problema è che no rileva quando la
registrazione va male.. Intanto provo  a guardarmi il codice che
m'avete linkato ;-)
Ecco la function completa...
Public Function RegisterCmp(cmpPath As String) As Boolean
    On Error GoTo err_RegisterCmp
    Dim hLib As Long
    Dim pAddress As Long
    Dim hThread As Long
    Dim dwThreadId As Long, dwRC As Long
    Dim lExitCode As Long
    RegisterCmp = False
    hLib = 0
    pAddress = 0
    hThread = 0
    dwThreadId = 0
    dwRC = 0
    hLib = LoadLibrary(cmpPath)
    ' controllo che hLib sia valido come valore (<>0)
    If hLib Then
    'Ottengo l'indirizzo della funzione DllRegisterServer
        pAddress = GetProcAddress(hLib, "DllRegisterServer")
    Else
        oLog.Scrivi "ClsMgmFls_RegisterCmp(): Error loading library " &
cmpPath & _
        ".", Error
        'Esco dalla function
        Exit Function
    End If
    'Controllo pAddress che sia valido (<>0)
    If pAddress Then
        'Creo un thread che esegue la funzione presente all'indirizzo
retReg
        '(DllRegisterServer). CreateThread restituisce un handle a tale
thread
        hThread = CreateThread(0&, 0, pAddress, 0&, 0, _
            dwThreadId)
    Else
        oLog.Scrivi "ClsMgmFls_RegisterCmp(): Error locating function "
& _
        "''DllRegisterServer''.", Error
        'Pulisco l'handle della library caricata in memoria
        FreeLibrary hLib
        Exit Function
    End If
    'Controllo che hThread sia valido (<>0). Se valido sta girando il
thread
    If hThread Then
        'Se dwRC prende un valore<>0 significa che sta ancora girando.
        'Viene restituito un valore da WaitForSingleObject() ogni 100ms
        dwRC = WaitForSingleObject(hThread, 100000)
    Else
        oLog.Scrivi "ClsMgmFls_RegisterCmp(): Could not create the
thread " & _
        "''DllRegisterServer''.", Error
        'Pulisco l'handle della library caricata in memoria
        FreeLibrary hLib
        'Esco dalla funzione
        Exit Function
    End If
    'Finchè dwRC non assume il valore 0 gli viene riassegnato il
valore di
    'WaitForSingleObject ogni 100ms. Se ottiene 0 il thread è stato
eseguito
    'con successo. Ovviamente se è già a 0 dopo la precedente
chiamata di
    'WaitForSingleObject il ciclo non viene nemmeno eseguito.
    Do While dwRC <> WAIT_OBJECT_0
        dwRC = WaitForSingleObject(hThread, 100)
    Loop
    lExitCode = GetExitCodeThread(hThread, 0)
    If lExitCode <> 0 Then
        RegisterCmp = True
    End If
    'Pulisco gli handles del thread creato e della library caricata
    CloseHandle hThread
    FreeLibrary hLib
    Exit Function
err_RegisterCmp:
    oLog.Scrivi "ClsMgmFls_RegisterCmp(): " & Err.Number & " - " &
Err.Description, Error
    'Se esiste o l'handle della library o l'handle thread eseguo
pulizia
    If hThread Then CloseHandle hThread
    If hLib Then FreeLibrary hLib
End Function
La funzione GetExitCodeThread l'ho scoperta stamane ma restituisce
sempre un non-zero cioè, success! Anche in caso di fail.. Almeno lì
come la uso io... :-((

 non funziona!
Se per "propria funzione" intendi definita nel progetto VB, con lo scopo di
creare di un thread secondario all'interno del processo corrente, so anch'io che
non funziona.
Aggiungo che con opportune tecniche (piuttosto complesse, per la verità) alla
fine si supera anche questo scoglio, basta dare un'occhiata a questo:
http://www.fawcette.com/archives/premier/mgznarch/vbpj/1999/06jun99/bb0699.pdf
Bye
Raf

Cacchio spero di non scrivere due volte lo stesso post.. :-) Non
ricordo se ho premuto annulla o invia :-)
Comunque ripeto..
Il progetto che m'ha linkato Rafunk ha lo stesso problema del mio..
Ovvero dà in ogni caso esito positivo, sia che la registrazione sia
andata bene o male. O meglio dal momento in cui il Thread è creato e
la funzione (DllRegisterServer) è girata non si ottiene tramite queste
righe
        fSuccess = (WaitForSingleObject(hThread, 10000) =
WAIT_OBJECT_0)
        If Not fSuccess Then
il successo o meno della funzione. Più specificatamente ciò penso
accada perchè la WaitForSIngleObject non fa altro che attendere lo
stato 'segnalato' della funzione interna al thread e in tal caso
resituisce 0 o WAIT_OBJECT_0 che dir si voglia. Quindi WAIT_OBJECT_0
viene restituito sia in caso di successo che di insuccesso della
DllRegisterServer.. E alla fine il programma dice sempre 'Ok è andato
tutto bene'.
Chi sa come ottenere il risultato della funzione nel thread me lo dica
per piacere.. Sto diventando scemo su sta cosa!!! :-((
Grazie, ciao

 ha scritto nel messaggio
news:1129127762.0...@g47g2000cwa.googlegroups.com...


In un altro post ti avevo indicato la funzione GetExitCodeThread(), che
effettivamente nell'esempio viene chiamata solo se fallisce la
WaitForSingleObject.
Prova ad invocarla anche quando la WaitForSingleObject ha successo.
Non so se però effettivamente funzioni anche in quel caso... proverò.
Spiegami in quali casi può fallire la DLLRegisterServer, giusto per fare una
simulazione.
Ciao
Raf

 simulazione.
Ok, dovrebbe funzionare.
L'unico scenario in cui la DLLRegisterServer può fallire che io sappia è quello
in cui l'utente non ha i privilegi necessari per modificare il registro di
Windows.
Ho provato così: ho modificato il programma di prova in modo che invochi
GetExitCodeThread in tutti i casi e mostri il valore di dwExitCode così ottenuto
e l'ho fatto girare sotto l'identità di un utente con bassissimi privilegi.
Come risultato ho che dwExitCode vale 8002801C (TYPE_E_REGISTRYACCESS, "Error
accessing the OLE registry"), mentre con l'utente Administrator vale 0
(Success).
Intanto faccio tesoro di questo esperimento anche per i miei progetti...
Bye
Raf

Raf siamo arrivati ninsieme sai? Ieri sera alle 17 circa ho provato ad
invocare la GetExitCodeThread anche quando la Wait restituisce 0.. Ho
letto dwExitCode e m'ha trappato l'errore... Non sai l'esulto cacchio!!
2 gg e mezzo a madonne :-)) Intanto grazie mille per avermi indirizzato
su quella funzione che avevo già addocchiato ma l'avevo 'interpretata'
male nell'uso... :-))
Solo una cosa da buopn progrmmatore in erba.. Io se leggo dwExitCode
(che in teoria è un puntatore e già non so come possa leggerlo vb.. )
quando gira con utenti non admin mi da -
2147467259
 che andando a vedere
è E_FAIL (errore generico)... A te restituisce invece 8002801C
(TYPE_E_REGISTRYACCESS, "Error
accessing the OLE registry").. Com'è possibile? A me in decimale e a
te hex.. Come fai a farti restituire quel valore?

 te hex.. Come fai a farti restituire quel valore?
Mah, potrebbe dipendere dalla versione di Windows, io ho XP Pro SP1...
Ciao
Raf