Leopard su iBook G4: Safari 3.2.1 e CPU al 100%?

22 12 2008

Ho installato Leopard sul mio iBook G4 gia’ da qualche tempo, senza riscontrare nessun problema.

Tuttavia, dopo l’ultimo aggiornamento di Safari (che ha portato il browser alla versione 3.2.1) ho iniziato a notare un fastidioso comportamento: dopo qualche minuto di utilizzo, il browser di mamma Apple iniziava a impegnare il processore in maniera anomala, bloccando nel contempo anche la navigazione. L’unico modo per risolvere il blocco si riduceva a una ‘chiusura forzata’ e al restart del browser.

Dopo alcune prove, sono riuscito a restringere la ricerca del problema alle nuove funzionalita’ introdotte in questa ultima versione, e in particolare al ‘filtro anti-phishing’ (nella tab ‘Sicurezza’ delle preferenze di Safari):

immagine-1

Disabilitando questa utile funzionalita’ (che ho potuto verificare dare problemi anche su altre macchine con processore PowerPC, mentre funziona senza alcun intoppo sul mio MacMini Intel) Safari ricomincia a funzionare senza blocchi.

In attesa del prossimo aggiornamento di Safari…:-)





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.





Film-gratis.IT: film in streaming gratuiti finalmente in modo legale?

26 11 2008

Film-gratis e’ un portale realizzato dalla nota casa editrice Edizioni Master, che permette agli utenti registrati la visione di film in streaming, in maniera completamente legale.

Cito il sito:

Film-Gratis è un’iniziativa di Edizioni Master nata per consentire la fruizione gratuita e legale dei titoli cinematografici provenienti dalle principali etichette di settore.

Al contrario di ciò che si scarica da molte reti di file sharing, infatti, i film contenuti in Film-Gratis non infrangono la Normativa corrente sul diritto d’autore.
Ognuno di essi, infatti, è frutto di accordi con la major che lo produce e la sua riproduzione e trasmissione è autorizzata dalla SIAE.

I vantaggi sono molteplici.

Innanzitutto, non si hanno problemi con la Legge
È tutto assolutamente legale e non si corre il rischio di incappare in pesanti sanzioni.

 

Ancora, si evitano problemi di sicurezza, malware e phishing, tipici di molti siti non autorizzati il cui fine è solo quello di raggirare l’utente senza offrire alcunchè.

Dulcis in fundo, è tutto gratuito.
Accomodati pure in sala, il biglietto lo paghiamo noi!

Veramente una bella iniziativa, speriamo duri! Una sola (grande) pecca: tutti i contenuti sono protetti da DRM e visualizzabili solo su Windows Media Player, escludendo quindi tutti i sistemi non Microsoft.





The 7 Deadly Linux Commands

26 11 2008

Per la serie “Come far del male alla propria LinuxBox”.
Simpatici i 7 ‘comandi mortali’, ancora piu’ interessanti i numerosi commenti al post: TECH SOURCE FROM BOHOL: The 7 Deadly Linux Commands





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.





Windows non si avvia dopo la rimozione di user32.dll da parte di AVG

10 11 2008

Dando uno sguardo alle keyword con le quali il mio blog viene raggiunto, mi accorgo che in parecchi sono rimasti vittime di un ‘falso positivo’ dell’antivirus AVG che, dopo un aggiornamento rilasciato nella notte tra sabato e domenica, riconosceva il file User32.dll (su sistemi non aggiornati all’ultimissimo ‘patch level’) come infetto da un trojan e lo rimuoveva senza troppi scrupoli.

La mancanza di tale file, indispensabile a windows, non permetteva successivamente di avviare il PC.

La soluzione è semplice, e la trovo su SpippolAzione:

[...] potete ripristinare il file avviando con il cd di installazione di Windows XP, o quello di Vista ed avviare la console di ripristino, oppure potte usare una distribuzione linux sufficente recente da riuscire a scrivere sui dischi NTFS, una Ubuntu 8.04 o 8.10 o simili andranno benissimo.

Una volta avviata la console di ripristino o la distribuzione linux troverete una copia del file cancellato perfettamente utilizzabile in c:\windows\system32\DLLcache, dovete solo rimetterla in c:\windows\system32 e riavviare.

