Guida al Visual Basic .NET
Capitolo 86° - Lavorare con i processi
Premessa: Se non vi ricordate, o se non sapete, cos'è un processo, vi rimando alla prima lezione sulla Reflection.
La classe Process
La classe che contiene tutte le informazioni su un processo è Process. Ecco una lista dei suoi membri più significiativi:
- BasePriority : restituisce un numero intero che identifica la priorità di un processo. I valori che può assumere sono:
4 (solo per il ciclo Idle del sistema), 8 (priorità normale), 13 (priorità alta) e 24 (molto alta, usata per le applicazioni
in tempo reale). La priorità di ciuascun processo influenza la quantità di tempo macchina che il processore gli concede
- Close() : chiude il processo e rilascia le risorse ad esso associate
- CloseMainWindow() : chiude il processo comunicando alla sua finestra principale di chiudersi. Funziona solo se tale processo dispone
di un'interfaccia grafica qualsiasi
- EnableRaisingEvent : determina se l'oggetto Process debba generare un evento quando viene chiuso. In questo modo si può monitorare
un processo e visualizzare informazioni e messaggi alla sua chiusura
- ExitCode : restituisce il codice di chiusura del processo (questa informazione, ad esempio, può essere chiamata quando il
processo genera l'evento Exited per sapere se ha dato buoni risultati oppure no). Si può pensare al processo anche come a una funzione:
il sistema operativo gli passa degli argomenti (da linea di comando) e il processo restituisce un codice intero che determina il risultato
delle sue operazioni. Questo codice viene determinato dallo stesso programmatore che ha scritto il programma, ed generalmente è 0
quando il processo ha dato esiti positivi (chi sa il C conosce bene il return 0 finale di Main). Se si tenta di accedere a questa proprietà
prima della chiusura, verrà generato un errore
- ExitTime : restituisce la data e l'ora esatta della chiusura del processo. Anche questa proprietà è molto utile per
monitorare i processi
- Handle : restituisce l'indirizzo di memoria del processo, sottoforma di puntatore a intero (IntPtr)
- HandleCount : ottiene il numero di handles aperti dal processo (questo numero potrebbe anche corrispondere al numero di finestre aperte,
dato che ogni finestra ha un proprio handle
- HasExited : restituisce True se il processo è stato chiuso, altrimenti False
- Get... : analizzerò le funzioni che iniziano per "Get" a parte
- Id : ottiene l'identificativo univoco del processo, che non è altro che un Int32. Questo numero può essere utile nell'uso
di altre funzioni, come ad esempio GetProcessesById
- Kill() : ferma immediatamente il processo. È più brutale di Close
- MachineName : nome della macchina sulla quale il processo è in esecuzione. Generalmente restituisce il nome del computer
stesso, ma può cambiare ad esempio se si usa una macchina virtuale
- MainModule : restituisce un oggetto System.Diagnostics.ProcessModule che identifica il modulo principale del processo. Con modulo si
intende l'assembly dal quale il programma è stato fatto partire. I membri che questo oggetto espone sono:
- BaseAddress : restituisce l'indirizzo di memoria (IntPtr) all'inizio del quale il modulo è stato caricato. Ad esempio, in
un'applicazione console, questa proprietà restituisce l'indirizzo di memoria di Module1
- EntryPointAddress : restituisce l'indirizzo di memoria in cui è collocato l'entry point, ossia il metodo principale, da
cui il programma è stato avviato. Ad esempio, in un'applicazione console, questa proprietà restituisce l'indirizzo della
procedura Main
- FileName : restituisce il nome del file dal quale è stato caricato il modulo, ossia il percorso su disco del programma
- FileVersionInfo : restituisce una caterva di informazioni sulla versione dell'eseguibile. Non sto neanche ad analizzare tutti i suoi
membri
- ModuleMemorySize : restituisce la quantità di memoria, in bytes, che il modulo occupa
- ModuleName : nome del modulo
- MainWindowHandle : handle della finestra principale. Si tratta dello stesso handle ottenuto con EnumDesktopWindows nel capitolo precedente
- MainWindowTitle : titolo della finestra principale. Si tratta dello stesso titolo ottenuto con GetWindowText nel capitolo precedente
- Modules : restituisce una collezione di tutti i moduli caricati dal processo
- PriorityClass : come BasePriority restituisce la priorità del processo, ma attraverso un enumeratore. Può assumere i
seguenti valori: Idle (ciclo Idle del sistema), BelowNormal (bassa), Normal (normale), AboveNormal (alta), High (altissima), RealTime
(rappresenta il maggior valore di priorità possibile: un processo con priorità RealTime ha quasi il 100% di tempo macchina)
- PrivilegedProcessorTime : restituisce un oggetto TimeSpan che indica quanto tempo il processo ha passato ad eseguire del codice
nel sistema operativo
- ProcessName : nome del processo
- Responding : restituisce False se il processo non risponde ai comandi, altrimenti True
- Start / StartInfo : analizzerò questi due membri in seguito
- Threads : restituisce una collezione di ProcessThread che rappresentano tutti i thread aperti dal processo. Ogni oggetto della
collezione espone i seguenti membri:
- BasePriority : priorità di base del thread, espressa tramite un numero
- CurrentPriority : priorità corrente del thread. Questa proprietà esiste poiché il thread può cambiare la
sua priorità
- Id : restituisce l'identificatore univoco del thread (simile a Process.Id)
- IdealProcess : determina l'indice del processore sul quale il thread verrebbe eseguito in maniera ottimale. Vale solo per computer
multiprocessore
- PriorityBoostEnabled : determina se il thread può ricevere un aumento di priorità quanto la sua finestra riceve il
focus, ossia viene selezionata dall'utente
- PrivilegedProcessorTime : restituisce un oggetto TimeSpan che indica quanto tempo il thread ha passato ad eseguire del codice
nel sistema operativo
- StartAddress : restituisce l'indirizzo di membria del metodo principale di questo thread
- StartTime : restituisce la data e l'ora esatta in cui il thread è stato avviato
- ThreadState : stato del thread
- TotalProcessorTime : restituisce un oggetto TimeSpan che indica da quanto tempo il thread è attivo
- UserProcessorTime : restituisce un oggetto TimeSpan che indica quanto tempo il thread ha passato ad eseguire del codice all'interno
dell'applicazione
- TotalProcessorTime : restituisce un oggetto TimeSpan che indica da quanto tempo il processo è attivo
- UserProcessorTime : restituisce un oggetto TimeSpan che indica quanto tempo il processo ha passato ad eseguire del codice all'interno
dell'applicazione
Ottenere i processi in esecuzione
La classe process espone anche quattro funzioni statiche che permettono di ottenere un array dei processi in esecuzione, basandosi su determinati
parametri. Ad esempio, Process.GetCurrentProcess restituisce il processo attualmente in esecuzione, e perciò quello associato
direttamente all'applicazione. Process.GetProcess ottiene invece un array contenente tutti i processi attivi sul computer. Invece,
Process.GetProcessesByName("nome") restituisce un array di tutti i processi con dato nome, dove tale nome non è altero che il nome
dell'eseguibile dal quale sono partiti, ma senza l'estensione. Ad esempio Process.GetProcessesByName("explorer") restituisce un solo processo,
"explorer.exe", che costituisce il programma principale dell'interfaccia di windows. In ultimo, Process.GetProcessById(id) ottiene un
processo con dato id. Nell'esempio che segue, si chiede all'utente di immettere il nome di un processo e, se ne esiste un con quel nome,
il programma visualizza tutte le informazioni possibili su di esso, usando le proprietà spiegate nel paragrafo precedente:
Module Module1
'Ottiene tutte le informazioni possibili su un modulo
Public Sub ScanModule(ByVal M As ProcessModule)
Console.WriteLine(" Nome modulo: {0}", M.ModuleName)
Console.WriteLine(" Handle: {0:X8}", M.BaseAddress.ToInt32)
Console.WriteLine(" Handle del metodo principale: {0:X8}", _
M.EntryPointAddress.ToInt32)
Console.WriteLine(" Memoria occupata: {0:N0} bytes", _
M.ModuleMemorySize)
Console.WriteLine(" Informazioni versione del programma:")
With M.FileVersionInfo
Console.WriteLine(" Nome file: {0}", .FileName)
Console.WriteLine(" Versione file: {0}", .FileVersion)
Console.WriteLine(" Descrizione file: {0}", _
.FileDescription)
Console.WriteLine(" Versione prodotto: {0}", _
.ProductVersion)
Dim Rel As String = "Nessuna"
If .IsDebug Then
Rel = "Debug"
ElseIf .IsPatched Then
Rel = "Patch"
ElseIf .IsPreRelease Then
Rel = "Beta"
ElseIf .IsPrivateBuild Then
Rel = "Release privata"
ElseIf .IsSpecialBuild Then
Rel = "Release speciale"
End If
Console.WriteLine(" Caratteristiche: {0}", Rel)
Console.WriteLine(" Copyright: {0}", .LegalCopyright)
Console.WriteLine(" Trademark: {0}", .LegalTrademarks)
Console.WriteLine(" Commenti: {0}", .Comments)
Console.WriteLine(" Nome compagnia: {0}", .CompanyName)
End With
End Sub
'Formatta un valore timespan
Public Function FormatTime(ByVal T As TimeSpan) As String
Return String.Format("{0}h {1}m {2}s", T.Hours, T.Minutes, T.Seconds)
End Function
'Ottiene tutte le informazioni possibili su un processo
Public Sub ScanProcess(ByVal P As Process)
Console.WriteLine("Nome processo: " & P.ProcessName)
Console.WriteLine(" Handle: {0:X8}", P.Handle.ToInt32)
Console.WriteLine(" Handles usati: {0}", P.HandleCount)
Console.WriteLine(" Id: {0}", P.Id)
Console.WriteLine(" Nome macchina: {0}", P.MachineName)
Console.WriteLine(" Moduli:")
For Each M As ProcessModule In P.Modules
Console.WriteLine()
ScanModule(M)
Next
Console.WriteLine()
Console.WriteLine(" Handle finestra principale: {0:X8}", _
P.MainWindowHandle.ToInt32)
Console.WriteLine(" Titolo finestra principale: {0}", _
P.MainWindowTitle)
Console.WriteLine(" Threads: {0}", P.Threads.Count)
Console.WriteLine(" Tempo di esecuzione su OS: {0}", _
FormatTime(P.PrivilegedProcessorTime))
Console.WriteLine(" Tempo di esecuzione user: {0}", _
FormatTime(P.UserProcessorTime))
Console.WriteLine(" Tempo di esecuzione totale: {0}", _
FormatTime(P.TotalProcessorTime))
End Sub
Sub Main()
Dim Name As String
Dim Processes() As Process
'Fa inserire il nome del processo
Console.WriteLine("Inserire il nome di un processo:")
Name = Console.ReadLine
'Inizializza la collezione
Processes = Process.GetProcessesByName(Name)
'Se l'array è vuoto, non c'è nessun processo
'aperto con quel nome
If Processes.Length = 0 Then
Console.WriteLine("Non esiste alcun processo con questo nome!")
Else
'Altrimenti enumera tutti i processi aperti
For Each P As Process In Processes
Console.WriteLine()
ScanProcess(P)
Next
End If
Console.ReadKey()
End Sub
End Module
Avviare nuovi processi
Per avviare un nuovo processo, è possibile scegliere due strade diverse. La prima comporta l'uso di un nuovo oggetto Process e della
sua proprietà StartInfo, mentre la seconda usa solamente il metodo statico Process.Start.
Cominciamo a descrivere la prima. Dopo aver inizializzato un nuovo oggetto Process:
Dim P As New Process
Si accede alla proprietà StartInfo e tramite questa si specificano tutte le informazioni necessarie all'avvio. I membri di StartInfo
sono:
- Arguments : determina gli argomenti passati a linea di comando. È una semplice stringa. Per saperne di più sui parametri
passati da linea di comando, vedere il tutorial associato nella sezione Appunti
- CreateNoWindow : determina se il processo debba essere avviato in una nuova finestra
- EnvironmentVariables : è una collezione di stringhe che rappresenta tutte le variabili d'ambiente. Queste ultime sono speciali
tipi di variabili globali, che non vengono definite dall'applicazione ma dal sistema operativo (o dal programma che richiama l'applicazione
stessa) e possono essere utilizzate in qualsiasi punto del codice. È possibile ottenere una variabile d'ambiente precedentemente
impostata con la funzione Environment.GetEnvironmentVariable("nome variabile"). Di queste ne esistono alcune predefinite, che sono valide
per ogni processo avviato sul computer: per saperle, possiamo usare questo breve codice:
Module Module1
Sub Main()
Console.WriteLine("Variabili d'ambiente:")
Console.WriteLine()
For Each Name As String In Environment.GetEnvironmentVariables.Keys
Console.WriteLine("{0} = {1}", Name, _
Environment.GetEnvironmentVariable(Name))
Next
Console.ReadKey()
End Sub
End Module
Sul mio computer, questo è il risultato:
P.S.: io non mi chiamo Nicola, eh: quando il tecnico ha fatto backup e formattazione ha capito male il mio nome, e non mi sono ancora
preso la briga di cambiare le impostazioni
- FileName : nome del file da avviare. Se si tratta di un eseguibile, verrà avviato il programma relativo. Se si tratta, invece,
di un qualsiasi altro tipo di file, questo verrà aperto con il programma associato, se esiste (ad esempio, un'immagine sarà
aperta con Paint). Se l'estensione del file non è associata a nessun applicativo, verrà restituito un errore
- UserName / Password : se il processo deve essere avviato in un certo account, potrebbero essere richieste delle credenziali. Password
è di tipo SecureString (vedi capitolo "Lavorare con le stringhe")
- Verb : se il file non è eseguibile, questa stringa determina quale azione si debba usare per aprirlo. Ad esempio, se FileName
è un file *.txt, si potrebbe usare "print" in questa proprietà per stamparlo. Le azioni disponibili per un certo tipo di
file variano sulla base dei programmi associati e sono reperibili nel registro di sistema
- WindowStyle : determina come visualizzare la finestra aperta dal processo, se Massimizzata, Minimizzata, Normale con focus o Normale
senza focus
- WorkingDirectory : determina la directory di lavoro del processo
Dopo aver impostato le adeguate proprietà, si richiama semplicemente Start:
Dim P As New Process
With P.StartInfo
.FileName = "C:programma.exe"
.Arguments = "-t"
.WorkingDirectory = "C:cartella"
.WindowStyle = ProcessWindowStyle.Maximized
End With
P.Start()
Questo codice equivale ad aprire il prompt dei comandi di windows e scrivere:
CD "C:cartella"
C:programma.exe -t
La seconda possibilità consiste nell'usare la versione statica di Start:
Process.Start("nome file")
Essa accetta anche altri parametri, che permettono di impostare i dati come si farebbe con StartInfo.
A proposito dell'autore
C#, TypeScript, java, php, EcmaScript (JavaScript), Spring, Hibernate, React, SASS/LESS, jade, python, scikit, node.js, redux, postgres, keras, kubernetes, docker, hexo, etc...
|