Newsgroup: it.comp.lang.visual-basic
Titolo: [!][APRI E CHIUDI PROGRAMMI] Risultato finale

Lo scopo del progetto e' aprire e chiudere (chiudere il programma aperto dal
progetto) i programmi senza avere riferimenti diretti al programma (tipo
caption, window class, ecc.).
Ha alcune limitazioni, anche se abbastanza limitate (eehehe):
- i programmi che non possono essere attivati non possono essere chiusi (per
es. se sono solo in traybar)
- se un'altra applicazione si attiva mentre il progetto sta attivando il
programma da chiudere (multitasking, programmi che appena attivati ne
attivano altri) il programma non verra' chiuso.
- non possono essere chiusi ne terminati i programmi che partono con un
processo e poi lo chiudono (es. explore, iexplore, ecc.)
Per risolvere queste limitazioni mi serve un aiuto, magari dal qualche Vc++
esperto.
Salve
                Dbg
VERSION 5.00
Begin VB.Form Form1
   Caption         =   "Form1"
   ClientHeight    =   1440
   ClientLeft      =   3990
   ClientTop       =   4815
   ClientWidth     =   4140
   LinkTopic       =   "Form1"
   ScaleHeight     =   1440
   ScaleWidth      =   4140
   Begin VB.TextBox Text1
      Height          =   285
      Left            =   120
      TabIndex        =   2
      Text            =   "C:\Office52\program\soffice.exe"
      Top             =   120
      Width           =   3855
   End
   Begin VB.CommandButton Command2
      Caption         =   "Chiudi programma"
      Height          =   375
      Left            =   2400
      TabIndex        =   1
      Top             =   960
      Width           =   1575
   End
   Begin VB.CommandButton Command1
      Caption         =   "Apri programma"
      Height          =   375
      Left            =   120
      TabIndex        =   0
      Top             =   960
      Width           =   1575
   End
   Begin VB.Label Label1
      Caption         =   "Label1"
      Height          =   255
      Left            =   120
      TabIndex        =   3
      Top             =   480
      Width           =   3855
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Private Const WM_SHOWWINDOW = &H18, WM_ACTIVATE = &H6, WM_ACTIVATEAPP =
&H1C, _
WM_QUERYENDSESSION = &H11, WM_ENDSESSION = &H16, WM_QUIT = &H12, WM_CLOSE =
&H10, _
WM_DESTROY = &H2
Private Const DETACHED_PROCESS = &H8
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 Byte
        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 Type FILETIME
 dwLowDateTime As Long
 dwHighDateTime As Long
