Archive for the 'IT' Category

Verificare la correttezza sintattica dei path con .Net

Pochi giorni fa mi sono imbattuto nel seguente problema: verificare che una certa stringa contenga un path (di file o directory) valido o corretto. Ho scoperto che molti sviluppatori confondono la correttezza o validità con l’esistenza o meno della “risorsa” (file o directory) “descritta” dal path stesso. La correttezza o validità sintattica del path è, ovviamente, “platform dipendente”. Un path valido per la piattaforma GNU/Linux non lo è di certo per la piattaforma Microsoft Windows!

Esempio di path (assoluto) valido per piattaforma Microsoft:

c:\pippo\pluto\paperino

Esempio di path (assoluto) valido per piattaforma GNU/Linux:

/home/house/flat

Non è detto che la risorsa “descritta” da un path esista o no, ma i due esempi in precedenza esposti sono sicuramente sintatticamente corretti (per le rispettive piattaforme indicate). Ora, com’è possibile verificare la correttezza sintattica di un path nella piattaforma Microsoft ed utilizzando il framework .Net? In rete si trova un po’ di tutto, soprattutto si capisce, come accennavo all’inizio, che molta gente non è capace di inquadrare il problema.

Esempio di path (assoluto) non valido per piattaforma Microsoft:

hug:\\\pippo\\pluto\paperino

Una soluzione possibile è quella di utilizzare le regular expression: non così banale però definire la regola corretta! Quelle che ho trovato in rete sono di certo incomplete: un path può essere assoluto o relativo! Un soluzione veloce, forse non troppo elegante è quella che vi propongo qui di seguito.

private bool checkPathValidity(string sPath)
{
try
{
new FileInfo(sPath);

return true;
}
catch
{
return false;
}
}

Al fine di far funzionare correttamente il tutto, vi ricordo di includere il namespace System.IO (che definisce FileInfo).

Sebbene, dal mio punto di vista, non è buona cosa utilizzare l’occorrenza o meno di un’eccezione per determinare lo “stato” di qualcosa, la soluzione proposta è sicuramente completa e corretta. Mi riservo su eventuali problemi di concorrenza: al momento non riesco a trovarne, ma è meglio sempre mettere le mani avanti su queste cose! ;)

Advanced regular expression

Davvero illuminante, concedetemi il termine, questo post di Karthik Viswanathan apparso in Smashing Magazine.

Sebbene siano ormai diversi anni che utilizzo le espressioni regolari, diverse cose di quest’articolo non le conoscevo.

Consiglio a tutti di leggerlo.

Disinstallale VirtualBox 2.2.0 (Microsoft Windows host)

Per quanti hanno riscontrato il problema di installare, da Microsoft Windows, l’ultima versione di VirtualBox, la 2.2.2, o per quanti non riescono a disinstallare la versione 2.2.0, qui di seguito ho riportato la lista di passi da seguire. Potete trovare le stesse istruzioni da seguire nel forum ufficiale dell’applicativo: questo il link alla relative pagina del forum.

Ecco l’elenco delle operazioni da compiere:

  1. avviare il registry editor premere i tasti [Windows] + [R], digitare regedit e premere il pulsante [OK] oppure il tasto [Invio/Enter];
  2. nel pannello/tab di destra sfogliare fino tanto che non siete giunti al percorso [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\DIFxApp\Components]. A questo punto, all’interno della chiave [Components] dovreste trovare alcune ulteriori sotto-chiavi (GUID);
  3. esportare tutto il contenuto del percorso [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\DIFxApp\Components]. Per compiere quest’operazione basterà cliccare il tasto destro sulla chiave [Components] nel panello/tab di destra (vedere immagine qui di seguito);
    regedit right botton mouse menu
  4. aprire con un editor di testo il file appena salvato al punto precedente;
  5. sostituire tutte le occorrenze della stringa HKEY_CURRENT_USER con HKEY_LOCAL_MACHINE. Salvare le modifiche e chiudere l’editor;
  6. importare il file appena modificato. Basterà fare un doppio click su di esso dall’explorer.

A questo punto è possibili passare alla disinstallazione della versione 2.2.0.

Potrebbe capitarvi, come a me, che alla fine della procedura vi appaia nuovamente un messaggio di errore: nonostante quest’ultimo l’operazione viene portata a termine correttamente.

