Inviare notifiche Prowl utilizzando CURL

27 08 2009

Prowl e’ un progetto interessante: un sistema di notifiche push per iPhone che si interfaccia col piu’ famoso sistema di notifica Growl (per Mac e Windows).

Prowl fornisce anche una serie di API, utili per mandare notifiche Push agli iPhone registrati. Viene fornito anche uno script di esempio in Perl.

Io preferisco una soluzione piu’ ’scarna’ ma immediata: utilizzando CURL e’ possibili inviare una notifica con una sola riga di codice:


curl -X POST -d"apikey=APIKEY" -d"application=Test" -d"event=Messaggio" -d"message=Test" https://prowl.weks.net/publicapi/add

sostituite naturalmente la parola APIKEY con la vostra chiave API, reperibile a Questo Indirizzo.





Dreamhost: personalizzare php.ini

22 03 2009

Suggerimento rapidorapido pescato dal forum di supporto di Dreamhost.

Nel caso si abbia la necessità di personalizzare il PHP.INI, ad esempio (come è servito a me) per aumentare il timeout di uno script, la procedura è questa:

  1. Se non presente, creare una directory ‘cgi-bin’ all’interno della directory che ospita il dominio (mkdir ~/domain.com/cgi-bin/)
  2. Nella home del proprio utente, creare un file (php_update.sh) contenente il seguente script:
    #/bin/sh
    
    CGIFILE="$HOME/dominio.com/cgi-bin/php.cgi"
    INIFILE="$HOME/dominio.com/cgi-bin/php.ini"
    
    cp /usr/local/bin/php "$CGIFILE"
    cp /etc/php/php.ini "$INIFILE"
    
    perl -p -i -e '
    s/.*post_max_size.*/post_max_size = 100M/;
    s/.*upload_max_filesize.*/upload_max_filesize = 100M/;
    s/.*max_execution_time.*/max_execution_time = 600/;
    s/.*memory_limit.*/memory_limit = 90M/;
    ' "$INIFILE"
    
  3. Renderlo eseguibile (chmod +x php_update.sh) ed eseguirlo (./php_update.sh).
  4. Aggiornare il file .htaccess nella root del sito (o crearlo se non presente) e aggiungere la riga seguente: “AddHandler php-cgi .php” (senza i “)
  5. Aggiungere lo script al crontab in modo da farlo eseguire a scadenza settimanale, in modo da mantenere la propria copia locale di php.ini aggiornata con quello principale.




Migrare un DataBase da MySQL a MS SQLServer 2000

3 02 2009

La domanda su come fare mi è stata posta oggi in ufficio, e la risposta non posso che prenderla dalla pagina dedicata su TechNet:

Di seguito viene riportata una procedura per configurare Microsoft SQL Server al fine di migrare il database MySQL.

1. Installare il supporto MyODBC, disponibile all’indirizzo http://www.mysql.com/

