<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Blog2theMax</title>
    <link>http://www.dotnet2themax.it/blog/</link>
    <description>Il blog del team di Code Architects</description>
    <image>
      <url>http://www.dotnet2themax.it/images/logomini.gif</url>
      <title>Blog2theMax</title>
      <link>http://www.dotnet2themax.it/blog/</link>
    </image>
    <copyright>Code Architects S.r.l.</copyright>
    <lastBuildDate>Tue, 28 Oct 2008 14:19:38 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.7.5016.2</generator>
    <managingEditor>admin@dotnet2themax.it</managingEditor>
    <webMaster>admin@dotnet2themax.it</webMaster>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,707213e4-ca90-44bc-a69b-c03ef23741ec.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,707213e4-ca90-44bc-a69b-c03ef23741ec.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,707213e4-ca90-44bc-a69b-c03ef23741ec.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=707213e4-ca90-44bc-a69b-c03ef23741ec</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <table>
          <tbody>
            <tr>
              <td>
                <img src="http://media.hoepli.it/hoepli/Libro/GIACCAGLINI-GIANNI/OPEN-XML/9788882337438.jpeg" valign="top" />
              </td>
              <td>
                <p>
                  Fino a pochi anni fa per generare o modificare un file Word o Excel era necessario
                  operare sul modello a oggetti della stessa applicazione (e quindi avere a disposizione
                  una licenza di Office), oppure acquistare un componente di terze parti in grado di
                  generare tali file. In entrambi i casi si tratta di opzioni che hanno un costo, e
                  inoltre la prima opzione era improponibile per le applicazioni lato-server (che generano
                  file da inviare ai browser sul client) per i problemi di scalabilità che comporta.
               </p>
                <p>
                  La soluzione è arrivata con Office 2007 e il suo formato Open XML, che permette quindi
                  di salvare, rileggere, modificare e interrogare un file Word o Excel come se fosse
                  un semplice file di testo XML. Se lavorate in .NET, alla fine si riduce a saper usare
                  la classe XmlDocument per leggere/scrivere, conoscere la grammatica di XPath per le
                  query, e poco altro. Quello che realmente occorre è comprendere la sintassi e le sottigliezze
                  di Open XML, ma per quello da qualche tempo c'è un bel libro (in italiano!): <a href="http://www.hoepli.it/libro.asp?ib=9788882337438&amp;pc=000022007002024"><strong>Open
                  XML Guida allo Sviluppo.</strong></a>L'autore <strong>Gianni Giaccagliani</strong> è una
                  vecchia conoscenza per chi lavora in questo settore da tempo nonchè un mio amico dai
                  tempi delle gloriose riviste BIT (che non esiste più già da un paio di decenni) e
                  PC Magazine.
               </p>
                <p>
                  In questo agile libretto (250 pagine) Gianni introduce il DOM di Open XML e mostra
                  come manipolarlo usando direttamente il VBA degli stessi Word o Excel, quindi il libro
                  è alla portata anche di coloro che non hanno installato Visual Studio, anche se la
                  conversione in VB.NET è immediata, tanto più se si utilizza VSTO. Ci sono esempi approfonditi
                  sia con Word che Excel, e una buona introduzione a XPath, il tutto nello
                  stile semplice e "fluido" di Gianni, che ben conoscono i suoi lettori (incluso il
                  sottoscritto). Che volete di più?
               </p>
                <p>
                   
               </p>
                <p>
                   
               </p>
              </td>
            </tr>
          </tbody>
        </table>
        <p>
       
   </p>
        <p>
       
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=707213e4-ca90-44bc-a69b-c03ef23741ec" />
      </body>
      <author>Francesco Balena</author>
      <title>La guida italiana a Open XML</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,707213e4-ca90-44bc-a69b-c03ef23741ec.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,707213e4-ca90-44bc-a69b-c03ef23741ec.aspx</link>
      <pubDate>Tue, 28 Oct 2008 14:19:38 GMT</pubDate>
      <description>&lt;table&gt;
   &lt;tbody&gt;
      &lt;tr&gt;
         &lt;td&gt;
            &lt;img src="http://media.hoepli.it/hoepli/Libro/GIACCAGLINI-GIANNI/OPEN-XML/9788882337438.jpeg" valign="top"&gt;&lt;/td&gt;
         &lt;td&gt;
            &lt;p&gt;
               Fino a pochi anni fa per generare o modificare un file Word o Excel era necessario
               operare sul modello a oggetti della stessa applicazione (e quindi avere a disposizione
               una licenza di Office), oppure acquistare un componente di terze parti in grado di
               generare tali file. In entrambi i casi si tratta di opzioni che hanno un costo, e
               inoltre la prima opzione era improponibile per le applicazioni lato-server (che generano
               file da inviare ai browser sul client) per i problemi di scalabilità che comporta.
            &lt;/p&gt;
            &lt;p&gt;
               La soluzione è arrivata con Office 2007 e il suo formato Open XML, che permette quindi
               di salvare, rileggere, modificare e interrogare un file Word o Excel come se fosse
               un semplice file di testo XML. Se lavorate in .NET, alla fine si riduce a saper usare
               la classe XmlDocument per leggere/scrivere, conoscere la grammatica di XPath per le
               query, e poco altro. Quello che realmente occorre è comprendere la sintassi e le sottigliezze
               di Open XML, ma per quello da qualche tempo c'è un bel libro (in italiano!): &lt;a href="http://www.hoepli.it/libro.asp?ib=9788882337438&amp;amp;pc=000022007002024"&gt;&lt;strong&gt;Open
               XML Guida allo Sviluppo.&lt;/strong&gt; &lt;/a&gt;L'autore &lt;strong&gt;Gianni Giaccagliani&lt;/strong&gt; è&amp;nbsp;una
               vecchia conoscenza per chi lavora in questo settore da tempo nonchè un mio amico dai
               tempi delle gloriose riviste BIT (che non esiste più già da un paio di decenni) e
               PC Magazine.
            &lt;/p&gt;
            &lt;p&gt;
               In questo agile libretto (250 pagine) Gianni introduce il DOM di Open XML e mostra
               come manipolarlo usando direttamente il VBA degli stessi Word o Excel, quindi il libro
               è alla portata anche di coloro che non hanno installato Visual Studio, anche se la
               conversione in VB.NET è immediata, tanto più se si utilizza VSTO. Ci sono esempi approfonditi
               sia con Word che Excel,&amp;nbsp;e&amp;nbsp;una buona introduzione a XPath, il tutto nello
               stile semplice e "fluido" di Gianni, che ben conoscono i suoi lettori (incluso il
               sottoscritto). Che volete di più?
            &lt;/p&gt;
            &lt;p&gt;
               &amp;nbsp;
            &lt;/p&gt;
            &lt;p&gt;
               &amp;nbsp;
            &lt;/p&gt;
         &lt;/td&gt;
      &lt;/tr&gt;
   &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
   &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
   &amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=707213e4-ca90-44bc-a69b-c03ef23741ec"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,707213e4-ca90-44bc-a69b-c03ef23741ec.aspx</comments>
      <category>Libri</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,b4409446-e307-4ee6-ad3e-b100dcf2bd7e.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,b4409446-e307-4ee6-ad3e-b100dcf2bd7e.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,b4409446-e307-4ee6-ad3e-b100dcf2bd7e.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=b4409446-e307-4ee6-ad3e-b100dcf2bd7e</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a ref="http://www.theregion.com">
            <img src="http://www.dotnet2themax.it/blog/content/binary/RDLogo.gif" border="0" />
          </a> Ecco
      una bella notizia che mi ha fatto cominciare l'anno nel migliore dei modi.
   </p>
        <p>
      Microsoft Corp. ha confermato <strong>Giuseppe Dimauro</strong> e il sottoscritto
      come <strong>gli unici due Regional Director per l'Italia</strong>, per gli anni 2008-09.
      E' una grande soddisfazione far parte di una elite di soli 140 esperti in tutto il
      mondo - a differenza di altri gruppi come gli MVP, il numero degl RD è "contingentato",
      tipicamente 1 o 2 per ciascuna nazione e per ciascuno dei 50 stati degli USA. Negli
      ultimi tempi il Regional Director Program si è arricchito di <a href="http://www.theregion.com">un
      sito </a>tutto nostro, che funge anche da aggregatore dei blog. Data la qualiltà del
      materiale che si può trovare, è quasi meglio di una rivista tecnica.
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=b4409446-e307-4ee6-ad3e-b100dcf2bd7e" />
      </body>
      <author>Francesco Balena</author>
      <title>Regional Director again!</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,b4409446-e307-4ee6-ad3e-b100dcf2bd7e.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,b4409446-e307-4ee6-ad3e-b100dcf2bd7e.aspx</link>
      <pubDate>Fri, 11 Jan 2008 10:00:24 GMT</pubDate>
      <description>&lt;p&gt;
   &lt;a ref="http://www.theregion.com"&gt;&lt;img src="http://www.dotnet2themax.it/blog/content/binary/RDLogo.gif" border=0&gt;&lt;/a&gt;&amp;nbsp;Ecco
   una bella notizia che mi ha fatto cominciare l'anno nel migliore dei modi.