Tutte le eventuali macchine virtuali che avete creato non saranno cancellate: dopo l’installazione della nuova versione di VirtualBox saranno nuovamente disponibili senza compiere alcuna operazione (di conversione).

Vari modi di iterare su un array in Javascript

Davvero interessate questo post che ho trovato in ajaxian che illustra un gran numero di modi per iterare su un array in javascript.

Davvero molto eleganti alcune soluzione sintattiche che molto si avvicinano alla programmazione funzionale.

Web-page: cambio testo ad intervalli

Spesso, in una web-page, può risultare molto utile alternare diverse scritte di testo in determinate aree: lo scopo, aggiungendo i necessari fogli di stile (CSS) può essere quello di ottenere una sorta di bacheca/display con informazioni che cambiano ad intervalli regolari.

La cosa può essere fatta senza troppa fatica utilizzando, lato client, le dovute funzioni javascript. Ovviamente, se le stringhe da alternare sono contenute nel codice (javascript), si va a perdere “materiale informativo”: in sostanza Google indicizzerà il sito in questione senza “valutare” le stringhe di testo aggiunte “by code” (lato client attraverso javascript).

Requisito: tutte le nostre stringhe che si alterneranno nella parte di visualizzazione dovranno, per forza di cose, essere presenti nel markup della pagina.

Qui di seguito espongo la mia soluzione, o meglio, l’inizio della mia soluzione: tempo permettendo spero di poter ampliare il codice riportato sotto fino ad ottenere una sorta di mini-libreria. Obiettivi finali del progetto:

  • realizzare una soluzione “multi standard” che supporti sia pagine statiche (XHTML) che pagine dinamiche (ASP.NET e PHP);
  • ottenere una soluzione flessibile che permetta di definire il testo in un file XML (per le pagine dinamiche);
  • appoggiarsi alla libreria javascript jQuery.

Ecco la mia soluzione allo stato embrionale.

var current = -1
var max;

function timerEvent()
{
var Div = document.getElementById("bacheca");

if(Div != null)
{
var i;
var count;

if(current < 0)
{
for (i = 0, count = 0; i < Div.childNodes.length; ++i)
{
if(Div.childNodes[i].tagName == "DIV")
{
if(count < 1)
{
showDiv(Div.childNodes[i]);
}
else
{
hideDiv(Div.childNodes[i]);
}

++count;
}
}

current = 0;
max = count;
}
else
{
++current;
if(current >= max)
{
current = 0;
}

for (i = 0, count = 0; i < Div.childNodes.length; ++i)
{
if(Div.childNodes[i].tagName == "DIV")
{
if(count == current)
{
showDiv(Div.childNodes[i]);
}
else
{
hideDiv(Div.childNodes[i]);
}

++count;
}
}
}
setTimeout(timerEvent, 5000);
}
}

function showDiv(obj)
{
obj.style.display = "";
}

function hideDiv(obj)
{
obj.style.display = "none";
}
<div id="bacheca" style="height: 140px;">
<div>Text 0</div>
<div>Text 1</div>
<div>Text 2</div>
<div>...</div>
<div>Text n</div>
</div>

La funzione javascript [timerEvent] va collegata all’evento [onLoad] della pagina. Saranno visualizzate alternativamente ed in successione i vari DIV (contenuti nel DIV con id “bacheca”), quindi avremo: “Text 0”, “Text 1”, “Text 2”, …, “Text n”, “Text 0”, … Ovviamente il DIV “contenitore” va impostato ad un’altezza predefinita se si vogliono evitare ridimensionamenti (e riposizionamenti) ad ogni “cambio testo”.

In questo esmpio, il testo viene cambiato ogni 5 secondi (vedere linea 60 di codice javascript).

C#’s const vs. readonly

È da un po’ che mi chiedevo quale fosse la differenza tra le due keyword c# const e readonly. Ho trovato un interessante post di Patrick Steele che spiega sinteticamente ed esaustivamente le peculiarità di queste due parole riservate.

Qui di seguito ne riporto la traduzione in italiano.

Una variabile definita const:

  • non può essere anche static;
  • il suo valore è determinato in fase di compilazione;
  • può essere inizializzata solo nella sua dichiarazione.

Una variabile definita readonly:

  • può essere anche static;
  • il suo valore è determinato a run-time;
  • può essere inizializzata sia nella sua dichiarazione che dal costruttore della classe.