2. Durante l’installazione viene visualizzata la finestra di dialogo seguente:


      Configurare le impostazioni ODBC utilizzando le informazioni seguenti:
      Windows DSN name: test
      Description: Database di prova
      MySQL Database: test
      Server: seawolf.microsoft.com
      User: cgunn
      Password: my_password
      Port: 3306
      Nel caso delle impostazioni precedenti, il nome specificato nel campo “Windows DSN name” deve essere univoco nel computer che esegue la connessione, l’impostazione relativa al server può essere un nome di dominio completo (assicurarsi che sia disponibile un sistema di risoluzione dei nomi, per esempio tramite DNS) oppure un indirizzo IP.

    3. Quindi eseguire l’Importazione/Esportazione guidata DTS. Dal gruppo di programmi Microsoft SQL Server selezionare Importazione ed esportazione dati. Verrà visualizzata la finestra di dialogo seguente.

        Fare clic su Avanti, quindi proseguire con il passaggio successivo.

      4. Fornire le informazioni necessarie sull’origine dei dati: queste informazioni devono essere MySQL come origine dei dati ODBC e test come DSN del sistema. Quindi, fornire le credenziali di accesso, il nome utente e la password mostrati nella successiva finestra di dialogo, infine fare clic su Avanti.

        5. Fornire i dettagli della connessione di destinazione, come mostrato nella finestra di dialogo seguente, quindi fare clic su Avanti.

          6. La finestra di dialogo Copia tabella o query consente di selezionare gli oggetti del database dall’origine, in questo caso MySQL. Selezionare Copia tabelle e viste dal database di origine. È opportuno rammentare che MySQL non supporta le viste pertanto, selezionando questa opzione, verranno copiati solo gli oggetti tabella, come mostrato di seguito. Fare clic su Avanti per continuare.

            7. Verrà visualizzata la finestra di dialogo Seleziona tabelle e viste di origine, in cui è possibile selezionare le tabelle di origine e quelle di destinazione.

              8. Fare clic sul pulsante con i trattini per eseguire la trasformazione dei dati, come mostrato nella finestra di dialogo seguente Mapping e trasformazioni di colonna.

                  In questa finestra di dialogo vengono abbinati i tipi di dati di origine e di destinazione e vengono selezionati i campi di dati Null. Al termine, fare clic su OK.
                  Verrà visualizzata la finestra di dialogo Salva, pianifica e replica pacchetto, che consente di pianificare la migrazione fuori degli orari di punta e di salvare il pacchetto DTS in percorsi e formati diversi.

                9. La finestra di dialogo Salva pacchetto DTS fornisce due tipi di password per il pacchetto DTS. La prima password è quella del proprietario e consente di proteggere tutte le informazioni sugli utenti e sulle password incluse nel pacchetto, mentre la password dell’utente consente di eseguire il pacchetto e impedisce qualsiasi esecuzione non autorizzata, come mostrato di seguito. Fare clic su Avanti per continuare.

                  10. Infine, la finestra di dialogo Completamento della Importazione/Esportazione guidata DTS riepiloga le opzioni selezionate nella procedura guidata.

                      Fare clic su Fine per iniziare la migrazione dei dati.

                    11. La finestra di dialogo Esecuzione pacchetto visualizza lo stato di ogni attività mentre viene eseguita. Un segno di spunta verde indica il completamento di un’attività. Se l’esecuzione di un’attività non riesce e l’errore interrompe il processo, verrà visualizzata una finestra che riporta le informazioni sull’errore.





                      .NET: effettuare query SQL su DataTable in memoria

                      2 02 2009

                      Scenario: realizzazione di un sistema di ‘aggregazione dati’ in grado di caricare in memoria dati da fonti diverse (Db SQLServer/Oracle/MySQL, files Excel, Db Access) ed utilizzarli per realizzare semplici ‘reports’.

                      Riempire di dati le DataTables e’ cosa da poco, aggregarle all’interno di un DataSet e’ ancora piu’ semplice, comincia a saltar fuori qualche difficolta’ quando arriva il momento di permettere agli utenti di  ‘interrogare’ il DataSet utilizzando una sintassi ‘SQL-Like’: soluzione ottima per l’utente finale con una minima infarinatura di Structured Query Language, difficile da realizzare senza scomodare LINQ e il Framework 3.5.

                      Per fortuna ci viene incontro Emmet Gray, ottimo programmatore che ha realizzato una classe che implementa un engine SQL minimale utilizzabile sui DataSet: SQL_Engine.

                      L’utilizzo di tale classe e’ straordinariamente semplice: una volta riempito il nostro DataSet con le tabelle contenenti i dati da interrogare, basta instanziare l’oggetto passando al constructor il dataset

                      
                      Dim sc As New SQL_Engine.SelectCommand(ds)
                      

                      e richiamare il metodo ‘Execute’ (passando come parametro la query da eseguire) , che si occupera di restituire una DataTable contenente i risultati

                      
                      Dim dt As DataTable = sc.Execute(query)
                      




                      iUI, framework per interfacce web compatibili con iPhone

                      8 01 2009

                      Leggo questa richiesta nei commenti di un post dedicato a BloggerSync:

                      [...] realizzare una pagine navigabile con iphone, è solo un probelma di dimensioni e css.. ??
                      Puoi indicarmi qualche risorsa in merito per imparare qualcosa ? [...]

                      Ultimamente sto realizzando delle semplici Web Applications per iPhone e sto utilizzando iUI, un framework che, con un uso intensivo di Javascript punta alla realizzazione di applicazioni web con look&feel assolutamente simile a quello delle applicazioni ’stand-alone’.

                      L’utilizzo e’ estremamente semplice, la documentazione e gli esempi presenti aiutano non poco: buon divertimento!

                      http://code.google.com/p/iui/





                      PHP Snippets: copiare ricorsivamente una directory

                      15 12 2008
                      
                      function full_copy( $source, $target )
                          {
                              if ( is_dir( $source ) )
                              {
                                  @mkdir( $target );
                      
                                  $d = dir( $source );
                      
                                  while ( FALSE !== ( $entry = $d->read() ) )
                                  {
                                      if ( $entry == '.' || $entry == '..' )
                                      {
                                          continue;
                                      }
                      
                                      $Entry = $source . '/' . $entry;           
                                      if ( is_dir( $Entry ) )
                                      {
                                          full_copy( $Entry, $target . '/' . $entry );
                                          continue;
                                      }
                                      copy( $Entry, $target . '/' . $entry );
                                  }
                      
                                  $d->close();
                              }else
                              {
                                  copy( $source, $target );
                              }
                          }
                      




                      PHP Snippets: ridimensionare immagini jpeg ed estrarne il thumbnail exif

                      8 12 2008

                      FileName: thumb.php

                      
                      < ?php 
                      
                      $im      = $_GET['im'];
                      $maxsize = $_GET['maxsize'];
                      
                      if ($maxsize == '') {
                          $image = exif_thumbnail($im, $width, $height, $type);
                      
                          if ($image) {
                              header('Content-type: ' .image_type_to_mime_type($type));
                              print $image;
                          }
                          else {
                              print 'No thumbnail available';
                          }    
                      
                      } else {
                      
                      $filename = $im;
                      
                      $width  = $maxsize;
                      $height = $maxsize;
                      
                      header('Content-type: image/jpeg');
                      
                      list($width_orig, $height_orig) = getimagesize($filename);
                      
                      if ($width && ($width_orig < $height_orig)) {
                          $width = ($height / $height_orig) * $width_orig;
                      } else {
                          $height = ($width / $width_orig) * $height_orig;
                      }
                      
                      $image_p = imagecreatetruecolor($width, $height);
                      $image   = imagecreatefromjpeg($filename);
                      imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
                      
                      imagejpeg($image_p);
                      imagedestroy($image);
                      imageDestroy($image_p);
                      }
                      ?>
                      

                      utilizzo:

                      thumb.php?im=uploads/immagine.jpg&maxsize=100

                      ridimensiona l’immagine con il lato maggiore non superiore a 100 pixels.

                      Se non viene specificata la dimensione massima, viene estratto (se disponibile) il thumbnail Exif contenuto nel file Jpeg (metodo molto più veloce nel caso di immagini di un certo peso).





                      PHP Snippets: calcolare l’occupazione su disco di una directory

                      2 12 2008
                      
                      function diskspace($dir)
                      {
                         $s = stat($dir);
                         $space = $s["size"];
                         if (is_dir($dir))
                         {
                           $dh = opendir($dir);
                           while (($file = readdir($dh)) !== false)
                             if ($file != "." and $file != "..")
                               $space += dskspace($dir."/".$file);
                           closedir($dh);
                         }
                         return $space;
                      }
                      

                      restituisce le dimensioni in bytes della directory specificata, comprese eventuali sotto-directory.





                      BloggerSync, layout compatibile con iPhone

                      14 11 2008

                      bloggersyncVisto l’interesse nato attorno a BloggerSync (le statistiche degli accessi mi hanno stupito), ho deciso di rilasciare un piccolo aggiornamento, correggendo un paio di bugs e adattando il (semplicissimo) layout dell’applicazione alla visualizzazione con iPhone.

                      Essendo già sviluppato in maniera ‘verticale’, l’unica modifica necessaria per renderlo fruibile comodamente col melafonino consiste nel ‘forzare’ il livello di zoom di default, in modo da centrare la webapp nello schermo senza successivi ridimensionamenti a colpi di dita, utilizzando il metatag ‘viewport’:

                      
                      <meta name="viewport" content="width=480" />
                      

                      inoltre è una buona pratica il realizzare un foglio di stile dedicato a Safari Mobile (adattando ad esempio i fonts allo schermo di dimensioni ridotte) includendolo in questo modo:

                      	<link media="only screen and (max-device-width: 480px)"  href="css_iphone.css" type="text/css" rel="stylesheet" />
                      

                      photoCosì facendo tutti i device con uno schermo di dimensione superiore ai 480 pixel (iPhone in modalità ‘landscape’) ignoreranno il caricamento del CSS dedicato all’iPhone.





                      FriendsOnGmaps e lo sviluppo di applicazioni su Facebook

                      7 11 2008

                      facebooklogoL’interesse per Facebook da parte dei media negli ultimi tempi e’ cresciuto in maniera esponenziale: il mio account, registrato distrattamente ormai piu’ di un anno orsono ultimamente ha avuto un ‘boom’ di richieste di amicizie (e ovviamente di attivita’).

                      Visto il grande movimento intorno alla piattaforma di socialnetworking, mi e’ sembrato naturale iniziare a dare uno sguardo alle API fornite e alla sviluppo di applicazioni che si appoggino su di essa.

                      Il primo passo da compiere e’ visitare il sito ufficiale per gli sviluppatori FaceBook,  http://developers.facebook.com/, dal quale e’ possibile sia scaricare le ‘client libraries‘ (in PHP, ma sono state gia’ realizzate conversioni in molti altri linguaggi), sia aggiungere al proprio profilo il tool Facebook Developer App, indispensabile per la creazione di (appunto) nuove applicazioni.

                      E’ disponibile anche un indispensabile wiki (http://wiki.developers.facebook.com/index.php/Main_Page), contenente tutta la documentazione sulla piattaforma e le API e una comodissima Getting started guide, e un forum (http://forum.developers.facebook.com/).

                      La struttura di una applicazione Facebook e’ particolare: non viene infatti ospitata dai server di FaceBook, ma si interfaccia con essi tramite un sistema di callback:

                      facebook-app-servers

                      da qui deriva una metodologia di sviluppo che utilizza l’accesso a FaceBook solamente per ricevere e inviare informazioni, mentre il ‘peso computazionale’  e’ esclusivamente a carico dell’hosting che ospita l’applicazione.
                      Vi rimando quindi all’ottimo Tutorial  presente sul sito ufficiale.

                      fogm_iphoneLa mia creatura prende il titolo di FriendsOnGmaps, e non fa altro che localizzare su una mappa (realizzata con Google Maps) gli amici collegati al proprio profilo (prendendo come punto di riferimento i dati inseriti dall’utente riguardo la citta’ di residenza).

                      Per velocizzare lo sviluppo ho affidato la compilazione del codice Js di GoogleMaps a una libreria PHP pre-esistente, Phoogle Maps.

                      E sembra funzionare correttamente anche sull’iPhone!





                      VB.NET: inserire un post su BlogSpot utilizzando le Google Blogger Data API

                      20 10 2008

                      Un breve frammento di codice che sto utilizzando per la realizzazione di un tool di ‘blog-sync’ (che rilascero’ a breve).

                      Utilizzando le Google Blogger Data API e’ possibile collegarsi alla piattaforma di blogging di Google e aggiungere un post a un blog.

                      Per prima cosa e’ necessario scaricare le Google Data API e, una volta scompattato l’archivio, e’ necessario aggiungere nel progetto VB le reference ai file presenti nella directory ‘Redist’.

                      A questo punto, realizziamo una breve sub in VB:

                      
                      Imports Google.GData.Extensions
                      Imports Google.GData.GoogleBase
                      Imports Google.GData.Client
                      Imports System.Net
                      Imports System.Xml
                      Imports System.IO
                      Imports System.Text.RegularExpressions
                      
                        Private Sub PostToBlogger(ByVal titolo As String, ByVal contenuto As String,  ByVal blogid As String)
                              Dim service As Service = New Service("blogger", "BlogName")
                              service.Credentials = New GDataCredentials("BLOGGER USERNAME", "BLOGGER PASSWORD")
                              Dim factory As GDataGAuthRequestFactory = service.RequestFactory()
                              factory.AccountType = "GOOGLE"
                      
                              Dim newPost As New AtomEntry()
                              newPost.Title.Text = titolo
                              newPost.Content = New AtomContent()
                              newPost.Content.Content =  contenuto
                              TextBox1.Text = TextBox1.Text & "--- " & newPost.Title.Text
                              newPost.Updated = Date.Now
                      
                              Dim query As New FeedQuery()
                              query.Uri = New Uri("http://www.blogger.com/feeds/" + blogid + "/posts/default")
                      
                              ' Verifico se il post e' gia' presente. Se si esco.
                              Dim feed As AtomFeed = service.Query(query)
                              For Each entry As AtomEntry In feed.Entries
                                  If Trim(entry.Title.Text).ToUpper = Trim(newPost.Title.Text).ToUpper Then
                                      TextBox1.Text = TextBox1.Text & " -- NOTIZIA GIA' PRESENTE --" & vbCrLf
                                      Exit Sub
                                  End If
                              Next
                      
                              Dim blogFeedUri As New Uri("http://www.blogger.com/feeds/" + blogid + "/posts/default")
                              Try
                                  Dim createdEntry As AtomEntry = service.Insert(blogFeedUri, newPost)
                                  TextBox1.Text = TextBox1.Text & " -- PUBBLICATO --" & vbCrLf
                              Catch ex As Exception
                                  TextBox1.Text = TextBox1.Text & " -- ERRORE: " & vbCrLf & ex.InnerException.Message & vbCrLf
                              End Try
                          End Sub
                      

                       

                      La sub si discosta da quanto presentato nella documentazione ufficiale solo per la possibilita’ di verificare che il post sia stato gia’ inserito (proprio per la necessita’ di utilizzare in un tool di sincronizzazione di blogs) prendendo come ‘dato univoco’ il titolo dello stesso.

                      Probabilmente il metodo di identificazione dei duplicati e’ migliorabile, ci lavorero’! (naturalmente ogni suggertimento e’ ben accetto!).





                      VB.NET: rilevare un server di Quake3 su una rete locale

                      10 10 2008

                      Classica applicazione inutile ma divertente da sviluppare :-)

                      Qualche giorno fa ho iniziato a chiedermi come il mio amato Quake3 Arena lavorasse per ricercare i server per il gioco in multiplayer sulla rete locale.

                      Dopo una breve ricerca su Google mi sono imbattuto in questo articolo che spiega a grandi linee come funziona il protocollo utilizzato dal motore di Q3A: tutto basato su UDP (scelta obbligata, per la maggiore velocità) e a dire il vero abbastanza semplice e lineare.

                      To query a server is very simple. Send a connectionless (UDP) packet with 4 OOB header bytes (0xff) and the text string getstatus. There are many sites which contain a thorough description of this so I won’t go into details.

                      Quindi, per rilevare se su una macchina remota sia attivo un server è sufficiente forgiare un pacchetto UDP come descritto sopra, inviarlo sulla porta 27960 e attendere una eventuale risposta (non all’infinito, essendo UDP un protocollo ‘connection-less’).

                      Con queste informazioni la realizzazione di una semplice funzione in VB.NET è cosa da poco:

                      
                      Imports System.Net
                      
                      Public Function CheckServer(ByVal hostaddress As String)
                              Dim _UdpClient As New System.Net.Sockets.UdpClient
                      
                              Dim client As New Sockets.Socket(Sockets.AddressFamily.InterNetwork, Sockets.SocketType.Dgram, Sockets.ProtocolType.Udp)
                      
                              client.ReceiveTimeout = 5
                              client.Connect(IPAddress.Parse(hostaddress), 27960)
                      
                              Dim bytCommand As Byte() = System.Text.Encoding.ASCII.GetBytes("xxxxxgetstatus")
                              bytCommand(0) = Byte.Parse("255")
                              bytCommand(1) = Byte.Parse("255")
                              bytCommand(2) = Byte.Parse("255")
                              bytCommand(3) = Byte.Parse("255")
                              bytCommand(4) = Byte.Parse("02")
                      
                              Dim remoteEndPoint As New IPEndPoint(IPAddress.Any, 0)
                      
                              Dim pret As String = client.Send(bytCommand, socketFlags:=Sockets.SocketFlags.None)
                              Dim bufferRec(65000) As Byte
                              Try
                                  client.Receive(bufferRec)
                                  Return System.Text.Encoding.ASCII.GetString(bufferRec)
                      
                              Catch ex As Exception
                                  Return ""
                              End Try
                      
                          End Function
                      

                      Da notare che ho settato manualmente il timeout della connessione e ‘trappato’ l’errore di connessione, verificando in questo modo se il server sia in funzione o meno.

                      La funzione mi restituisce una stringa contenente (qualora sia attivo un server sulla macchina esaminata) una serie di informazioni sulla partita in corso; nel caso la connessione vada in timeout, restituisce una stringa vuota.

                      Ora so verificare se su un determinato sistema stia girando Q3A in modalità multiplayer, il passo successivo è ripetere questa procedura per tutti quelli presenti sulla mia rete locale.

                      Per farlo questo mi sono affidato a una soluzione ’sporca’ ma funzionale: utilizzo il comando ‘net view’ di windows, ne analizzo il risultato ottenendo un elenco di indirizzi:

                      
                      Public Function GetIpAddresses()
                              Dim addresses As New ArrayList
                              Dim MyAdd As String = Dns.GetHostByName(Dns.GetHostName()).AddressList(0).ToString
                              Dim psi As System.Diagnostics.ProcessStartInfo = New System.Diagnostics.ProcessStartInfo()
                              psi.FileName = ("C:\WINDOWS\System32\cmd.exe")
                              psi.Arguments = "/c net view > lista.txt"
                              psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden
                              Application.DoEvents()
                              System.Diagnostics.Process.Start(psi)
                              Dim sr As System.IO.StreamReader = Nothing
                              Dim run As Boolean = False
                              While run = False
                                  Application.DoEvents()
                                  Try
                                      System.Threading.Thread.Sleep(1000)
                                      sr = New System.IO.StreamReader(Application.StartupPath & "\lista.txt")
                                      run = True
                      
                                  Catch ex As Exception
                                      run = False
                                  End Try
                              End While
                      
                              While sr.ReadLine().StartsWith("--")  True
                                  Application.DoEvents()
                              End While
                      
                              Dim str As String = ""
                              Dim comp(64) As String
                              Dim i As Integer = 0
                      
                              While str.StartsWith("The")  True
                                  Application.DoEvents()
                                  str = sr.ReadLine
                                  comp(i) = str.Split(Char.Parse(" "))(0)
                                  comp(i) = comp(i).Substring(2, comp(i).Length - 2)
                                  If comp(i) = "e" Then
                                      Application.DoEvents()
                                      comp(i) = Nothing
                                  End If
                                  i = i + 1
                              End While
                              sr.Close()
                              sr = Nothing
                              For Each s As String In comp
                                  If s  Nothing Then
                                      If s.ToUpper  Dns.GetHostName.ToUpper Then
                                         addresses.Add(Dns.GetHostByName(s).AddressList(0).ToString)
                                      End If
                                  End If
                              Next
                              Return addresses
                          End Function
                      

                      a questo punto non mi resta che sottoporre l’array di indirizzi restituito dalla funzione GetIpAddresses a CheckServer e, se viene rilevato un server, leggere i dati restituiti e formattarli adeguatamente:

                      
                       Dim lista As ArrayList = GetIpAddresses()        
                      
                              For Each riga As String In lista.ToArray
                                  Dim server As String = CheckServer(riga)
                                  If server  "" Then
                                      Dim ServerName As String = server.Split("\")(Array.IndexOf(server.Split("\"), "sv_hostname") + 1)
                                      Dim MapName As String = server.Split("\")(Array.IndexOf(server.Split("\"), "mapname") + 1)
                                      Dim FragLimit As String = server.Split("\")(Array.IndexOf(server.Split("\"), "fraglimit") + 1)
                                      Dim TimeLimit As String = server.Split("\")(Array.IndexOf(server.Split("\"), "timelimit") + 1)
                                      Dim Version As String = server.Split("\")(Array.IndexOf(server.Split("\"), "version") + 1)
                      
                                      risultato = risultato & "--- Trovato Server ---" & vbCrLf
                                      risultato = risultato & "Ip Address:" & riga & vbCrLf
                                      risultato = risultato & "Server Name: " & ServerName & vbCrLf
                                      risultato = risultato & "Mappa: " & MapName & vbCrLf
                                      risultato = risultato & "FragLimit: " & FragLimit & vbCrLf
                                      risultato = risultato & "TimeLimit: " & TimeLimit & FragLimit & vbCrLf
                                      risultato = risultato & "Versione: " & Version & FragLimit & vbCrLf
                      
                                      TextBox1.Text =  TextBox1.Text  & risultato
                                  End If
                                  Application.DoEvents()
                              Next   
                          End Sub
                      

                      Ho completato il tutto con il codice necessario a ridurre l’applicazione nella system tray (facendo ripetere la procedura di scan ogni 5 secondi) e a far riapparire un form qualora la ricerca fornisca esito positivo.

                      Il sorgente completo è scaricabile da QUI.

                      (e sperate che non finisca mai tra le mani del vostro capoufficio!) :-D





                      .NET: gestione manuale della Garbage Collection

                      26 09 2008

                      Per chi arriva da linguaggi di ‘basso livello’, il Garbage Collector è una scoperta allo stesso tempo meravigliosa e sconvolgente, che (cito Wikipedia) porta ad un notevole cambio nello stile di programmazione dei linguaggi che lo implementano. Infatti non è più possibile richiedere esplicitamente di liberare la memoria utilizzata da un oggetto, ovvero terminare tale oggetto in modo deterministico, ma si lascia che il sistema esegua questa operazione automaticamente, nel momento in cui lo riterrà più opportuno per migliorare le prestazioni complessive (finalizzazione non deterministica).

                      Non quindi possibile, con un linguaggio ad ‘alto livello’, finalizzare un oggetto singolarmente ma è necessario porlo nella ‘raccolta di rifiuti’ e attendere che il sistema/compilatore si occupi di fare pulizia.

                      Può tuttavia essere necessario ‘forzare’ questa procedura di pulizia, anzichè lasciarla gestire automaticamente: un esempio potrebbe essere l’utilizzo di oggetti che incapsulano molte ‘risorse non gestite’ (ad esempio risorse del sistema operativo, quali file, finestre o connessioni di rete), quando l’applicazione non necessità più dell’oggetto, è certo che le risorse da esso utilizzate non saranno più necessarie. Ai fini delle prestazioni, può essere opportuno rilasciarle tutte insieme.

                      Per eseguire il ‘collect’ della GC, il Framework .NET fornisce, nella classe GC (Garbage Collection) il metodo GC.Collect, che (da notare bene) prima di eseguire una procedura di Garbage Collection sospende tutti i thread in esecuzione.

                      Tale funzionamento comporta infatti una riduzione delle prestazioni che può diventare problematica se si chiama GC.Collect più spesso del necessario. È opportuno non inserire codice che richiama GC.Collect in quei punti del programma a cui l’utente accede frequentemente. Tale pratica potrebbe infatti impedire al motore di ottimizzazione di determinare il momento migliore in cui eseguire una procedura di Garbage Collection, facendo decadere in maniera drastica le prestazioni dell’applicazione.





                      Google e SEO: gli URL dinamici valgono quanto quelli statici?

                      24 09 2008

                      E si, è proprio quello che si dice in questo post sull’Official Google Webmaster Central Blog.

                      Dopo tanto lavoro sul rewriting degli url, convinti che far credere al googlebot che una pagina dinamica con parametri in realtà fosse una normalissima pagina statica, viene naturale stupirsi leggendo che:

                      One recommendation is to avoid reformatting a dynamic URL to make it look static. It’s always advisable to use static content with static URLs as much as possible, but in cases where you decide to use dynamic content, you should give us the possibility to analyze your URL structure and not remove information by hiding parameters and making them look static.

                      Ma non posso esimermi dal citare un commento in questo post su The Marketer, dedicato proprio a questo argomento:

                      A leggere a fondo l’articolo ciò che ne esce è che: piuttosto che fare male il rewriting è preferibile lasciare gli url dall’aspetto dinamico (purchè non abbiano errori madornali come le la presenza degli id di sessione)

                      Official Google Webmaster Central Blog: Dynamic URLs vs. static URLs





                      WordPress, plugin “Accade Oggi”

                      17 09 2008

                      Di recente mi e’ capitato di dover sviluppare alcune funzionalita’ aggiuntive per il sito di un cliente.

                      Essendo basato su wordpress ho realizzato un gruppo di widgets, con l’idea che alcune delle nuove features potevano essere facilmente riutilizzate.

                      “Accade oggi” e’ uno degli ultimi sviluppati.

                      Quando si utilizza wordpress per gestire un sito di news nel quale vengono pubblicizzati anche eventi che si verificheranno successivamente alla pubblicazione dell’articolo (nel mio caso aperture di mostre, aste, convegni) ci si puo’ trovare davanti alla necessita’ di dare risalto a una vecchia news proprio nel giorno di apertura dell’evento.

                      Una volta aggiunto e attivato il pugin viene aggiunto un widget nel set di base di wordpress che, se aggiunto nella sidebar del tema, visualizza la lista degli eventi che si verificano nella giornata corrente.

                      L’aggiunta della ‘data di apertura’ si effettua assegnando al post il campo personalizzato “inizio_evento” contenente la data (appunto) di inizio dell’evento, nel formato dd/mm/yyyy.

                      Il plugin e’ rilasciato (ovviamente) sotto licenza GPL, scaricabile da QUI.

                      Spero sia utile! :-)