&lt;/p&gt;
&lt;p&gt;
   Microsoft Corp. ha confermato &lt;strong&gt;Giuseppe Dimauro&lt;/strong&gt; e il sottoscritto
   come &lt;strong&gt;gli unici due Regional Director per l'Italia&lt;/strong&gt;, per gli anni 2008-09.
   E' una grande soddisfazione far parte di una elite di soli 140 esperti in tutto il
   mondo - a differenza di altri gruppi come gli MVP, il numero degl RD è "contingentato",
   tipicamente 1 o 2 per ciascuna nazione e per ciascuno dei 50 stati degli USA. Negli
   ultimi tempi il Regional Director Program si è arricchito di &lt;a href="http://www.theregion.com"&gt;un
   sito &lt;/a&gt;tutto nostro, che funge anche da aggregatore dei blog. Data la qualiltà del
   materiale che si può trovare, è quasi meglio di una rivista tecnica.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=b4409446-e307-4ee6-ad3e-b100dcf2bd7e"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,b4409446-e307-4ee6-ad3e-b100dcf2bd7e.aspx</comments>
      <category>Varie</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,36446eb4-9d7c-45af-a758-42b87a7f54ff.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,36446eb4-9d7c-45af-a758-42b87a7f54ff.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,36446eb4-9d7c-45af-a758-42b87a7f54ff.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=36446eb4-9d7c-45af-a758-42b87a7f54ff</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      In questo periodo sto facendo molta consulenza per aziende italiane alle prese con
      la migrazione da VB6, usando ovviamente la versione preliminare di <a href="http://www.vbmigration.com/">VB
      Migration Partner</a>. Oramai la beta è stabile e si comporta davvero molto bene.
      In un solo giorno, ad esempio, abbiamo migrato una applicazione di circa 20mila righe
      che lavora in modo intensivo con ADO in circa mezza giornata, e tutto funziona a meraviglia!
   </p>
        <p>
      Anche se la migrazione sta andando bene, a volte i programmi migrati sono più lenti
      del codice VB6 originario. Per esperienza le cause sono principalmente due: (1) l'uso
      di COM Interop per accedere agli oggetti ADO, (2) un uso massiccio di concatenazione
      di stringhe. Per il primo problema non c'è molto da fare, purtroppo: occorre migrare
      il codice di accesso al database da ADO a ADO.NET, un compito più semplice a dirsi
      che a farsi. Per il secondo problema ci sarebbe invece una soluzione semplice: basterebbe
      sostituire la variabile stringa con una variabile <strong>StringBuilder</strong>,
      e le concatenazioni sarebbero automaticamente più veloci. Peccato che questa sostituzione
      comporti una revisione completa del codice, perchè richiede di trasformare tutti gli
      operatori &amp; (concatenazione) con il metodo <strong>Append</strong>, per non parlare
      dei casi in cui la variabile stringa viene usata come argomento a funzioni come Trim
      o Left. Ad esempio, il seguente codice richiede ben 17 secondi sul mio sistema a 3GHz:
   </p>
        <p>
          <font color="#0000ff">Dim</font> s <font color="#0000ff">As</font> <font color="#0000ff">String</font> = <font color="#800000">""<br /></font><font color="#0000ff">Dim</font> sw <font color="#0000ff">As</font> Stopwatch
      = Stopwatch.StartNew()<br /><font color="#0000ff">For</font> i <font color="#0000ff">As</font><font color="#0000ff">Integer</font> =
      1 <font color="#0000ff">To</font> 100000<br />
          s = s + <font color="#800000">"*"<br /></font><font color="#0000ff">Next<br /></font>MsgBox(sw.Elapsed.ToString)
   </p>
        <p>
      Per fortuna la soluzione è davvero semplice: basta creare una classe che utilizzi
      internamente un oggetto StringBuilder, che ridefinisca gli operatori &amp; e +, e
      che supporti la conversione implicita da-a stringa. Il codice di questa classe StringBuilder6
      si scrive davvero in pochi minuti:
   </p>
        <font color="#0000ff">
          <p>
      Imports
   </p>
        </font>
        <font color="#000000"> System.Text</font>
        <font color="#008000">
          <p>
      ' a wrapper for the StringBuilder object, with support for + and &amp; operators
   </p>
        </font>
        <font color="#0000ff">
          <p>
      Public
   </p>
        </font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Class</font>
        <font color="#000000"> StringBuilder6</font>
        <p>
          <font color="#0000ff">    Private</font> buffer <font color="#0000ff">As</font><font color="#0000ff">New</font> StringBuilder
   </p>
        <p>
          <font color="#008000">
            <font color="#0000ff">    </font>' return the
      inner string
      </font>
        </p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Overrides</font>
          <font color="#0000ff">Function</font> ToString() <font color="#0000ff">As</font><font color="#0000ff">String<br />
              </font><font color="#0000ff">Return</font> buffer.ToString()<br /><font color="#0000ff">    End</font><font color="#0000ff">Function
      </font></p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">Operator</font> +(<font color="#0000ff">ByVal</font> op1 <font color="#0000ff">As</font> StringBuilder6, <font color="#0000ff">ByVal</font> op2 <font color="#0000ff">As</font><font color="#0000ff">String</font>) <font color="#0000ff">As</font> StringBuilder6<br />
              op1.buffer.Append(op2)<br />
              <font color="#0000ff">Return</font> op1<br /><font color="#0000ff">    End</font><font color="#0000ff">Operator
      </font></p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">Operator</font> &amp;(<font color="#0000ff">ByVal</font> op1 <font color="#0000ff">As</font> StringBuilder6, <font color="#0000ff">ByVal</font> op2 <font color="#0000ff">As</font><font color="#0000ff">String</font>) <font color="#0000ff">As</font> StringBuilder6<br />
              op1.buffer.Append(op2)<br />
              <font color="#0000ff">Return</font> op1<br /><font color="#0000ff">    End</font><font color="#0000ff">Operator
      </font></p>
        <p>
          <font color="#008000">    ' convert to string
      </font>
        </p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">Widening</font>
          <font color="#0000ff">Operator</font>
          <font color="#0000ff">CType</font>(<font color="#0000ff">ByVal</font> op <font color="#0000ff">As</font> StringBuilder6) <font color="#0000ff">As</font><font color="#0000ff">String<br />
              </font><font color="#0000ff">Return</font> op.ToString()<br /><font color="#0000ff">    End</font><font color="#0000ff">Operator
      </font></p>
        <p>
          <font color="#008000">    ' convert from string 
      </font>
        </p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">Widening</font>
          <font color="#0000ff">Operator</font>
          <font color="#0000ff">CType</font>(<font color="#0000ff">ByVal</font> str <font color="#0000ff">As</font><font color="#0000ff">String</font>) <font color="#0000ff">As</font> StringBuilder6<br />
              <font color="#0000ff">Dim</font> op <font color="#0000ff">As</font><font color="#0000ff">New</font> StringBuilder6()<br />
              op.buffer.Append(str)<br />
              <font color="#0000ff">Return</font> op<br /><font color="#0000ff">    End</font><font color="#0000ff">Operator
      </font></p>
        <p>
      End<font color="#000000"></font><font color="#0000ff">Class</font></p>
        <p>
      A questo punto per velocizzare il codice visto prima è sufficiente modificare UNA
      SOLA ISTRUZIONE, ovvero la dichiarazione della variabile stringa:
   </p>
        <p>
          <font color="#0000ff">Dim</font> s <font color="#0000ff">As</font> StringBuilder6
      = <font color="#800000">""<br /></font></p>
        <font color="#000000">
          <p>
      Dopo questa sostituzione, il ciclo visto prima viene eseguito in <strong><em>8 millesimi
      di secondo</em></strong>, ovvero <strong><font color="#ff0000">circa 2000 volte più
      velocemente</font></strong>!!! Non male, per una fix così semplice :-)
   </p>
          <p>
      Indipendentemente dal fatto che state migrando codice da VB6 o se avete scritto codice
      VB.NET (o C#) da zero: se trovate dei punti in cui fate uso massiccio di concatenazione
      di stringhe e che pensate possano rallentare l'esecuzione, provate a sostituire la
      variabile stringa con un oggetto StringBuilder6: in alcuni casi il programma girerà
      molto ma molto più velocemente.
   </p>
          <p>
          </p>
        </font>
        <font color="#0000ff"> 
   </font>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=36446eb4-9d7c-45af-a758-42b87a7f54ff" />
      </body>
      <author>Francesco Balena</author>
      <title>Velocizzare le concatenazioni di stringhe nei programmi migrati da VB6</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,36446eb4-9d7c-45af-a758-42b87a7f54ff.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,36446eb4-9d7c-45af-a758-42b87a7f54ff.aspx</link>
      <pubDate>Sun, 16 Dec 2007 11:44:27 GMT</pubDate>
      <description>&lt;p&gt;
   In questo periodo sto facendo molta consulenza per aziende italiane alle prese con
   la migrazione da VB6, usando ovviamente la versione preliminare di &lt;a href="http://www.vbmigration.com/"&gt;VB
   Migration Partner&lt;/a&gt;. Oramai la beta è stabile e si comporta davvero molto bene.
   In un solo giorno, ad esempio, abbiamo migrato una applicazione di circa 20mila righe
   che lavora in modo intensivo con ADO in circa mezza giornata, e tutto funziona a meraviglia!
&lt;/p&gt;
&lt;p&gt;
   Anche se la migrazione sta andando bene, a volte i programmi migrati sono più lenti
   del codice VB6 originario. Per esperienza le cause sono principalmente due: (1) l'uso
   di COM Interop per accedere agli oggetti ADO, (2) un uso massiccio di concatenazione
   di stringhe. Per il primo problema non c'è molto da fare, purtroppo: occorre migrare
   il codice di accesso al database da ADO a ADO.NET, un compito più semplice a dirsi
   che a farsi. Per il secondo problema ci sarebbe invece una soluzione semplice: basterebbe
   sostituire la variabile stringa con una variabile &lt;strong&gt;StringBuilder&lt;/strong&gt;,
   e le concatenazioni sarebbero automaticamente più veloci. Peccato che questa sostituzione
   comporti una revisione completa del codice, perchè richiede di trasformare tutti gli
   operatori &amp;amp; (concatenazione) con il metodo &lt;strong&gt;Append&lt;/strong&gt;, per non parlare
   dei casi in cui la variabile stringa viene usata come argomento a funzioni come Trim
   o Left. Ad esempio, il seguente codice richiede ben 17 secondi sul mio sistema a 3GHz:
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#0000ff&gt;Dim&lt;/font&gt; s &lt;font color=#0000ff&gt;As&lt;/font&gt;&amp;nbsp;&lt;font color=#0000ff&gt;String&lt;/font&gt; = &lt;font color=#800000&gt;""&lt;br&gt;
   &lt;/font&gt;&lt;font color=#0000ff&gt;Dim&lt;/font&gt; sw &lt;font color=#0000ff&gt;As&lt;/font&gt; Stopwatch =
   Stopwatch.StartNew()&lt;br&gt;
   &lt;font color=#0000ff&gt;For&lt;/font&gt; i &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;Integer&lt;/font&gt; =
   1 &lt;font color=#0000ff&gt;To&lt;/font&gt; 100000&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp; s = s + &lt;font color=#800000&gt;"*"&lt;br&gt;
   &lt;/font&gt;&lt;font color=#0000ff&gt;Next&lt;br&gt;
   &lt;/font&gt;MsgBox(sw.Elapsed.ToString)
&lt;/p&gt;
&lt;p&gt;
   Per fortuna la soluzione è davvero semplice: basta creare una classe che utilizzi
   internamente un oggetto StringBuilder, che ridefinisca gli operatori &amp;amp; e +, e
   che supporti la conversione implicita da-a stringa. Il codice di questa classe StringBuilder6
   si scrive davvero in pochi minuti:
&lt;/p&gt;
&lt;font color=#0000ff&gt; 
&lt;p&gt;
   Imports
&lt;/font&gt;&lt;font color=#000000&gt; System.Text&lt;/font&gt;&gt;
&lt;font color=#008000&gt; 
&lt;p&gt;
   ' a wrapper for the StringBuilder object, with support for + and &amp;amp; operators
&lt;/p&gt;
&lt;/font&gt;&lt;font color=#0000ff&gt; 
&lt;p&gt;
   Public
&lt;/font&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;Class&lt;/font&gt;&lt;font color=#000000&gt; StringBuilder6&lt;/font&gt;&gt;
&lt;p&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Private&lt;/font&gt; buffer &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;New&lt;/font&gt; StringBuilder
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' return the inner
   string
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public&lt;/font&gt; &lt;font color=#0000ff&gt;Overrides&lt;/font&gt; &lt;font color=#0000ff&gt;Function&lt;/font&gt; ToString() &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;String&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Return&lt;/font&gt; buffer.ToString()&lt;br&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End&lt;/font&gt; &lt;font color=#0000ff&gt;Function
&lt;/p&gt;
&lt;p&gt;
   &gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public&lt;/font&gt; &lt;font color=#0000ff&gt;Shared&lt;/font&gt; &lt;font color=#0000ff&gt;Operator&lt;/font&gt; +(&lt;font color=#0000ff&gt;ByVal&lt;/font&gt; op1 &lt;font color=#0000ff&gt;As&lt;/font&gt; StringBuilder6, &lt;font color=#0000ff&gt;ByVal&lt;/font&gt; op2 &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;String&lt;/font&gt;) &lt;font color=#0000ff&gt;As&lt;/font&gt; StringBuilder6&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; op1.buffer.Append(op2)&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;Return&lt;/font&gt; op1&lt;br&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End&lt;/font&gt; &lt;font color=#0000ff&gt;Operator
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public&lt;/font&gt; &lt;font color=#0000ff&gt;Shared&lt;/font&gt; &lt;font color=#0000ff&gt;Operator&lt;/font&gt; &amp;amp;(&lt;font color=#0000ff&gt;ByVal&lt;/font&gt; op1 &lt;font color=#0000ff&gt;As&lt;/font&gt; StringBuilder6, &lt;font color=#0000ff&gt;ByVal&lt;/font&gt; op2 &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;String&lt;/font&gt;) &lt;font color=#0000ff&gt;As&lt;/font&gt; StringBuilder6&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; op1.buffer.Append(op2)&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;Return&lt;/font&gt; op1&lt;br&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End&lt;/font&gt; &lt;font color=#0000ff&gt;Operator
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' convert to string
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public&lt;/font&gt; &lt;font color=#0000ff&gt;Shared&lt;/font&gt; &lt;font color=#0000ff&gt;Widening&lt;/font&gt; &lt;font color=#0000ff&gt;Operator&lt;/font&gt; &lt;font color=#0000ff&gt;CType&lt;/font&gt;(&lt;font color=#0000ff&gt;ByVal&lt;/font&gt; op &lt;font color=#0000ff&gt;As&lt;/font&gt; StringBuilder6) &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;String&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Return&lt;/font&gt; op.ToString()&lt;br&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End&lt;/font&gt; &lt;font color=#0000ff&gt;Operator
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' convert from string 
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public&lt;/font&gt; &lt;font color=#0000ff&gt;Shared&lt;/font&gt; &lt;font color=#0000ff&gt;Widening&lt;/font&gt; &lt;font color=#0000ff&gt;Operator&lt;/font&gt; &lt;font color=#0000ff&gt;CType&lt;/font&gt;(&lt;font color=#0000ff&gt;ByVal&lt;/font&gt; str &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;String&lt;/font&gt;) &lt;font color=#0000ff&gt;As&lt;/font&gt; StringBuilder6&lt;br&gt;
   &amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;Dim&lt;/font&gt; op &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;New&lt;/font&gt; StringBuilder6()&lt;br&gt;
   &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; op.buffer.Append(str)&lt;br&gt;
   &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;font color=#0000ff&gt;Return&lt;/font&gt; op&lt;br&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End&lt;/font&gt; &lt;font color=#0000ff&gt;Operator
&lt;/p&gt;
&lt;p&gt;
   End&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;Class&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   A questo punto per velocizzare il codice visto prima è sufficiente modificare UNA
   SOLA ISTRUZIONE, ovvero la dichiarazione della variabile stringa:
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#0000ff&gt;Dim&lt;/font&gt; s &lt;font color=#0000ff&gt;As&lt;/font&gt;&amp;nbsp;StringBuilder6
   = &lt;font color=#800000&gt;""&lt;br&gt;
   &lt;/font&gt;
&lt;/p&gt;
&lt;font color=#000000&gt; 
&lt;p&gt;
   Dopo questa sostituzione, il ciclo visto prima viene eseguito in &lt;strong&gt;&lt;em&gt;8 millesimi
   di secondo&lt;/em&gt;&lt;/strong&gt;, ovvero &lt;strong&gt;&lt;font color=#ff0000&gt;circa 2000 volte più
   velocemente&lt;/font&gt;&lt;/strong&gt;!!! Non male, per una fix così semplice :-)