Talvolta (a me è capitato), dopo aver ripristinato il file è possibile trovarsi nuovamente impossibilitati ad avviare il sistema, questa volta con l’errore

“Si è verificato un problema e Windows è stato arrestato per impedire danni al computer. Informazioni tecniche: STOP: c0000135 {Impossibile individuare un componente} Impossibile avviare l’applicazione specificata. Winsrv non è stato trovato. Una nuova installazione dell’applicazione potrebbe risolvere il problema.”

E anche questa volta la soluzione è stata prontamente pubblicata su SpippolAzione:

Questo e’ dovuto al fatto che, non si capisce per quale motivo, il file preso dalla DLLcache non gli andava bene.

Questo c000015 è un vecchio errore che usciva fuori quando si installava il service pack 2 di XP quando nel computer era presente un ben preciso malware, ma non è il nostro caso.

Ho risolto con il solito sistema, rimettendo a posto user32.dll, ma non quella presente nella DLLcache ma quello che ho trovato nella cartella C:\WINDOWS\$NtUninstallKB925902$

ATTENZIONE: potrebbe non andare bene per tutti, dipende dai livelli di service pack e aggiornamenti che avete nel pc, comunque se da prompt dos vi spostate in c:\windows e fate un

dir usr32.dll /s

vedrete dove trovare le varie copie di user32.dll, quindi provate a copiarli uno per uno in c:\windows\system32 e riavviare.





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!





Utilizzare il Rock Band Drum Controller con GarageBand

3 11 2008

Bell’hack! Conosco giusto qualcuno che ha appena acquistato il DrumController…chissà se me lo presterebbe! :-)

(Fausto! Se ci sei batti un colpo!)

via Rock Out in GarageBand with the Rock Band Drum Controller | Mac|Life





Apple Mighty Mouse, risolvere il problema della rotella di scroll

27 10 2008

Pare che in parecchi si siano scontrati con la comodissima rotella di scroll del Mighty Mouse che, dopo qualche mese di uso intenso causa polvere e sporcizia, inizi a ’scrollare a vuoto’.

In giro sulla rete si trovano tutorial che prevedono l’apertura del mouse, o interventi sui forum che suggeriscono di richiederne la sostituzione in garanzia.

Niente di tutto questo: ho scovato questo video che propone un metodo semplice e rapidissimo. Provato di persona, funziona perfettamente!

YouTube – Apple – Mighty Mouse – Scrolling Problem!





BloggerSync, da RSS a post su Blogger in un click!

27 10 2008

Nel precedente articolo spiegavo come utilizzare le Google Blogger Data Api per pubblicare post sulla piattaforma di blogging di google.

Lo studio di tali API aveva come obiettivo la realizzazione di un piccolo tool per la pubblicazione automatica su Blogspot da blogs ospitati su piattaforme differenti: per dirla semplice, “ho un blog su wordpress.com, lo voglio ‘migrare’ su blogspot e magari tenere aggiornata questo ‘mirror’, come fare senza utilizzare plugin aggiuntivi? (che, tra le altre cose, wordpress.com non permette di installare)”.
Ho realizzato quindi una prima bozza di applicazione (in VB.NET) che si occupasse di scorrere un Feed RSS e pubblicare in maniera automatica quanto letto su un blog ospitato su Blogger, tenendo naturalmente conto di quando già pubblicato.

Successivamente ad una prima versione in VB.NET, ho effettuato la conversione in Python, garantendomi la compatibilità con Linux e Mac senza ricorrere all’utilizzo di Mono.
L’idea di trasformare il tutto in una WebApp mi frullava per la testa (sarebbe stato bello rendere il tutto fruibile anche da iPhone e dispositivi simili): Google App Engine mi è venuto in aiuto.

Basata interamente su Python, la piattaforma di ‘application hosting’ fornita da Google mi permetteva di riutilizzare quanto già scritto senza grosse modifiche e, ‘giocando in casa’, mi permetteva di utilizzare il sistema di autenticazione interno per passare le credenziali a Blogspot.

