Qualche tempo fa, quando il DOS e la riga di comando la facevano ancora da padrone, era frequente l’uso del reindirizzamento dello standard input/output/error (stdin, stdout, stderr) per passare il contenuto di un file ad un applicativo e farlo elaborare.
Mi capita ancora di utilizzare questa tecnica con i tool da riga di comando del database MySql.
Per esempio, per importare un dump o uno script sql in un db, è sufficiente digitare (da cmd.exe) il seguente testo
mysql -h 192.168.1.1 -u user -ppwd dbname < C:\updateDb.sql
Questo fa si che lo script contenuto nel file updateDb.sql venga interpretato dal mysql come se immesso a mano da tastiera.
Qualche giorno fa, invece, ho avuto la necessità di automatizzare questo processo all’interno di un’applicazione C#.
Di seguito riporto il codice utilizzato ed al suo interno i commenti necessari
//Aggiornamento db
try
{
FileInfo file = new FileInfo(Config.sqlUpdateScript); //sqlUpdateScript è il percorso di updateDb.sql
if (file.Exists)
{//Config.applicazioneDbUpdate rappresenta il file dell’applicazione da eseguire: mysql.exe
ProcessStartInfo appDump = new ProcessStartInfo(Config.applicazioneDbUpdate);
appDump.WindowStyle = ProcessWindowStyle.Hidden;
appDump.UseShellExecute = false;
appDump.RedirectStandardError = true;
appDump.RedirectStandardOutput = true;
appDump.RedirectStandardInput = true;
//Le credenziali vengono passate come stringhe e concatenate da string.Format
appDump.Arguments = string.Format(“-h {0} -u {1} -p{2} {3}”, server, userid, password, database);
Process p = Process.Start(appDump);//Apro lo StreamReader verso il file di script sql
using (var streamReader = new StreamReader(Config.sqlUpdateScript))
{
//QUESTA E’ LA PARTE PRINCIPALE: passo il file allo StandardInput del processo “p”
p.StandardInput.Write(streamReader.ReadToEnd());
p.StandardInput.Flush();
p.StandardInput.Close();
}
//Verifico eventuali output del programma o messaggi di errore
string output = p.StandardOutput.ReadToEnd(); //Lettura prima di WaitForExit, altrimenti si blocca
string outerr = p.StandardError.ReadToEnd();
p.WaitForExit(60000); //60 secondiif (p.ExitCode != 0)
{
//LogMe.log(…) è un metodo di una -mia- classe di log
LogMe.log(LogLevel.Error, outerr);
LogMe.log(LogLevel.Error, appDump.Arguments);
MessageBox.Show(“Impossibile completare il backup\n” + outerr, Config.titolo, MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
else
{
LogMe.log(LogLevel.Error, “Script di aggiornamento non trovato!”);
MessageBox.Show(“Script di aggiornamento non trovato!\nAggiornamento non riuscito.”, Config.titolo, MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
catch (Exception exe)
{
LogMe.log(LogLevel.Error, exe);
MessageBox.Show(“Errore generico\n” + exe.Message, Config.titolo, MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}