&lt;/p&gt;
&lt;p&gt;
   Indipendentemente dal fatto che state migrando codice da VB6 o se avete scritto codice
   VB.NET (o C#) da zero: se trovate dei punti in cui fate uso massiccio di concatenazione
   di stringhe e che pensate possano rallentare l'esecuzione, provate a sostituire la
   variabile stringa con un oggetto StringBuilder6: in alcuni casi il programma girerà
   molto ma molto più velocemente.
&lt;/p&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&gt;
&lt;/font&gt;&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=36446eb4-9d7c-45af-a758-42b87a7f54ff"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,36446eb4-9d7c-45af-a758-42b87a7f54ff.aspx</comments>
      <category>Migrazione da VB6</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,78327f62-ab87-4f6b-b296-366aedcb1ab4.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,78327f62-ab87-4f6b-b296-366aedcb1ab4.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,78327f62-ab87-4f6b-b296-366aedcb1ab4.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=78327f62-ab87-4f6b-b296-366aedcb1ab4</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      L'altro giorno un nostro amico-cliente ci chiama per un problema con un controllo
      WinForm wordprocessor-like. Nella loro applicazione usano questo controllo anche per
      la capacità di importare HTML, solo che a un certo punto scoprono che il controllo
      va in crash se il test HTML contiene un tag IMG con attributo ALIGN e che punta a
      una immagine "remota", ovvero il cui URL comincia per http:// , come in questo esempio:
   </p>
        <pre>   &lt;IMG SRC="http://www.somesite.com/image.jpg" ALIGN=left WIDTH=100&gt;</pre>
        <p>
      Con un po' di tentativi scoprono che il problema è la presenza dell'attributo ALIGN
      e che il crash si può evitare se si trasforma l'HTML in questo modo:
   </p>
        <pre>   &lt;DIV style="float:left"&gt;&lt;IMG SRC="http://www.somesite.com/image.jpg" WIDTH=100&gt;&lt;/DIV&gt;</pre>
        <p>
      in altre parole, occorre eliminare l'attributo ALIGN dall'interno del tag IMG e renderlo
      come style di un blocco DIV che racchiude il tag IMG. Questa sostituzione va fatta
      un attimo prima di caricare il testo HTML nel controllo, ma solo se il tag IMG contiene
      un attributo ALIGN e solo se l'URL dell'immagine comincia con i caratteri "http://".
      Il tutto è complicato dal fatto che il valore dei vari attributi può essere o non
      essere racchiuso tra virgolette. Insomma, un bel problemino. 
   </p>
        <p>
      Ovviamente, la soluzione sarebbe stata basata su qualche regex, ma era la prima volta
      che mi imbattevo in un caso di questo tipo. I problemi da risolvere erano principalmente
      due: come agire solo sui tag IMG contenenti un SRC remoto e come fare per "spostare"
      solo l'attributo ALIGN, senza toccare tutti gli altri attributi che compaiono nel
      tag IMG. Il primo problema lo si risolve con le cosiddette <em>positive look-ahed
      assertion</em>, ovvero il costrutto <strong>(?=...)</strong>, che permette di controllare
      che esista una certa sottostringa a destra della regex principale, ma senza consumare
      caratteri per il match. Il secondo problema si risolve facilmente se si pensa a suddividere
      l'intero contenuto del tag IMG in tre gruppi: il gruppo <strong>pre </strong>contiene
      tutti i caratteri prima dell'attributo ALIGN, il gruppo <strong>align </strong>contiene
      il valore dell'attributo ALIGN, e il gruppo <strong>post </strong>contiene tutti i
      caratteri dopo l'attributo align. Ecco la soluzione in VB e C#:
   </p>
        <p>
          <span style="COLOR: #0000ff; FONT-FAMILY: Microsoft Sans Serif">
            <font face="Courier New">   Dim
      search As String = "&lt;img(?=.*src=\""?http://.*?&gt;)(?=.*\balign=.*?&gt;)(?&lt;pre&gt;[^&gt;]*)\balign=\""?(?&lt;align&gt;[^
      \""]+)\""?(?&lt;post&gt;[^&gt;]*&gt;)"<br />
         Dim replace As String = "&lt;div style=""float:${align}""&gt;&lt;img
      ${pre} ${post}&lt;/div&gt;"<br />
         Dim result As String = Regex.Replace(htmlText, search, replace,
      RegexOptions.IgnoreCase Or RegexOptions.Multiline)</font>
          </span>
        </p>
        <span style="COLOR: #0000ff; FONT-FAMILY: Microsoft Sans Serif">
          <p>
            <span style="COLOR: #0000ff; FONT-FAMILY: Microsoft Sans Serif">
              <font face="Courier New">   string
      pattern = @"&lt;img(?=.*src=\""?http://.*?&gt;)(?=.*\balign=.*?&gt;)(?&lt;pre&gt;[^&gt;]*)\balign=\""?(?&lt;align&gt;[^
      \""]+)\""?(?&lt;post&gt;[^&gt;]*&gt;)";<br />
         string replace = @"&lt;div style=""float:${align}""&gt;&lt;img ${pre}
      ${post}&lt;/div&gt;";<br />
         string result = Regex.Replace(htmlText, search, replace, RegexOptions.IgnoreCase |
      RegexOptions.Multiline);</font>
            </span>
          </p>
        </span>
        <p>
      La cosa notevole non è tanto che questo problema è risolvibile con le regex - lo davo
      per scontato, in effetti - ma che possa essere risolto senza implementare un loop
      o un metodo di callback per il replace.
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=78327f62-ab87-4f6b-b296-366aedcb1ab4" />
      </body>
      <author>Francesco Balena</author>
      <title>Una regex per manipolare HTML</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,78327f62-ab87-4f6b-b296-366aedcb1ab4.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,78327f62-ab87-4f6b-b296-366aedcb1ab4.aspx</link>
      <pubDate>Sat, 08 Dec 2007 13:46:40 GMT</pubDate>
      <description>&lt;p&gt;
   L'altro giorno un nostro amico-cliente ci chiama per un problema con un controllo
   WinForm wordprocessor-like. Nella loro applicazione usano questo controllo anche per
   la capacità di importare HTML, solo che a un certo punto scoprono che il controllo
   va in crash se il test HTML contiene un tag IMG con attributo ALIGN e che punta a
   una immagine "remota", ovvero il cui URL comincia per http:// , come in questo esempio:
&lt;/p&gt;
&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;IMG SRC="http://www.somesite.com/image.jpg" ALIGN=left WIDTH=100&amp;gt;&lt;/pre&gt;
&lt;p&gt;
   Con un po' di tentativi scoprono che il problema è la presenza dell'attributo ALIGN
   e che il crash si può evitare se si trasforma l'HTML in questo modo:
&lt;/p&gt;
&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DIV style="float:left"&amp;gt;&amp;lt;IMG SRC="http://www.somesite.com/image.jpg" WIDTH=100&amp;gt;&amp;lt;/DIV&amp;gt;&lt;/pre&gt;
&lt;p&gt;
   in altre parole, occorre eliminare l'attributo ALIGN dall'interno del tag IMG e renderlo
   come style di un blocco DIV che racchiude il tag IMG. Questa sostituzione va fatta
   un attimo prima di caricare il testo HTML nel controllo, ma solo se il tag IMG contiene
   un attributo ALIGN e solo se l'URL dell'immagine comincia con i caratteri "http://".
   Il tutto è complicato dal fatto che il valore dei vari attributi può essere o non
   essere racchiuso tra virgolette. Insomma, un bel problemino. 
&lt;/p&gt;
&lt;p&gt;
   Ovviamente, la soluzione sarebbe stata basata su qualche regex, ma era la prima volta
   che mi imbattevo in un caso di questo tipo. I problemi da risolvere erano principalmente
   due: come agire solo sui tag IMG contenenti un SRC remoto e come fare per "spostare"
   solo l'attributo ALIGN, senza toccare tutti gli altri attributi che compaiono nel
   tag IMG.&amp;nbsp;Il primo problema lo si risolve con le cosiddette &lt;em&gt;positive&amp;nbsp;look-ahed
   assertion&lt;/em&gt;, ovvero il costrutto &lt;strong&gt;(?=...)&lt;/strong&gt;, che permette di controllare
   che esista una certa sottostringa a destra della regex principale, ma senza consumare
   caratteri per il match. Il secondo problema si risolve facilmente se si pensa a suddividere
   l'intero contenuto del tag IMG in tre gruppi: il gruppo &lt;strong&gt;pre &lt;/strong&gt;contiene
   tutti i caratteri prima dell'attributo ALIGN, il gruppo &lt;strong&gt;align &lt;/strong&gt;contiene
   il valore dell'attributo ALIGN, e il gruppo &lt;strong&gt;post &lt;/strong&gt;contiene tutti i
   caratteri dopo l'attributo align. Ecco la soluzione in VB e C#:
&lt;/p&gt;
&lt;p&gt;
   &lt;span style="COLOR: #0000ff; FONT-FAMILY: Microsoft Sans Serif"&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim
   search As String = "&amp;lt;img(?=.*src=\""?http://.*?&amp;gt;)(?=.*\balign=.*?&amp;gt;)(?&amp;lt;pre&amp;gt;[^&amp;gt;]*)\balign=\""?(?&amp;lt;align&amp;gt;[^
   \""]+)\""?(?&amp;lt;post&amp;gt;[^&amp;gt;]*&amp;gt;)"&lt;br&gt;
   &amp;nbsp;&amp;nbsp; Dim replace As String = "&amp;lt;div style=""float:${align}""&amp;gt;&amp;lt;img
   ${pre} ${post}&amp;lt;/div&amp;gt;"&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;Dim result As String = Regex.Replace(htmlText, search, replace,
   RegexOptions.IgnoreCase Or RegexOptions.Multiline)&lt;/font&gt; &lt;/span&gt;
&lt;/p&gt;
&lt;span style="COLOR: #0000ff; FONT-FAMILY: Microsoft Sans Serif"&gt; 
&lt;p&gt;
   &lt;span style="COLOR: #0000ff; FONT-FAMILY: Microsoft Sans Serif"&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;string
   pattern = @"&amp;lt;img(?=.*src=\""?http://.*?&amp;gt;)(?=.*\balign=.*?&amp;gt;)(?&amp;lt;pre&amp;gt;[^&amp;gt;]*)\balign=\""?(?&amp;lt;align&amp;gt;[^
   \""]+)\""?(?&amp;lt;post&amp;gt;[^&amp;gt;]*&amp;gt;)";&lt;br&gt;
   &amp;nbsp;&amp;nbsp; string replace = @"&amp;lt;div style=""float:${align}""&amp;gt;&amp;lt;img ${pre}
   ${post}&amp;lt;/div&amp;gt;";&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;string result = Regex.Replace(htmlText, search, replace, RegexOptions.IgnoreCase&amp;nbsp;|
   RegexOptions.Multiline);&lt;/font&gt;&lt;/span&gt;
