maurogsc.eu
|
![]() |
home ==> Excel: articoli ==> Celle - Aprire e chiudere un programma con una macro(32/64 bit)
Sistema - Aprire e chiudere un programma con
una macro(32/64 bit)
Situazione.
Abbiamo la necessità di aprire un programma da codice, utilizzarlo e quindi di
poterlo eventualmente chiudere sempre da macro.
Nota.
Il codice è fornito *così com'è* e l’autore declina ogni responsabilità per eventuali
problemi causati dal codice se usato
impropriamente. Utilizzate il codice in files
di test per le vostre prove. Il codice è stato
testato con(e quindi validi per) Excel 2003/2007/2010.
Aprire un programma.
Nelllo specifico apriremo il Blocco Note(Notepad) di Windows. Quello che
dobbiamo fare è richiamare il Notepad con la funzione Shell(vedere anche la
guida del vb di Excel). Questo il codice da inserire, ad esempio, in un
modulo di codice standard(Inserisci-->Modulo o vedi qui:
xlsdoveinserirecodice.aspx)
Public Sub m_1()
Shell ("Notepad.exe"), vbNormalNoFocus
End Sub
Una soluzione diversa per aprire il Notepad è questa:
Public Sub m_2()
Dim v As Variant
v = Shell("Notepad.exe", vbNormalNoFocus)
End Sub
Quanto visto fino ad ora si può facilmente ricavare dalla guida di Excel. E sempre nella guida, si legge che viene restituito alla variabile che abbiamo dichiarato un valore di tipo Variant(Double), Come posssiamo utilizzare quel vaolre? Per esempio per gestire una eventuale eccezione(errore) nel caso il programma non sia disponibile. Nel codice della macro m_3() ho aggiunto una x davanti a Notepad.exe; il programma non esiste e quindi il valore di v sarà 0( o False se vogliamo vederlo come tipo Variant(Boolean), ma non complichiamo troppo la cosa):
Public Sub m_3()
Dim v As Variant
On Error Resume Next
v = Shell("xNotepad.exe", vbNormalNoFocus)
If v = 0 Then
MsgBox "Programma non trovato"
Else
MsgBox v
End If
End Sub
Se togliamo la x, ci verrà restituito un valore di tipo Variant(Double). Sì, ma cos'è quel valore? La guida ci dice che è l'idetificativo(univoco) del task del programma avviato. In altre parole, il processore sa che qul identificativo si riferisce ad un determinato programma eseguito(non può riferirsi al nome del programma, ad esempio Excel; potreste avere più sessioni di Excel aperte contemporaneamente). Vediamo come utilizzare quel valore per chiudere il programma non con quello che il programma stesso mette a disposizione, ma con il nostro codice. Abbiamo bisogno di utilizzare le API di Windows e qui la cosa si complica un po' perchè sono diverse in sistemi operativi Windows a 32 o 64 bit e in più abbiamo Office a 32 o 64 bit.
1 - Il codice qui sotto , sempre da copia/incollare in un modulo standard, apre o chiude il Notepad in sistemi operativi a 32 bit con tutte le versioni a 32 bit di Office:
Public v As Variant
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
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
Private Declare Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Public Sub mApriProgramma()
v = Shell("Notepad.exe", vbNormalFocus)
End Sub
Public Sub mChiudiProgramma()
Dim lng1 As Long
Dim lng2 As Long
lng1 = OpenProcess(PROCESS_ALL_ACCESS, 0&, v)
If lng1 Then
GetExitCodeProcess lng1, lng2
If lng2 Then TerminateProcess lng1, lng2
End If
End Sub
2 - Il codice qui sotto apre o chiude il Notepad nelle versioni a 64 bit del sistema operativo con installato Office 2010 e con le versioni a 32 bit del sitema operativo con installato Office 2010:
Public v As Variant
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As LongPtr, ByVal bInheritHandle As LongPtr, _
ByVal dwProcessId As LongPtr) As Long
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As LongPtr, lpExitCode As LongPtr) As Long
Private Declare PtrSafe Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As LongPtr, ByVal uExitCode As LongPtr) As Long
Public Sub mApriProgramma()
v = Shell("Notepad.exe", vbNormalFocus)
End Sub
Public Sub mChiudiProgramma()
Dim lng1 As Long
Dim lng2 As LongPtr
lng1 = OpenProcess(PROCESS_ALL_ACCESS, 0&, v)
If lng1 Then
GetExitCodeProcess lng1, lng2
If lng2 Then TerminateProcess lng1, lng2
End If
End Sub
3 - Il codice qui sotto apre e chiude il Notepad e grazie all'struzione di compilazione #If...Then...#EndI If e alla costante Win64 discrimina fra sistemi operativi a 32 o 64 bit:
Public v As Variant
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
#If Win64 Then
Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As LongLong, ByVal bInheritHandle As LongLong, _
ByVal dwProcessId As LongLong) As Longlong
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As LongLong, lpExitCode As LongLong) As LongLong
Private Declare PtrSafe Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As LongLong, ByVal uExitCode As LongLong) As LongLong
#Else
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
Private Declare Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As Long, ByVal uExitCode As Long) As Long
#End If
Public Sub mApriProgramma()
v = Shell("Notepad.exe", vbNormalFocus)
End Sub
Public Sub mChiudiProgramma()
Dim lng1 As Long
#If VBA7 Then
Dim lng2 As LongLong
#Else
Dim lng2 As Long
#End If
lng1 = OpenProcess(PROCESS_ALL_ACCESS, 0&, v)
If lng1 Then
GetExitCodeProcess lng1, lng2
If lng2 Then TerminateProcess lng1, lng2
End If
End Sub
4 - Il codice qui sotto apre e chiude il Notepad e grazie all'struzione di compilazione #If...Then...#EndI If e alla costante VBA7 discrimina fra versioni di Office con la versione 7 del VBA, introdotta con Office 2010 e le precedenti:
Public v As Variant
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
#If VBA7 Then
Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As LongPtr, ByVal bInheritHandle As LongPtr, _
ByVal dwProcessId As LongPtr) As Long
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As LongPtr, lpExitCode As LongPtr) As Long
Private Declare PtrSafe Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As LongPtr, ByVal uExitCode As LongPtr) As Long
#Else
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
Private Declare Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As Long, ByVal uExitCode As Long) As Long
#End If
Public Sub mApriProgramma()
v = Shell("Notepad.exe", vbNormalFocus)
End Sub
Public Sub mChiudiProgramma()
Dim lng1 As Long
#If VBA7 Then
Dim lng2 As LongPtr
#Else
Dim lng2 As Long
#End If
lng1 = OpenProcess(PROCESS_ALL_ACCESS, 0&, v)
If lng1 Then
GetExitCodeProcess lng1, lng2
If lng2 Then TerminateProcess lng1, lng2
End If
End Sub
5 - Il codice qui sotto apre e chiude il Notepad se lavorate in ambiente tutto a 64 bit, sistema operativo e Office:
Public v As Variant
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As LongLong, ByVal bInheritHandle As LongLong, _
ByVal dwProcessId As LongPtr) As LongLong
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As LongLong, lpExitCode As LongLong) As LongLong
Private Declare PtrSafe Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As LongLong, ByVal uExitCode As LongLong) As LongLong
Public Sub mApriProgramma()
v = Shell("Notepad.exe", vbNormalFocus)
End Sub
Public Sub mChiudiProgramma()
Dim lng1 As LongLong
Dim lng2 As LongLong
lng1 = OpenProcess(PROCESS_ALL_ACCESS, 0&, v)
If lng1 Then
GetExitCodeProcess lng1, lng2
If lng2 Then TerminateProcess lng1, lng2
End If
End Sub
Quindi, quale utilizzare delle soluzioni proposte?
NOTA.
Per ulteriori informazioni sulla compatibilità fra le versioni a 32 e 64
bit di Office, vedere qui:
http://msdn.microsoft.com/en-us/library/ee691831(office.14).aspx .
Per ulteriori informazioni su Microsoft Excel ed il suo Visual Basic, utilizzate
questo forum:
http://social.answers.microsoft.com/Forums/it-IT/officeexcelit/threads
Ultimo aggiornamento di questa pagina: 23/11/2010 - mauro gamberini