<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" 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:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Esame 70-536</title>
        <link>http://blogs.ugidotnet.org/IDamiani/category/Esame 70-536.aspx</link>
        <description>Serie di post sull'esame 70-536 per conseguire la certificazione MCPD</description>
        <language>it-IT</language>
        <copyright>Igor Damiani</copyright>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>[70-536, #33] Passato!</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/07/26/45355.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;Innanzitutto chiedo scusa a tutti per essere stato così 
poco produttivo nella mia serie di post relativi all'&lt;A title="" href="http://blogs.ugidotnet.org/idamiani/category/1704.aspx" target=_new name=""&gt;esame 70-536&lt;/A&gt;. Purtroppo ho avuto francamente poca voglia di scrivere 
(e studiare), e quando l'ho fatto è stato nei rari momenti in cui mi sentivo 
ispirato. Ho studiato&amp;nbsp;molto meno per questo esame, ma sono rimasto contento 
perchè se l'ho superato devo ringraziare&amp;nbsp;soprattutto la mia esperienza.&lt;/P&gt;
&lt;P&gt;L'unico rammarico è che avrei potuto prendere un punteggio nettamente 
superiore al &lt;STRONG&gt;&lt;FONT color=red&gt;718/1000&lt;/FONT&gt;&lt;/STRONG&gt; che ho miseramente 
conquistato. Ho&amp;nbsp;sfiorato i punteggi massimi in quasi tutte le categorie 
(&lt;EM&gt;&lt;FONT color=#008040&gt;Developing applications that use types and 
applications, Implementing service processes, threading and application domains 
in a .NET Framework application, Implementing serialization and input/output 
functionality in a .NET Framework application, Improving the security of .NET 
Framework applications by using the .NET Framework 2.0 security features, 
Implementing globalization, drawing and text manipulation functionality in a 
.NET Framework application&lt;/FONT&gt;&lt;/EM&gt;), ma sono letteralmente caduto a picco 
nelle ultime due categorie rimaste &lt;EM&gt;(&lt;FONT color=#008040&gt;Embedding 
configuration, diagnostic, management and installation features into a .NET 
Framework application, Implementing interoperability, reflection and mailing 
functionality in a .NET Framework application&lt;/FONT&gt;&lt;/EM&gt;). Se avrò voglia 
questa sera scansiono la parte del report e la metto on-line, così me la 
guarderò tutte le mattine e mi do le martellate sulla testa. &lt;IMG height=19 src="http://www.imhoproject.org/files/serio.gif" width=19 align=absMiddle border=0&gt;&amp;nbsp;Devo dire che più che la teoria studiata 
da MSDN, questa volta ho sfruttato molto tutto quello che ho imparato lavorando 
con .NET - un'esperienza molto maggiore rispetto all'ottobre scorso.&lt;/P&gt;
&lt;P&gt;Comunque mi sento un pollo questa mattina, perchè me ne sarei potuto tornare 
a casa con un punteggio altissimo. &lt;IMG height=19 src="http://www.imhoproject.org/files/deluso.gif" width=19 align=absMiddle border=0&gt;&amp;nbsp;Beh, insomma, pazienza, ormai è andata! 
Adesso non voglio più pensare ad esami per un bel pezzo, prima devo tornare 
ricaricato dalle vacanze che mi aspettano!&lt;/P&gt;
&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;P&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.2&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO Instant Blogger Copyright (c) 2004 A.Boschin - http://www.elite.boschin.it --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/45355.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/07/26/45355.aspx</guid>
            <pubDate>Wed, 26 Jul 2006 13:26:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/07/26/45355.aspx#feedback</comments>
            <slash:comments>28</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/45355.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/45355.aspx</trackback:ping>
        </item>
        <item>
            <title>[70-536, #32] L'attributo DllImport nei dettagli</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/12/42703.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;&lt;STRONG&gt;I parametri dell'attributo 
DllImport&lt;/STRONG&gt;&lt;BR&gt;&lt;A title="" href="http://blogs.ugidotnet.org/idamiani/archive/2006/06/07/42435.aspx" target=_new name=""&gt;Nell'ultimo post&lt;/A&gt; riguardante l'esame 70-536, abbiamo 
visto come utilizzare l'attributo &lt;STRONG&gt;DllImport&lt;/STRONG&gt; per poter 
utilizzare una funzione esportata da una libreria &lt;EM&gt;unmanaged&lt;/EM&gt;. Nella sua 
forma base, &lt;STRONG&gt;DllImport&lt;/STRONG&gt; richiede un solo parametro: una stringa 
che contiene il nome del file DLL che esporta la funzione che ci interessa 
utilizzare nella nostra applicazione &lt;EM&gt;managed&lt;/EM&gt;. L'ultima volta avevamo 
fatto un piccolo esempio, considerando la funzione GetTempPath, esportata da 
kernel32.dll. la dichiarazione nella nostra classe &lt;EM&gt;managed&lt;/EM&gt;era:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;[DllImport("kernel32.dll")]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;private&amp;nbsp;static&amp;nbsp;extern&amp;nbsp;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;GetTempPath(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;nBufferLength,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Out]&amp;nbsp;StringBuilder&amp;nbsp;lpBuffer);&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;L'attributo &lt;STRONG&gt;DllImport&lt;/STRONG&gt; può avere qualche parametro 
aggiuntivo. Ad esempio, nel codice qui sopra il nome della funzione GetTempPath 
corrisponde al nome della funzione contenuta in kernel32.dll. Se per qualche 
motivo il nome della funzione &lt;EM&gt;managed&lt;/EM&gt; contenuta nel prototipo 
differisce dal nome della funzione contenuta nella libreria &lt;EM&gt;unmanaged&lt;/EM&gt;, 
dobbiamo fornire al framework l'&lt;STRONG&gt;entrypoint&lt;/STRONG&gt; corretto. Ad 
esempio:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;[DllImport("kernel32.dll",&amp;nbsp;EntryPoint&amp;nbsp;=&amp;nbsp;"GetTempPath")]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;private&amp;nbsp;static&amp;nbsp;extern&amp;nbsp;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;GetTemporaryPath(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;nBufferLength,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Out]&amp;nbsp;StringBuilder&amp;nbsp;lpBuffer);&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Il parametro &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.entrypoint.aspx" target=_new name=""&gt;&lt;STRONG&gt;EntryPoint&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; di 
&lt;STRONG&gt;DllImport&lt;/STRONG&gt; nella dichiarazione qui sopra dice semplicemente che 
il nome della funzione in &lt;EM&gt;managed&lt;/EM&gt; code è GetTemporaryPath, 
che&amp;nbsp;punta all'entrypoint GetTempPath della libreria kernel32.dll. Un 
secondo possibile parametro è &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.charset.aspx" target=_new name=""&gt;&lt;STRONG&gt;CharSet&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, che riveste 
un'importanza fondamentale nel caso in cui dobbiamo lavorare con le stringhe: 
impostando questo parametro su &lt;STRONG&gt;CharSet.Auto&lt;/STRONG&gt;, ci assicuriamo che 
le stringhe vengono passate correttamente dal mondo &lt;EM&gt;managed&lt;/EM&gt; al mondo 
&lt;EM&gt;unmanaged&lt;/EM&gt;, e viceversa. Per il marshaling, il CLR si basa sul sistema 
operativo su cui sta girando l'assembly.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Il default marshaling e l'attributo MarshalAsAttribute&lt;/STRONG&gt;&lt;BR&gt;Il 
default marshaling è il comportamento di default che .NET assume ogni volta che 
deve passare oggetti tra il mondo &lt;EM&gt;managed&lt;/EM&gt; ed il mondo 
&lt;EM&gt;unmanaged&lt;/EM&gt;. Tecnicamente, è espresso da una serie di tabelle che 
esprimono come un tipo &lt;EM&gt;managed&lt;/EM&gt; viene convertito nel tipo 
&lt;EM&gt;unmanaged&lt;/EM&gt;. Ad esempio, &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/0t2cwe11.aspx" target=_new name=""&gt;questa tabella&lt;/A&gt; considera i value-typed di .NET.&amp;nbsp;Tener 
presente&amp;nbsp;l'attributo &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute.aspx" target=_new name=""&gt;&lt;STRONG&gt;MarshalAs&lt;/STRONG&gt;&lt;/A&gt;, grazie al 
quale&amp;nbsp;possiamo modificare questo comportamento, comunicando esplicitamente 
al CLR come effettuare il marshaling in un particolare frangente. Caso tipico 
sono le stringhe, che in base al tipo &lt;EM&gt;unmanaged&lt;/EM&gt; (LPStr, BStr, LPWStr, 
etc.) possono subire il marshaling verso il contesto &lt;EM&gt;managed&lt;/EM&gt; secondo 
diverse tipi di destinazione.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Fare il marshaling di strutture&lt;BR&gt;&lt;/STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/awbckfbz.aspx" target=_new name=""&gt;Esiste una pagina su MSDN&lt;/A&gt; che descrive accuratamente questo 
scenario. Fino ad adesso, abbiamo trattato con tipi di dato semplici, ad 
esclusione delle stringhe dove abbiamo a che fare innanzitutto con il CharSet, 
in secondo luogo con stringhe a lunghezza fissa o variabile (dove quindi 
dobbiamo usare il tipo &lt;FONT color=blue&gt;string&lt;/FONT&gt; oppure la classe &lt;FONT color=blue&gt;StringBuilder&lt;/FONT&gt;).&lt;/P&gt;
&lt;P&gt;Cosa succede se dobbiamo invece trasferire intere strutture dati? Ne dobbiamo 
fare ovviamente il marshaling, ma come? Dobbiamo capire&amp;nbsp;essenzialmente che 
il codice del mondo&amp;nbsp;&lt;EM&gt;managed&lt;/EM&gt; ed il codice del&amp;nbsp;mondo 
&lt;EM&gt;unmanaged&lt;/EM&gt; formattano i dati in memoria in modo diverso. Dobbiamo 
trovare quindi una strada per dire al CLR di non mappare i dati in memoria come 
vorrebbe lui, ma di rispettare determinate logiche. Questa strada è disponibile, 
ancora una volta, con&amp;nbsp;un attributo .NET dedicato: &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute.aspx" target=_new name=""&gt;&lt;STRONG&gt;StructLayout&lt;/STRONG&gt;&lt;/A&gt;. Questo attributo prende 
come parametro un valore dell'enum &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.layoutkind.aspx" target=_new name=""&gt;&lt;STRONG&gt;LayoutKind&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, che esprime la 
modalità con cui i campi della nostra struttura vengono mappati in memoria. I 
valori di questo enum più interessanti sono principalmente due:&lt;/P&gt;
&lt;OL&gt;
  &lt;LI&gt;&lt;STRONG&gt;Explicit&lt;/STRONG&gt;: siamo noi che indichiamo al CLR come mappare 
  (uno ad uno) i campi della struttura. Attraverso l'attributo &lt;STRONG&gt;&lt;A   title=""   href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.fieldoffsetattribute.aspx"   target=_new name=""&gt;&lt;STRONG&gt;FieldOffset&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, esprimiamo in 
  bytes la posizione fisica di un campo all'interno di una classe o di una 
  struttura. Questo vale ovviamente sia nel mondo &lt;EM&gt;managed&lt;/EM&gt;, che in 
  &lt;EM&gt;unmanaged&lt;/EM&gt;.&lt;/LI&gt;
  &lt;LI&gt;&lt;STRONG&gt;Sequential&lt;/STRONG&gt;: i campi vengono mappati in memoria 
  sequenzialmente, nello stesso ordine con cui questi servono dal lato 
  &lt;EM&gt;unmanaged&lt;/EM&gt; della nostra applicazione. I campi possono essere non 
  contigui&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;STRONG&gt;Funzioni di callback&lt;BR&gt;&lt;/STRONG&gt;In altri scenari serve una funzione 