Prendiamo ora in considerazione la stessa funzione da me realizzata in VB.NET, convertita per funzionare sul Google App Engine:


  def CreatePublicPost(self, blogger_service, blog_id, title, content, link):
    query = service.Query()

    #Check entry
    checkentry = db.GqlQuery("SELECT * FROM PostedEntries where blogid=:1 and titolo=:2", blog_id, title)
    if (checkentry.count() > 0):
      return "notizia presente"

    entry = gdata.GDataEntry()
    entry.title = atom.Title('xhtml', title)
    content = content + "
<a href='" + link + "'> FONTE </a>"
    entry.content = atom.Content(content_type='html', text=content)

    #Storing title of posted entry
    elemento = dataclasses.PostedEntries()
    elemento.blogid = blog_id
    elemento.titolo = title
    elemento.put()
    blogger_service.Post(entry, str('/feeds/' + blog_id + '/posts/default'))
    return "pubblicata"

l’unica differenza con la precedente è il metodo utilizzato per controllare la presenza o meno del post che si sta per pubblicare.
Nella versione in VB effettuavo una query su Blogger, scorrendo tutti i post e confrontandone il titolo con quanto stavo per pubblicare.

Sull’App Engine mi sono quasi subito scontrato con le limitazioni di quota: se un processo utilizza troppi cicli di CPU, l’applicazione viene momentaneamente ‘bloccata’.
Cosa che accadeva continuamente, essendo il vecchio metodo di controllo non proprio parco nell’uso della CPU.

Per risolvere il problema mi sono appoggiato sul DataStore interno all’AppEngine: ogni post inserito viene archiviato, in modo che un successivo ciclo di sincronizzazione escluda automaticamente quanto già pubblicato senza dover andarselo a cercare accedendo a Blogger.

La primissima beta della WebApp la trovate all’indirizzo http://bloggersync.appspot.com.

L’utilizzo è estremamente semplice: una volta effettuato il login con il vostro account di Google e autorizzato BloggerSync ad accedere ai dati di Blogger, verrà visualizzata una scarna pagina contenente i titoli dei blog legati all’account, con accanto un campo di testo da compilare con il Feed Rss scelto come ‘fonte’ per la pubblicazione.

Con la pressione del pulsante “Pubblica da RSS” si da il via alla procedura di copia dei contenuti, che si conclude con un report di quanto pubblicato (in quanto nuovo) e quanto già presente e quindi non aggiunto. Il feed inserito viene salvato e riproposto al successivo accesso.

L’applicazione è ancora immatura, devo occuparmi di risolvere ancora parecchi bugs (come un fastidioso timeout quando viene effettuata primissima operazione di copia), quindi utilizzatela ‘as-is’ e a vostro rischio e pericolo: considerando che era nata per mantenere allineati http://andreafortuna.wordpress.com e http://andreafortuna.blogspot.com, e che ora il secondo a forza di prove e test è diventato un deposito di posts duplicati (nonostante sia riuscito a far funzionare la verifica degli elementi duplicati), ci andrei comunque cauto! :-)

Un’ultima nota: leggendo queste righe, molti avranno pensato “simpatico questo, rilascia questo tool e ora sai quanti si divertiranno a copiare i blog altrui!“. Per arginare almeno in parte il problema, l’applicazione si prende la briga di aggiungere in coda a ogni post pubblicato un link ben evidente alla fonte. :-)





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!).





Facebook Party…senza parole…

13 10 2008

Leggo su Repubblica un ‘interessante’ articolo sul Facebook Party di Roma: bel modo per banalizzare un progetto interessante come quello di Facebook.

Tra i tanti partecipanti al primo raduno romano c’è anche chi, in fila da più di mezz’ora, cerca di entrare al Facebook Party. Ma la parola Facebook non l’ha mai sentita. “Ho saputo che c’era una festa e sono venuto con altri tre amici – spiega Carlo, 43 anni, romano – non so cosa sia Facebook e su internet non ci vado mai”. Sempre in fila ci sono anche Giovanni, psicologo 46enne, e la sua compagna. Lui può vantare un primato assoluto. Nella sua lista di contatti Facebook non ha neanche un amico. “Mi sono iscritto da poco – spiega – e ho trovato solo alcuni miei pazienti. Ho preferito non aggiungerli”.

via Pianeta Facebook tra vero e virtuale Tremila al party. “Bello, anzi no” – Scienza & Tecnologia – Repubblica.it





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