End Type
Private StartProc As STARTUPINFO, InfProc As PROCESS_INFORMATION
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA"
(ByVal _
lpApplicationName As String, ByVal lpCommandLine As String, ByVal
lpProcessAttributes As _
Any, ByVal lpThreadAttributes As Any, ByVal bInheritHandles _
As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal
lpCurrentDriectory _
As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As
PROCESS_INFORMATION) _
As Long
Private Declare Function TerminateThread Lib "kernel32" (ByVal hThread As
Long, ByVal _
dwExitCode As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As
Long, ByVal _
uExitCode As Long) As Long
Private Declare Function GetExitCodeThread Lib "kernel32" (ByVal hThread As
Long, _
lpExitCode As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess
As Long, _
lpExitCode As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long)
As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd
As Long, _
lpdwProcessId As Long) As Long
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As _
Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SendMessageTimeout Lib "user32" Alias
"SendMessageTimeoutA" _
(ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam
As Long, ByVal _
fuFlags As Long, ByVal uTimeout As Long, lpdwResult As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Sub Command1_Click()
'apre l'applicazione
'chiude gli handle associati all'applicazione aperta
 If CloseAllHandle() Then
'apre l'applicazione
  If ApriApp(Text1.Text) Then
   Form1.Caption = "Applicazione aperta"
  Else
   Form1.Caption = "Fallita apertura dell'applicazione"
  End If
 Else
  Form1.Caption = "Fallita chiusura handle dell'applicazione"
 End If
 Label1.Caption = "DllErr:" & Err.LastDllError
'C:\windows\notepad.exe
'C:\Programmi\WinZip\winzip32.exe
End Sub
Private Sub Command2_Click()
'chiude l'applicazione
 Dim Esito As Long
'chiude l'applicazione senza terminarla
 Form1.Caption = "Applicazione in chiusura, attendere"
 If ChiudiApp(False) Then
  Form1.Caption = "Applicazione chiusa"
 Else
'chiede se terminare l'applicazione
  Esito = MsgBox("L'applicazione non si chiude terminarla?", vbYesNo)
  If Esito = vbYes Then
   If ChiudiApp(True) Then
    Form1.Caption = "Applicazione terminata"
   Else
    Form1.Caption = "Terminazione applicazione fallita"
   End If
  Else
   Form1.Caption = "Applicazione non chiusa"
  End If
 End If
 Label1.Caption = "DllErr:" & Err.LastDllError
End Sub
Private Sub Form_Unload(Cancel As Integer)
'chiude gli handle associati all'applicazione aperta
 Cancel = Not CloseAllHandle
End Sub
Private Function ApriApp(FileApp As String) As Boolean
 StartProc.cb = Len(StartProc)
'apre l'applicazione FileApp e restituisce gli identificatori
dell'applicazione
 ApriApp = CreateProcess(FileApp, vbNullString, vbNullString, vbNullString,
True, _
 DETACHED_PROCESS, vbNullString, vbNullString, StartProc, InfProc)
End Function
Private Function ChiudiApp(Termina As Boolean) As Boolean
'chiude l'applicazione aperta
'se il processo esiste esegue la sua chiusura
 If IsProcess(InfProc.hProcess) Then
'se il thread esiste esegue la sua chiusura
  If IsThread(InfProc.hThread) Then
'chiude il thread
'se il thread non si e' chiuso ed e' richiesta terminazione
dell'applicazione
   If Not ChiudiThread() And Termina Then
    Call TerminateThread(InfProc.hThread, 0)
    Call TerminateProcess(InfProc.hProcess, 0)
   End If
   ChiudiApp = Not IsProcess(InfProc.hProcess)
  End If 'IsThread(InfProc.hThread)
 Else 'IsProcess(InfProc.hProcess)
  ChiudiApp = True
 End If
'chiude gli handle associati all'applicazione aperta
 If ChiudiApp Then ChiudiApp = CloseAllHandle()
End Function
Private Function CloseAllHandle() As Boolean
'chiude gli handle associati all'applicazione aperta
 With InfProc
'chiude l'handle del thread
  If .hThread > 0 Then
   Call CloseHandle(.hThread)
   .hThread = 0
  End If
  CloseAllHandle = True
  If CloseAllHandle Then
'chiude l'handle del processo
   If .hProcess > 0 Then
    Call CloseHandle(.hProcess)
    .hProcess = 0
   End If
   CloseAllHandle = True
  End If
 End With
End Function
Private Function IsThread(hThread As Long) As Boolean
 Dim lpExitCode As Long
'verifica se il thread esiste
'se l'handle e' valido viene letto il codice di uscita del thread
 If GetExitCodeThread(InfProc.hThread, lpExitCode) Then
'se il thread non e' stato ancora chiuso
  If lpExitCode > 0 Then IsThread = True
 End If
End Function
Private Function IsProcess(hProcess As Long) As Boolean
 Dim lpExitCode As Long
'verifica se il processo esiste
'se l'handle e' valido viene letto il codice di uscita del processo
 If GetExitCodeProcess(InfProc.hProcess, lpExitCode) Then
'se il processo non e' stato ancora chiuso
  If lpExitCode > 0 Then IsProcess = True
 End If
End Function
Private Function ChiudiThread() As Boolean
'chiude il thread
 Dim Esito As Boolean, hWindow As Long, ThreadId As Long, CicloNum As
Integer
 On Error GoTo Error
 Esito = True
'attiva l'applicazione (se non e' possibile la gestione degli errori pone
esito a false)
 AppActivate (InfProc.dwProcessId)
'se l'applicazione e' stata attivata
 If Esito Then
'se viene attivata a questo punto un'altra applicazione, l'handle della
window non fa' _
parte dell'applicazione aperta ed impossibile chiudere il thread
'legge l'handle della finestra attiva
  hWindow = GetForegroundWindow()
'legge l'ID del thread che ha creato la finestra attiva
  ThreadId = GetWindowThreadProcessId(hWindow, 0)
'se il thread dell'applicazione aperta e' attivo
  If IsThread(InfProc.hThread) Then
'se l'handle della window fa' parte dell'applicazione aperta
   If InfProc.dwThreadId = ThreadId Then
'chiude il thread
'chiede alla window di chiudersi
        'SendMessageTimeout (per evitare di attendere all'infinito)
    Call SendMessage(hWindow, WM_CLOSE, 0, 0)