di callback, ovvero una funzione scritta in &lt;EM&gt;managed&lt;/EM&gt; code che viene 
eseguita al termine dell'esecuzione di una funzione &lt;EM&gt;unmanaged&lt;/EM&gt;. In altre 
parole, dal nostro codice .NET eseguiamo una funzione nativa attraverso 
P/Invoke, la quale deve sapere cosa eseguire quando la sua esecuzione termina. 
In realtà, come vedremo fra poco, non è detto che la callback serva solamente al 
termine dell'esecuzione: la funzione &lt;EM&gt;unmanaged&lt;/EM&gt; potrebbe utilizzare la 
callback quando necessario, magari per avvisare il mondo .NET. Anche in questo 
caso, possiamo fare riferimento &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/d186xcf0.aspx" target=_new name=""&gt;a questa pagina su MSDN&lt;/A&gt; per maggiori dettagli. La tecnica consiste 
nell'utilizzare un delegate, che non è nient'altro che un puntatore a funzione 
in ambiente .NET. &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/843s5s5x.aspx" target=_new name=""&gt;L'esempio su MSDN&lt;/A&gt; tratta un caso molto particolare: attraverso 
P/Invoke, utilizziamo la funzione &lt;STRONG&gt;EnumWindows&lt;/STRONG&gt;, la quale 
richiede una callback, che viene eseguita ogni volta che la funzione 
&lt;EM&gt;unmanaged&lt;/EM&gt; lo richiede. &lt;STRONG&gt;&lt;FONT color=green&gt;Come facciamo a capire 
quando una funzione &lt;EM&gt;unmanaged&lt;/EM&gt; richiede una callback?&lt;/FONT&gt;&lt;/STRONG&gt; 
Bisogna leggere con attenzione il prototipo della funzione stessa, perchè dal 
tipo e dal nome dei parametri possiamo arrivare a capirlo. Il prototipo C++ 
della funzione &lt;STRONG&gt;EnumWindows&lt;/STRONG&gt; è il seguente:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;BOOL&amp;nbsp;EnumWindows(WNDENUMPROC&amp;nbsp;lpEnumFunc,&amp;nbsp;LPARAM&amp;nbsp;lParam)&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Ciò significa che se vogliamo usare questa funzione &lt;EM&gt;unmanaged&lt;/EM&gt; 
dobbiamo semplicemente convertire il primo parametro in un delegate:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;public&amp;nbsp;delegate&amp;nbsp;bool&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;CallBack(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;int&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;hwnd,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;int&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;lParam);&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;e conseguente utilizzare questo delegate come funzione di callback.&lt;/P&gt;
&lt;P&gt;
&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.2&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO Instant Blogger Copyright (c) 2004 A.Boschin - http://www.elite.boschin.it --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/42703.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/12/42703.aspx</guid>
            <pubDate>Mon, 12 Jun 2006 16:08:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/12/42703.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/42703.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/42703.aspx</trackback:ping>
        </item>
        <item>
            <title>[70-536, #31] P/Invoke e l'attributo DllImport</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/07/42435.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;&lt;STRONG&gt;Introduzione&lt;/STRONG&gt;&lt;BR&gt;P/Invoke è 
l'abbreviazione di &lt;STRONG&gt;Platform Invoke&lt;/STRONG&gt;  &amp;nbsp;e consiste 
nella capacità da parte del nostro &lt;EM&gt;managed code&lt;/EM&gt; di utilizzare DLL di 
sistema ed eseguire le funzioni contenute. Ho trovato di grande comodità il sito 
&lt;A href="http://www.pinvoke.net/"&gt;www.pinvoke.net&lt;/A&gt;, che ci aiuta con una 
grande raccolta di tutte le librerie di sistema e come poterle importare in una 
classe managed per rendere accessibile da C#, VB.NET e da tutti gli altri 
linguaggi della famiglia .NET. Anche in questo caso, come nel mio ultimo post, 
&lt;STRONG&gt;&lt;FONT color=#008040&gt;abbiamo a che fare con una classe 
wrapper&lt;/FONT&gt;&lt;/STRONG&gt;: sarà questa che il codice &lt;EM&gt;managed&lt;/EM&gt; eseguirà. 
Tale classe deve essere decorata dall'attributo &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx" target=_new name=""&gt;&lt;STRONG&gt;DllImport&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, specificando il 
nome del file DLL che si vuole utilizzare in questa chiamata. Il namespace di 
riferimento per tutto quello che riguarda P/Invoke è &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.aspx" target=_new name=""&gt;&lt;STRONG&gt;System.Runtime.InteropServices&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Una chiamata semplice a GetTempPath&lt;/STRONG&gt;&lt;BR&gt;La funzione 
GetTempPath è funzione contenuta nel file kernel32.dll di Windows. Partendo da 
questo presupposto, in C# possiamo dichiarare una classe statica PInvoke ed 
inserire un metodo definito così:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;static&amp;nbsp;class&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;PInvoke&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DllImport("kernel32.dll")]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;public&amp;nbsp;static&amp;nbsp;extern&amp;nbsp;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;GetTempPath(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;nBufferLength,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Out]&amp;nbsp;StringBuilder&amp;nbsp;lpBuffer);&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Il metodo è marcato come statico e come &lt;STRONG&gt;&lt;A title="" href="http://lab.msdn.microsoft.com/search/Redirect.aspx?title=" target=_new name="" ?&gt;&lt;STRONG&gt;extern&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, che esplicita il fatto che il 
metodo è implementato esternamente rispetto all'assembly. Il secondo parametro è 
un oggetto &lt;A title="" href="http://lab.msdn.microsoft.com/search/Redirect.aspx?title=" target=_new name="" ?&gt;StringBuilder&lt;/A&gt; che verrà restituito (notare la 
keyword &lt;STRONG&gt;out&lt;/STRONG&gt;     )&amp;nbsp;e conterrà il path per i 
files temporanei restituito dall'OS. Questo è un caso estremamente semplice. 
L'unica verrà difficoltà è alla fin fine mappare correttamente i tipi tra il mondo 
&lt;EM&gt;managed&lt;/EM&gt; ed il mondo &lt;EM&gt;unmanaged&lt;/EM&gt;. Per questo risorse on-line come 
&lt;A href="http://www.pinvoke.net/"&gt;www.pinvoke.net&lt;/A&gt; sono estremamente 
importanti ed utili, perchè hanno fatto gran parte del lavoro e ci basta copiare 
&amp;amp; incollare.&lt;/P&gt;
&lt;P&gt;Torniamo a noi. Una volta dichiarata la classe ed il metodo, chiamarlo non è 
per nulla diverso a qualsiasi altro metodo statico scritto in C#.&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;StringBuilder&amp;nbsp;bld&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;StringBuilder();&lt;BR&gt;PInvoke.GetTempPath(255,&amp;nbsp;bld);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;string&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;tempPath&amp;nbsp;=&amp;nbsp;bld.ToString();&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#008040&gt;Quando ha senso usare 
P/Invoke?&lt;/FONT&gt;&lt;/STRONG&gt; In primo luogo, &lt;STRONG&gt;&lt;FONT color=#008040&gt;quando una 
certa funzionalità non è esposta dal Framework&lt;/FONT&gt;&lt;/STRONG&gt;            
    . Ad esempio, la libreria &lt;EM&gt;kernel32.dll&lt;/EM&gt; 
