Newsgroup: it.comp.lang.visual-basic
Titolo: aprire file con l'api ShellExecuteEx ed attenderne la chiusura

Io devo capire!
Su un pc Win2000 vorrei creare un'applicazione in grado di aprire dei
documenti e restare in attesa della loro chiusura.
Per fare ciò ho pensato di usare le API ShellExecuteEx per usufruire dei
parametri lpVerb (vedi "open" e "print") e della WaitForSingleObject per
attendere la fine dell'applicazione.
Tutto funziona correttamente con qualsiasi applicazione, tranne che con
Word: la prima volta che apro un documento .doc tutto è ok (viene lanciato
Word, aperto il documento e poi l'api WaitForSingleObject mi fa restare in
attesa), mentre all'apertura del secondo documento la ShellExecuteEx invece
di settare il parametro hProcess ad un numero valido, lo imposta a Zero. Di
conseguenza la chiamata alla WaitForSingleObject non mi fa più restare in
attesa (ma ritrona il valore -1).
Per spiegarmi meglio vi invio anche il codice di un progettino di esempio e
le istruzioni per poterlo utilizzare:
A) aprite un progetto vb6 standard exe, piazzateci dentro 4 textbox (Text1,
Text2, Text3 e Text4) affiancate, 4 pulsanti (Command1, Command2, Command3 e
Command4) sotto i rispettivi textbox, e una label (Label1) con un'altezza in
grado di contenere una decina di righe di testo.
B)Ora, aggiungete questo codice al form Form1:
Private Sub Command1_Click()
  Call StartDoc(Text1, "open")
End Sub
Private Sub Command2_Click()
  Call StartDoc(Text2, "open")
End Sub
Private Sub Command3_Click()
  Call StartDoc(Text3, "open")
End Sub
Private Sub Command4_Click()
  Call StartDoc(Text4, "open")
End Sub
Private Sub Form_Load()
  Text1 = "c:\temp\stampami.doc"
  Text2 = "c:\temp\test2.doc"
  Text3 = "c:\temp\stampami.txt"
  Text4 = "c:\temp\test2.txt"
  Label1 = ""
End Sub
C) Ora aggiungete al progetto un modulo (Module1) e meteteci questo codice:
Option Explicit
Private Type SHELLEXECUTEINFO
   cbSize As Long
   fMask As Long
   hwnd As Long
   lpVerb As String
   lpFile As String
   lpParameters As String
   lpDirectory As String
   nShow As Long
   hInstApp As Long
   lpIDList As Long
   lpClass As String
   hkeyClass As Long
   dwHotKey As Long
   hIcon As Long
   hProcess As Long
End Type
Const SEE_MASK_NOCLOSEPROCESS = &H40
Const SW_SHOWNORMAL = 1
Const SW_HIDE = 0
Private Declare Function ShellExecuteEx Lib "shell32.dll" Alias
"ShellExecuteExA" (lpExecInfo As _
   SHELLEXECUTEINFO) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function WaitForSingleObject Lib "kernel32.dll" (ByVal
hHandle As Long, ByVal _
   dwMilliseconds As Long) As Long
Const INFINITE = &HFFFF
Const WAIT_TIMEOUT = &H102
'
' Valori possibili per sCommand:
'
'   - "open"
'   - "print"
'
Public Sub StartDoc(ByVal sFile As String, ByVal sCommand As String)
  Dim sei As SHELLEXECUTEINFO
  Dim retval As Long
  With sei
    .cbSize = Len(sei)
    .fMask = SEE_MASK_NOCLOSEPROCESS
    .hwnd = GetDesktopWindow()
    .lpVerb = sCommand
    .lpFile = sFile
    .lpParameters = ""
    .lpDirectory = ""
    .nShow = SW_SHOWNORMAL
  End With
  ' Open the file using its associated program.
  retval = ShellExecuteEx(sei)
  If retval = 0 Then
    MsgBox "ERRORE"
  Else
    '--- attesa ---
    Do
      DoEvents
      retval = WaitForSingleObject(sei.hProcess, 0)
    Loop While retval = WAIT_TIMEOUT
    Form1.Label1 = Form1.Label1 & vbCrLf & sFile
  End If
End Sub
D) Infine dentro la cartella c:\temp create due documenti di Word (es.
"stampami.doc" e "test2.doc") e due documenti del blocco note (es.
"stampami.txt" e "test2.txt").
E) Ora lanciate il progetto e vi accorgerete che aprendo i file .txt tutto è
ok, mentre all'apertura del secondo file .doc l'API WaitForSingleObject non
ritorna un valore corretto.
La domanda finale è: Cosa succede? Come posso ovviare alla cosa?
--
   .o0o.o0o.o0o.o0o.
   0    zMatteo    0
   .o0o.o0o.o0o.o0o.

ritorna un valore corretto.
Ho appena provato con vb6 ent eng sp5, win2000 pro eng, word xp eng
e tutto pare funzionare a dovere.
-- 
ciao, hal

e tutto pare funzionare a dovere.
Ipotizzo ovviamente che sia solo un codice di esempio e non quello
finale di produzione, perche' se l'applicazione di esempio viene
chiusa _prima_ di word allora il processo di tale applicazione rimane
"appeso".
-- 
ciao, hal


come dici "pare"..... in effetti succede questo: all'apertura del secondo
documento word (perchè il secondo documento word viene effettivamente
aperto), l'api ShellExecuteEx imposta a zero la variabile sei.hProcesses
(all'apertura del primo documento in sei.hProcesses ci viene messo un numero
tipo 3212), questo perchè il processo word è già in esecuzione!
Conseguentemente a questo l'api WaitForSingleObject funziona poi
correttamente.
In effetti se dal menu avvio di windows lancio due volte il blocco note
posso constatare che nella lista dei processi del task manager di win2000
vedo due righe del notepad, mentre invece, se apro due documenti word vedo
un solo processo.
Resto comunque in attesa di risolvere il mio problema!!

un solo processo.
Ok, adesso ho anche letto il codice ;-)
Imho e' concettualmente errato il loop col doevents ed il test sul
valore di ritorno di WaitForSingleObject.
Guarda un po' su msdn questo articolo, che potrebbe darti qualche
spunto.
HOWTO: 32-Bit App Can Determine When a Shelled Process EndsPSS ID
Number: Q129796
Article Last Modified on 07-28-2001
-- 
hth, hal