&lt;/span&gt;&gt;
&lt;p&gt;
   La cosa notevole non è tanto che questo problema è risolvibile con le regex - lo davo
   per scontato, in effetti - ma che possa essere risolto senza implementare un loop
   o un metodo di callback per il replace.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=78327f62-ab87-4f6b-b296-366aedcb1ab4"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,78327f62-ab87-4f6b-b296-366aedcb1ab4.aspx</comments>
      <category>C#</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,cbed76be-be56-454b-a5a4-a116c7edabcd.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,cbed76be-be56-454b-a5a4-a116c7edabcd.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,cbed76be-be56-454b-a5a4-a116c7edabcd.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=cbed76be-be56-454b-a5a4-a116c7edabcd</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      VB Migration Partner - il progetto a cui ho lavorato praticamente a tempo pieno negli
      ultimi 22 mesi è finalmente in beta!
   </p>
        <p>
      Cosa faccia questo tool lo dice il suo nome: è un <strong>convertitore di applicazioni
      da VB6 a VB.NET</strong>. Immagino bene che a questo punto molti di voi scrolleranno
      le spalle e penseranno "Ancora VB6?" oppure "Ecco un altro che ci tenta!", ma la verità
      è che VB6 continua a imperversare tra le software house, anche e soprattutto perchè
      non ci sono strumenti decenti per convertire centinaia di migliaia di righe di codice
      VB6 in VB.NET, in modo veloce e (almeno relativamente) indolore. Davanti alla prospettiva
      di sprecare diversi anni uomo di lavoro sulla migrazione di un gestionale VB6 complesso,
      e di dover fare tutto a mano, beh... sono in molti a farsi indietro. Ora però ci si
      sta rendendo conto che la decisione non può più essere rimandata: è risaputo che i
      programmi VB6 non funzionano bene sotto Vista (in particolare, non funzionano molti
      controlli ActiveX) e soprattutto Microsoft ha dichiarato che <a href="http://msdn2.microsoft.com/en-us/vbrun/ms788707.aspx">il
      supporto esteso per VB6 termina a Marzo del 2008</a></p>
        <p>
      Il problema dei convertitori automatici di codice è che quasi mai mantengono le promesse,
      si tratti di conversione da VB6, Java, Delphi, o qualsiasi altro linguaggio. Nel migliore
      dei casi, riescono a convertire circa il 95% delle istruzioni, ma con una applicazione
      VB6 da 100mila righe (quindi neanche estremamente complesse), il 5% di istruzioni
      errate significa dover mettere mano a <strong><i>cinque mila righe</i></strong>! Quel
      che è peggio è che quasi sempre non si tratta di piccole modifiche che prendono qualche
      minuto. Ad es. VB6 e VB.NET espongono due modelli completamente differenti per le
      istruzioni grafiche, il printing, e il drag-and-drop, quindi in realtà anche se il
      compilatore VB.NET segnala relativamente pochi errori, in effetti per implementare
      grafica, printing, e D&amp;D in VB.NET occorrerà rifare intere porzioni di programma.
      Per non parlare di tutti i controlli ActiveX non supportati, il databinding, e tanto
      altro.
   </p>
        <p>
      Nei test che abbiamo eseguito su centinaia di applicazioni VB6 (circa un milione di
      righe di codice in totale), VB Migration Partner offre la notevole media di <strong>un
      errore di compilazione ogni 1,100 righe di codice</strong>, ovvero una percentuale
      di precisione superiore al 99.9%. Scusate se è poco! Del resto, per avere una idea
      della precisione di questo strumento, basta un piccolo elenco delle feature di VB6
      che sono pienamente supportate (eccetto dove indicato) e che sono quasi tutti fuori
      dalla portata di qualsiasi altro strumento sul mercato, incluso ovviamente l’Upgrade
      Wizard incluso in Visual Studio:
   </p>
        <p>
        </p>
        <ul>
          <li>
         array con indice LBound diverso da zero</li>
          <li>
         Gosub, On...Goto, e On ...Gosub</li>
          <li>
         variabili auto-instancing (Dim x As New Person) che mantengono il comportamento anche
         in VB.NET</li>
          <li>
         Declare con parametri As Any e indirizzi di callback (es. EnumWindows)</li>
          <li>
         proprietà di default risolte correttamente anche in modalità late-bound</li>
          <li>
         finalizzazione deterministica per le variabili di tipo Connection, Recordset, ecc.,
         ad es. per ottenere che la connessione sia chiusa quando la variabile è messa a Nothing
         o esce dallo scope</li>
          <li>
         supporto (limitato) per Variant e propagazione dei valori Null</li>
          <li>
         tutti i 60+ controlli di VB6 (uniche eccezioni: OLE e Repeater)</li>
          <li>
         control array, anche di controlli ActiveX di terze parti</li>
          <li>
         menu popup</li>
          <li>
         metodo Controls.Add e oggetti VBControlExtender per creare dinamicamente form di data
         entry</li>
          <li>
         metodi grafici (Line, Circle, PSet, PaintPicture, ecc.) con supporto per ScaleMode
         custom</li>
          <li>
         oggetto Printer e collection Printers</li>
          <li>
         OLE drag-and-drop</li>
          <li>
         UserControl, con supporto di feature avanzate e oggetti Ambient e Extender</li>
          <li>
         data-binding con controlli Data ADO, RDO, ADO, con recordset ADO, con DataEnvironment</li>
          <li>
         classi DataEnvironment non gerarchici 
      </li>
          <li>
         classi e user control ADO data source e simple data consumer</li>
          <li>
         classi MultiUse, PublicNotCreatable, GlobalMultiUse</li>
          <li>
         classi persistable, classi MTS/COM+</li>
        </ul>
        <p>
      In realtà, è più semplice elencare cosa il nostro tool <b><i>non</i></b> supporta:
      gli UserDocument, le PropertyPage, le WebClass, gli DHTML Page designer, istruzioni
      non documentate (VarPtr, ObjPtr, StrPtr), il drag-and-drop “classico” (non OLE D&amp;D),
      e poco altro.
   </p>
        <p>
      VB Migration Partner è in grado di convertire un intero <b>gruppo di progetti VB6</b> in
      una sola operazione, e riesce a generare codice di migliore qualità proprio perchè
      riesce a vedere “dentro” una DLL che fa parte del project group. Il tool dispone anche
      di un <b>code analyzer</b> molto sofisticato, in grado ad esempio di segnalare classi,
      metodi, e variabili non utilizzate: se si considera che in un progetto di grandi dimensioni
      che si è evoluto negli anni molto spesso il 5-10% di codice è “dead code”, si vede
      che questa feature da sola è in grado di far risparmiare parecchio tempo prezioso.
   </p>
        <p>
      Uno dei segreti dell’alto tasso di conversione senza errori è il supporto per i <b>migration
      pragmas</b>. Un pragma di migrazione non è che uno speciale commento inserito nel
      codice VB6 che indica a VB Migration Partner come convertire certi costrutti che permettono
      approcci differenti. Per esempio, il seguente pragma ArrayBounds indica che l’indice
      di tutti gli array nel progetto corrente deve essere forzato a zero:
   </p>
        <pre>
          '##project:ArrayBounds ForceZero
</pre>
        <p>
      I pragma possono avere scope di progetto, di classe, di metodo o di singolo elemento;
      un pragma ha sempre la precedenza su tutti i pragma dello stesso tipo con scope più
      ampio. Per esempio, io posso fare l’override del precedente pragma dentro un metodo,
      e specificare un ulteriore pragma relativo ad uno specifico array:
   </p>
        <pre>
          Sub Test()
             '## ArrayBounds Shift
             '##arr.ForceZero
             Dim names(1 To 10) As String
             Dim values(1 To 10) As Long
             Dim arr(1 To 10) As Integer
          End Sub
</pre>
        <p>
      L’opzione Shift indica a VB Migration Partner che i valori di LBound e UBound dell’array
      devono essere “shiftati” verso lo zero, in modo da preservare il numero di elementi
      dell’array originario in VB6:
   </p>
        <pre>
          Sub Test()
             Dim names(9) As String
             Dim values(9) As Integer
             Dim arr(0 To 10) As Short
          End Sub
</pre>
        <p>
      VB Migration Partner supporta una cinquantina di pragma per gli scope più differenti.
      Ad esempio, SetName modifica il nome di un elemento, SetType il suo tipo, AutoNew
      implementa il comportamento auto-instancing delle variabili As New, AutoDispose fa
      sì che le variabili siano “disposed” correttamente prima di essere impostate a Nothing,
      ecc.
   </p>
        <p>
      Uno dei difetti principali di un tool di conversione “tradizionale” è il fatto che
      – dopo la prima conversione – il progetto originario VB6 e il nuovo progetto VB.NET
      vivono due vite completamente separate. Se la migrazione dura settimane o mesi – com’è
      plausibile per i gestionali di grandi dimensioni – quando finalmente il programma
      VB.NET compila ed esegue senza errori il codice sarà già “vecchio”, ovvero non allineato
      alle modifiche e ai bugfix che nel frattempo sono state apportate al programma VB6.
   </p>
        <p>
      Per evitare questo problema, VB Migration Partner offre il supporto al cosiddetto <b>ciclo
      convert-test-fix</b>. In pratica, si tratta della possibilità di migrare in modo iterativo
      un determinato progetto VB6 raggiungendo lo stadio <i>“zero compilation error”</i> e
      poi <i>“zero runtime error”</i> semplicemente arricchendo il sorgente VB6 con degli
      opportuni pragma, ma senza modificarlo in altro modo. Grazie al ciclo convert-test-fix
      è possibile affrontare migrazioni complesse – che possono durare anche settimane o
      mesi – mantenendo sempre sincronizzati le versioni VB6 e VB.NET della applicazione.
   </p>
        <p>
      Io sono particolarmente contento delle feature del <b>refactoring engine</b>, che
      dopo la prima conversione “grezza” applica al codice VB.NET numerose tecniche di ottimizzazione.
      Ad esempio, è in grado di accorpare la dichiarazione e l’inizializzazione di variabili,
      di generare istruzioni Return, di sfruttare gli operatori composti di assegnazione
      (tipo += e *=), e di altro ancora:
   </p>
        <pre>
Function GetValue() As Long     =&gt;     Function GetValue() As Integer
   Dim x As Long                          Dim x As Integer = 123
   x = 123                                ...
   ...                                    If x &gt; 0 Then
   If x &gt; 0 Then                             Return x
      GetValue = x                        ElseIf x = 0 Then
	  Exit Function                          Return -1
   ElseIf x = 0 Then                      End If
      GetValue = -1                       ...
	  Exit Function                       x += 1
   End If                                 ...
   ...                                 End Function
   x = x + 1
End Function
</pre>
        <p>
      Ci sono altri tipi di refactoring che si possono ottenere mediante opportuni pragma.
      Ad esempio, è possibile inserire la dichiarazione di una variabile dentro un ciclo
      For o For Each, come in questo esempio:
   </p>
        <pre>
Dim i As Integer                =&gt;     For i As Integer = 1 To 100
For i = 1 To 100                          ...
   ...                                 Next
Next
</pre>
        <p>
      Ciliegina sulla torta: nonostante tutte queste feature VB Migration Partner è circa <b>8
      volte più veloce</b> dell’Upgrade Wizard incluso in Visual Studio. Devo dire che mi
      sono tolto una bella soddisfazione!
   </p>
        <p>
      Siamo alla fine di questo lungo post, ma ne seguiranno altri. Potete scoprire tutto
      (ma veramente tutto!) su VB Migration Partner sul nuovo sito <a href="http://www.vbmigration.com/">www.vbmigration.com</a>,
      dove troverete anche molto materiale sulla migrazione <i>tout court</i> nonchè <a href="http://www.vbmigration.com/Blog/default.aspx">il
      mio nuovo blog in inglese</a>, tutto dedicato alle problematiche di migrazione da
      VB6.
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=cbed76be-be56-454b-a5a4-a116c7edabcd" />
      </body>
      <author>Francesco Balena</author>
      <title>VB Migration Partner è in beta</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,cbed76be-be56-454b-a5a4-a116c7edabcd.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,cbed76be-be56-454b-a5a4-a116c7edabcd.aspx</link>
      <pubDate>Tue, 27 Nov 2007 13:20:44 GMT</pubDate>
      <description>&lt;p&gt;
   VB Migration Partner - il progetto a cui ho lavorato praticamente a tempo pieno negli
   ultimi 22 mesi è finalmente in beta!