espone la funzione &lt;A title="" href="http://www.pinvoke.net/default.aspx/kernel32.CopyFileEx" target=_new name=""&gt;CopyFileEx&lt;/A&gt;, che però è direttamente utilizzabile da codice 
&lt;EM&gt;managed&lt;/EM&gt;. P/Invoke è molto utile, ripeto,&amp;nbsp;se vogliamo interagire 
con componenti COM che al contrario non sono disponibili in .NET. &lt;A title="" href="http://www.codeproject.com/csharp/wmp_pinvoke.asp?print=true" target=_new name=""&gt;Questo articolo&lt;/A&gt; su CodeProject ad esempio dimostra come usare P/Invoke con 
Windows Media Player, cosa che può essere fatta tra l'altro con le tecniche 
viste ieri (ovvero aggiungere come riferimento il file WMP.dll ed accedere così 
all'object model).&lt;/P&gt;
&lt;P&gt;Ovviamente P/Invoke non funziona solo con le librerie di sistema, ma 
con&amp;nbsp;qualsiasi libreria COM scritta in C++, comprese quindi le nostre.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Usiamo&amp;nbsp;P/Invoke, ma usiamolo 
pulito!&lt;BR&gt;&lt;/STRONG&gt;In alcune occasioni, P/Invoke è davvero necessario, per cui 
siamo obbligati per forza di cose a servirci delle sue potenzialità. Però 
dobbiamo pensare bene alle 
complicazioni ed agire di conseguenza.&lt;/P&gt;
&lt;P&gt;Le Windows API ritornano le condizioni di errori come banali costanti. Questo 
è in netta contrapposizione con la logica delle Exception messa in campo da .NET 
e dal framework. Per ovviare a questo inconveniente, è opportuno costruire una 
classe wrapper che converta un HRESULT restituito da Windows nella Exception più 
opportuna. Questa classe wrapper può inoltre &lt;STRONG&gt;nascondere l'accesso al 
mondo unmanaged&lt;/STRONG&gt;: in pratica, una best practice da applicare è rendere 
privata la dichiarazione del metodo extern e creare invece un metodo public di 
buffer che sarà quello che useremo realmente nel nostro codice.&lt;/P&gt;
&lt;P&gt;Vediamo di applicare nel concreto queste best practices. Vogliamo sempre 
utilizzare la funzione API GetTempPath esportata dalla libreria 
&lt;STRONG&gt;kernel32.dll&lt;/STRONG&gt;. Ho creato una classe PInvoke, il cui codice 
è:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: black 1px solid; WIDTH: 668px; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; HEIGHT: 138px; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;sealed&amp;nbsp;class&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;PInvoke&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;public&amp;nbsp;static&amp;nbsp;string&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;GetTemporaryPath()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StringBuilder&amp;nbsp;bld&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;StringBuilder();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;ret&amp;nbsp;=&amp;nbsp;&amp;nbsp;GetTempPath(255,&amp;nbsp;bld);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;return&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;(bld.ToString());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DllImport("kernel32.dll")]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;private&amp;nbsp;static&amp;nbsp;extern&amp;nbsp;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;GetTempPath(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;uint&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;nBufferLength,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Out]&amp;nbsp;StringBuilder&amp;nbsp;lpBuffer);&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/SPAN&gt;Ho&amp;nbsp;riportato&amp;nbsp;due metodi. Un metodo pubblico 
&lt;STRONG&gt;GetTemporaryPath&lt;/STRONG&gt;, scritto completamente in codice 
&lt;EM&gt;managed&lt;/EM&gt;. Un metodo privato &lt;STRONG&gt;GetTempPath&lt;/STRONG&gt; che invece è 
extern, ed è in &lt;EM&gt;unmanaged code&lt;/EM&gt;. Tale classe sarà accessibile dal 
chiamante solo attraverso il metodo pubblico, come è normale che sia. Questo 
&lt;EM&gt;modus operandi&lt;/EM&gt; rende possibili alcune migliorie al codice che abbiamo 
scritto:&lt;/P&gt;
&lt;OL&gt;
  &lt;LI&gt;quando il Framework renderà eventualmente disponibile la funzionalità alla 
  quale adesso accediamo attraverso P/Invoke, ci basterà modificare 
  l'implementazione del metodo pubblico &lt;STRONG&gt;GetTemporaryPath&lt;/STRONG&gt; ed il 
  gioco è fatto.&lt;/LI&gt;
  &lt;LI&gt;così facendo, isoliamo&amp;nbsp;tutto quello che riguarda&amp;nbsp;P/Invoke. 
  Questo ci permette di limitare le porzioni di codice interessate ad eventuali 
  crash o a problemi dovuti ad Interop.&lt;/LI&gt;
  &lt;LI&gt;come dicevo prima (ed è domanda di esame) possiamo mascherare gli errori 
  ritornati da Win32 in opportune exception. Nel codice qui sopra, per esempio, 
  memorizza nella variabile ret di tipo &lt;STRONG&gt;uint&lt;/STRONG&gt; il valore 
  ritornato dalla chiamata: mi basterebbe implementare un costrutto switch per 
  intercettare eventuali errori ed agire di conseguenza.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;STRONG&gt;Come usare DllImport&lt;BR&gt;&lt;/STRONG&gt;L'attributo DllImport ci permette di 
