Ciao a tutti,
quello che devo fare, semplificando molto, è questo:
1) creare con Access un file PRIMO.TXT che contiene dei dati
2) lanciare un programma DOS (con la funzione Shell) che esegue dei
calcoli con i dati letti dal file PRIMO.TXT, scrivendo i risultati nel
file
SECONDO.TXT
3) lanciare un secondo programma DOS (sempre con Shell) che legga dal file
SECONDO.TXT e faccia delle operazioni di conseguenza.
Problema: come fare in modo che il secondo programma parta solo quando il
primo ha finito l'elaborazione e chiuso il file PRIMO.TXT ?
Facendo:
Creazione file PRIMO.TXT
Shell "prog1" 'crea il file SECONDO.TXT
Shell "prog2" 'legge dal file SECONDO.TXT
succede che prog2 parte immediatamente dopo prog1, e va a leggere da un
file che prog1 non ha ancora finito di creare.
ps:
- non conosco a priori i tempi di elaborazione, non posso inserire quindi
pause fisse
- non posso cambiare la sequenza delle operazioni descritte.
Una soluzione non molto elegante che mi viene in mente è di creare un file
BAT che chiama prog1 e prog2, e richiamarlo da Access, in modo che si
abbia un'esecuzione sequenziale e non in parallelo, però è possibile che
non si
riesca a capire quando un EXE chiamato con Shell sia terminato? Serve a
qualcosa l'ID del task del programma avviato restituito da Shell?
In alternativa come si può verificare se un file è stato scritto
completamente, prima di iniziarne la lettura?
Risposte anche in e-mail har...@freenet.hut.fi grazie :)
Ciao, AntoGal.
Function TestWaitShell ()
Dim X%
X = WaitShell("Command.com")
MsgBox "Done!"
End Function
Function WaitShell (AppName As String)
Dim hMod As Integer
hMod = Shell(AppName, 1)
If (Abs(hMod) > 32) Then
While (GetModuleUsage(hMod))
DoEvents
Wend
Else
MsgBox "Impossibile lanciare " & AppName
End If
End Function
-----------------
Il secondo parametro della chiamata alla func Shell determina come viene
visualizzata la finestra dos.
Oppure, per cortesia di Ken Getz and Paul Litwin, una versione a 32 bit
(Win95) piu` sofisticata:
-----------------
' Code courtesy of:
' Microsoft Access 95 How-To
' Ken Getz and Paul Litwin
' Waite Group Press, 1996
Const PROCESS_QUERY_INFORMATION = &H400
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFFFFFF
Const STILL_ACTIVE = &H103&
Const ERR_FILE_NOT_FOUND = 53
Private Declare Function OpenProcess Lib "kernel32" ( _
ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" ( _
ByVal hProcess As Long, lpExitCode As Long) As Long
Sub ahtRunAppWait(strCommand As String, intMode As Integer)
' Run an application, waiting for its completion
' before returning to the caller.
Dim hInstance As Long
Dim hProcess As Long
Dim lngRetval As Long
Dim lngExitCode As Long
On Error GoTo ahtRunAppWait_Err
' Start up the application.
hInstance = Shell(strCommand, intMode)
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or SYNCHRONIZE, _
True, hInstance)
Do
' Attempt to retrieve the exit code, which will
' just not exist until the application has quit.
lngRetval = GetExitCodeProcess(hProcess, lngExitCode)
DoEvents
Loop Until lngExitCode <> STILL_ACTIVE
ahtRunAppWait_Exit:
Exit Sub
ahtRunAppWait_Err:
Select Case Err.Number
Case ERR_FILE_NOT_FOUND
MsgBox "Unable to find '" & strCommand & "'"
Case Else
MsgBox Err.Description
End Select
Resume ahtRunAppWait_Exit
End Sub
---------------
-------------------------------------------------------
riccardo romei
rro...@village.it
http://www.global.village.it/~rromei
REMOVE ANTISPAM to reply
RIMUOVI ANTISPAM per replicare
AntoGal <har...@freenet.hut.fi> scritto nell'articolo
<5vp11m$l...@mikasa.iol.it>...
>
> Ciao a tutti,
> quello che devo fare, semplificando molto, è questo:
>
> 1) creare con Access un file PRIMO.TXT che contiene dei dati
> 2) lanciare un programma DOS (con la funzione Shell) che esegue dei
> calcoli con i dati letti dal file PRIMO.TXT, scrivendo i risultati nel
> file
> SECONDO.TXT
> 3) lanciare un secondo programma DOS (sempre con Shell) che legga dal
file
> SECONDO.TXT e faccia delle operazioni di conseguenza.
>
> Problema: come fare in modo che il secondo programma parta solo quando il
> primo ha finito l'elaborazione e chiuso il file PRIMO.TXT ?
...
>
> Ciao a tutti,
> [...]
I meccanismi a disposizione sono MOLTO diversi a seconda
se sviluppi a 16 (win 3.x, Access 2.0) o 32 bit. Meglio se
specifichi.
_ ________________________________
R1100RS/ /R80GS Louis Cretier - lcre...@show.it
___/ /____ http://www.show.it/moto/home.htm
__/ | __ ___)
(_|(__) "Un buon viaggiatore
______(__) non segue le vie tracciate" (Daodejing, 27)
Ho avuto a lungo un problema del genere, cercando di aspettare un file
ascii importato con un programma di FTP da un host as/400 con una procedura
lanciata da Excel.
L'unica soluzione funzionante che ho trovato è continuare ad intervalli
regolari a verificare la dimensione del file e/o se il programma lanciato è
ancora attivo, oltre che chiedere periodicamente all'utente se aveva ancora
intenzione di aspettare i dati.
Il problema consiste nel fatto che quando lanci un programma da
un'applicazione Windows, questo è, (come mi diceva un tecnico Microsoft)
"Out of process", il che per noi poveri mortali significa che Windows lo
esegue come un task separato, non controllato dal processo del programma
che lo ha lanciato, ovvero Access.
Ovviamente la soluzione ideale è usare una .dll, peccato che scriverla non
è alla portata di tutti. Se da VBA di un qualsiasi prodotto Microsoft
chiami una .dll ,la .dll è "in process", cioè blocca l'esecuzione di Access
fino a quando non è terminato il processo. A quel punto Access riprende il
controllo e legge i file ascii effettivamente completi.
Spero che qualcun altro ti risponda con soluzioni diverse, tipo uso di
qualche API WIndows, perchè un problemi che mi interessa ancora.
ciao
AntoGal <har...@freenet.hut.fi> wrote in article
<5vp11m$l...@mikasa.iol.it>...
> Problema: come fare in modo che il secondo programma parta solo quando il
> primo ha finito l'elaborazione e chiuso il file PRIMO.TXT ?
>
Louis ha scritto nell'articolo <34200995.9839647@news>...
>
>I meccanismi a disposizione sono MOLTO diversi a seconda
>se sviluppi a 16 (win 3.x, Access 2.0) o 32 bit. Meglio se
>specifichi.
32 bit (Win95 OSR2) e Access 97
Qualche soluzione?
Ciao :)
Louis <soldier.o...@cselt.it> scritto nell'articolo
<3420e089.2762099@news>...
> On 17 Sep 1997 22:10:39 GMT, "Riccardo Romei" <rro...@village.it>
> wrote:
> La soluzione che uso io e' leggermente diversa: uso
> CreateProcess anziche' shell(), ma e' equivalente.
> Io uso pero' un diverso metodo per sincronizzarmi
> con la fine del task "shelled", piu' coerente con
> win32 e che NON usa la cpu. Sostituirei le righe:
> ...
> l'operazione sospende il thread chiamante finche' l'oggetto
> hProcess non termina. Ciao.
AntoGal <har...@freenet.hut.fi> scritto nell'articolo
<5vp11m$l...@mikasa.iol.it>...
>
> Ciao a tutti,
> quello che devo fare, semplificando molto, è questo:
>
> 1) creare con Access un file PRIMO.TXT che contiene dei dati
> 2) lanciare un programma DOS (con la funzione Shell) che esegue dei
> calcoli con i dati letti dal file PRIMO.TXT, scrivendo i risultati nel
> file
> SECONDO.TXT
> 3) lanciare un secondo programma DOS (sempre con Shell) che legga dal
file
> SECONDO.TXT e faccia delle operazioni di conseguenza.
>
Devi ricorrere all'uso delle API Windows in particolare alla
GETMODULEUSAGE:
1) Dichiarare la funzione con:
Declare Function GetModuleUsage Lib "Kernel" (ByVal hModule As Integer) As
Integer
2) Il controllo invece può essere effettuato nel modo seguente:
IdTask = Shell("..........") ' Esecuzione pgm.1
'** Aspetta fino a quando pgm.1 è attivo
RetCode = 1
Do While Retcode > 0
RetCode = GetModuleUsage (IdTask)
Loop
'**
dove ReTCode è un Integer!!!
> Ciao a tutti,
> quello che devo fare, semplificando molto, è questo:
>
> 1) creare con Access un file PRIMO.TXT che contiene dei dati
> 2) lanciare un programma DOS (con la funzione Shell) che esegue dei
> calcoli con i dati letti dal file PRIMO.TXT, scrivendo i risultati nel
>
> file
> SECONDO.TXT
> 3) lanciare un secondo programma DOS (sempre con Shell) che legga dal
> file
> SECONDO.TXT e faccia delle operazioni di conseguenza.
>
> Risposte anche in e-mail har...@freenet.hut.fi grazie :)
> Ciao, AntoGal.
La funzione Shell del VB ritorna un ID di processo, utilizzando questo
ID e alcune funzioni API è possibile "congelare" il programma padre in
attesa che il programma filgio sia terminato. Si dovranno utilizzare le
funzioni API OpenProcess, WaitForSingleObject, CloseHandle e
TaskFromInst, per la dichiarazione di queste utilizza il Visualizzatore
API.
Sub Esegui(sExe as String)
Dim hProg As Long
hProg = Shell(sExe, vbNormalFocus)
WaitOnProgram hProg
End Sub
Sub WaiOnProgram(idProg as Long)
#If Win32 Then
Dim hProc As Long, iRet As Long
hProc = OpenProcess(PROCESS_ALL_ACCESS, False, idProg)
If hProc <> vbNull Then
iRet = WaitForSingleObject(hProc, INFINITE)
CloseHandle hProc
End If
#Else
Do While TaskFromInst(idProg)
DoEvents
Loop
#End If
End Sub
Se non si vuole aspettare senza far nulla ma comunque si vuole
controllare quando l'applicazione figlio ha finito si puo usare la
funzione di seguito:
Function IsRunning(idProg) As Boolean
#If Win32 Then
Dim hProc As Long, iRet As Long
hProc = OpenProcess(PROCESS_QUERY_INFORMATION, False, idProg)
If hProc <> vbNull Then GetExitCodeProcess hProc, iRet
IsRunning = (iRet = STILL_ACTIVE)
CloseHandle hProc
#Else
isRunning = TaskFromInst(idProg)
#End If
End Function
In questa bisognerà dichiarare anche la funzione API GetExitCodeProcess.
--
Centro Studi Informatica di Danilo Priore
Via Pio VII, 9 - 00163 - Rome - Italy
Phone: (06) 66.40.052
Mobile Phone: (0335) 63.87.643
P.IVA 10149810581 Iscr. CCIAA 841531
e-mail: pri...@infocenter.it
URL: http://www.infocenter.it/priore