Newsgroup: it.comp.lang.visual-basic
Titolo: Chiudere una  applicazione, non ucciderla.

Nonostante i numerosi post sull'argomento non sono riuscito, nella marea di
materiale, a trovare ciò che mi occorre.
Ho fatto un programma per schedulare dei back up dei dati e vorrei fare in
modo che questo chiudesse alcune applicazioni che potrebbero bloccare dei
file, roba tipo Excel o Outlook... Ho trovato solo esempi di procedure per
chiudere processi generati dal programma stesso, oppure questo codice:
    Dim obj As Object
     For Each obj In GetObject("winmgmts:").ExecQuery("SELECT * FROM
 Win32_Process WHERE Name='Nome.exe'")
         obj.Terminate
     Next
Che però "termina" il processo nella maniera in cui accadrebbe se da task
manager io lo killassi, non come se lo chiudessi col pulsantino X o con un
alt+F4. Dico questo perché chiudendo Outlook con la procedura indicata, al
successivo riavvio compare un avviso che dice che la precedente chiusura è
avvenuta in modo improprio, pertanto cerca di ripristinare il file pst,
avvertendomi che potrebbe essere danneggiato.
Qualcuno sa suggerirmi una soluzione migliore?
Grazie!
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

P@olo ha scritto:

Se usassi la strategia di accedere ai Processi con TerminateProcess
sarebbe come
Killarlo via WMI.
Per chiudere un'applicazione esterna in modo equivalente al Click su
"X" puoi usare
SendMessage o PostMessage, inviando il messaggio WM_CLOSE all'handle
dell'applicazione in questione.
Per ricavare l'handle però devi sapere il ClassName dell'applicativo
oppure il Nome
della Finestra....
Ti passo un esempio tratto da:
 Code Courtesy of
' Dev Ashish
'
Private Const WM_CLOSE = &H10
Private Const INFINITE = &HFFFFFFFF
Private Declare Function apiPostMessage _
    Lib "user32" Alias "PostMessageA" _
    (ByVal hWnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Long, _
    lParam As Any) _
    As Long
Private Declare Function apiFindWindow _
    Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, _
    ByVal lpWindowName As String) _
    As Long
Private Declare Function apiWaitForSingleObject _
    Lib "kernel32" Alias "WaitForSingleObject" _
    (ByVal hHandle As Long, _
    ByVal dwMilliseconds As Long) _
    As Long
Private Declare Function apiIsWindow _
    Lib "user32" Alias "IsWindow" _
    (ByVal hWnd As Long) _
    As Long
Private Declare Function apiGetWindowThreadProcessId _
    Lib "user32" Alias "GetWindowThreadProcessId" _
    (ByVal hWnd As Long, _
    lpdwProcessID As Long) _
    As Long
Function fCloseApp(lpClassName As String) As Boolean
'Usage Examples:
'   To close Calculator:
'       ?fCloseApp("SciCalc")
'
Dim lngRet As Long, hWnd As Long, pID As Long
    hWnd = apiFindWindow(lpClassName, vbNullString)
    If (hWnd) Then
        lngRet = apiPostMessage(hWnd, WM_CLOSE, 0, ByVal 0&)
        Call apiGetWindowThreadProcessId(hWnd, pID)
        Call apiWaitForSingleObject(pID, INFINITE)
        fCloseApp = Not (apiIsWindow(hWnd) = 0)
    End If 
End Function 
 
@Alex

Qualcuno sa suggerirmi una soluzione migliore?
' adattatelo .. e' intuitivo _:    oppure  >>>> [1]
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal _
 lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal _
 hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal _
 hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal _
 nCmdShow As Long) As Long
Const SW_SHOWNORMAL = 1
Const WM_CLOSE = &H10
Const gcClassnamePACT = "PactJumpToRegKey"
Const gcClassnameBabylon = "Babylon"
Const gcClassnameMSIExplorer = "IEFrame"
Const gcClassnameMSVBasic = "wndclass_desked_gsk"
Const gcClassnameNotePad = "Notepad"
Const gcClassnameMyVBApp = "ThunderForm"
Private Sub Form_Load()
    Dim WinWnd As Long, Ret As String, RetVal As Long, lpClassName As String
    WinWnd = FindWindow("Babylon", vbNullString)
    lpClassName = Space(256)
    RetVal = GetClassName(WinWnd, lpClassName, 256)
    PostMessage WinWnd, WM_CLOSE, 0&, 0&
      WinWnd = FindWindow("Notepad", vbNullString)
    lpClassName = Space(256)
    RetVal = GetClassName(WinWnd, lpClassName, 256)
    PostMessage WinWnd, WM_CLOSE, 0&, 0&
' ecc
End Sub
'[1]  visto che usi (vorresti usare )il WMI  questo e' migliore e piu semplice :
http://www.hiddensoft.com/autoit3/
ProcessClose("msimn.exe")
ProcessClose("notepad.exe")
; l'help
ProcessClose
--------------------------------------------------------------------------------
Terminates a named process.
ProcessClose ( "process" )
Parameters
process The title or PID of the process to terminate.
Return Value
None. (Returns 1 regardless of success/failure.)
Remarks
Process names are executables without the full path, e.g.,
"notepad.exe" or "winword.exe"
--
Fosco

 
http://www.hiddensoft.com/autoit3/
puoi compilarlo e funzionera su QUALSIASI pc  .. il metodo del
WMI penso che NON vada per esempio qui sul mio PC
in qui non ho il WMI   installato
--
Fosco