&lt;/p&gt;
&lt;p&gt;
   Cosa faccia questo tool lo dice il suo nome: è un &lt;strong&gt;convertitore di applicazioni
   da VB6 a VB.NET&lt;/strong&gt;. Immagino bene che a questo punto molti di voi scrolleranno
   le spalle e penseranno "Ancora VB6?" oppure "Ecco un altro che ci tenta!", ma la verità
   è che VB6 continua a imperversare tra le software house, anche e soprattutto perchè
   non ci sono strumenti decenti per convertire centinaia di migliaia di righe di codice
   VB6 in VB.NET, in modo veloce e (almeno relativamente) indolore. Davanti alla prospettiva
   di sprecare diversi anni uomo di lavoro sulla migrazione di un gestionale VB6 complesso,
   e di dover fare tutto a mano, beh... sono in molti a farsi indietro. Ora però ci si
   sta rendendo conto che la decisione non può più essere rimandata: è risaputo che i
   programmi VB6 non funzionano bene sotto Vista (in particolare, non funzionano molti
   controlli ActiveX) e soprattutto Microsoft ha dichiarato che &lt;a href="http://msdn2.microsoft.com/en-us/vbrun/ms788707.aspx"&gt;il
   supporto esteso per VB6 termina a Marzo del 2008&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
   Il problema dei convertitori automatici di codice è che quasi mai mantengono le promesse,
   si tratti di conversione da VB6, Java, Delphi, o qualsiasi altro linguaggio. Nel migliore
   dei casi, riescono a convertire circa il 95% delle istruzioni, ma con una applicazione
   VB6 da 100mila righe (quindi neanche estremamente complesse), il 5% di istruzioni
   errate significa dover mettere mano a &lt;strong&gt;&lt;i&gt;cinque mila righe&lt;/i&gt;&lt;/strong&gt;! Quel
   che è peggio è che quasi sempre non si tratta di piccole modifiche che prendono qualche
   minuto. Ad es. VB6 e VB.NET espongono due modelli completamente differenti per le
   istruzioni grafiche, il printing, e il drag-and-drop, quindi in realtà anche se il
   compilatore VB.NET segnala relativamente pochi errori, in effetti per implementare
   grafica, printing, e D&amp;amp;D in VB.NET occorrerà rifare intere porzioni di programma.
   Per non parlare di tutti i controlli ActiveX non supportati, il databinding, e tanto
   altro.
&lt;/p&gt;
&lt;p&gt;
   Nei test che abbiamo eseguito su centinaia di applicazioni VB6 (circa un milione di
   righe di codice in totale), VB Migration Partner offre la notevole media di &lt;strong&gt;un
   errore di compilazione ogni 1,100 righe di codice&lt;/strong&gt;, ovvero una percentuale
   di precisione superiore al 99.9%. Scusate se è poco! Del resto, per avere una idea
   della precisione di questo strumento, basta un piccolo elenco delle feature di VB6
   che sono pienamente supportate (eccetto dove indicato) e che sono quasi tutti fuori
   dalla portata di qualsiasi altro strumento sul mercato, incluso ovviamente l’Upgrade
   Wizard incluso in Visual Studio:
&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
   &lt;li&gt;
      array con indice LBound diverso da zero&lt;/li&gt;
   &lt;li&gt;
      Gosub, On...Goto, e On ...Gosub&lt;/li&gt;
   &lt;li&gt;
      variabili auto-instancing (Dim x As New Person) che mantengono il comportamento anche
      in VB.NET&lt;/li&gt;
   &lt;li&gt;
      Declare con parametri As Any e indirizzi di callback (es. EnumWindows)&lt;/li&gt;
   &lt;li&gt;
      proprietà di default risolte correttamente anche in modalità late-bound&lt;/li&gt;
   &lt;li&gt;
      finalizzazione deterministica per le variabili di tipo Connection, Recordset, ecc.,
      ad es. per ottenere che la connessione sia chiusa quando la variabile è messa a Nothing
      o esce dallo scope&lt;/li&gt;
   &lt;li&gt;
      supporto (limitato) per Variant e propagazione dei valori Null&lt;/li&gt;
   &lt;li&gt;
      tutti i 60+ controlli di VB6 (uniche eccezioni: OLE e Repeater)&lt;/li&gt;
   &lt;li&gt;
      control array, anche di controlli ActiveX di terze parti&lt;/li&gt;
   &lt;li&gt;
      menu popup&lt;/li&gt;
   &lt;li&gt;
      metodo Controls.Add e oggetti VBControlExtender per creare dinamicamente form di data
      entry&lt;/li&gt;
   &lt;li&gt;
      metodi grafici (Line, Circle, PSet, PaintPicture, ecc.) con supporto per ScaleMode
      custom&lt;/li&gt;
   &lt;li&gt;
      oggetto Printer e collection Printers&lt;/li&gt;
   &lt;li&gt;
      OLE drag-and-drop&lt;/li&gt;
   &lt;li&gt;
      UserControl, con supporto di feature avanzate e oggetti Ambient e Extender&lt;/li&gt;
   &lt;li&gt;
      data-binding con controlli Data ADO, RDO, ADO, con recordset ADO, con DataEnvironment&lt;/li&gt;
   &lt;li&gt;
      classi DataEnvironment non gerarchici 
   &lt;/li&gt;
   &lt;li&gt;
      classi e user control ADO data source e simple data consumer&lt;/li&gt;
   &lt;li&gt;
      classi MultiUse, PublicNotCreatable, GlobalMultiUse&lt;/li&gt;
   &lt;li&gt;
      classi persistable, classi MTS/COM+&lt;/li&gt;
&lt;/ul&gt;
&gt;
&lt;p&gt;
   In realtà, è più semplice elencare cosa il nostro tool &lt;b&gt;&lt;i&gt;non&lt;/i&gt;&lt;/b&gt; supporta:
   gli UserDocument, le PropertyPage, le WebClass, gli DHTML Page designer, istruzioni
   non documentate (VarPtr, ObjPtr, StrPtr), il drag-and-drop “classico” (non OLE D&amp;amp;D),
   e poco altro.
&lt;/p&gt;
&lt;p&gt;
   VB Migration Partner è in grado di convertire un intero &lt;b&gt;gruppo di progetti VB6&lt;/b&gt; in
   una sola operazione, e riesce a generare codice di migliore qualità proprio perchè
   riesce a vedere “dentro” una DLL che fa parte del project group. Il tool dispone anche
   di un &lt;b&gt;code analyzer&lt;/b&gt; molto sofisticato, in grado ad esempio di segnalare classi,
   metodi, e variabili non utilizzate: se si considera che in un progetto di grandi dimensioni
   che si è evoluto negli anni molto spesso il 5-10% di codice è “dead code”, si vede
   che questa feature da sola è in grado di far risparmiare parecchio tempo prezioso.
&lt;/p&gt;
&lt;p&gt;
   Uno dei segreti dell’alto tasso di conversione senza errori è il supporto per i &lt;b&gt;migration
   pragmas&lt;/b&gt;. Un pragma di migrazione non è che uno speciale commento inserito nel
   codice VB6 che indica a VB Migration Partner come convertire certi costrutti che permettono
   approcci differenti. Per esempio, il seguente pragma ArrayBounds indica che l’indice
   di tutti gli array nel progetto corrente deve essere forzato a zero:
&lt;/p&gt;
&lt;pre&gt;
          '##project:ArrayBounds ForceZero
&lt;/pre&gt;
&lt;p&gt;
   I pragma possono avere scope di progetto, di classe, di metodo o di singolo elemento;
   un pragma ha sempre la precedenza su tutti i pragma dello stesso tipo con scope più
   ampio. Per esempio, io posso fare l’override del precedente pragma dentro un metodo,
   e specificare un ulteriore pragma relativo ad uno specifico array:
&lt;/p&gt;
&lt;pre&gt;
          Sub Test()
             '## ArrayBounds Shift
             '##arr.ForceZero
             Dim names(1 To 10) As String
             Dim values(1 To 10) As Long
             Dim arr(1 To 10) As Integer
          End Sub
&lt;/pre&gt;
&lt;p&gt;
   L’opzione Shift indica a VB Migration Partner che i valori di LBound e UBound dell’array
   devono essere “shiftati” verso lo zero, in modo da preservare il numero di elementi
   dell’array originario in VB6:
&lt;/p&gt;
&lt;pre&gt;
          Sub Test()
             Dim names(9) As String
             Dim values(9) As Integer
             Dim arr(0 To 10) As Short
          End Sub
&lt;/pre&gt;
&lt;p&gt;
   VB Migration Partner supporta una cinquantina di pragma per gli scope più differenti.
   Ad esempio, SetName modifica il nome di un elemento, SetType il suo tipo, AutoNew
   implementa il comportamento auto-instancing delle variabili As New, AutoDispose fa
   sì che le variabili siano “disposed” correttamente prima di essere impostate a Nothing,
   ecc.
&lt;/p&gt;
&lt;p&gt;
   Uno dei difetti principali di un tool di conversione “tradizionale” è il fatto che
   – dopo la prima conversione – il progetto originario VB6 e il nuovo progetto VB.NET
   vivono due vite completamente separate. Se la migrazione dura settimane o mesi – com’è
   plausibile per i gestionali di grandi dimensioni – quando finalmente il programma
   VB.NET compila ed esegue senza errori il codice sarà già “vecchio”, ovvero non allineato
   alle modifiche e ai bugfix che nel frattempo sono state apportate al programma VB6.
&lt;/p&gt;
&lt;p&gt;
   Per evitare questo problema, VB Migration Partner offre il supporto al cosiddetto &lt;b&gt;ciclo
   convert-test-fix&lt;/b&gt;. In pratica, si tratta della possibilità di migrare in modo iterativo
   un determinato progetto VB6 raggiungendo lo stadio &lt;i&gt;“zero compilation error”&lt;/i&gt; e
   poi &lt;i&gt;“zero runtime error”&lt;/i&gt; semplicemente arricchendo il sorgente VB6 con degli
   opportuni pragma, ma senza modificarlo in altro modo. Grazie al ciclo convert-test-fix
   è possibile affrontare migrazioni complesse – che possono durare anche settimane o
   mesi – mantenendo sempre sincronizzati le versioni VB6 e VB.NET della applicazione.
&lt;/p&gt;
&lt;p&gt;
   Io sono particolarmente contento delle feature del &lt;b&gt;refactoring engine&lt;/b&gt;, che
   dopo la prima conversione “grezza” applica al codice VB.NET numerose tecniche di ottimizzazione.
   Ad esempio, è in grado di accorpare la dichiarazione e l’inizializzazione di variabili,
   di generare istruzioni Return, di sfruttare gli operatori composti di assegnazione
   (tipo += e *=), e di altro ancora:
&lt;/p&gt;
&lt;pre&gt;
Function GetValue() As Long     =&gt;     Function GetValue() As Integer
   Dim x As Long                          Dim x As Integer = 123
   x = 123                                ...
   ...                                    If x &gt; 0 Then
   If x &gt; 0 Then                             Return x
      GetValue = x                        ElseIf x = 0 Then
	  Exit Function                          Return -1
   ElseIf x = 0 Then                      End If
      GetValue = -1                       ...
	  Exit Function                       x += 1
   End If                                 ...
   ...                                 End Function
   x = x + 1
End Function
&lt;/pre&gt;
&lt;p&gt;
   Ci sono altri tipi di refactoring che si possono ottenere mediante opportuni pragma.
   Ad esempio, è possibile inserire la dichiarazione di una variabile dentro un ciclo
   For o For Each, come in questo esempio:
&lt;/p&gt;
&lt;pre&gt;
Dim i As Integer                =&gt;     For i As Integer = 1 To 100
For i = 1 To 100                          ...
   ...                                 Next
Next
&lt;/pre&gt;
&lt;p&gt;
   Ciliegina sulla torta: nonostante tutte queste feature VB Migration Partner è circa &lt;b&gt;8
   volte più veloce&lt;/b&gt; dell’Upgrade Wizard incluso in Visual Studio. Devo dire che mi
   sono tolto una bella soddisfazione!