'attende per alcuni cicli di pausa che il thread segnali la sua chiusura
    For CicloNum = 0 To 15
'se la window e' ancora aperta
     If IsWindow(hWindow) Then
'pausa di attesa di 200 msec
      Sleep (200)
     Else
'il thread e' terminato
      ChiudiThread = True
'alcune applicazioni possono mantenere il thread attivo anche se la window
si e' chiusa
      Call TerminateThread(InfProc.hThread, 0)
      Call TerminateProcess(InfProc.hProcess, 0)
      Exit For
     End If
    Next CicloNum
   End If 'InfProc.dwThreadId = ThreadId
  Else 'IsThread(InfProc.hThread)
'se il thread dell'applicazione e' stato chiuso
   ChiudiThread = True
  End If
'se l'attivazione dell'applicazione e' fallito
 Else 'esito
  ChiudiThread = Not IsThread(InfProc.hThread)
 End If
Exit Function
Error:
 Esito = False
 Resume Next
End Function

esperto.
Beh, intanto complimenti per l'ottimo lavoro!
Perché non prepari un progettino da pubblicare sul Sito Comune?
Ciao,
Moreno
#sirri#@#morenosoft#.com
(togliete "#" dall'indirizzo)
Moreno Sirri VB Site - 
http://www.morenosoft.com/MSVBSite/
---------------------------------------------------------------------------
Le risposte alle tue domande le trovi sul Sito Comune di questo NewsGroup:
 
http://www.murialdo.it/it_lang_vb
---------------------------------------------------------------------------

Grazie.
E' un buon lavoro, anche decisamente sproporzionato rispetto al sangue e
alla bile usata.
Intanto acchiappo un po' di cavie 'volontarie' (nel multitasking le prove
sono sempre poche), poi sentire le critiche (anche se tutti quelli che hanno
usato i miei lavori non mi hanno mai fatto un commento, o li trovano ben
fatti o ci rimangono secchi alla prima occhiata), spedisco.
Salve
            Dbg
Moreno Sirri ha scritto nel messaggio


 fatti o ci rimangono secchi alla prima occhiata), spedisco.
Ma la ver.3 e' quella definitiva?
o c'e' pure una 4?
--
Fibia "Sakamoto" FBI
URL: 
http://www.geocities.com/fibiafbi
VB Simple: 
http://vbsimple.virtualave.net
E-Mail: 
fibi...@hotmail.com
ICQ UIN 63586057
Membro #25 delle Brigate Takahashi Sez. Sud

Questa e' definitiva.
A meno che qualche anima pia non mi dia qualche altro spunto su cui poter
fare migliorie.
Salve
            Dbg
Fibia FBI ha scritto nel messaggio


 esperto.
ho provato il form. posso segnalarti solo due inezie:
- se non si include ".exe", non lo apre
- quando si preme "chiudi", prima chiude, poi chiede.
ciao, a.

- quando si preme "chiudi", prima chiude, poi chiede.
??? cosa intendi esattamente? con che applicazione?
Se intendi la maschera "Terminare l'applicazione?" quella compare solo se il
programma non vuole chiudersi normalmente.
Salve
                Dbg

 programma non vuole chiudersi normalmente.
ah, ok.
io facevo apri, poi chiudi.
risultato: prima chiude l'app, poi viene fuori il msgbox.
ok cosi'.
ciao, a.

risultato: prima chiude l'app, poi viene fuori il msgbox.
Questo non dovrebbe succedere, cioe' se l'applicazione si e' chiusa, non
dovrebbe comparire la richiesta di terminazione.
Compare se non si e' chiusa (ad esempio, l'utente ha annullato l'operazione
(es. in notepad con il testo modificato)).
Fammi sapere.
Ciao
            Dbg