indicare in quale libreria viene esportata una certa funzione. Questo attributo 
ha diverse proprietà importanti. &lt;STRONG&gt;EntryPoint&lt;/STRONG&gt; ci permette di 
specificare il nome della funzione contenuta nella libreria, nel caso in cui il 
nome sia diverso rispetto a quello che indichiamo noi nella dichiarazione del 
metodo. &lt;STRONG&gt;CharSet&lt;/STRONG&gt; va impostato su CharSet.Auto, e ha importanza 
solo se la funzione esportata utilizza le stringhe; questo permette al CLR di 
utilizzare il set di caratteri corretto in base all'OS su cui si sta eseguendo 
il codice.&lt;/P&gt;
&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;P&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.2&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO Instant Blogger Copyright (c) 2004 A.Boschin - http://www.elite.boschin.it --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/42435.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/07/42435.aspx</guid>
            <pubDate>Wed, 07 Jun 2006 12:42:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/07/42435.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/42435.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/42435.aspx</trackback:ping>
        </item>
        <item>
            <title>[70-536, #30] Primi passi con il mondo Interop</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/05/42185.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;&lt;STRONG&gt;Introduzione&lt;/STRONG&gt;&lt;BR&gt;Fino ad oggi abbiamo 
sempre discusso con un mondo completamente &lt;EM&gt;managed&lt;/EM&gt;, ovvero il cui 
codice è scritto al 100% in linguaggi previsti dal FX (VB.NET e C# in primo 
luogo), e che quindi&amp;nbsp;gira all'interno del CLR. Possiamo però andare oltre, 
e permettere al nostro codice di oltrepassare le normali barriere ed avere a che 
fare con il managed &lt;EM&gt;unmanaged&lt;/EM&gt;, ovvero tutto quello che riguarda codice 
Win32, mondo COM e via dicendo.&lt;/P&gt;
&lt;P&gt;Ovviamente, il fatto che sia possibile non vuol dire che sia una cosa 
semplice, nè tantomeno che siamo esenti da rischi. La difficoltà principale è 
saper mappare in memoria&amp;nbsp;gli oggetti managed in modo tale che siano 
utilizzabili dalle funzioni native Win32, e viceversa. Tale operazione è nota 
con il termine di &lt;EM&gt;marshaling&lt;/EM&gt;: vi rimando &lt;A title="" href="http://www.microsoft.com/indonesia/msdn/pinvoke.aspx#docum_topic3" target=_new name=""&gt;alla tabella in fondo a questo articolo&lt;/A&gt; per tutti i 
dettagli del caso. Oggi cominciamo con le cose più semplici: vediamo infatti 
come poter aggiungere ad un nostro progetto .NET un riferimento ad un componente 
COM, sia esso un OCX, una DLL ActiveX o una type library.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Un riferimento ai componenti di Microsoft Word&lt;/STRONG&gt;&lt;BR&gt;Il 
concetto che ruota a queste problematiche è che .NET crea una 
classe&amp;nbsp;&lt;EM&gt;managed&lt;/EM&gt; che il nostro codice utilizza come wrapper per 
tutte le chiamate al mondo &lt;EM&gt;unmanaged&lt;/EM&gt;. Ad esempio, se apriamo un 
qualsiasi progetto .NET con Visual Studio 2005, clicchiamo con il pulsanto 
destro sul nome del progetto e selezioniamo la voce &lt;STRONG&gt;Add 
Reference&lt;/STRONG&gt;, l'IDE ci propone una finestra di dialogo dalla quale 
possiamo selezionare qualsiasi cosa ci passi per la testa: oggetti .NET, oggetti 
COM, altri progetti inseriti nella nostra solution, e via dicendo. Il tab 
&lt;STRONG&gt;Browse&lt;/STRONG&gt; ci permette di sfogliare il contenuto del nostro 
hard-disk alla ricerca di files DLL, TLB, OLB, OCX ed EXE che vogliamo mettere 
nei riferimenti del nostro progetto.&lt;/P&gt;
&lt;P&gt;Supponiamo per esempio di voler &lt;EM&gt;interoperare&lt;/EM&gt; con Microsoft Word 
all'interno della nostra applicazione.&amp;nbsp;Una delle possibili 
soluzioni&amp;nbsp;consiste nell'aggiungere come riferimento il file MSWORD.OLB, 
seguendo il procedimento indicato prima. Questa semplice operazione si traduce 
in:&lt;/P&gt;
&lt;UL&gt;
  &lt;LI&gt;la creazione di un nuovo assembly in &lt;EM&gt;managed code&lt;/EM&gt;, ottenuto 
  partendo dal file MSWORD.OLB&lt;/LI&gt;
  &lt;LI&gt;l'inserimento del nuovo assembly nella GAC&lt;/LI&gt;
  &lt;LI&gt;l'aggiunta del nuovo assembly come riferimento al nostro progetto 
.NET&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Così facendo, otteniamo in tutto e per tutto un riferimento valido all'object 
model di Word, utilizzabile quindi direttamente nel nostro codice attraverso la 
classe wrapper. Tale wrapper viene inserito in un namespace dedicato, che va 
quindi referenziato tramite la solita &lt;STRONG&gt;using&lt;/STRONG&gt;. Per esempio:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;Microsoft.Office.Interop.Word.Application&amp;nbsp;appWord&amp;nbsp;=&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;Microsoft.Office.Interop.Word.Application();&lt;BR&gt;Document&amp;nbsp;doc&amp;nbsp;=&amp;nbsp;appWord.Documents.Open(&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #008000; FONT-FAMILY: Courier New"&gt;/*Parametri*/&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;);&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Il metodo &lt;STRONG&gt;Open&lt;/STRONG&gt; esposto dall'oggetto 
&lt;STRONG&gt;Documents&lt;/STRONG&gt; richiede un gran numero di parametri obbligatori, 
cosa che invece non accade per esempio quando facciamo la stessa con VB6. Il 
motivo è che molti dei parametri sono opzionali: in .NET questo comportamento si 
attua sfruttando l'overloading dei metodi. Questo esempio vale solo a scopo 
didattico, per cui ho deciso comunque di mantenerlo.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Il tool Tlbimp.exe&lt;BR&gt;&lt;/STRONG&gt;Il meccanismo di creazione della 
classe wrapper in managed code è disponibile anche attraverso il tool &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/tt0cf3sx.aspx" target=_new name=""&gt;&lt;STRONG&gt;tlbimp.exe&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; fornito dal FX2.0. 
Questo tool richiede essenzialmente il nome del file DLL di cui si vuole creare 
il wrapper. Rispetto alle funzionalità esposte dall'IDE, abbiamo diverse marce 
in più:&lt;/P&gt;
&lt;UL&gt;
  &lt;LI&gt;l'opzione &lt;STRONG&gt;/namespace:&lt;/STRONG&gt; permette di specificare il 
  namespace attraverso il quale sarà possibile raggiungere la nuova classe 
  wrapper&lt;/LI&gt;
  &lt;LI&gt;l'opzione &lt;STRONG&gt;/out:&lt;/STRONG&gt; permette di specificare il nome del file 
  generato&lt;/LI&gt;
  &lt;LI&gt;l'opzione &lt;STRONG&gt;/keyfile:&lt;/STRONG&gt; permette di specificare un file SNK 
  per firmare con uno strong name l'assembly (tale file viene generato dal tool 
  &lt;STRONG&gt;sn.exe&lt;/STRONG&gt;, &lt;A title=""   href="http://msdn2.microsoft.com/en-us/library/k5b5tt23.aspx" target=_new   name=""&gt;cliccare qui per maggiori informazioni&lt;/A&gt;)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Questo tool, quindi, permette di generare la classe wrapper al di fuori 
dell'IDE ed in modo completamente indipendente. L'unico parametro davvero 
necessario è il nome del file (&lt;EM&gt;tlbFile&lt;/EM&gt;), che deve contenere 
obbligatoriamente una COM type library.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Compilare un progetto che fa uso di Interop&lt;BR&gt;&lt;/STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/538aes2a.aspx" target=_new name=""&gt;Esiste una pagina su MSDN&lt;/A&gt; che descrive come compilare un progetto 
.NET che usa InterOp per interagire con il mondo &lt;EM&gt;unmanaged&lt;/EM&gt;. Se 
compiliamo dall'IDE, non cambia nulla: la classe wrapper nasconde il mondo 
&lt;EM&gt;unmanaged&lt;/EM&gt; e siamo a posto. Se compiliamo da command-line, assicuriamoci 
di utilizzare il parametro &lt;STRONG&gt;/reference:&lt;/STRONG&gt; del compilatore per 
referenziare l'assembly contenente la classe wrapper che ci serve.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Deploy di un'applicazione che fa uso di InterOp&lt;BR&gt;&lt;/STRONG&gt;Se stiamo 
facendo il deploy di un'applicazione InterOp, dobbiamo considerare se i nostri 
assembly wrapper devono essere condivisi fra più applicazioni. La &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/tc0204w0.aspx" target=_new name=""&gt;pagina dedicata su MSDN&lt;/A&gt; è piuttosto chiara. Se gli assembly wrapper 
sono condivisi, vale la pena firmarli con uno strong name, inserirli nella GAC 
(che alla fin fine è un &lt;EM&gt;centralized repository&lt;/EM&gt; fatto apposta per questo 
scopo)&amp;nbsp;ed il gioco è fatto. Se gli assembly sono privati per una certa 
applicazione, il deploy deve essere fatto nella stessa directory dove si trova 
l'applicazione.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Dietro le quinte: come fa Tlbimp a convertire?&lt;BR&gt;&lt;/STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/k83zzh38(vs.80).aspx" target=_new name=""&gt;A partire da questa pagina su MSDN&lt;/A&gt;, vengono descritte 
quali sono le logiche che Tlbimp.exe mette in campo per convertire dal mondo COM 
al mondo &lt;EM&gt;managed&lt;/EM&gt;. Si parla quindi di Imported Member Conversion, 
Imported Library Conversion, Imported Module Conversion e via 
dicendo.&lt;/P&gt;
&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;P&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.2&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO Instant Blogger Copyright (c) 2004 A.Boschin - http://www.elite.boschin.it --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/42185.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/05/42185.aspx</guid>
            <pubDate>Mon, 05 Jun 2006 14:32:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/05/42185.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/42185.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/42185.aspx</trackback:ping>
        </item>
        <item>
            <title>Manca un mese al mio esame 70-536</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/04/42155.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;In molti, giustamente, mi hanno detto che i miei post 
per &lt;A title="" href="http://blogs.ugidotnet.org/idamiani/category/1704.aspx" target=_new name=""&gt;l'esame 70-536&lt;/A&gt; sono più discontinui rispetto alla mia 
prima serie per &lt;A title="" href="http://blogs.ugidotnet.org/idamiani/category/1246.aspx" target=_new name=""&gt;l'esame 70-316&lt;/A&gt;. Effettivamente, i miei impegni di lavoro mi hanno 
portato via più tempo del previsto e anche se trovo il tempo per studiare un po' 
(ho giusto giusto&amp;nbsp;del materiale&amp;nbsp;su P/Invoke che mi aspetta sul letto), 
ho sicuramente meno tempo per dedicarmi alla scrittura di post.&lt;/P&gt;
&lt;P&gt;Spero davvero di poter riprendere a parlare come una volta, perlomeno sugli 
argomenti più importanti come P/Invoke che citavo prima. Rimane da vedere 
qualcosa sulla sicurezza ed altro ancora: avevo fissato l'esame il 1° Giugno, ma 
ho dovuto per forza spostarlo in là di un mese per essere sicuro di studiare 
tutto e per bene. Tra l'altro, non avere software di&amp;nbsp;self-test come i 
&lt;STRONG&gt;Boson&lt;/STRONG&gt; che avevo usato per il 70-316, mi incita ad arrivare più 
preparato rispetto al solito. &lt;EM&gt;Sperem...&lt;/EM&gt;&lt;/P&gt;

&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;P&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.3&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO 1.3 (IT) Instant Blogger Copyright (c) 2005 A.Boschin - http://www.imhoproject.org --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/42155.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/04/42155.aspx</guid>
            <pubDate>Sun, 04 Jun 2006 23:42:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/06/04/42155.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/42155.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/42155.aspx</trackback:ping>
        </item>
        <item>
            <title>[70-536, #29] Qualche dettaglio in pi&amp;#249; sulla gestione dei thread</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/05/04/40019.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;&lt;STRONG&gt;Introduzione&lt;/STRONG&gt;&lt;BR&gt;Nel post precedente 
abbiamo visto come utilizzare la classe &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.thread.aspx" target=_new name=""&gt;&lt;STRONG&gt;Thread&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; in modo basilare. In 
breve: come creare un nuovo thread, utilizzando le classi &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.threadstart.aspx" target=_new name=""&gt;&lt;STRONG&gt;ThreadStart&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; e &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.parameterizedthreadstart.aspx" target=_new name=""&gt;&lt;STRONG&gt;ParameterizedThreadStart&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, a 
seconda del fatto che il metodo da eseguire in modo asincrono abbiamo parametri 
oppure no.&lt;/P&gt;
&lt;P&gt;Quello che vediamo oggi va un po' più in là. Sarà un po' tutto teorico, 
perchè francamente non ho mai avuto bisogno di scendere così nel dettaglio. 
Innanzitutto il Framework ci mette a disposizione la classe &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.threadpool(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;ThreadPool&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;. Questa classe è 
definita come static, di conseguenza non abbiamo bisogno di istanziarla per 
poterla utilizzare. Come dice la pagina su MSDN, la classe ThreadPooo...&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Provides a pool of threads that can be used to post work items, process 
asynchronous I/O, wait on behalf of other threads, and process timers.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Direi che è tutto abbastanza chiaro. Attraverso il metodo &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx" target=_new name=""&gt;&lt;STRONG&gt;QueueUserWorkItem&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, possiamo 
richiedere al pool di thread la creazione di un nuovo thread che - ovviamente - 
giri in modo asincrono. Tutti i thread gestiti all'interno di ThreadPool hanno 
la property &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx" target=_new name=""&gt;&lt;STRONG&gt;IsBackground&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; = &lt;FONT color=blue&gt;true&lt;/FONT&gt;. Una cosa importante da sottolineare è che la chiamata al 
metodo QueueUserWorkItem ritorna &lt;FONT color=blue&gt;true&lt;/FONT&gt; se il thread è 
stato accodato al pool, oppure &lt;FONT color=blue&gt;false&lt;/FONT&gt; se qualcosa non è 
andato bene (in tal caso, verrà sollevata un eccezione di tipo &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.applicationexception.aspx" target=_new name=""&gt;ApplicationException&lt;/A&gt;). Il metodo specificato nel 
costruttore inoltre non viene eseguito immediatamente, ma viene eseguito quando 
diventa disponibile il pool.&lt;/P&gt;
&lt;P&gt;&lt;A title="" href="http://blogs.ugidotnet.org/idamiani/archive/2006/04/27/39545.aspx" target=_new name=""&gt;Nell'ultimo post&lt;/A&gt; avevo parlato di un'applicazione creata 
apposta per studiare questo argomento. In questa applicazione avevo implementato 
un semplice metodo &lt;EM&gt;aggiungiRecord&lt;/EM&gt; per inserire qualche migliaio di 
record dentro una tabella di SQL Server, e lo avevo fatto girare in modo 
asincrono facendomi avvisare alla fine. Vediamo come ottenere lo stesso 
risultato con il pool di thread.&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;WaitCallback&amp;nbsp;clk&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;WaitCallback(aggiungiRecord);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;bool&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;ret&amp;nbsp;=&amp;nbsp;ThreadPool.QueueUserWorkItem(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;WaitCallback(aggiungiRecord));&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Il codice qui sopra istanzia un oggetto &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.waitcallback.aspx" target=_new name=""&gt;&lt;STRONG&gt;WaitCallback&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, da usare nella 
chiamata al metodo &lt;STRONG&gt;QueueUserWorkItem&lt;/STRONG&gt;. La classe WaitCallback 
espone due proprietà interessanti: &lt;STRONG&gt;Method&lt;/STRONG&gt; e 
&lt;STRONG&gt;Target&lt;/STRONG&gt;. La prima è un'istanza della classe &lt;STRONG&gt;&lt;A title="" href="http://lab.msdn.microsoft.com/search/Redirect.aspx?title=" target=_new name="" ?&gt;&lt;STRONG&gt;MethodInfo&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; che ci permette (tramite 
Reflection) di analizzare a run-time il metodo che sta per essere eseguito in 
modo asincrono nel ThreadPool. La seconda proprietà invece è un riferimento 
all'object nel quale ci troviamo: nel mio caso, trattandosi di un Button, tale 
object è la Windows Forms relativa.&lt;BR&gt;La seconda riga di codice non fa altro 
che richiedere l'inserimento all'interno del ThreadPool dell'oggetto 
WaitCallback. Salvo il risultato in una variabile bool per controllare che tutto 
sia andato regolarmente.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Metodi interessanti del&amp;nbsp;ThreadPool&lt;/STRONG&gt;&lt;BR&gt;La classe 
ThreadPool espone alcuni metodi interessanti. Il metodo &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.threadpool.getavailablethreads.aspx" target=_new name=""&gt;&lt;STRONG&gt;GetAvaiableThreads&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; ritorna il 
numero di thread disponibili all'interno del thread.&amp;nbsp; Esiste un pool di 
thread per ogni processo. Per default, il numero di thread disponibili per ogni 
pool è 25. E' possibile cambiare il numero di thread attraverso i metodi 
&lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.threadpool.setmaxthreads.aspx" target=_new name=""&gt;&lt;STRONG&gt;SetMaxThreads&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; e &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.threading.threadpool.setminthreads.aspx" target=_new name=""&gt;&lt;STRONG&gt;SetMinThreads&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;Mi sento di consigliare inoltre la lettura di &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/0ka9477y.aspx" target=_new name=""&gt;questo articolo su MSDN&lt;/A&gt; che tratta in modo esauriente questo 
argomento.&lt;/P&gt;

&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;P&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.3&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO 1.3 (IT) Instant Blogger Copyright (c) 2005 A.Boschin - http://www.imhoproject.org --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/40019.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/05/04/40019.aspx</guid>
            <pubDate>Thu, 04 May 2006 11:19:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/05/04/40019.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/40019.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/40019.aspx</trackback:ping>
        </item>
        <item>
            <title>Ho fissato la data dell'esame</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/04/27/39548.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;Il &lt;STRONG&gt;1° Giugno&lt;/STRONG&gt;, alle ore 
&lt;STRONG&gt;10:00&lt;/STRONG&gt;, andrò a&amp;nbsp;sostenere l'&lt;STRONG&gt;esame 70-536&lt;/STRONG&gt;. 
In tempo per riprendere a lavorare, per ripassare un po' di roba, per vedere le 
cose che mancano, per farmi venire un po' d'ansia.&lt;/P&gt;
&lt;P&gt;E, credetemi, se lo passo, io salto dalla gioia, e ve lo&amp;nbsp;dico 
anche,&amp;nbsp;&lt;A title="" href="http://blogs.ugidotnet.org/lbarbieri/archive/2006/04/26/39442.aspx" target=_new name=""&gt;alla faccia delle polemiche&lt;/A&gt;&amp;nbsp;che ogni tanto 
imperversano sul blog.&amp;nbsp;&lt;IMG height=19 src="http://www.imhoproject.org/files/complice.gif" width=19 align=absMiddle border=0&gt;&amp;nbsp;Su questo discorso, mi allineo con &lt;A title="" href="http://blogs.ugidotnet.org/lbarbieri" target=_new name=""&gt;Lorenzo&lt;/A&gt;, 
sinceramente: quando posto sul mio blog, so di rivolgermi ad un mio gruppo di 
amici e quindi mi viene naturale raccontare le cose che mi succedono, sia belle 
che brutte. Tra queste cose, ci sono anche i miei esami, per cui...Posso però 
capire chi magari ha fallito un esame, e sente gli altri che magari lo 
passano...&lt;/P&gt;
&lt;P&gt;Che dire...che il byte sia con me, e con tutti voi. &lt;IMG height=19 src="http://www.imhoproject.org/files/allegro.gif" width=19 align=absMiddle border=0&gt;&lt;/P&gt;
&lt;P&gt;

&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.3&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO 1.3 (IT) Instant Blogger Copyright (c) 2005 A.Boschin - http://www.imhoproject.org --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/39548.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/04/27/39548.aspx</guid>
            <pubDate>Thu, 27 Apr 2006 19:27:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/04/27/39548.aspx#feedback</comments>
            <slash:comments>27</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/39548.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/39548.aspx</trackback:ping>
        </item>
        <item>
            <title>[70-536, #28] Esecuzione asincrona? Thread!</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/04/27/39545.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;Ve l'avevo promesso che avrei ricominciato. Dopo questa 
lunga pausa, dovuta un po' a motivi di lavoro e salute, vediamo oggi di 
riprendere la mia serie di post per l'esame 70-536.&lt;/P&gt;
&lt;P&gt;Questa ripresa dei lavori vede come protagonista la class &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.thread.aspx" target=_new name=""&gt;&lt;STRONG&gt;Thread&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; ed affini, ovvero tutte 
quelle classi definite nel namespace &lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.aspx" target=_new name=""&gt;System.Threading&lt;/A&gt; che ci permettono di eseguire 
operazioni in modo asincrono. Ne avevamo già parlato in passato quando avevamo 
trattato il nuovo componente &lt;STRONG&gt;&lt;A title="" href="http://blogs.ugidotnet.org/idamiani/archive/2006/02/28/35763.aspx" target=_new name=""&gt;&lt;STRONG&gt;BackgroundWorker&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;: con nuovo, 
intendo con il FX2.0. Il BackgroundWorker internamente fa ovviamente uso di 
thread secondari, e risolve la maggior parte delle problematiche riguardanti la 
gestione della UI. Come sappiamo, infatti, non possiamo manipolare i controlli 
sulla Windows Forms al di fuori del thread che le ha create: se abbiamo un task 
che dura un po' di tempo, e vogliamo ogni tanto notificare qualcosa su una 
Label, per esempio, non possiamo farlo in modo diretto come faremmo di solito, 
ma dobbiamo avere qualche accorgimento in più. Il 
&lt;STRONG&gt;BackgroundWorker&lt;/STRONG&gt; semplifica e gestisce direttamente questi 
accorgimenti.&lt;/P&gt;
&lt;P&gt;Se abbiamo bisogno di qualcosa di più performante, oppure non abbiamo UI da 
gestire (magari stiamo sviluppando un web-services), possiamo lavorare con la 
classe &lt;STRONG&gt;Thread&lt;/STRONG&gt;. Vediamo come.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Introduzione alla classe Thread&lt;/STRONG&gt;&lt;BR&gt;Non mi capita tutti i 
giorni di sviluppare software che abbiano bisogno di thread secondari. Per 
questo motivo, ho sviluppato una piccola applicazione di test. In pratica, una 
semplice Windows Forms che si connette ad un database SQL Server, chiede quanti 
record si vogliono inserire e poi comincia a lanciare INSERT INTO su una 
tabella. La tabella non è importante (ha un campo identity ed un varchar(50)): 
ci basta sapere che per aggiungere 20.000 records, ci metto circa 20 
secondi.&lt;/P&gt;
&lt;P&gt;All'interno della form, ho creato un metodo privato aggiungiRecord:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;private&amp;nbsp;void&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;aggiungiRecord()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #008000; FONT-FAMILY: Courier New"&gt;//&amp;nbsp;codice&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;for&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;int&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;cycle&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;cycle&amp;nbsp;&amp;lt;=&amp;nbsp;20000;&amp;nbsp;cycle++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&amp;nbsp;=&amp;nbsp;"Marca&amp;nbsp;"&amp;nbsp;+&amp;nbsp;cycle.ToString();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters[0].Value&amp;nbsp;=&amp;nbsp;msg;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.ExecuteNonQuery();&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;updateUI.BeginInvoke(msg,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;null&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;null&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #008000; FONT-FAMILY: Courier New"&gt;//&amp;nbsp;codice&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;}&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Ho eliminato le parti di codice non interessanti. Sul click di un pulsante, 
vogliamo eseguire il metodo qui sopra in un thread separato, cosicchè questo 
comincia a fare 20.000 inserimenti senza interrompere il nostro lavoro. Oltre 
alla classe Thread vera e propria, abbiamo bisogno di una delle due classi: 
&lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.threadstart.aspx" target=_new name=""&gt;&lt;STRONG&gt;ThreadStart&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; oppure &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.parameterizedthreadstart.aspx" target=_new name=""&gt;&lt;STRONG&gt;ParameterizedThreadStart&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;. La 
prima se il metodo che vogliamo eseguire non ha parametri di input (come nel 
nostro caso), la seconda se invece c'è qualche parametro.&lt;BR&gt;Quindi, per 
esempio:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;ThreadStart&amp;nbsp;start&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;ThreadStart(aggiungiRecord);&lt;BR&gt;_th&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;Thread(start);&lt;BR&gt;&lt;FONT size=2&gt;_th.Start();&lt;/FONT&gt;&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Questo è la tecnica assolutamente più semplice: al click del pulsante, il 
thread parte ed esegue il codice. Il thread non ha nome, non ha priorità. Se il 
metodo aggiungiRecord avesse un parametro, dobbiamo usare un altro modalità:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;int&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;howMany;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;int&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;.TryParse(txtHowManyRecords.Text,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;out&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;howMany);&lt;BR&gt;&lt;BR&gt;ParameterizedThreadStart&amp;nbsp;start&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;ParameterizedThreadStart(aggiungiRecord);&lt;BR&gt;_th&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;new&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;Thread(start);&lt;BR&gt;_th.Start(howMany);&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Ho aggiunto sulla form una TextBox chiamata txtHowManyRecords&amp;nbsp;che 
l'utente può usare per esprimere quanti record vuole inserire in tabella. 
Utilizzo il metodo statico &lt;STRONG&gt;&lt;A title="" href="http://lab.msdn.microsoft.com/search/Redirect.aspx?title=" target=_new name="" ?&gt;&lt;STRONG&gt;TryParse&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; della classe int: il metodo 
ritorna un bool, e in howMany finisce il numero richiesto. Il thread viene 
inizializzato con la classe ParameterizedThreadStart: per farlo, ho dovuto 
ovviamente modificare la firma di aggiungiRecord in questo modo:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;private&amp;nbsp;void&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;aggiungiRecord(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;object&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;o)&lt;BR&gt;{&amp;nbsp;}&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;&lt;STRONG&gt;Il thread sta girando...e allora?&lt;BR&gt;&lt;/STRONG&gt;Giunti a questo punto, 
il thread sta girando. Il thread secondario sta eseguendo il codice del metodo 
aggiungiRecord. Probabilmente, il ciclo for inserito occuperà gran parte del 
tempo. All'interno di questo ciclo, possiamo notificare sulla UI qualsiasi cosa 
all'utente, ma con le dovute attenzioni che - credo - esulano un po' dallo scopo 
di questo post. Basta giocherellare con delegate, con &lt;A title="" href="http://lab.msdn.microsoft.com/search/Redirect.aspx?title=" target=_new name="" ?&gt;BeginInvoke&lt;/A&gt;, &lt;A title="" href="http://lab.msdn.microsoft.com/search/Redirect.aspx?title=" target=_new name="" ?&gt;InvokeRequired&lt;/A&gt; e dintorni, ed il gioco è fatto. Personalmente, 
avevo studiato il capitolo 14 "Multithreaded User Interfaces" di "Windows Forms 
Programming in C#", scritto da Chris Sells: credo il miglior capitolo di quel 
libro.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Maggior controllo sul thread&lt;BR&gt;&lt;/STRONG&gt;La classe Thread ha alcune 
caratteristiche molto interessanti, che consentono al nostro codice di 
controllarla, magari via UI. Innanzitutto, il thread secondario può girare con 
una cultura differente da quella standard (proprietà &lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.thread.currentculture.aspx" target=_new name=""&gt;CurrentCulture&lt;/A&gt; e &lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.thread.currentuiculture.aspx" target=_new name=""&gt;CurrentUICulture&lt;/A&gt;). Possiamo dargli un nome (proprietà &lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.thread.name.aspx" target=_new name=""&gt;Name&lt;/A&gt;)&amp;nbsp;e capire in quale stato si trova (&lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.thread.threadstate.aspx" target=_new name=""&gt;ThreadState&lt;/A&gt;, che è &lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.threadstate.aspx" target=_new name=""&gt;un'enum&lt;/A&gt;). Possiamo usare il metodo &lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.thread.suspend.aspx" target=_new name=""&gt;Suspend&lt;/A&gt; per interrompere l'esecuzione e il metodo &lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.thread.resume.aspx" target=_new name=""&gt;Resume&lt;/A&gt; per riprenderla. Il metodo &lt;A title="" href="http://msdn2.microsoft.com/en-US/library/system.threading.thread.abort.aspx" target=_new name=""&gt;Abort&lt;/A&gt; blocca del tutto l'esecuzione del thread.&lt;/P&gt;
&lt;P&gt;Vedremo nel prossimo post qualche dettaglio in più, e il download 
dell'applicazione di esempio che ho creato.&lt;/P&gt;

&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;P&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.3&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO 1.3 (IT) Instant Blogger Copyright (c) 2005 A.Boschin - http://www.imhoproject.org --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/39545.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/04/27/39545.aspx</guid>
            <pubDate>Thu, 27 Apr 2006 19:01:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/04/27/39545.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/39545.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/39545.aspx</trackback:ping>
        </item>
        <item>
            <title>[70-536, #27] Le classi Installer, InstallContext ed altre classi</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/03/28/37966.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;Della classe Installer abbiamo &lt;A title="" href="http://blogs.ugidotnet.org/idamiani/archive/2005/09/27/27129.aspx" target=_new name=""&gt;già parlato molto tempo fa&lt;/A&gt;. Era il 27 settembre, e mi 
stavo preparando per l'esame 70-316. Quel giorno abbiamo visto come aggiungere 
alla nostra soluzione un nuovo progetto&amp;nbsp;&lt;STRONG&gt;Class Library&lt;/STRONG&gt;, 
come implementare una classe custom che eredita da &lt;STRONG&gt;Installer&lt;/STRONG&gt;. 
Tale classe viene consumata da Windows Installer durante il setup della nostra 
applicazione. Possiamo in pratica fare l'overloading degli eventi che accadono 
durante il processo di installazione, quindi gestire manualmente la Commit, 
provocare il Rollback, e via dicendo. Ma non solo: ci eravamo spinti un po' più 
in là. Avevamo aggiunto Custom Dialog, richiedendo alcune informazioni 
all'utente, come il suo indirizzo e-mail, oppure altre informazioni più semplici 
tramite CheckButton o RadioButton. Se volete implementare qualcosa di simile, 
consiglio caldamente di vedere il mio vecchio post, perchè io stesso ho avuto 
qualche difficoltà che sono riuscito a risolvere &lt;EM&gt;consultando me stesso&lt;/EM&gt; 
indietro nel tempo. Questo è un paradosso temporale, ma lascio che siano Doc e 
Marty a tirarmi fuori dai guai senza provocare qualche casino nello 
spazio-tempo. &lt;IMG height=19 src="http://www.imhoproject.org/files/risate.gif" width=19 align=absMiddle border=0&gt;&lt;/P&gt;
&lt;P&gt;In questo post, darò per assodate un sacco di cose, quelle cioè descritte nel 
post a cui mi riferivo più sopra. In questi giorni ho ripreso in mano 
l'argomento, perchè ho voluto preparare un setup un po' particolare al mio 
software di fatturazione. Quindi, mi sono complicato la vita, giusto per 
approfondire la questione. Nulla di trascendentale, sia chiaro, ma è comunque 
qualcosa di interessante. Vediamo perchè.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;La classe InstallContext&lt;BR&gt;&lt;/STRONG&gt;Dal punto di vista prettamente 
teorico, la classe &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installcontext(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;InstallContext&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; ci fornisce 
informazioni sull'Installer corrente. Essa si trova nel namespace &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/1yece858(VS.80).aspx" target=_new name=""&gt;System.Configuration.Install&lt;/A&gt;. Involontariamente, ne abbiamo già 
parlato. Quando ad esempio &lt;EM&gt;overloadiamo&lt;/EM&gt; l'evento 
&lt;STRONG&gt;Commit&lt;/STRONG&gt;, possiamo scrivere quanto segue:&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: black 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: black 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: gainsboro"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;public&amp;nbsp;override&amp;nbsp;void&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;Commit(System.Collections.IDictionary&amp;nbsp;savedState)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;base&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;.Commit(savedState);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InstallContext&amp;nbsp;ctx&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;this&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;.Context;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;string&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;db&amp;nbsp;=&amp;nbsp;ctx.Parameters["DB"];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;string&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;cognomeNome&amp;nbsp;=&amp;nbsp;ctx.Parameters["COGNOME_NOME"];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;string&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;provincia&amp;nbsp;=&amp;nbsp;ctx.Parameters["PROVINCIA"];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #0000ff; FONT-FAMILY: Courier New"&gt;string&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #000000; FONT-FAMILY: Courier New"&gt;email&amp;nbsp;=&amp;nbsp;ctx.Parameters["EMAIL"];&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;P&gt;Nel codice qui sopra, non facciamo altro che usare un'istanza di 
InstallContext, che ci permette di reperire le informazioni inserite dall'utente 
nella prima fase del setup. La proprietà &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installcontext.parameters(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;Parameters&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; serve proprio a 
questo: nell'esempio qui sopra, DB è un CheckButton (che può essere recuperato 
anche dal metodo &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installcontext.isparametertrue(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;IsParameterTrue&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;), mentre le 
altre COGNOME_NOME, PROVINCIA ed EMAIL sono normali TextBox che l'utente ha 
inputato. L'istanza è ritornata dalla property &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installer.context(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;Context&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; della classe 
&lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installer(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;Installer&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, che rappresenta per 
l'appunto l'engine di Windows Installer che sta girando in questo momento. 
Interessante l'uso del metodo &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installcontext.logmessage(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;LogMessage&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; che ci permette di 
scrivere sul file di log dedicato per questo setup, utile magari per capire cosa 
ha inserito l'utente e come si è comportato di conseguenza l'installer.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Altre classi che riguardano il setup&lt;BR&gt;&lt;/STRONG&gt;Il namespace 
System.Configuration.Install contiene altre classi, alcune interessanti, altre 
un po' meno. La classe &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.managedinstallerclass(VS.80).aspx" target=_new name=""&gt;ManagedInstaller&lt;/A&gt;, per esempio, non deve essere usata 
direttamente nei nostri Installer: fa parte integrante dell'engine del FX, e 
quindi viene utilizzata solo internamente. Stesso discorso per l'interfaccia 
&lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.imanagedinstaller(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;IManagedInstaller&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;La classe &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.transactedinstaller(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;TransactedInstaller&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; invece è 
più interessante. Essa permette di installare una serie di assembly in un'unica 
transazione: o tutto avviene con successo, oppure in presenza di qualche errore, 
il tutto viene &lt;EM&gt;rollbackato&lt;/EM&gt;. Questa classe espone la proprietà 
&lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installer.installers(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;Installers&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt;, a cui vanno 
aggiunti a mano gli installer che vogliamo inserire in transazione. Dal momento 
che non è inserita nell'esame 70-536, non ne parlerò, ma è interessante sapere 
che c'è e su che principio funziona. &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.transactedinstaller_members(VS.80).aspx" target=_new name=""&gt;Date un'occhiata all'interfaccia esposta&lt;/A&gt; da questa 
classe e buona lettura! &lt;IMG height=19 src="http://www.imhoproject.org/files/allegro.gif" width=19 align=absMiddle border=0&gt;&lt;/P&gt;
&lt;P&gt;Le classi &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.assemblyinstaller(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;AssemblyInstaller&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; e &lt;STRONG&gt;&lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.componentinstaller(VS.80).aspx" target=_new name=""&gt;&lt;STRONG&gt;ComponentInstaller&lt;/STRONG&gt;&lt;/A&gt;&lt;/STRONG&gt; ereditano 
entrambe da Installer. La prima, in particolare, ci permette di caricare un 
assembly - specificato attraverso il costruttore - e di far partire il setup 
contenuto. Ovviamente, l'assembly deve derivare da Installer. &lt;A title="" href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.assemblyinstaller_members(VS.80).aspx" target=_new name=""&gt;L'interfaccia esposta&lt;/A&gt; ci permette di fare tutto quanto 
necessario per agevolare il lavoro.&lt;/P&gt;
&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;P&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.2&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO Instant Blogger Copyright (c) 2004 A.Boschin - http://www.elite.boschin.it --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/37966.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/03/28/37966.aspx</guid>
            <pubDate>Tue, 28 Mar 2006 17:46:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/03/28/37966.aspx#feedback</comments>
            <slash:comments>16</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/37966.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/37966.aspx</trackback:ping>
        </item>
        <item>
            <title>[70-536, #26] Punto della situazione e rallentamenti</title>
            <link>http://blogs.ugidotnet.org/IDamiani/archive/2006/03/24/37806.aspx</link>
            <description>&lt;FONT face=Verdana size=2&gt;
&lt;P&gt;Ultimamente ho un po' rallentato&amp;nbsp;la pubblicazione 
dei miei post &lt;A title="" href="http://blogs.ugidotnet.org/idamiani/category/1704.aspx?Show=All" target=_new name=""&gt;sull'esame 70-536&lt;/A&gt;. In questo periodo sono un po' 
stra-carico, in tutti i casi per motivi di lavoro. Ho impegni che riguardano il 
mio software di fatturazione, ho impegni con la società con la quale lavoro, ho 
impegni personali, etc. etc. Insomma, il tempo è davvero poco. Gli argomenti da 
affrontare per coprire tutta la &lt;A title="" href="http://www.microsoft.com/learning/exams/70-536.asp" target=_new name=""&gt;Preparation Guide&lt;/A&gt; dell'esame per ottenere la &lt;A title="" href="http://www.microsoft.com/learning/mcp/mcpd/windev/" target=_new name=""&gt;MCPD : Windows Developer&lt;/A&gt;&amp;nbsp;invece sono ancora tanti.&lt;/P&gt;
&lt;P&gt;Bisogna parlare di Thread ed affini, bisogna parlare di ServiceBase e 
dintorni, qualche concetto teorico su Application Domain, la classe 
Configuration e le sue relative interfacce. Altri argomenti invece sono bene o 
male gli stessi già affrontati in passato per il 70-316: mi sto riferendo in 
particolare alla classe Installer (per customizzare il setup della nostra 
applicazione), le classi Debug e Trace e a qualcosa inerente la globalizzazione 
(CultureInfo, prima fra tutte, ad esempio). C'è molta carne al fuoco anche per 
quanto riguarda P/Invoke ed Interop, c'è tutta una parte dedicata al 
System.Drawing: Brush, Pen, Color, TextureBrush, Font, Graphics, Point, etc. 
etc. Altre cose invece le salterò a piedi uniti con un solo balzo senza pensarci 
troppo: le classi File, Directory, DriveInfo, Path, EventArgs. Non che non siano 
importanti, ma ritengo che se uno si vuole certificare, debba sapere il minimo 
necessario e, onestamente, preferisco approfondire altri argomenti più 
succulenti.&lt;/P&gt;
&lt;P&gt;Nonostante io continui a studiare per conto mio, ho veramente poco tempo per 
aprire IMHO e scrivere i miei soliti post. Continuerò a scrivere, questo è 
ovvio, ma sicuramente sarò un po' più rallentato rispetto ai miei soliti ritmi 
con i quali vi ho "viziato" fino ad oggi. Pazienza!&lt;/P&gt;
&lt;/FONT&gt;
&lt;FONT face=Verdana size=2&gt;&lt;P&gt;&lt;A href="http://imhoproject.org/"&gt;&lt;FONT face=Verdana size=1&gt;powered by IMHO 1.2&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;!-- Powered by IMHO Instant Blogger Copyright (c) 2004 A.Boschin - http://www.elite.boschin.it --&gt;
&lt;img src="http://blogs.ugidotnet.org/IDamiani/aggbug/37806.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/IDamiani/archive/2006/03/24/37806.aspx</guid>
            <pubDate>Fri, 24 Mar 2006 18:33:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/IDamiani/archive/2006/03/24/37806.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/IDamiani/comments/commentRss/37806.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/IDamiani/services/trackbacks/37806.aspx</trackback:ping>
        </item>
    </channel>
</rss>