Shell sospensiva blocca il form in Visual Basic 6.0

Pubblicità

SalCar83

Utente Attivo
Messaggi
167
Reazioni
1
Punteggio
55
Salve a tutti!!
Ho il seguente problema e sono certo che qui qualcuno mi saprà aiutare...

Ho realizzato un programma in VB6 che deve richiamare un eseguibile esterno e attenderne il completamento prima di riprendere l'esecuzione...

Chiarisco:
1) Lancio il progetto VB6
2) Il progetto lancia un .exe da shell
3) il .exe termina
4) il progetto VB6 passa all'istruzione successiva

Per realizzare questa esecuzione "Sincrona" non ho potuto usare il comando Shell (perchè è asincrono e sarebbe passato all'istruzione VB6 successiva senza attendere il completamento dell'eseguibile esterno), pertanto ho importato il modulo "ShellSospensiva" come suggeritomi qui:
Visual Basic Simple

Riporto il codice:
Codice:
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (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 String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Const WAIT_TIMEOUT As Long = 258&
Private Const WAIT_FAILED As Long = &HFFFFFFFF
Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const STARTF_USESHOWWINDOW As Long = &H1
Private Const STARTF_USESIZE As Long = &H2
Private Const STARTF_USEPOSITION As Long = &H4
Private Const STARTF_USECOUNTCHARS As Long = &H8
Private Const STARTF_USEFILLATTRIBUTE As Long = &H10
Private Const STARTF_RUNFULLSCREEN As Long = &H20
Private Const STARTF_FORCEONFEEDBACK As Long = &H40
Private Const STARTF_FORCEOFFFEEDBACK As Long = &H80
Private Const STARTF_USESTDHANDLES As Long = &H100
Private Const STARTF_USEHOTKEY As Long = &H200
Public Function ShellSospensiva(ByVal CommandLine As String, ByVal Directory As String, ByVal WindowStyle As VbAppWinStyle, ByVal WaitTime As Long) As Long
    Dim proc As PROCESS_INFORMATION
    Dim Start As STARTUPINFO
 
    With Start
        .dwFlags = STARTF_USESHOWWINDOW
        .wShowWindow = WindowStyle
        .cb = Len(Start)
    End With
 
    Call CreateProcess(0, CommandLine, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, Directory, Start, proc)
    If proc.hProcess <> 0 Then
        ShellSospensiva = WaitForSingleObject(proc.hProcess, WaitTime)
        Call CloseHandle(proc.hProcess)
    Else
        ShellSospensiva = WAIT_FAILED
    End If
 
End Function

Il problema è il seguente:
questa shell sospensiva lancia il programma esterno (.exe) e l'interfaccia del mio programma VB6 si blocca, è praticamente inutilizzabile...
In effetti non mi serve dare comandi, ma è brutto vedere quella clessidra fissa e l'interfaccia "Freezata" durante l'esecuzione dell'eseguibile esterno (che tra l'altro dura 2 o 3 minuti...)

Occorrerebbe qualcosa in background che mi permetterebbe di fare un "Form1.Show" ogni tanto...

Ho pensato ad aggiungere un Timer che aggiorna l'interfaccia ogni secondo, ma come lo implemento??

Per favore aiutatemi... Vi ringrazio in anticipo...
 
Salve a tutti, è la prima volta che posto qui un problema e nessuno mi aiuta...
Comunque sono riuscito a risolverlo da solo, metto qui la mia soluzione così da renderla disponibile a chiunque avrà il mio stesso problema in futuro:

Codice:
Public Function ShellSospensiva(ByVal CommandLine As String, ByVal Directory As String, ByVal WindowStyle As VbAppWinStyle, ByVal WaitTime As Long) As Long
    Dim proc As PROCESS_INFORMATION
    Dim Start As STARTUPINFO
    Dim Esito As Long
    Dim Time_Iniziale As Long
    Esito = -1
 
    With Start
        .dwFlags = STARTF_USESHOWWINDOW
        .wShowWindow = WindowStyle
        .cb = Len(Start)
    End With
 
    Call CreateProcess(0, CommandLine, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, Directory, Start, proc)
    'Se ha creato il processo ne attende la fine, altrimenti esce con errore "Wait_FAILED"
    If proc.hProcess <> 0 Then
        'Prende il tempo iniziale e ogni 200ms controlla l'esito del processo
        'se è KO rinfresca l'interfaccia e ricontrolla, se è OK esce e ritorna il valore "0"
        'l'attesa dura al massimo 1000 secondi, dopo i quali si ritorna "-1"
        Time_Iniziale = Timer
        While Esito <> 0 And Timer < Time_Iniziale + 1000
            Esito = WaitForSingleObject(proc.hProcess, 200)
            Form1.Refresh
            If Esito = 0 Then
                ShellSospensiva = Esito
                Call CloseHandle(proc.hProcess)
                Exit Function
            End If
        Wend
        'Sono trascorsi 1000 secondi e la shell non ha terminato la sua esecuzione
        ShellSospensiva = -1
        Exit Function
    Else
        ShellSospensiva = WAIT_FAILED
    End If
 
End Function

in pratica ho semplicemente creato un loop in cui testo il processo chiamato (la shell) ogni 200ms (mentre prima la chiamata a WaitForSingleObject era bloccante dato che WaitTime era -1 e cioè infinito).
L'uscita dal loop è determinata o dall'esito positivo della shell (che ritorna zero) o dallo scadere di un timer di 1000 secondi da quando si lancia la shell esterna...
Ovviamente nel loop ho inserito un "Refresh" del form che prima mi si freezava nell'attesa "sincrona"...

Ciaoooo
 
Pubblicità
Pubblicità
Indietro
Top