Più che evidente che le due keyword non sono proprio così intercambiabili.

WindowsForms e chiusura dell’applicazione

Della serie “non si finisce mai di imparare”.

L’argomento in questione sono le WindowsForm del framework Microsoft .NET. Il soggetto, nel dettaglio, la funzione Application.Exit.

Ieri ho scoperto che invocare la funzione sopra citata all’interno del costruttore della finestra non porta ai risultati per cui la funzione è stata realizzata. A pensarci un attimo la cosa è anche ovvia, ma al momento di scrivere il codice, quasi mai affiorano alla mente gli eventuali “back side effects”.

Qui di seguito il codice originale.

using System;
using System.Windows.Forms;

namespace test
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();

try
{
// ...
}
catch(Exception)
{
Application.Exit();
}
}
}
}

Come aggirare la cosa? Abbastanza semplice, e direi anche, molto spesso la via è facilmente percorribile: basta spostare il nostro codice “incriminato” nella funzione “allacciata” all’evento load della form stesa. All’interno di questo evento il metodo exit funziona correttamente in quanto, una volta che il costruttore della classe form ha terminato, la coda dei messaggi è attiva e, finalmente, può processare il messaggio generato dalla exit.

Qui di seguito il codice aggiornato.

using System;
using System.Windows.Forms;

namespace test
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
}

private void FormMain_Load(object sender, EventArgs e)
{
try
{
// ...
}
catch(Exception)
{
Application.Exit();
}
}
}

Asynchronous Method Invocation

Ho appena scovato in The Code Project un articolo veramente ben fatto che, in poche parole, illustra come invocare in modo asincrono un delegate.
L’articolo è veramente ben fatto e, tra le altre cose, mette bene in evidenza quali sono i limiti del sistema descritto.
Potete trovare l’articolo a questo link.

Libro: “patterns & practices Application Architecture Guide 2.0″

Segnalo con piacere la possibilità di scaricare gratuitamente alla seguente pagina, il libro “patterns & practices Application Architecture Guide 2.0”. Si tratta di un “vecchio” libro (se non sbaglio la prima versione risale al 2001) che è stato riadattato e rivisto per adeguarsi alle novità apportate dal Microsoft .Net framework.
Non l’ho ancora letto, ma mi sono imposto di farlo a breve! ;)

…ancora sulla classe Process (System.Diagnostics)

Della serie: quando ci si aspetta che le cose funzionino in ben altro modo!

In sostanza, quando lanciamo dalla nostra applicazione .Net un altro processo tramite la classe Process, possiamo benissimo “schematizzare” il funzionamento come un thread che controlla l’andamento del programma concorrente.

Consideriamo il seguente codice allora.

OtherProcess = new Process();

OtherProcess.StartInfo.FileName = "OtherProcess.exe";
OtherProcess.StartInfo.Arguments = "/someParameters";
OtherProcess.Exited += delegate(object sender, EventArgs e) { otherProcessTerminated(); };
OtherProcess.EnableRaisingEvents = true;

OtherProcess.Start();

Nella situazione sopra proposta, una volta che l’applicazione OtherProcess.exe termina verrà lanciato l’evento Exited che porterà all’esecuzione del relativo delegate e, per finire, alla chiamata della funzione otherProcessTerminated.

E fin qui nulla da obbiettare. La domanda è: in che modo viene “gestito” l’evento? Mi sarei aspettato che venisse messo in coda e processato ordinatamente (nel Main thread) dopo quanti lo precedevano. In realtà ciò non avviene, ma è lo stesso thread creato appositamente dalla classe Process che si prende in carico anche l’esecuzione del delegate, generando delle “race condition” che portano a side effects quasi mai considerati in fase di sviluppo.

Come poter aggirare la cosa, che risulta assai sgradevole se si è fatto di tutto al fine di evitare problemi di concorrenza? Molto semplice: prima di invocare il metodo Start, aggiungete la seguente linea di codice.

OtherProcess.SynchronizingObject = this;

Ovviamente il puntatore this dovrà far riferimento ad un controllo WindowsForm in grado di “gestire” i messaggi (per dirlo con terminologia Win32).

Qui la documentazione relativa alla proprietà SynchronizingObject della classe System.Diagnostics.Process.

P.s.: per questo post si ringrazia il Sig. Botsutoshi per il suo indispensabile contributo.