&lt;/p&gt;
&lt;p&gt;
   Siamo alla fine di questo lungo post, ma ne seguiranno altri. Potete scoprire tutto
   (ma veramente tutto!) su VB Migration Partner sul nuovo sito &lt;a href="http://www.vbmigration.com/"&gt;www.vbmigration.com&lt;/a&gt;,
   dove troverete anche molto materiale sulla migrazione &lt;i&gt;tout court&lt;/i&gt; nonchè &lt;a href="http://www.vbmigration.com/Blog/default.aspx"&gt;il
   mio nuovo blog in inglese&lt;/a&gt;, tutto dedicato alle problematiche di migrazione da
   VB6.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=cbed76be-be56-454b-a5a4-a116c7edabcd"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,cbed76be-be56-454b-a5a4-a116c7edabcd.aspx</comments>
      <category>Migrazione da VB6</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,cbed76be-be56-454b-a5a4-a116c7ed527d.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,cbed76be-be56-454b-a5a4-a116c7ed527d.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,cbed76be-be56-454b-a5a4-a116c7ed527d.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=cbed76be-be56-454b-a5a4-a116c7ed527d</wfw:commentRss>
      <slash:comments>0</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://www.microsoft.com/silverlight/default_ns.aspx">
            <b>Silverlight</b>
          </a> in
      primis, ma anche le anteprime di <a href="http://go.microsoft.com/?linkid=7168453">Visual
      Studio 2008</a> e <a href="http://go.microsoft.com/?linkid=7168454">Windows server
      2008</a>, sono solo alcune delle novità che promettono un inverno più caldo di questa
      torrida estate italiana.
   </p>
        <p>
      Un aspetto trascurato, ma che non può lasciarci indifferenti, è che molte di queste
      novità hanno avuto un contributo da rappresentanti del Bel Paese. Sviluppatori, program
      manager, tester, evangelisti, ognuno di questi ruoli è rappresentato anche da italiani
      illustri come Vittorio Bertocci, Marco Ottaviani, il caro Aldo Donetti e molti altri.
      Vi segnalo una iniziativa da non perdere legata al nuovo tag center di <a href="http://channel9.msdn.com/">Channel9</a>: <a href="http://go.microsoft.com/?linkid=7168461">Italia9</a>.
      Vittorio Bertocci, si prodigherà in una serie di interviste, rigorosamente in italiano,
      in giro per il campus di Redmond parlandoci direttamente nella nostra lingua. Grande
      !!! Altre interviste saranno disponibili nei prossimi mesi; in linea è già disponibile
      la prima, fatta a Marco Ottaviani, devlead per le Performance nel Connected Framework
      team (Windows Communication Foundation, Windows Workflow), nella quale Marco ci mostra
      qualche errore tipico in cui si può incorrere quando si cerca di misurare le performance
      di WCF e ci svela quali strumenti utilizza nel suo mestiere.
   </p>
        <p>
      Che dire, un plauso a Vittorio e a tutti quelli che stanno sostenendo questa straordinaria
      inziativa oltre ad un in bocca al lupo per il prosieguo del lavoro a tutti i nostri
      connazionali oltreoceano dei quali essere orgogliosi.
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=cbed76be-be56-454b-a5a4-a116c7ed527d" />
      </body>
      <author>Giuseppe Dimauro</author>
      <title>Da non perdere: “la Redmond” che parla italiano</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,cbed76be-be56-454b-a5a4-a116c7ed527d.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,cbed76be-be56-454b-a5a4-a116c7ed527d.aspx</link>
      <pubDate>Wed, 01 Aug 2007 13:20:44 GMT</pubDate>
      <description>&lt;p&gt;
   &lt;a href="http://www.microsoft.com/silverlight/default_ns.aspx"&gt;&lt;b&gt;Silverlight&lt;/b&gt;&lt;/a&gt; in
   primis, ma anche le anteprime di &lt;a href="http://go.microsoft.com/?linkid=7168453"&gt;Visual
   Studio 2008&lt;/a&gt; e &lt;a href="http://go.microsoft.com/?linkid=7168454"&gt;Windows server
   2008&lt;/a&gt;, sono solo alcune delle novità che promettono un inverno più caldo di questa
   torrida estate italiana.
&lt;/p&gt;
&lt;p&gt;
   Un aspetto trascurato, ma che non può lasciarci indifferenti, è che molte di queste
   novità hanno avuto un contributo da rappresentanti del Bel Paese. Sviluppatori, program
   manager, tester, evangelisti, ognuno di questi ruoli è rappresentato anche da italiani
   illustri come Vittorio Bertocci, Marco Ottaviani, il caro Aldo Donetti e molti altri.
   Vi segnalo una iniziativa da non perdere legata al nuovo tag center di &lt;a href="http://channel9.msdn.com/"&gt;Channel9&lt;/a&gt;: &lt;a href="http://go.microsoft.com/?linkid=7168461"&gt;Italia9&lt;/a&gt;.
   Vittorio Bertocci, si prodigherà in una serie di interviste, rigorosamente in italiano,
   in giro per il campus di Redmond parlandoci direttamente nella nostra lingua. Grande
   !!! Altre interviste saranno disponibili nei prossimi mesi; in linea è già disponibile
   la prima, fatta a Marco Ottaviani, devlead per le Performance nel Connected Framework
   team (Windows Communication Foundation, Windows Workflow), nella quale Marco ci mostra
   qualche errore tipico in cui si può incorrere quando si cerca di misurare le performance
   di WCF e ci svela quali strumenti utilizza nel suo mestiere.
&lt;/p&gt;
&lt;p&gt;
   Che dire, un plauso a Vittorio e a tutti quelli che stanno sostenendo questa straordinaria
   inziativa oltre ad un in bocca al lupo per il prosieguo del lavoro a tutti i nostri
   connazionali oltreoceano dei quali essere orgogliosi.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=cbed76be-be56-454b-a5a4-a116c7ed527d"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,cbed76be-be56-454b-a5a4-a116c7ed527d.aspx</comments>
      <category>Eventi</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37</wfw:commentRss>
      <slash:comments>0</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      Oggi gironzolavo per la rete e ho trovato un <a href="http://discuss.joelonsoftware.com/default.asp?design.4.502229.13">forum </a>dove
      qualcuno poneva la seguente domanda: "<em>data la stringa ABCD è possibile scrivere
      una regular expression che fa il match con un qualsiasi anagramma di tale stringa
      - ad es. DBAC o CDBA ma non ABDE oppure AABC?</em>". Ovviamente la domanda era intrigante
      per uno che come me smanetta molto con le regex, e stranamente non l'avevo mai vista
      in giro. Qualcuno obiettava che le regex non erano abbastanza potenti, e che serviva
      scrivere un piccolo programmino per testare le varie combinazioni, quindi mi sono
      sentito in obbligo di pensarci un po' su e postare la mia soluzione.
   </p>
        <p>
      Se state semplicemente controllando che una stringa fornita dall'utente sia una permutazione
      di ABCD la soluzione è in effetti molto semplice:
   </p>
        <p>
      ^(?=.*a)(?=.*b)(?=.*c)(?=.*d)[abcd]{4}$
   </p>
        <p>
      dove il costrutto <strong>(?=.*a) </strong>si chiama <em>positive lookahead </em>ed
      esegue il match con l'espressione nella parentesi <em>ma senza consumare caratteri</em>,
      quindi in altre parole significa che la stringa deve contenere il carattere A da qualche
      parte, ovvero preceduto da zero o più caratteri. Con le successive espressioni positive
      lookahead si controlla che nella stringa ci siano anche i caratteri B,C e D. Quando
      questa fase è completata, la regex [abcd]{4} assicura che la stringa contenga <strong>solo</strong> questi
      quattro caratteri e non altri.
   </p>
        <p>
      Se invece stiamo cercando tutti i possibili anagrammi di ABCD all'interno di un testo
      di lunghezza qualsiasi, allora la regex è solo leggermente più complicata:
   </p>
        <p>
      \b(?=.{0,3}a)(?=.{0,3}b)(?=.{0,3}c)(?=.{0,3}d)[abcd]{4}\b
   </p>
        <p>
      In questo caso oltre a imporre che i caratteri A,B,C,D siano tutti presenti ci accertiamo
      anche che non distino più di 3 caratteri dall'inizio della parola, e usiamo i delimitatori
      \b per imporre che la parola stessa contenga esattamente quattro caratteri. Ovviamente
      dovete specificare se il case dei caratteri è significativo o meno, perchè il match
      avvenga indipendentemente dal fatto che le parole siano in maiuscolo o minuscolo.
   </p>
        <p>
        </p>
        <p>
        </p>
        <p>
        </p>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37" />
      </body>
      <author>Francesco Balena</author>
      <title>Anagrammi e regular expression</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37.aspx</link>
      <pubDate>Wed, 06 Jun 2007 09:30:10 GMT</pubDate>
      <description>&lt;p&gt;
   Oggi gironzolavo per la rete e ho trovato un &lt;a href="http://discuss.joelonsoftware.com/default.asp?design.4.502229.13"&gt;forum &lt;/a&gt;dove
   qualcuno poneva la seguente domanda: "&lt;em&gt;data la stringa ABCD è possibile scrivere
   una regular expression che fa il match con un qualsiasi anagramma di tale stringa
   - ad es. DBAC o CDBA ma non ABDE oppure AABC?&lt;/em&gt;". Ovviamente la domanda era intrigante
   per uno che come me smanetta molto con le regex, e stranamente non l'avevo mai vista
   in giro. Qualcuno obiettava che le regex non erano abbastanza potenti, e che serviva
   scrivere un piccolo programmino per testare le varie combinazioni, quindi mi sono
   sentito in obbligo di pensarci un po' su e postare la mia soluzione.
&lt;/p&gt;
&lt;p&gt;
   Se state semplicemente controllando che una stringa fornita dall'utente sia una permutazione
   di ABCD la soluzione è in effetti molto semplice:
&lt;/p&gt;
&lt;p&gt;
   ^(?=.*a)(?=.*b)(?=.*c)(?=.*d)[abcd]{4}$
&lt;/p&gt;
&lt;p&gt;
   dove il costrutto &lt;strong&gt;(?=.*a) &lt;/strong&gt;si chiama &lt;em&gt;positive lookahead &lt;/em&gt;ed
   esegue il match con l'espressione nella parentesi &lt;em&gt;ma senza consumare caratteri&lt;/em&gt;,
   quindi in altre parole significa che la stringa deve contenere il carattere A da qualche
   parte, ovvero preceduto da zero o più caratteri. Con le successive espressioni positive
   lookahead si controlla che nella stringa ci siano anche i caratteri B,C e D. Quando
   questa fase è completata, la regex [abcd]{4} assicura che la stringa contenga &lt;strong&gt;solo&lt;/strong&gt; questi
   quattro caratteri e non altri.
&lt;/p&gt;
&lt;p&gt;
   Se invece stiamo cercando tutti i possibili anagrammi di ABCD all'interno di un testo
   di lunghezza qualsiasi, allora la regex è solo leggermente più complicata:
&lt;/p&gt;
&lt;p&gt;
   \b(?=.{0,3}a)(?=.{0,3}b)(?=.{0,3}c)(?=.{0,3}d)[abcd]{4}\b
&lt;/p&gt;
&lt;p&gt;
   In questo caso oltre a imporre che i caratteri A,B,C,D siano tutti presenti ci accertiamo
   anche che non distino più di 3 caratteri dall'inizio della parola, e usiamo i delimitatori
   \b per imporre che la parola stessa contenga esattamente quattro caratteri. Ovviamente
   dovete specificare se il case dei caratteri è significativo o meno, perchè il match
   avvenga indipendentemente dal fatto che le parole siano in maiuscolo o minuscolo.
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,d05d7bd5-5b99-4f96-9f0b-0aa828cc1d37.aspx</comments>
      <category>.NET Framework</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,d40b1b7e-3499-44af-9692-90f37a70bb33.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,d40b1b7e-3499-44af-9692-90f37a70bb33.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,d40b1b7e-3499-44af-9692-90f37a70bb33.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d40b1b7e-3499-44af-9692-90f37a70bb33</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <author>Francesco Balena</author>
      <title>Proteggere gli assembly dalla decompilazione e dalle copie illegali !</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,d40b1b7e-3499-44af-9692-90f37a70bb33.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,d40b1b7e-3499-44af-9692-90f37a70bb33.aspx</link>
      <pubDate>Mon, 04 Jun 2007 20:06:09 GMT</pubDate>
      <description>&lt;p&gt;
   &lt;strong&gt;Premessa. &lt;/strong&gt;Non so se questa piccola scoperta che ho fatto di recente
   sia già documentata da qualche parte su Internet. Non ne ho mai sentito parlare, ma
   mi sembra strano che nessun’altro ci abbia pensato prima. Comunque, ci sono arrivato
   da solo e questo è sufficiente per scriverne sul blog.
&lt;/p&gt;
&lt;p&gt;
   &lt;hr&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
   Mi sembra inutile rimarcare il fatto che uno dei problemi che assilla chi scrive software
   per professione è la protezione dalle copie. In più, se programmate con .NET avete
   anche il problema di proteggere le applicazioni dalla decompilazione. Ovviamente i
   due problemi sono collegati, perchè se volete proteggere una applicazione con qualche
   meccanismo software (ad es. la lettura delle caratteristiche della macchina su cui
   il cliente installa la sua copia) occorre evitare che una semplice decompilazione
   + ricompilazione possa permettere ad un hacker neanche troppo esperto di bypassare
   la vostra protezione.
