This article is currently in the process of being translated into Italian (~99% done).
Starting applications with the Process class
Una cosa molto utile da fare dalla propria applicazione è avviare un'altra applicazione. Ad esempio, potreste voler includere un link al vostro sito web nella vostra applicazione e, invece di costringere l'utente a digitarlo manualmente nel browser o a copiare/incollare l'URL, sarebbe bello rendere il link cliccabile e quindi farlo aprire semplicemente nel browser predefinito dell'utente.
In questo tutorial utilizzeremo soprattutto applicazioni Console, perché sono meno complesse e possono dimostrare meglio la sintassi del linguaggio senza troppi fronzoli. L'esempio precedente è ovviamente più pertinente per un'applicazione basata su GUI, utilizzando uno dei framework GUI .NET come WinForms o WPF, ma può comunque essere utile avviare un'altra applicazione dalla vostra applicazione Console; in caso contrario, avrete almeno imparato la tecnica per il futuro.
Utilizzo della classe Process
Per istanziare un'altra applicazione, si può usare la classe Process. La classe Process si trova nel namespace System.Diagnostics, quindi è necessario includerla:
using System.Diagnostics;
Nella sua forma più elementare, si può semplicemente usare il metodo statico Start() per avviare un'applicazione:
Process.Start("https://www.google.com/");
Noterete che qui fornisco un URL, che potrebbe anche essere il percorso di un'applicazione locale, ad esempio Notepad (se lavorate su Microsoft Windows):
Process.Start(@"C:\Windows\notepad.exe");
Il motivo per cui entrambe le cose funzionano è che la classe Process passa semplicemente l'istruzione al sistema operativo, dicendo sostanzialmente "esegui questo!". Il sistema operativo esaminerà quindi le informazioni fornite e vedrà se ha un'azione supportata o meno. Se viene fornito un percorso a un file eseguibile, questo verrà avviato; se viene fornito qualcos'altro, ad esempio un URL o un percorso a un qualche tipo di file locale, cercherà di gestirlo con un'applicazione associata. Questo significa anche che si può dire al programma di eseguire un percorso a una cartella locale; se si utilizza Windows, si avvierà l'Esplora file di Windows, mostrando il percorso richiesto.
Avvio di applicazioni con argomenti/parametri
Spesso è utile fornire uno o più argomenti/parametri quando si avvia un'applicazione. Le applicazioni per console di solito accettano un'ampia gamma di parametri, ma anche le applicazioni di Windows sono in grado di gestire i parametri forniti tramite la riga di comando. Ad esempio, se si avvia il Blocco note, è possibile fornirgli un file che si desidera modificare, in questo modo:
Process.Start(@"C:\Windows\notepad.exe", @"C:\Windows\win.ini");
Questo funziona perché Notepad è progettato per cercare un parametro nella riga di comando: utilizzerà il primo parametro, se fornito, come percorso del file da aprire. Si può facilmente sostituire il percorso di win.ini con il percorso di uno dei propri file per fare una prova!
Utilizzo della classe ProcessStartInfo
La classe Process è una classe piuttosto complessa, che può fare molto di più del semplice avvio di un'applicazione. Non la analizzeremo tutta in questo articolo, dove ci concentreremo principalmente sulla sua capacità di avviare un nuovo processo. Quando si fa questo, a volte è necessario avere un po' più di controllo sulle modalità di esecuzione ed è qui che entra in gioco la classe ProcessStartInfo. Invece di fornire al metodo Start() un percorso, si può passare un'istanza della classe ProcessStartInfo, in questo modo:
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = @"C:\Windows\notepad.exe";
processStartInfo.Arguments = @"C:\Windows\win.ini";
Process.Start(processStartInfo);
In questo modo si otterrà semplicemente ciò che abbiamo già ottenuto, quindi analizziamo alcune delle proprietà interessanti della classe ProcessStartInfo, oltre alle proprietà Filename e Arguments che abbiamo appena usato nell'esempio precedente, che ci daranno un maggiore controllo:
WindowStyle
Utilizzate la proprietà WindowStyle per controllare come appare la finestra dell'applicazione avviata. Ad esempio, è possibile avviarla come massimizzata o ridotta, come in questo caso:
processStartInfo.WindowStyle = ProcessWindowStyle.Minimized;
CreateNoWindow
La proprietà CreateNoWindow realizza esattamente ciò che il nome implica: Se impostata su true, non verrà generata una finestra per l'applicazione avviata. Questo è ovviamente rilevante solo per le applicazioni in grado di fare cose senza l'interazione dell'utente, ad esempio un'applicazione Console che riceve input, fa qualcosa con essi e restituisce un risultato all'applicazione chiamante.
UseShellExecute
Questa proprietà consente di controllare se la shell di sistema deve essere utilizzata per avviare il processo, altrimenti il processo viene creato direttamente dal file eseguibile. Questa proprietà è true per impostazione predefinita se si lavora con il framework .NET prima di .NET Core, ma false per impostazione predefinita se si utilizza .NET Core. Utilizzeremo questa proprietà in un esempio esteso più avanti.
WorkingDirectory
Utilizzare questa proprietà per impostare il percorso della cartella da cui si desidera eseguire le operazioni. Tuttavia, occorre tenere presente che viene utilizzata in modo diverso a seconda che UseShellExecute sia impostato su true o false. Quando UseShellExecute è impostato su true, la proprietà WorkingDirectory specifica semplicemente la posizione dell'eseguibile e la directory di lavoro dell'applicazione che avvia l'eseguibile è anche la directory di lavoro dell'eseguibile. Quando UseShellExecute è impostato su false, la proprietà WorkingDirectory non viene utilizzata per trovare l'eseguibile, ma il suo valore viene applicato al processo avviato e ha significato solo nel contesto del nuovo processo.
RedirectStandardInput, RedirectStandardOutput e RedirectStandardError
Queste proprietà, se impostate a true, possono reindirizzare input/output ed errori dal processo eseguito al processo chiamante. Questo è utile, ad esempio, in combinazione con CreateNoWindow, perché consente di avviare un processo e di fornirgli input e/o ricevere errori e output da esso. La utilizzerò nell'esempio finale che segue, in cui combineremo diverse delle proprietà descritte.
Combinarle tutte
Ci sono altre proprietà su cui potremmo discutere, ma quelle evidenziate sono sicuramente le più interessanti. Invece, vi mostrerò un ultimo esempio, in cui combiniamo diverse delle tecniche appena descritte in qualcosa di molto interessante. Prima vi fornirò l'intero codice dell'esempio e poi lo commenteremo:
Console.WriteLine("Press any key to run CMD...");
Console.ReadKey();
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = @"C:\Windows\system32\cmd.exe";
processStartInfo.Arguments = "/c date /t";
processStartInfo.CreateNoWindow = true;
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardOutput = true;
Process process = new Process();
process.StartInfo = processStartInfo;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
Console.WriteLine("Current date (received from CMD):");
Console.Write(output);
Si inizia creando l'oggetto ProcessStartInfo. Utilizziamo le proprietà Filename e Arguments per specificare che vogliamo eseguire un Prompt dei comandi di Windows, utilizzando il file cmd.exe (l'interprete predefinito della riga di comando di Windows). Il comando che si vuole eseguire è specificato come Arguments: in questo caso utilizziamo il comando date con l'argomento /t, che restituirà semplicemente la data corrente.
Noterete anche che utilizzo le tre proprietà di cui abbiamo appena parlato: CreateNoWindow = true (vogliamo catturare l'output senza visualizzare una finestra cmd), UseShellExecute = false (ne abbiamo bisogno per poter eseguire questo tipo di comando) e RedirectStandardOutput = false (di nuovo, vogliamo catturare l'output).
Quindi, creiamo l'istanza di Process, assegniamo lo StartInfo e chiamiamo il metodo Start() per avviare il processo.
Nelle due righe successive, chiediamo di ricevere l'output generato, chiamando il metodo Process.StandardOutput.ReadToEnd(). Lo memorizziamo in una variabile stringa e poi chiamiamo il metodo WaitForExit(), per assicurarci che il processo avviato possa terminare.
Nelle ultime due righe, scriviamo semplicemente l'output ricevuto, che dovrebbe risultare nella data corrente. Ovviamente si tratta di un sacco di lavoro per ottenere la data corrente: avremmo potuto farlo con una sola riga di codice. Ma questo dimostra una tecnica piuttosto potente, che consente di chiamare altre applicazioni e di utilizzare il loro lavoro all'interno della propria applicazione.
Riepilogo
La classe Process è uno strumento molto potente, che consente di avviare altri processi e persino di controllarli. In questo articolo abbiamo mostrato solo alcune delle sue capacità, ma speriamo di avervi mostrato quanto sia versatile, in modo che possiate sperimentarla meglio.