&lt;/p&gt;
&lt;p&gt;
   Non si tratta certo di problemi nati con .NET. Una quindicina di anni fa campavo sviluppando
   tool per programmatori con la mia azienda personale – la SoftWhale, dove “Whale” =
   “Balena” per chi non lo sapesse – e uno dei miei prodotti più gettonati era NOWAY,
   un programma che crittografava gli eseguibili MS-DOS proteggendoli quindi dalla decompilazione
   (un problema molto sentito da chi lavorava in Clipper) e permetteva di lanciarli solo
   sui computer per i quali la software house forniva al cliente dei codici di sblocco.
   NOWAY era scritto in puro Assembly 8086 e non è sopravvissuto al passaggio da MS-DOS
   a Windows. 
&lt;/p&gt;
&lt;p&gt;
   In commercio esistono molti tool per .NET che servono a risolvere questi problemi,
   incluso obfuscator, compilatori “nativi” e chiavi hardware. Se volete proteggere la
   vostra IP (Intellectual Property) dovreste darci una occhiata approfondita.Per nostra
   fortuna, in Code Architects scriviamo soprattutto applicazioni Enterprise che non
   richiedono questo tipo di protezione, quindi non ho mai approfondito la questione.
   Immagino che questi tool facciano bene il loro lavoro, e li testerò se e quando avremo
   la necessità di farlo. 
&lt;/p&gt;
&lt;p&gt;
   Se però &lt;strong&gt;(a)&lt;/strong&gt; scrivete perlopiù applicazioni Windows Forms, &lt;strong&gt;(b)&lt;/strong&gt; non
   vendete software pacchettizzato ed eseguite direttamente voi le installazioni presso
   il cliente, e &lt;strong&gt;(c)&lt;/strong&gt; fate anche assistenza post-vendita, allora è possibile
   ottenere la protezione dalla decompilazione e dalle copie illegali con un meccanismo
   davvero molto semplice.
&lt;/p&gt;
&lt;p&gt;
   Cominciamo scrivendo una semplice applicazione Windows Forms. In questo esempio uso
   VB2005 ma ovviamente la tecnica si applica a qualsiasi linguaggio .NET.
&lt;/p&gt;
&lt;p&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;Imports&lt;/span&gt;&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt; System.Reflection&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;Friend&lt;/span&gt;&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Module&lt;/span&gt;&lt;font color=#000000&gt; Module1&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;STAThread()&amp;gt;
   _&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Public&lt;/span&gt;&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Sub&lt;/span&gt;&lt;font color=#000000&gt; Main()&lt;span style="mso-tab-count: 1"&gt; &lt;/span&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR: green"&gt;'
   in this demo we call the secret routine both directly and via reflection&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR: green"&gt;'
   just to prove that either method works&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;MySecretCode(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"Direct
   call"&lt;/span&gt;&lt;font color=#000000&gt;)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR: blue"&gt;GetType&lt;/span&gt;&lt;font color=#000000&gt;(Module1).InvokeMember(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"MySecretCode"&lt;/span&gt;&lt;font color=#000000&gt;,
   BindingFlags.InvokeMethod, _&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;Nothing&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Nothing&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: blue"&gt;New&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Object&lt;/span&gt;&lt;font color=#000000&gt;()
   {&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"Reflection call"&lt;/span&gt;&lt;font color=#000000&gt;})&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;End&lt;/span&gt;&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Sub&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;
   &lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;Public&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Sub&lt;/span&gt;&lt;font color=#000000&gt; MySecretCode(&lt;/font&gt;&lt;span style="COLOR: blue"&gt;ByVal&lt;/span&gt;&lt;font color=#000000&gt; title &lt;/font&gt;&lt;span style="COLOR: blue"&gt;As&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;String&lt;/span&gt;&lt;font color=#000000&gt;)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;#&lt;/font&gt;&lt;span style="COLOR: blue"&gt;If&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Not&lt;/span&gt;&lt;font color=#000000&gt; COPYPROTECT &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Then&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR: green"&gt;'
   here goes all the code that you want to protect from decompilation&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;MessageBox.Show(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"Running
   secret code!"&lt;/span&gt;&lt;font color=#000000&gt;, title)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR: green"&gt;'
   ...&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;#&lt;/font&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;If&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Sub&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="COLOR: blue"&gt;&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Module&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;
   Poichè la variabile di compilazione COPYPROTECT non è definita, il codice nel metodo
   MySecretCode è incluso nell’eseguibile come se il blocco #IF non esistesse. In questo
   esempio proteggo un solo metodo, ma in una applicazione reale dovreste ripetere il
   procedimento con tutti i metodi che contengono del codice critico, magari dove implementate
   gli algoritmi più interessanti oppure dove controllate che l’utente abbia la licenza
   di eseguire il programma sul computer in questione. &lt;strong&gt;&lt;font color=#ff0000&gt;È
   importante che tutti i blocchi #IF... #ENDIF siano completamente contenuti in singoli
   metodi&lt;/font&gt;&lt;/strong&gt;, ovvero che non capiti mai che uno di questi blocchi contenga
   le keyword Sub o Function (o le corrispettive End Sub o End Function). Per lo stesso
   motivo, potete utilizzare il meccanismo anche con le Property ma solo se utilizzate
   i blocchi #IF all’interno del blocco Get o Set. I blocchi #IF non devono assolutamente
   includere field, definizioni di eventi, o altro.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
   Per completare la preparazione è opportuno definire una nuova configurazione per la
   soluzione. Dal menù Build selezionate il comando Configuration Manager, dalla combobox
   in alto a sinistra selezionate &amp;lt;New&amp;gt; e create una configurazione chiamata CopyProtected,
   che copia le impostazioni iniziali dalla configurazione Release. 
   &lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://www.dotnet2themax.it/blog/content/binary/CopyProtection1.gif" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   Dopo esservi accertati che la nuova configurazione è quella attiva, create una costante
   condizionale di compilazione chiamata COPYPROTECT e impostata al valore True. In C#
   questa costante si crea dalla pagina Build delle proprietà di progetto, mentre in
   VB2005 dovete cliccare sul pulsante Advanced Compile Options che trovate nella pagina
   Compile:
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://www.dotnet2themax.it/blog/content/binary/CopyProtection2.gif" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   Grazie a questa nuova configurazione, potete passare facilmente dalla versione normale
   (ossia Release) a quella copy-protected. Compilando l’applicazione in entrambe le
   configurazioni, avrete due eseguibili con lo stesso nome (ad es. Project1.exe) e contenenti
   gli stessi metadati (perchè le #IF sono sempre all’interno dei metodi e non includono
   campi, proprietà, o altro). L’esempio che segue presume che abbiate compilato una
   applicazione che si chiama Project1, che NON è firmata con uno strong name.
&lt;/p&gt;
&lt;p&gt;
   Preparate il setup, se necessario, utilizzando la versione Release, ma ricordatevi
   anche di memorizzare separatamente (ad es. su una chiavetta USB) l’eseguibile ottenuto
   in configurazione copy-protected e l’utility NGEN fornita con .NET Framework. Infine,
   recatevi presso il vostro cliente e seguite accuratamente la semplice procedura: 
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;1)&lt;/strong&gt;&amp;nbsp;Lanciate il setup della applicazione, o più banalmente utilizzate
   XCOPY per copiare tutti i file sul disco rigido del cliente. In questo esempio supporremo
   che l’installazione sia avvenuta nella directory c:\myapp e che quindi il file eseguibile
   sia c:\myapp\Project1.exe.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;2)&lt;/strong&gt;&amp;nbsp;Aprite una finestra di comandi, navigate nella directory
   che contiene l’esegubile e lanciate NGEN per creare una immagine in codice nativo
   della applicazione. Il comportamento di default di NGEN è OK, quindi non preoccupatevi
   troppo delle varie opzioni. (Lasciate aperta questa finestra, perchè vi servirà presto.)
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;3)&lt;/strong&gt;&amp;nbsp;Aprite una seconda finestra di comandi, navigate nella directory
   c:\windows\assembly\NativeImages_v2.0.50727_32\&lt;strong&gt;nomeassembly&lt;em&gt;,&lt;/em&gt;&lt;/strong&gt; dove &lt;em&gt;nomeassembly &lt;/em&gt;è
   il nome dell’EXE ma senza l’estensione (Project1 in questo esempio). Noterete che
   in questa directory contiene una sottodirectory il cui nome è una stringa di caratteri
   esadecimali (nel mio esempio ho ottenuto d37032afe4f6f44588d52ca99d7bb1e5). Questa
   directory contiene un eseguibile dal nome nomeassembly.ni.exe (Project1.ni.exe nel
   nostro esempio), che contiene la versione compilata (senza IL e quindi non decompilabile)
   dell’eseguibile completo.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;4)&lt;/strong&gt;&amp;nbsp;Dal prompt della seconda finestra dei comandi, con un comando
   COPY o MOVE spostate il file &amp;lt;&lt;strong&gt;nomeassembly&amp;gt;.ni.exe&lt;/strong&gt; su qualche
   altra directory del disco rigido, ad esempio:&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MOVE d37032afe4f6f44588d52ca99d7bb1e5\Project1.ni.exe c:\&lt;br&gt;
   Questa operazione serve ad evitare che questo eseguibile sia cancellato dalla successiva
   invocazione di NGEN. Lasciate aperta anche questa seconda finestra dei comandi.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;5)&lt;/strong&gt;&amp;nbsp;Sovrascrivete il file c:\myapp\Project1.exe con la versione
   copy-protected che avete sulla chiavetta USB.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;6)&lt;/strong&gt;&amp;nbsp;Dalla prima finestra di comandi lanciate nuovamente NGEN,
   questa volta sulla versione copy-protected. Se questo programma venisse eseguito ora
   probabilmente andrebbe in errore o comunque non funzionerebbe bene, perchè alcune
   parti del codice non sono presenti, quindi NON lo mandate in esecuzione.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;7)&lt;/strong&gt;&amp;nbsp;Dalla seconda finestra dei comandi, eseguite un comando DIR
   e noterete che la directory creata precedentemente (d37032afe4f6f44588d52ca99d7bb1e5,
   in questo esempio) è stata sostituita oppure è stata affiancata da un’altra directory
   dal nome random. (Nell’esempio che sto eseguendo mentre scrivo queste note è stata
   creata una directory di nome 9990426218ec334e9d3d62f41cb9a255.) Questa nuova directory
   contiene una nuova versione di Project1.ni.exe, che corrisponde alla versione in codice
   nativo dell'’eseguibile incompleto.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;8)&lt;/strong&gt;&amp;nbsp;Sempre dalla seconda finestra dei comandi, copiate la copia
   precedente di Project1.ni.exe (salvata al punto #4) sulla nuova copia, ad esempio
   con questo comando:&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MOVE c:\project1.ni.exe 9990426218ec334e9d3d62f41cb9a255&lt;br&gt;
   rispondendo Yes alla domanda se intendiamo sovrascrivere il file Project1.ni.exe. 
&lt;/p&gt;
&lt;p&gt;
   Fatto! Ora potete staccare la chiavetta USB e lasciare sul disco rigido del vostro
   cliente solo l'assembly "copy-protected" (in versione&amp;nbsp;IL) e l'assembly completo
   (solo in versione compilata in modo nativo e quindi non decompilabile). Per quanto
   può sembrare incredibile, l'applicazione funziona correttamente e&amp;nbsp;mostra le due
   message box :-) Ma se provate a usare ILDASM o Reflector per sbirciare dentro il metodo
   MySecretCode (e qualsiasi altro metodo il cui interno è racchiuso con un #IF Not COPYPROTECT)
   troverete che il metodo è vuoto! 
   &lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://www.dotnet2themax.it/blog/content/binary/CopyProtection3.gif" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   Ovviamente neanche Reflector riesce a decompilare alcunchè, visto che proprio manca
   il codice IL. Nè aiuta usare ILDASM sull’eseguibile Project1.ni.exe, perchè l’unica
   cosa che si ottiene è visualizzare un manifest senza codice IL:
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://www.dotnet2themax.it/blog/content/binary/CopyProtection4.gif" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   Come può funzionare questa piccola magia? La spiegazione è semplice: quando lanciate
   un qualsiasi eseguibile .NET, per prima cosa il CLR va a controllare se vi è una “native
   image” che corrisponde esattamente a quella applicazione, e la corrispondenza viene
   cercata confrontando il nome della applicazione e la sua firma (la stringona esadecimale).
   Se esiste una immagine nativa, quella viene lanciata al posto dell’eseguibile. La
   condizione però perchè tutto il codice funzioni correttamente è che i metadati coincidano
   anch’essi, altrimenti troppe funzioni del CLR non funzionerebbero a dovere (il garbage
   collector, tanto per citarne il più importante). Nel nostro caso noi abbiamo creato
   due eseguibili con gli stessi metadati (ecco perchè è importante che i blocchi #IF
   non devono eliminare alcun metodo, campo, o proprietà), e siamo riusciti a mantenere
   sul disco rigido la versione IL “incompleta” mentre mandiamo in esecuzione la versione
   nativa “completa”. 
&lt;/p&gt;
&lt;p&gt;
   Oltre a proteggere dalla decompilazione, molto simpaticamente questo meccanismo protegge
   anche dalle copie illegali. Infatti, se provate a spostare tutti i file (compreso
   l’eseguibile Project1.ni.exe) su un’altro computer, è praticamente certo che l'applicazione
   NON funzionerà correttamente. Da quel che ho potuto capire, questo accade perchè il
   nome della directory creata da NGEN – ovvero la “firma” di un particolare eseguibile
   – dipende anche da qualche informazione di sistema e quindi varia da macchina a macchina.
&lt;/p&gt;
&lt;p&gt;
   Per quanto interessante, questa tecnica ha alcune limitazioni abbastanza serie:
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;A)&lt;/strong&gt; Se si intende proteggere una DLL peer Windows Forms l'assembly
   non deve essere segnato con uno strong name. Il motivo è che nel manifest degli assembly
   che referenziano una DLL con strong-name viene memorizzato anche l'hash dell'assembly
   in questione, e questo è un valore che cambia quando si compila la versione copy-protected.
   Quindi, visto che la DLL non può avere uno strong-name, neanche gli EXE che usano
   la DLL possono averlo, il che rappresenta una limitazione notevole. Questo limite
   non esiste per le applicazioni ASP.NET.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;B)&amp;nbsp;&lt;/strong&gt;Se avviene un errore in una applicazione ASP.NET protetta
   oppure si modifica il Web config in qualsiasi modo, l'applicazione smette di funzionare.
   Il problema si risolve con un IISRESET.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;C)&amp;nbsp;&lt;/strong&gt;Se avviene qualche modifica sostanziale all’hardware o al
   software di sistema – ad es. la sostituzione della CPU, l’aggiunta di memoria, l'upgrade
   del sistema operativo, ecc. – il .NET Framework non può più usare l’immagine nativa
   e lancerà l’eseguibile normale, che ovviamente non funzionerà bene perchè alcune porzioni
   di codice mancano. In quel caso occorre ripetere l’installazione e tutto il procedimento
   descritto sopra. È importante quindi mettere in guardia il vostro cliente dai rischi
   che corre facendo questi upgrade durante la notte, il fine settimana, o mentre siete
   in vacanza alle Bahamas.
&lt;/p&gt;
&lt;p&gt;
   Per mitigare il problema potete almeno fare in modo che l’applicazione mostri un chiaro
   messaggio di errore quando l’immagine nativa non è aggiornata e il CLR torna ad usare
   l’eseguibile “incompleto”. Per fare questo è sufficiente avere una istruzione MessageBox.Show
   in un blocco #IF COPYPROTECT (senza il Not), ad es:
&lt;/p&gt;
&lt;p&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;Friend&lt;/span&gt;&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Module&lt;/span&gt;&lt;font color=#000000&gt; Module1&lt;br&gt;
   &lt;/font&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;Public&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Sub&lt;/span&gt;&lt;font color=#000000&gt; Main()&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;#&lt;/font&gt;&lt;span style="COLOR: blue"&gt;If&lt;/span&gt;&lt;font color=#000000&gt; COPYPROTECT &lt;/font&gt;&lt;span style="COLOR: blue"&gt;Then&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;MessageBox.Show(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"This
   app requires reinstallation. Please contact tech support."&lt;/span&gt;&lt;font color=#000000&gt;)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR: blue"&gt;Exit
   Sub&lt;/span&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;#&lt;/font&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;If&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: green; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;'
   Here the real application begins&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: green; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;'
   ...&lt;/span&gt;&lt;span style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;End
   Sub&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;
   &lt;span style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;End
   Module&lt;/span&gt;&lt;span style="FONT-SIZE: 9pt; FONT-FAMILY: 'Lucida Console'; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;
   Per quanto ne so, Microsoft non ha mai documentato quali modifiche al sistema disabilitano
   l’immagine nativa creata con NGEN, quindi non posso essere più preciso su questo punto.
   Se qualcuno conosce qualche articolo che spiega questi casi, lo menzioni nei commenti. 
&lt;/p&gt;
&lt;p&gt;
   Per il resto, ho fatto un po’ di prove, sembra che tutto quanto fili liscio e che
   la tecnica non abbia altre controindicazioni. Se vi imbattete in qualche problema,
   fatemelo sapere.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=d40b1b7e-3499-44af-9692-90f37a70bb33"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,d40b1b7e-3499-44af-9692-90f37a70bb33.aspx</comments>
      <category>.NET Framework</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de</wfw:commentRss>
      <slash:comments>0</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <img src="http://www.dotnet2themax.it/blog/content/binary/Server_error.jpg" border="0" />
        </p>
        <p>
       
   </p>
        <p>
          <img src="http://www.dotnet2themax.it/blog/content/binary/PageNotFound_Error.jpg" border="0" />
        </p>
        <p>
      Sembra siano state scattate nella Silicon Valley e stanno diventando la barzelletta
      tra molti anti-Microsoft-tiani. Le potete trovare a <a href="http://www.tassography.com/ViewPhoto.aspx?CollectionType=Album&amp;CollectionFilter=PhotosInCollection&amp;CollectionID=167&amp;SlideShow=True&amp;PhotoID=1352">questo
      indirizzo</a>.
   </p>
        <p>
      Ovviamente, il problema non è nella tecnologia ma in quanto bene (o male, in questo
      caso) la si usa. Quanto costava controllare meglio gli errori o redirezionarli su
      una pagina più "carina"? Sicuramente meno della brutta figura che la ditta di mobili
      svedese (e non Microsoft) sta facendo. 
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de" />
      </body>
      <author>Francesco Balena</author>
      <title>La più grande pagina di errore ASP.NET</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de.aspx</link>
      <pubDate>Mon, 14 May 2007 16:13:40 GMT</pubDate>
      <description>&lt;p&gt;
   &lt;img src="http://www.dotnet2themax.it/blog/content/binary/Server_error.jpg" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://www.dotnet2themax.it/blog/content/binary/PageNotFound_Error.jpg" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   Sembra siano state scattate&amp;nbsp;nella Silicon Valley e stanno diventando la barzelletta
   tra molti anti-Microsoft-tiani. Le potete trovare a &lt;a href="http://www.tassography.com/ViewPhoto.aspx?CollectionType=Album&amp;amp;CollectionFilter=PhotosInCollection&amp;amp;CollectionID=167&amp;amp;SlideShow=True&amp;amp;PhotoID=1352"&gt;questo
   indirizzo&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
   Ovviamente, il problema non è nella tecnologia ma in quanto bene (o male, in questo
   caso) la si usa. Quanto costava controllare meglio gli errori o redirezionarli su
   una pagina più "carina"? Sicuramente meno della brutta figura che la ditta di mobili
   svedese (e non Microsoft) sta facendo. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,4f8d02a2-1948-42bb-84bf-ea5e8c5ef7de.aspx</comments>
      <category>Varie</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnet2themax.it/blog/Trackback,guid,334c17f5-aaee-4542-b086-a3c7504aad40.aspx</trackback:ping>
      <pingback:server>http://www.dotnet2themax.it/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnet2themax.it/blog/PermaLink,guid,334c17f5-aaee-4542-b086-a3c7504aad40.aspx</pingback:target>
      <wfw:comment>http://www.dotnet2themax.it/blog/CommentView,guid,334c17f5-aaee-4542-b086-a3c7504aad40.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnet2themax.it/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=334c17f5-aaee-4542-b086-a3c7504aad40</wfw:commentRss>
      <slash:comments>0</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://www.tuapensione.it/index.html">
            <img src="http://www.dotnet2themax.it/blog/content/binary/LogoTuaPensione.gif" border="0" />
          </a>
        </p>
        <p>
      Ecco un post che ha poco a che fare con la tecnologia e molto a che fare con il lavoro. 
   </p>
        <p>
      Il nostro amico <strong>Eugenio Lamesa</strong>, il migliore esperto che abbiamo in
      Italia di Mail Marketing nonchè la mente dietro il programma/sito <a href="http://www.salesware.it">SalesWare</a> (a
      cui sono orgoglioso di aver contribuito come consulente) ha da poco inaugurato
      il sito <a href="http://www.tuapensione.it/index.html">TuaPensione.it</a>, dedicato
      a chi entro il 30 giugno deve decidere cosa fare del proprio TFR. 
   </p>
        <p>
      Tra le tante iniziative Eugenio ha preparato una <a href="http://www.tuapensione.it/scaricaGuidaTFR.html">whitepaper</a> che
      spiega in modo chiaro e sintetico i dettagli della nuova leggere e come prendere la
      decisione più giusta e conveniente. Non solo le informazioni sono più chiare e dirette
      di quelle che ho potuto leggere su alcuni giornali, ma sono anche depurate dai possibili
      "conflitto di interessi" che abbondano anche in questo settore. Da qualche giorno
      su sito c'è anche un interessante <a href="http://www.tuapensione.it/TFR_SoftwareCalcolo.html">calcolatore
      online</a>, che permette di confrontare le varie opzioni. TuaPensione.it è assolutamente
      no-profit (non ci sono neanche i banner di Google!), come lo è <a href="http://www.menostato.it/">MenoStato.it</a>,
      l'altro sito a cui Eugenio lavora con passione da qualche anno.
   </p>
        <p>
       
   </p>
        <p>
       
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=334c17f5-aaee-4542-b086-a3c7504aad40" />
      </body>
      <author>Francesco Balena</author>
      <title>TuaPensione.it</title>
      <guid>http://www.dotnet2themax.it/blog/PermaLink,guid,334c17f5-aaee-4542-b086-a3c7504aad40.aspx</guid>
      <link>http://www.dotnet2themax.it/blog/PermaLink,guid,334c17f5-aaee-4542-b086-a3c7504aad40.aspx</link>
      <pubDate>Wed, 09 May 2007 17:53:49 GMT</pubDate>
      <description>&lt;p&gt;
   &lt;a href="http://www.tuapensione.it/index.html"&gt;&lt;img src="http://www.dotnet2themax.it/blog/content/binary/LogoTuaPensione.gif" border=0&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
   Ecco un post che ha poco a che fare con la tecnologia e molto a che fare con il lavoro. 
&lt;/p&gt;
&lt;p&gt;
   Il nostro amico &lt;strong&gt;Eugenio Lamesa&lt;/strong&gt;, il migliore esperto che abbiamo in
   Italia di Mail Marketing nonchè la mente dietro il programma/sito &lt;a href="http://www.salesware.it"&gt;SalesWare&lt;/a&gt;&amp;nbsp;(a
   cui sono orgoglioso di aver contribuito&amp;nbsp;come consulente)&amp;nbsp;ha da poco inaugurato
   il sito &lt;a href="http://www.tuapensione.it/index.html"&gt;TuaPensione.it&lt;/a&gt;, dedicato
   a chi entro il 30 giugno deve decidere cosa fare del proprio TFR. 
&lt;/p&gt;
&lt;p&gt;
   Tra le tante iniziative Eugenio ha preparato una &lt;a href="http://www.tuapensione.it/scaricaGuidaTFR.html"&gt;whitepaper&lt;/a&gt; che
   spiega in modo chiaro e sintetico i dettagli della nuova leggere e come prendere la
   decisione più giusta e conveniente. Non solo le informazioni sono più chiare e dirette
   di quelle che ho potuto leggere su alcuni giornali, ma sono anche depurate dai possibili
   "conflitto di interessi" che abbondano anche in questo settore. Da qualche giorno
   su sito c'è anche un interessante &lt;a href="http://www.tuapensione.it/TFR_SoftwareCalcolo.html"&gt;calcolatore
   online&lt;/a&gt;, che permette di confrontare le varie opzioni. TuaPensione.it è assolutamente
   no-profit (non ci sono neanche i banner di Google!), come lo è &lt;a href="http://www.menostato.it/"&gt;MenoStato.it&lt;/a&gt;,
   l'altro sito a cui Eugenio lavora con passione da qualche anno.
&lt;/p&gt;
&lt;p&gt;
   &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
   &amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnet2themax.it/blog/aggbug.ashx?id=334c17f5-aaee-4542-b086-a3c7504aad40"&gt;</description>
      <comments>http://www.dotnet2themax.it/blog/CommentView,guid,334c17f5-aaee-4542-b086-a3c7504aad40.aspx</comments>
      <category>Varie</category>
    </item>
  </channel>
</rss>